Java tutorial
/* * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. */ package org.apache.felix.bundleplugin; import java.io.ByteArrayOutputStream; import java.io.File; import java.io.FileInputStream; import java.io.IOException; import java.io.InputStream; import java.lang.reflect.Method; import java.util.ArrayList; import java.util.Arrays; import java.util.Collection; import java.util.Collections; import java.util.Enumeration; import java.util.Iterator; import java.util.LinkedHashMap; import java.util.LinkedHashSet; import java.util.List; import java.util.Map; import java.util.Properties; import java.util.Set; import java.util.jar.Attributes; import java.util.jar.Manifest; import org.apache.maven.archiver.ManifestSection; import org.apache.maven.archiver.MavenArchiveConfiguration; import org.apache.maven.archiver.MavenArchiver; import org.apache.maven.artifact.Artifact; import org.apache.maven.artifact.handler.manager.ArtifactHandlerManager; import org.apache.maven.model.License; import org.apache.maven.model.Model; import org.apache.maven.plugin.AbstractMojo; import org.apache.maven.plugin.MojoExecutionException; import org.apache.maven.plugin.MojoFailureException; import org.apache.maven.plugin.logging.Log; import org.apache.maven.project.MavenProject; import org.apache.maven.project.MavenProjectHelper; import org.apache.maven.shared.osgi.DefaultMaven2OsgiConverter; import org.apache.maven.shared.osgi.Maven2OsgiConverter; import org.codehaus.plexus.archiver.UnArchiver; import org.codehaus.plexus.archiver.manager.ArchiverManager; import org.codehaus.plexus.util.DirectoryScanner; import org.codehaus.plexus.util.StringInputStream; import org.codehaus.plexus.util.StringUtils; import aQute.lib.osgi.Analyzer; import aQute.lib.osgi.Builder; import aQute.lib.osgi.EmbeddedResource; import aQute.lib.osgi.FileResource; import aQute.lib.osgi.Jar; import aQute.lib.spring.SpringXMLType; /** * Create an OSGi bundle from Maven project * * @goal bundle * @phase package * @requiresDependencyResolution test * @description build an OSGi bundle jar */ public class BundlePlugin extends AbstractMojo { /** * Directory where the manifest will be written * * @parameter expression="${manifestLocation}" default-value="${project.build.outputDirectory}/META-INF" */ protected File manifestLocation; /** * When true, unpack the bundle contents to the outputDirectory * * @parameter expression="${unpackBundle}" */ protected boolean unpackBundle; /** * Comma separated list of artifactIds to exclude from the dependency classpath passed to BND (use "true" to exclude everything) * * @parameter expression="${excludeDependencies}" */ protected String excludeDependencies; /** * Classifier type of the bundle to be installed. For example, "jdk14". * Defaults to none which means this is the project's main bundle. * * @parameter */ protected String classifier; /** * @component */ private MavenProjectHelper m_projectHelper; /** * @component */ private ArchiverManager m_archiverManager; /** * @component */ private ArtifactHandlerManager m_artifactHandlerManager; /** * Project types which this plugin supports. * * @parameter */ private List supportedProjectTypes = Arrays.asList(new String[] { "jar", "bundle" }); /** * The directory for the generated bundles. * * @parameter expression="${project.build.outputDirectory}" * @required */ private File outputDirectory; /** * The directory for the pom * * @parameter expression="${basedir}" * @required */ private File baseDir; /** * The directory for the generated JAR. * * @parameter expression="${project.build.directory}" * @required */ private String buildDirectory; /** * The Maven project. * * @parameter expression="${project}" * @required * @readonly */ private MavenProject project; /** * The BND instructions for the bundle. * * @parameter */ private Map instructions = new LinkedHashMap(); /** * Use locally patched version for now. */ private Maven2OsgiConverter m_maven2OsgiConverter = new DefaultMaven2OsgiConverter(); /** * The archive configuration to use. * * @parameter */ private MavenArchiveConfiguration archive; // accessed indirectly in JarPluginConfiguration private static final String MAVEN_SYMBOLICNAME = "maven-symbolicname"; private static final String MAVEN_RESOURCES = "{maven-resources}"; private static final String[] EMPTY_STRING_ARRAY = {}; private static final String[] DEFAULT_INCLUDES = { "**/**" }; protected Maven2OsgiConverter getMaven2OsgiConverter() { return m_maven2OsgiConverter; } protected void setMaven2OsgiConverter(Maven2OsgiConverter maven2OsgiConverter) { m_maven2OsgiConverter = maven2OsgiConverter; } protected MavenProject getProject() { return project; } /** * @see org.apache.maven.plugin.AbstractMojo#execute() */ public void execute() throws MojoExecutionException { Properties properties = new Properties(); String projectType = getProject().getArtifact().getType(); // ignore unsupported project types, useful when bundleplugin is configured in parent pom if (!supportedProjectTypes.contains(projectType)) { getLog().warn( "Ignoring project type " + projectType + " - supportedProjectTypes = " + supportedProjectTypes); return; } execute(getProject(), instructions, properties); } protected void execute(MavenProject currentProject, Map originalInstructions, Properties properties) throws MojoExecutionException { try { execute(currentProject, originalInstructions, properties, getClasspath(currentProject)); } catch (IOException e) { throw new MojoExecutionException("Error calculating classpath for project " + currentProject, e); } } /* transform directives from their XML form to the expected BND syntax (eg. _include becomes -include) */ protected static Map transformDirectives(Map originalInstructions) { Map transformedInstructions = new LinkedHashMap(); for (Iterator i = originalInstructions.entrySet().iterator(); i.hasNext();) { Map.Entry e = (Map.Entry) i.next(); String key = (String) e.getKey(); if (key.startsWith("_")) { key = "-" + key.substring(1); } String value = (String) e.getValue(); if (null == value) { value = ""; } else { value = value.replaceAll("\\p{Blank}*[\r\n]\\p{Blank}*", ""); } transformedInstructions.put(key, value); } return transformedInstructions; } protected void execute(MavenProject currentProject, Map originalInstructions, Properties properties, Jar[] classpath) throws MojoExecutionException { try { File jarFile = new File(getBuildDirectory(), getBundleName(currentProject)); Builder builder = buildOSGiBundle(currentProject, originalInstructions, properties, classpath); List errors = builder.getErrors(); List warnings = builder.getWarnings(); for (Iterator w = warnings.iterator(); w.hasNext();) { String msg = (String) w.next(); getLog().warn("Warning building bundle " + currentProject.getArtifact() + " : " + msg); } for (Iterator e = errors.iterator(); e.hasNext();) { String msg = (String) e.next(); getLog().error("Error building bundle " + currentProject.getArtifact() + " : " + msg); } if (errors.size() > 0) { String failok = builder.getProperty("-failok"); if (null == failok || "false".equalsIgnoreCase(failok)) { jarFile.delete(); throw new MojoFailureException("Error(s) found in bundle configuration"); } } // attach bundle to maven project jarFile.getParentFile().mkdirs(); builder.getJar().write(jarFile); Artifact mainArtifact = currentProject.getArtifact(); // workaround for MNG-1682: force maven to install artifact using the "jar" handler mainArtifact.setArtifactHandler(m_artifactHandlerManager.getArtifactHandler("jar")); if (null == classifier || classifier.trim().length() == 0) { mainArtifact.setFile(jarFile); } else { m_projectHelper.attachArtifact(currentProject, jarFile, classifier); } if (unpackBundle) { unpackBundle(jarFile); } if (manifestLocation != null) { File outputFile = new File(manifestLocation, "MANIFEST.MF"); try { Manifest manifest = builder.getJar().getManifest(); ManifestPlugin.writeManifest(manifest, outputFile); } catch (IOException e) { getLog().error("Error trying to write Manifest to file " + outputFile, e); } } // cleanup... builder.close(); } catch (MojoFailureException e) { getLog().error(e.getLocalizedMessage()); throw new MojoExecutionException("Error(s) found in bundle configuration", e); } catch (Exception e) { getLog().error("An internal error occurred", e); throw new MojoExecutionException("Internal error in maven-bundle-plugin", e); } } protected Builder buildOSGiBundle(MavenProject currentProject, Map originalInstructions, Properties properties, Jar[] classpath) throws Exception { properties.putAll(getDefaultProperties(currentProject)); properties.putAll(transformDirectives(originalInstructions)); Builder builder = new Builder(); builder.setBase(currentProject.getBasedir()); builder.setProperties(properties); builder.setClasspath(classpath); // update BND instructions to add included Maven resources includeMavenResources(currentProject, builder, getLog()); // calculate default export/private settings based on sources if (builder.getProperty(Analyzer.PRIVATE_PACKAGE) == null || builder.getProperty(Analyzer.EXPORT_PACKAGE) == null) { addLocalPackages(currentProject.getCompileSourceRoots(), builder); } // update BND instructions to embed selected Maven dependencies Collection embeddableArtifacts = getEmbeddableArtifacts(currentProject, builder); new DependencyEmbedder(getLog(), embeddableArtifacts).processHeaders(builder); dumpInstructions("BND Instructions:", builder.getProperties(), getLog()); dumpClasspath("BND Classpath:", builder.getClasspath(), getLog()); builder.build(); Jar jar = builder.getJar(); dumpManifest("BND Manifest:", jar.getManifest(), getLog()); String[] removeHeaders = builder.getProperty(Analyzer.REMOVE_HEADERS, "").split(","); mergeMavenManifest(currentProject, jar, removeHeaders, getLog()); builder.setJar(jar); dumpManifest("Final Manifest:", jar.getManifest(), getLog()); return builder; } protected static void dumpInstructions(String title, Properties properties, Log log) { if (log.isDebugEnabled()) { log.debug(title); log.debug("------------------------------------------------------------------------"); for (Enumeration e = properties.propertyNames(); e.hasMoreElements();) { String key = (String) e.nextElement(); log.debug(key + ": " + properties.getProperty(key)); } log.debug("------------------------------------------------------------------------"); } } protected static void dumpClasspath(String title, List classpath, Log log) { if (log.isDebugEnabled()) { log.debug(title); log.debug("------------------------------------------------------------------------"); for (Iterator i = classpath.iterator(); i.hasNext();) { File path = ((Jar) i.next()).getSource(); log.debug(null == path ? "null" : path.toString()); } log.debug("------------------------------------------------------------------------"); } } protected static void dumpManifest(String title, Manifest manifest, Log log) { if (log.isDebugEnabled()) { log.debug(title); log.debug("------------------------------------------------------------------------"); for (Iterator i = manifest.getMainAttributes().entrySet().iterator(); i.hasNext();) { Map.Entry entry = (Map.Entry) i.next(); log.debug(entry.getKey() + ": " + entry.getValue()); } log.debug("------------------------------------------------------------------------"); } } protected static void includeMavenResources(MavenProject currentProject, Analyzer analyzer, Log log) { // pass maven resource paths onto BND analyzer final String mavenResourcePaths = getMavenResourcePaths(currentProject); final String includeResource = (String) analyzer.getProperty(Analyzer.INCLUDE_RESOURCE); if (includeResource != null) { if (includeResource.indexOf(MAVEN_RESOURCES) >= 0) { // if there is no maven resource path, we do a special treatment and replace // every occurance of MAVEN_RESOURCES and a following comma with an empty string if (mavenResourcePaths.length() == 0) { String cleanedResource = removeTagFromInstruction(includeResource, MAVEN_RESOURCES); if (cleanedResource.length() > 0) { analyzer.setProperty(Analyzer.INCLUDE_RESOURCE, cleanedResource); } else { analyzer.unsetProperty(Analyzer.INCLUDE_RESOURCE); } } else { String combinedResource = StringUtils.replace(includeResource, MAVEN_RESOURCES, mavenResourcePaths); analyzer.setProperty(Analyzer.INCLUDE_RESOURCE, combinedResource); } } else if (mavenResourcePaths.length() > 0) { log.warn(Analyzer.INCLUDE_RESOURCE + ": overriding " + mavenResourcePaths + " with " + includeResource + " (add " + MAVEN_RESOURCES + " if you want to include the maven resources)"); } } else if (mavenResourcePaths.length() > 0) { analyzer.setProperty(Analyzer.INCLUDE_RESOURCE, mavenResourcePaths); } } protected void mergeMavenManifest(MavenProject currentProject, Jar jar, String[] removeHeaders, Log log) throws IOException { boolean addMavenDescriptor = true; try { /* * Grab customized manifest entries from the maven-jar-plugin configuration */ MavenArchiveConfiguration archiveConfig = JarPluginConfiguration .getArchiveConfiguration(currentProject); String mavenManifestText = new MavenArchiver().getManifest(currentProject, archiveConfig).toString(); addMavenDescriptor = archiveConfig.isAddMavenDescriptor(); Manifest mavenManifest = new Manifest(); // First grab the external manifest file (if specified) File externalManifestFile = archiveConfig.getManifestFile(); if (null != externalManifestFile && externalManifestFile.exists()) { InputStream mis = new FileInputStream(externalManifestFile); mavenManifest.read(mis); mis.close(); } // Then apply the customized entries from the jar plugin mavenManifest.read(new StringInputStream(mavenManifestText)); if (!archiveConfig.isManifestSectionsEmpty()) { /* * Add customized manifest sections (for some reason MavenArchiver doesn't do this for us) */ List sections = archiveConfig.getManifestSections(); for (Iterator i = sections.iterator(); i.hasNext();) { ManifestSection section = (ManifestSection) i.next(); Attributes attributes = new Attributes(); if (!section.isManifestEntriesEmpty()) { Map entries = section.getManifestEntries(); for (Iterator j = entries.entrySet().iterator(); j.hasNext();) { Map.Entry entry = (Map.Entry) j.next(); attributes.putValue((String) entry.getKey(), (String) entry.getValue()); } } mavenManifest.getEntries().put(section.getName(), attributes); } } Attributes mainMavenAttributes = mavenManifest.getMainAttributes(); mainMavenAttributes.putValue("Created-By", "Apache Maven Bundle Plugin"); // apply -removeheaders to the custom manifest for (int i = 0; i < removeHeaders.length; i++) { for (Iterator j = mainMavenAttributes.keySet().iterator(); j.hasNext();) { if (j.next().toString().matches(removeHeaders[i].trim())) { j.remove(); } } } /* * Overlay generated bundle manifest with customized entries */ Manifest bundleManifest = jar.getManifest(); bundleManifest.getMainAttributes().putAll(mainMavenAttributes); bundleManifest.getEntries().putAll(mavenManifest.getEntries()); jar.setManifest(bundleManifest); } catch (Exception e) { log.warn("Unable to merge Maven manifest: " + e.getLocalizedMessage()); } if (addMavenDescriptor) { doMavenMetadata(currentProject, jar); } } private void unpackBundle(File jarFile) { File outputDir = getOutputDirectory(); if (null == outputDir) { outputDir = new File(getBuildDirectory(), "classes"); } try { /* * this directory must exist before unpacking, otherwise the plexus * unarchiver decides to use the current working directory instead! */ if (!outputDir.exists()) { outputDir.mkdirs(); } UnArchiver unArchiver = m_archiverManager.getUnArchiver("jar"); unArchiver.setDestDirectory(outputDir); unArchiver.setSourceFile(jarFile); unArchiver.extract(); } catch (Exception e) { getLog().error("Problem unpacking " + jarFile + " to " + outputDir, e); } } protected static String removeTagFromInstruction(String instruction, String tag) { StringBuffer buf = new StringBuffer(); String[] clauses = instruction.split(","); for (int i = 0; i < clauses.length; i++) { String clause = clauses[i].trim(); if (!tag.equals(clause)) { if (buf.length() > 0) { buf.append(','); } buf.append(clause); } } return buf.toString(); } private static Map getProperties(Model projectModel, String prefix) { Map properties = new LinkedHashMap(); Method methods[] = Model.class.getDeclaredMethods(); for (int i = 0; i < methods.length; i++) { String name = methods[i].getName(); if (name.startsWith("get")) { try { Object v = methods[i].invoke(projectModel, null); if (v != null) { name = prefix + Character.toLowerCase(name.charAt(3)) + name.substring(4); if (v.getClass().isArray()) properties.put(name, Arrays.asList((Object[]) v).toString()); else properties.put(name, v); } } catch (Exception e) { // too bad } } } return properties; } private static StringBuffer printLicenses(List licenses) { if (licenses == null || licenses.size() == 0) return null; StringBuffer sb = new StringBuffer(); String del = ""; for (Iterator i = licenses.iterator(); i.hasNext();) { License l = (License) i.next(); String url = l.getUrl(); if (url == null) continue; sb.append(del); sb.append(url); del = ", "; } if (sb.length() == 0) return null; return sb; } /** * @param jar * @throws IOException */ private void doMavenMetadata(MavenProject currentProject, Jar jar) throws IOException { String path = "META-INF/maven/" + currentProject.getGroupId() + "/" + currentProject.getArtifactId(); File pomFile = new File(baseDir, "pom.xml"); jar.putResource(path + "/pom.xml", new FileResource(pomFile)); Properties p = new Properties(); p.put("version", currentProject.getVersion()); p.put("groupId", currentProject.getGroupId()); p.put("artifactId", currentProject.getArtifactId()); ByteArrayOutputStream out = new ByteArrayOutputStream(); p.store(out, "Generated by org.apache.felix.bundleplugin"); jar.putResource(path + "/pom.properties", new EmbeddedResource(out.toByteArray(), System.currentTimeMillis())); } protected Jar[] getClasspath(MavenProject currentProject) throws IOException, MojoExecutionException { List list = new ArrayList(); if (getOutputDirectory() != null && getOutputDirectory().exists()) { list.add(new Jar(".", getOutputDirectory())); } final Collection artifacts = getSelectedDependencies(currentProject.getArtifacts()); for (Iterator it = artifacts.iterator(); it.hasNext();) { Artifact artifact = (Artifact) it.next(); if (artifact.getArtifactHandler().isAddedToClasspath()) { if (!Artifact.SCOPE_TEST.equals(artifact.getScope())) { File file = getFile(artifact); if (file == null) { getLog().warn("File is not available for artifact " + artifact + " in project " + currentProject.getArtifact()); continue; } Jar jar = new Jar(artifact.getArtifactId(), file); list.add(jar); } } } Jar[] cp = new Jar[list.size()]; list.toArray(cp); return cp; } private Collection getSelectedDependencies(Collection artifacts) throws MojoExecutionException { if (null == excludeDependencies || excludeDependencies.length() == 0) { return artifacts; } else if ("true".equalsIgnoreCase(excludeDependencies)) { return Collections.EMPTY_LIST; } Collection selectedDependencies = new LinkedHashSet(artifacts); DependencyExcluder excluder = new DependencyExcluder(artifacts); excluder.processHeaders(excludeDependencies); selectedDependencies.removeAll(excluder.getExcludedArtifacts()); return selectedDependencies; } /** * Get the file for an Artifact * * @param artifact */ protected File getFile(Artifact artifact) { return artifact.getFile(); } private static void header(Properties properties, String key, Object value) { if (value == null) return; if (value instanceof Collection && ((Collection) value).isEmpty()) return; properties.put(key, value.toString().replaceAll("[\r\n]", "")); } /** * Convert a Maven version into an OSGi compliant version * * @param version Maven version * @return the OSGi version */ protected String convertVersionToOsgi(String version) { return getMaven2OsgiConverter().getVersion(version); } /** * TODO this should return getMaven2Osgi().getBundleFileName( project.getArtifact() ) */ protected String getBundleName(MavenProject currentProject) { String finalName = currentProject.getBuild().getFinalName(); if (null != classifier && classifier.trim().length() > 0) { return finalName + '-' + classifier + ".jar"; } return finalName + ".jar"; } protected String getBuildDirectory() { return buildDirectory; } protected void setBuildDirectory(String _buildirectory) { buildDirectory = _buildirectory; } protected Properties getDefaultProperties(MavenProject currentProject) { Properties properties = new Properties(); String bsn; try { bsn = getMaven2OsgiConverter().getBundleSymbolicName(currentProject.getArtifact()); } catch (Exception e) { bsn = currentProject.getGroupId() + "." + currentProject.getArtifactId(); } // Setup defaults properties.put(MAVEN_SYMBOLICNAME, bsn); properties.put(Analyzer.BUNDLE_SYMBOLICNAME, bsn); properties.put(Analyzer.IMPORT_PACKAGE, "*"); properties.put(Analyzer.BUNDLE_VERSION, getMaven2OsgiConverter().getVersion(currentProject.getVersion())); // remove the extraneous Include-Resource and Private-Package entries from generated manifest properties.put(Analyzer.REMOVE_HEADERS, Analyzer.INCLUDE_RESOURCE + ',' + Analyzer.PRIVATE_PACKAGE); header(properties, Analyzer.BUNDLE_DESCRIPTION, currentProject.getDescription()); StringBuffer licenseText = printLicenses(currentProject.getLicenses()); if (licenseText != null) { header(properties, Analyzer.BUNDLE_LICENSE, licenseText); } header(properties, Analyzer.BUNDLE_NAME, currentProject.getName()); if (currentProject.getOrganization() != null) { String organizationName = currentProject.getOrganization().getName(); header(properties, Analyzer.BUNDLE_VENDOR, organizationName); properties.put("project.organization.name", organizationName); properties.put("pom.organization.name", organizationName); if (currentProject.getOrganization().getUrl() != null) { String organizationUrl = currentProject.getOrganization().getUrl(); header(properties, Analyzer.BUNDLE_DOCURL, organizationUrl); properties.put("project.organization.url", organizationUrl); properties.put("pom.organization.url", organizationUrl); } } properties.putAll(currentProject.getProperties()); properties.putAll(currentProject.getModel().getProperties()); properties.putAll(getProperties(currentProject.getModel(), "project.build.")); properties.putAll(getProperties(currentProject.getModel(), "pom.")); properties.putAll(getProperties(currentProject.getModel(), "project.")); properties.put("project.baseDir", baseDir); properties.put("project.build.directory", getBuildDirectory()); properties.put("project.build.outputdirectory", getOutputDirectory()); properties.put("classifier", classifier == null ? "" : classifier); // Add default plugins header(properties, Analyzer.PLUGIN, BlueprintPlugin.class.getName() + "," + SpringXMLType.class.getName()); return properties; } protected void setBasedir(File _basedir) { baseDir = _basedir; } protected File getOutputDirectory() { return outputDirectory; } protected void setOutputDirectory(File _outputDirectory) { outputDirectory = _outputDirectory; } private static void addLocalPackages(List sourceDirectories, Analyzer analyzer) { Collection packages = new LinkedHashSet(); for (Iterator d = sourceDirectories.iterator(); d.hasNext();) { String sourceDirectory = (String) d.next(); if (sourceDirectory != null && new File(sourceDirectory).isDirectory()) { // scan local Java sources for potential packages DirectoryScanner scanner = new DirectoryScanner(); scanner.setBasedir(sourceDirectory); scanner.setIncludes(new String[] { "**/*.java" }); scanner.addDefaultExcludes(); scanner.scan(); String[] paths = scanner.getIncludedFiles(); for (int i = 0; i < paths.length; i++) { packages.add(getPackageName(paths[i])); } } } StringBuffer exportedPkgs = new StringBuffer(); StringBuffer privatePkgs = new StringBuffer(); for (Iterator i = packages.iterator(); i.hasNext();) { String pkg = (String) i.next(); // mark all source packages as private by default (can be overridden by export list) privatePkgs.append(pkg).append(";-split-package:=merge-first,"); // we can't export the default package (".") and we shouldn't export internal packages if (!(".".equals(pkg) || pkg.contains(".internal") || pkg.contains(".impl"))) { exportedPkgs.append(pkg).append(','); } } if (analyzer.getProperty(Analyzer.EXPORT_PACKAGE) == null) { if (analyzer.getProperty(Analyzer.EXPORT_CONTENTS) == null) { // no -exportcontents overriding the exports, so use our computed list analyzer.setProperty(Analyzer.EXPORT_PACKAGE, exportedPkgs.toString()); } else { // leave Export-Package empty (but non-null) as we have -exportcontents analyzer.setProperty(Analyzer.EXPORT_PACKAGE, ""); } } if (analyzer.getProperty(Analyzer.PRIVATE_PACKAGE) == null) { // if there are really no private packages then use "!*" as this will keep the Bnd Tool happy analyzer.setProperty(Analyzer.PRIVATE_PACKAGE, privatePkgs.length() == 0 ? "!*" : privatePkgs.toString()); } } private static String getPackageName(String filename) { int n = filename.lastIndexOf(File.separatorChar); return n < 0 ? "." : filename.substring(0, n).replace(File.separatorChar, '.'); } private static String getMavenResourcePaths(MavenProject project) { final String basePath = project.getBasedir().getAbsolutePath(); Set pathSet = new LinkedHashSet(); for (Iterator i = project.getResources().iterator(); i.hasNext();) { org.apache.maven.model.Resource resource = (org.apache.maven.model.Resource) i.next(); final String sourcePath = resource.getDirectory(); final String targetPath = resource.getTargetPath(); // ignore empty or non-local resources if (new File(sourcePath).exists() && ((targetPath == null) || (targetPath.indexOf("..") < 0))) { DirectoryScanner scanner = new DirectoryScanner(); scanner.setBasedir(resource.getDirectory()); if (resource.getIncludes() != null && !resource.getIncludes().isEmpty()) { scanner.setIncludes((String[]) resource.getIncludes().toArray(EMPTY_STRING_ARRAY)); } else { scanner.setIncludes(DEFAULT_INCLUDES); } if (resource.getExcludes() != null && !resource.getExcludes().isEmpty()) { scanner.setExcludes((String[]) resource.getExcludes().toArray(EMPTY_STRING_ARRAY)); } scanner.addDefaultExcludes(); scanner.scan(); List includedFiles = Arrays.asList(scanner.getIncludedFiles()); for (Iterator j = includedFiles.iterator(); j.hasNext();) { String name = (String) j.next(); String path = sourcePath + '/' + name; // make relative to project if (path.startsWith(basePath)) { if (path.length() == basePath.length()) { path = "."; } else { path = path.substring(basePath.length() + 1); } } // replace windows backslash with a slash // this is a workaround for a problem with bnd 0.0.189 if (File.separatorChar != '/') { name = name.replace(File.separatorChar, '/'); path = path.replace(File.separatorChar, '/'); } // copy to correct place path = name + '=' + path; if (targetPath != null) { path = targetPath + '/' + path; } // use Bnd filtering? if (resource.isFiltering()) { path = '{' + path + '}'; } pathSet.add(path); } } } StringBuffer resourcePaths = new StringBuffer(); for (Iterator i = pathSet.iterator(); i.hasNext();) { resourcePaths.append(i.next()); if (i.hasNext()) { resourcePaths.append(','); } } return resourcePaths.toString(); } protected Collection getEmbeddableArtifacts(MavenProject project, Analyzer analyzer) throws MojoExecutionException { final Collection artifacts; String embedTransitive = analyzer.getProperty(DependencyEmbedder.EMBED_TRANSITIVE); if (Boolean.valueOf(embedTransitive).booleanValue()) { // includes transitive dependencies artifacts = project.getArtifacts(); } else { // only includes direct dependencies artifacts = project.getDependencyArtifacts(); } return getSelectedDependencies(artifacts); } }