blob: d374574510495041699072849474910821cf8355 [file] [log] [blame]
Richard S. Hallf3120092006-10-31 17:32:16 +00001/*
2 * Licensed to the Apache Software Foundation (ASF) under one
3 * or more contributor license agreements. See the NOTICE file
4 * distributed with this work for additional information
5 * regarding copyright ownership. The ASF licenses this file
6 * to you under the Apache License, Version 2.0 (the
7 * "License"); you may not use this file except in compliance
8 * with the License. You may obtain a copy of the License at
9 *
10 * http://www.apache.org/licenses/LICENSE-2.0
11 *
12 * Unless required by applicable law or agreed to in writing,
13 * software distributed under the License is distributed on an
14 * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
15 * KIND, either express or implied. See the License for the
16 * specific language governing permissions and limitations
17 * under the License.
18 */
Richard S. Hall01a56ce2007-05-20 22:31:11 +000019package org.apache.felix.bundleplugin;
Carsten Ziegeler8fb2f052007-08-01 08:28:54 +000020
Stuart McCulloch5ae59142008-01-29 06:21:05 +000021
Stuart McCulloch340a8dd2011-06-28 22:47:10 +000022import java.io.ByteArrayInputStream;
Carsten Ziegeler8fb2f052007-08-01 08:28:54 +000023import java.io.ByteArrayOutputStream;
24import java.io.File;
Stuart McCulloch3d34d502008-01-09 15:19:32 +000025import java.io.FileInputStream;
Carsten Ziegeler8fb2f052007-08-01 08:28:54 +000026import java.io.IOException;
Stuart McCulloch3d34d502008-01-09 15:19:32 +000027import java.io.InputStream;
Stuart McCulloch9e631952011-11-09 00:45:12 +000028import java.lang.reflect.Array;
Carsten Ziegeler8fb2f052007-08-01 08:28:54 +000029import java.lang.reflect.Method;
Guillaume Nodetdfe0fe72015-07-09 19:45:35 +000030import java.util.*;
Stuart McCulloch3d34d502008-01-09 15:19:32 +000031import java.util.jar.Attributes;
Stuart McCulloch717740b2007-09-21 11:18:31 +000032import java.util.jar.Manifest;
Richard S. Hall420d2782007-06-14 12:31:48 +000033
Guillaume Nodetdfe0fe72015-07-09 19:45:35 +000034import aQute.bnd.header.OSGiHeader;
35import aQute.bnd.header.Parameters;
36import aQute.bnd.osgi.Instruction;
37import aQute.bnd.osgi.Instructions;
38import aQute.lib.collections.ExtList;
39import aQute.libg.generics.Create;
Stuart McCulloch3d34d502008-01-09 15:19:32 +000040import org.apache.maven.archiver.ManifestSection;
Stuart McCullochf978c532007-12-27 09:16:34 +000041import org.apache.maven.archiver.MavenArchiveConfiguration;
42import org.apache.maven.archiver.MavenArchiver;
Richard S. Hallf3120092006-10-31 17:32:16 +000043import org.apache.maven.artifact.Artifact;
Stuart McCullochffadcf62007-08-24 10:39:35 +000044import org.apache.maven.artifact.handler.manager.ArtifactHandlerManager;
Stuart McCullochcdad75f2011-06-28 00:03:15 +000045import org.apache.maven.execution.MavenSession;
Carsten Ziegeler8fb2f052007-08-01 08:28:54 +000046import org.apache.maven.model.License;
47import org.apache.maven.model.Model;
Stuart McCulloche71aa492011-06-24 18:21:16 +000048import org.apache.maven.model.Resource;
Carsten Ziegeler8fb2f052007-08-01 08:28:54 +000049import org.apache.maven.plugin.AbstractMojo;
50import org.apache.maven.plugin.MojoExecutionException;
51import org.apache.maven.plugin.MojoFailureException;
Stuart McCulloch48fcb1e2008-01-30 06:58:34 +000052import org.apache.maven.plugin.logging.Log;
Carsten Ziegeler318c2cb2015-03-09 13:57:23 +000053import org.apache.maven.plugins.annotations.Component;
Carsten Ziegeler318c2cb2015-03-09 13:57:23 +000054import org.apache.maven.plugins.annotations.LifecyclePhase;
55import org.apache.maven.plugins.annotations.Mojo;
56import org.apache.maven.plugins.annotations.Parameter;
57import org.apache.maven.plugins.annotations.ResolutionScope;
Richard S. Hallf3120092006-10-31 17:32:16 +000058import org.apache.maven.project.MavenProject;
Stuart McCulloch2d301732008-02-18 09:01:17 +000059import org.apache.maven.project.MavenProjectHelper;
Guillaume Nodeted7b1102015-07-09 19:45:09 +000060import org.apache.maven.shared.dependency.graph.DependencyGraphBuilder;
61import org.apache.maven.shared.dependency.graph.DependencyGraphBuilderException;
62import org.apache.maven.shared.dependency.graph.DependencyNode;
Stuart McCulloch99f4aa62009-02-17 13:40:44 +000063import org.apache.maven.shared.osgi.DefaultMaven2OsgiConverter;
Richard S. Hall17b8e3d2007-06-13 16:20:40 +000064import org.apache.maven.shared.osgi.Maven2OsgiConverter;
Stuart McCullochdd0d9ba2007-12-07 08:22:20 +000065import org.codehaus.plexus.archiver.UnArchiver;
66import org.codehaus.plexus.archiver.manager.ArchiverManager;
Stuart McCulloch44deaef2007-11-18 04:36:21 +000067import org.codehaus.plexus.util.DirectoryScanner;
Stuart McCulloch340a8dd2011-06-28 22:47:10 +000068import org.codehaus.plexus.util.FileUtils;
Stuart McCulloch437f4872013-06-07 21:24:26 +000069import org.codehaus.plexus.util.PropertyUtils;
Stuart McCulloch6cb86db2008-03-15 21:38:26 +000070import org.codehaus.plexus.util.StringUtils;
Richard S. Hall420d2782007-06-14 12:31:48 +000071
Stuart McCulloch1648f402013-06-07 22:21:11 +000072import aQute.bnd.header.Attrs;
Stuart McCulloch42151ee2012-07-16 13:43:38 +000073import aQute.bnd.osgi.Analyzer;
74import aQute.bnd.osgi.Builder;
75import aQute.bnd.osgi.Constants;
Stuart McCulloch1648f402013-06-07 22:21:11 +000076import aQute.bnd.osgi.Descriptors.PackageRef;
Stuart McCulloch42151ee2012-07-16 13:43:38 +000077import aQute.bnd.osgi.EmbeddedResource;
78import aQute.bnd.osgi.FileResource;
79import aQute.bnd.osgi.Jar;
Stuart McCulloch1648f402013-06-07 22:21:11 +000080import aQute.bnd.osgi.Packages;
Stuart McCulloch42151ee2012-07-16 13:43:38 +000081import aQute.bnd.osgi.Processor;
Guillaume Nodet459eaed2009-09-02 21:15:28 +000082import aQute.lib.spring.SpringXMLType;
Carsten Ziegeler8fb2f052007-08-01 08:28:54 +000083
Stuart McCulloch5ae59142008-01-29 06:21:05 +000084
Richard S. Hallf3120092006-10-31 17:32:16 +000085/**
Richard S. Hall420d2782007-06-14 12:31:48 +000086 * Create an OSGi bundle from Maven project
Carsten Ziegeler8fb2f052007-08-01 08:28:54 +000087 *
Richard S. Hallf3120092006-10-31 17:32:16 +000088 */
Carsten Ziegeler0a4eff12015-05-12 06:04:41 +000089@Mojo( name = "bundle", requiresDependencyResolution = ResolutionScope.TEST,
90 threadSafe = true,
91 defaultPhase = LifecyclePhase.PACKAGE )
Stuart McCulloch5ae59142008-01-29 06:21:05 +000092public class BundlePlugin extends AbstractMojo
93{
Carsten Ziegeler8fb2f052007-08-01 08:28:54 +000094 /**
Stuart McCulloch717740b2007-09-21 11:18:31 +000095 * Directory where the manifest will be written
Stuart McCulloch717740b2007-09-21 11:18:31 +000096 */
Carsten Ziegeler318c2cb2015-03-09 13:57:23 +000097 @Parameter( property = "manifestLocation", defaultValue = "${project.build.outputDirectory}/META-INF" )
Stuart McCulloch0ab63892007-10-19 11:43:24 +000098 protected File manifestLocation;
Stuart McCulloch717740b2007-09-21 11:18:31 +000099
100 /**
Stuart McCulloch9a710e52014-06-23 12:01:53 +0000101 * Output a nicely formatted manifest that still respects the 72 character line limit.
Stuart McCulloch9a710e52014-06-23 12:01:53 +0000102 */
Carsten Ziegeler318c2cb2015-03-09 13:57:23 +0000103 @Parameter( property = "niceManifest", defaultValue = "false" )
Stuart McCulloch9a710e52014-06-23 12:01:53 +0000104 protected boolean niceManifest;
105
106 /**
Stuart McCulloch340a8dd2011-06-28 22:47:10 +0000107 * File where the BND instructions will be dumped
Stuart McCulloch340a8dd2011-06-28 22:47:10 +0000108 */
Carsten Ziegeler318c2cb2015-03-09 13:57:23 +0000109 @Parameter( property = "dumpInstructions" )
Stuart McCulloch340a8dd2011-06-28 22:47:10 +0000110 protected File dumpInstructions;
111
112 /**
113 * File where the BND class-path will be dumped
Stuart McCulloch340a8dd2011-06-28 22:47:10 +0000114 */
Carsten Ziegeler318c2cb2015-03-09 13:57:23 +0000115 @Parameter( property = "dumpClasspath" )
Stuart McCulloch340a8dd2011-06-28 22:47:10 +0000116 protected File dumpClasspath;
117
118 /**
Stuart McCullochdd0d9ba2007-12-07 08:22:20 +0000119 * When true, unpack the bundle contents to the outputDirectory
Stuart McCullochdd0d9ba2007-12-07 08:22:20 +0000120 */
Carsten Ziegeler318c2cb2015-03-09 13:57:23 +0000121 @Parameter( property = "unpackBundle" )
Stuart McCullochdd0d9ba2007-12-07 08:22:20 +0000122 protected boolean unpackBundle;
123
124 /**
Stuart McCulloch5ffc3fe2008-02-20 05:37:57 +0000125 * Comma separated list of artifactIds to exclude from the dependency classpath passed to BND (use "true" to exclude everything)
Stuart McCullochcb02d6a2008-01-09 16:42:16 +0000126 */
Carsten Ziegeler318c2cb2015-03-09 13:57:23 +0000127 @Parameter( property = "excludeDependencies" )
Stuart McCulloch5ffc3fe2008-02-20 05:37:57 +0000128 protected String excludeDependencies;
Stuart McCullochcb02d6a2008-01-09 16:42:16 +0000129
130 /**
Stuart McCulloch0614c702013-06-07 20:00:40 +0000131 * Final name of the bundle (without classifier or extension)
Carsten Ziegeler67c8ce32014-08-07 06:41:23 +0000132 */
Carsten Ziegeler318c2cb2015-03-09 13:57:23 +0000133 @Parameter( defaultValue = "${project.build.finalName}")
Carsten Ziegeler67c8ce32014-08-07 06:41:23 +0000134 private String finalName;
Stuart McCulloch0614c702013-06-07 20:00:40 +0000135
136 /**
Stuart McCulloch2d301732008-02-18 09:01:17 +0000137 * Classifier type of the bundle to be installed. For example, "jdk14".
138 * Defaults to none which means this is the project's main bundle.
Stuart McCulloch2d301732008-02-18 09:01:17 +0000139 */
Carsten Ziegeler318c2cb2015-03-09 13:57:23 +0000140 @Parameter
Stuart McCulloch2d301732008-02-18 09:01:17 +0000141 protected String classifier;
142
143 /**
Stuart McCulloch01c93bd2013-06-07 18:23:07 +0000144 * Packaging type of the bundle to be installed. For example, "jar".
145 * Defaults to none which means use the same packaging as the project.
Stuart McCulloch01c93bd2013-06-07 18:23:07 +0000146 */
Carsten Ziegeler318c2cb2015-03-09 13:57:23 +0000147 @Parameter
Stuart McCulloch01c93bd2013-06-07 18:23:07 +0000148 protected String packaging;
149
Carsten Ziegeler318c2cb2015-03-09 13:57:23 +0000150 @Component
Stuart McCulloch2d301732008-02-18 09:01:17 +0000151 private MavenProjectHelper m_projectHelper;
152
Carsten Ziegeler318c2cb2015-03-09 13:57:23 +0000153 @Component
Stuart McCulloch9366a822008-01-29 07:45:57 +0000154 private ArchiverManager m_archiverManager;
Stuart McCullochdd0d9ba2007-12-07 08:22:20 +0000155
Carsten Ziegeler318c2cb2015-03-09 13:57:23 +0000156 @Component
Stuart McCulloch9366a822008-01-29 07:45:57 +0000157 private ArtifactHandlerManager m_artifactHandlerManager;
Stuart McCullochffadcf62007-08-24 10:39:35 +0000158
Guillaume Nodeted7b1102015-07-09 19:45:09 +0000159 @Component
160 private DependencyGraphBuilder m_dependencyGraphBuilder;
161
Stuart McCullochffadcf62007-08-24 10:39:35 +0000162 /**
Carsten Ziegeler8fb2f052007-08-01 08:28:54 +0000163 * Project types which this plugin supports.
Carsten Ziegeler8fb2f052007-08-01 08:28:54 +0000164 */
Carsten Ziegeler318c2cb2015-03-09 13:57:23 +0000165 @Parameter
Carsten Ziegeler82d87402015-03-04 13:26:21 +0000166 protected List<String> supportedProjectTypes = Arrays.asList( new String[]
Stuart McCulloch5ae59142008-01-29 06:21:05 +0000167 { "jar", "bundle" } );
Richard S. Hall3c0051d2007-04-27 17:07:17 +0000168
Carsten Ziegeler8fb2f052007-08-01 08:28:54 +0000169 /**
170 * The directory for the generated bundles.
Carsten Ziegeler8fb2f052007-08-01 08:28:54 +0000171 */
Carsten Ziegeler318c2cb2015-03-09 13:57:23 +0000172 @Parameter( defaultValue = "${project.build.outputDirectory}" )
Carsten Ziegeler8fb2f052007-08-01 08:28:54 +0000173 private File outputDirectory;
Richard S. Hall17b8e3d2007-06-13 16:20:40 +0000174
Carsten Ziegeler8fb2f052007-08-01 08:28:54 +0000175 /**
Carsten Ziegeler8fb2f052007-08-01 08:28:54 +0000176 * The directory for the generated JAR.
Carsten Ziegeler8fb2f052007-08-01 08:28:54 +0000177 */
Carsten Ziegeler318c2cb2015-03-09 13:57:23 +0000178 @Parameter( defaultValue = "${project.build.directory}" )
Stuart McCulloch5ae59142008-01-29 06:21:05 +0000179 private String buildDirectory;
Richard S. Hall17b8e3d2007-06-13 16:20:40 +0000180
Carsten Ziegeler8fb2f052007-08-01 08:28:54 +0000181 /**
182 * The Maven project.
Carsten Ziegeler8fb2f052007-08-01 08:28:54 +0000183 */
Carsten Ziegeler318c2cb2015-03-09 13:57:23 +0000184 @Parameter( defaultValue = "${project}", readonly = true, required = true )
Carsten Ziegeler8fb2f052007-08-01 08:28:54 +0000185 private MavenProject project;
Richard S. Hall420d2782007-06-14 12:31:48 +0000186
Carsten Ziegeler8fb2f052007-08-01 08:28:54 +0000187 /**
Stuart McCulloch2d301732008-02-18 09:01:17 +0000188 * The BND instructions for the bundle.
Carsten Ziegeler8fb2f052007-08-01 08:28:54 +0000189 */
Carsten Ziegeler318c2cb2015-03-09 13:57:23 +0000190 @Parameter
Carsten Ziegeler82d87402015-03-04 13:26:21 +0000191 private Map<String, String> instructions = new LinkedHashMap<String, String>();
Richard S. Hall6cf6f0b2007-04-10 16:50:31 +0000192
Carsten Ziegeler8fb2f052007-08-01 08:28:54 +0000193 /**
Stuart McCulloch99f4aa62009-02-17 13:40:44 +0000194 * Use locally patched version for now.
Carsten Ziegeler8fb2f052007-08-01 08:28:54 +0000195 */
Carsten Ziegeler846bd7a2015-05-15 08:53:36 +0000196 private final Maven2OsgiConverter m_maven2OsgiConverter = new DefaultMaven2OsgiConverter();
Richard S. Hall6cf6f0b2007-04-10 16:50:31 +0000197
Stuart McCulloch378e76c2009-01-30 09:51:35 +0000198 /**
199 * The archive configuration to use.
Stuart McCulloch378e76c2009-01-30 09:51:35 +0000200 */
Carsten Ziegeler318c2cb2015-03-09 13:57:23 +0000201 @Parameter
Stuart McCulloch378e76c2009-01-30 09:51:35 +0000202 private MavenArchiveConfiguration archive; // accessed indirectly in JarPluginConfiguration
203
Carsten Ziegeler318c2cb2015-03-09 13:57:23 +0000204 @Parameter( defaultValue = "${session}", readonly = true, required = true )
Stuart McCullochd98b02e2011-06-28 23:20:37 +0000205 private MavenSession m_mavenSession;
Stuart McCullochcdad75f2011-06-28 00:03:15 +0000206
Stuart McCulloch6d4c8372009-02-16 06:49:21 +0000207 private static final String MAVEN_SYMBOLICNAME = "maven-symbolicname";
Stuart McCulloch9c406b12007-08-23 09:41:08 +0000208 private static final String MAVEN_RESOURCES = "{maven-resources}";
Guillaume Nodet09194e62014-06-16 07:07:12 +0000209 private static final String MAVEN_TEST_RESOURCES = "{maven-test-resources}";
Guillaume Nodete5f5c7a2010-11-17 08:09:42 +0000210 private static final String LOCAL_PACKAGES = "{local-packages}";
Stuart McCullochfe58ad52011-11-28 15:05:51 +0000211 private static final String MAVEN_SOURCES = "{maven-sources}";
Guillaume Nodet09194e62014-06-16 07:07:12 +0000212 private static final String MAVEN_TEST_SOURCES = "{maven-test-sources}";
Carsten Ziegeler66ff6052014-08-24 10:23:01 +0000213 private static final String BUNDLE_PLUGIN_EXTENSION = "BNDExtension-";
Guillaume Nodet04da5472015-03-04 12:08:38 +0000214 private static final String BUNDLE_PLUGIN_PREPEND_EXTENSION = "BNDPrependExtension-";
Stuart McCulloch6cb86db2008-03-15 21:38:26 +0000215
Stuart McCulloch5ae59142008-01-29 06:21:05 +0000216 private static final String[] EMPTY_STRING_ARRAY =
217 {};
218 private static final String[] DEFAULT_INCLUDES =
219 { "**/**" };
Stuart McCulloch9c406b12007-08-23 09:41:08 +0000220
Stuart McCulloch340a8dd2011-06-28 22:47:10 +0000221 private static final String NL = System.getProperty( "line.separator" );
222
Stuart McCulloch9c406b12007-08-23 09:41:08 +0000223
Carsten Ziegeler8fb2f052007-08-01 08:28:54 +0000224 protected Maven2OsgiConverter getMaven2OsgiConverter()
225 {
Stuart McCulloch9366a822008-01-29 07:45:57 +0000226 return m_maven2OsgiConverter;
Richard S. Hall5b521ff2007-04-11 14:25:20 +0000227 }
Richard S. Hallbec8dc42007-05-18 14:33:55 +0000228
Stuart McCulloch5ae59142008-01-29 06:21:05 +0000229
Carsten Ziegeler8fb2f052007-08-01 08:28:54 +0000230 protected MavenProject getProject()
231 {
Stuart McCulloch9366a822008-01-29 07:45:57 +0000232 return project;
Richard S. Hallf3120092006-10-31 17:32:16 +0000233 }
Carsten Ziegeler8fb2f052007-08-01 08:28:54 +0000234
Guillaume Nodeted7b1102015-07-09 19:45:09 +0000235 protected DependencyNode buildDependencyGraph( MavenProject mavenProject ) throws MojoExecutionException
236 {
237 DependencyNode dependencyGraph;
238 try
239 {
240 dependencyGraph = m_dependencyGraphBuilder.buildDependencyGraph( mavenProject, null );
241 }
242 catch ( DependencyGraphBuilderException e )
243 {
244 throw new MojoExecutionException( e.getMessage(), e );
245 }
246 return dependencyGraph;
247 }
Stuart McCulloch5ae59142008-01-29 06:21:05 +0000248
Carsten Ziegeler8fb2f052007-08-01 08:28:54 +0000249 /**
250 * @see org.apache.maven.plugin.AbstractMojo#execute()
251 */
252 public void execute() throws MojoExecutionException
253 {
254 Properties properties = new Properties();
Stuart McCulloch3a965b92008-03-24 02:34:11 +0000255 String projectType = getProject().getArtifact().getType();
Carsten Ziegeler8fb2f052007-08-01 08:28:54 +0000256
Stuart McCulloch3a965b92008-03-24 02:34:11 +0000257 // ignore unsupported project types, useful when bundleplugin is configured in parent pom
258 if ( !supportedProjectTypes.contains( projectType ) )
Carsten Ziegeler8fb2f052007-08-01 08:28:54 +0000259 {
Stuart McCulloch464dbac2008-08-03 09:47:04 +0000260 getLog().warn(
261 "Ignoring project type " + projectType + " - supportedProjectTypes = " + supportedProjectTypes );
Carsten Ziegeler8fb2f052007-08-01 08:28:54 +0000262 return;
263 }
264
Guillaume Nodeted7b1102015-07-09 19:45:09 +0000265 execute( getProject(), buildDependencyGraph(getProject()), instructions, properties );
Richard S. Hallf3120092006-10-31 17:32:16 +0000266 }
Carsten Ziegeler8fb2f052007-08-01 08:28:54 +0000267
Stuart McCulloch5ae59142008-01-29 06:21:05 +0000268
Guillaume Nodeted7b1102015-07-09 19:45:09 +0000269 protected void execute( MavenProject currentProject, DependencyNode dependencyGraph, Map<String, String> originalInstructions, Properties properties )
Stuart McCulloch5ae59142008-01-29 06:21:05 +0000270 throws MojoExecutionException
Carsten Ziegeler8fb2f052007-08-01 08:28:54 +0000271 {
272 try
273 {
Guillaume Nodeted7b1102015-07-09 19:45:09 +0000274 execute( currentProject, dependencyGraph, originalInstructions, properties, getClasspath( currentProject, dependencyGraph ) );
Carsten Ziegeler8fb2f052007-08-01 08:28:54 +0000275 }
276 catch ( IOException e )
277 {
Stuart McCulloch9366a822008-01-29 07:45:57 +0000278 throw new MojoExecutionException( "Error calculating classpath for project " + currentProject, e );
Carsten Ziegeler8fb2f052007-08-01 08:28:54 +0000279 }
Richard S. Hallf3120092006-10-31 17:32:16 +0000280 }
Carsten Ziegeler8fb2f052007-08-01 08:28:54 +0000281
Stuart McCulloch5ae59142008-01-29 06:21:05 +0000282
Carsten Ziegeler8fb2f052007-08-01 08:28:54 +0000283 /* transform directives from their XML form to the expected BND syntax (eg. _include becomes -include) */
Carsten Ziegeler82d87402015-03-04 13:26:21 +0000284 protected static Map<String, String> transformDirectives( Map<String, String> originalInstructions )
Carsten Ziegeler8fb2f052007-08-01 08:28:54 +0000285 {
Carsten Ziegeler82d87402015-03-04 13:26:21 +0000286 Map<String, String> transformedInstructions = new LinkedHashMap<String, String>();
287 for ( Iterator<Map.Entry<String, String>> i = originalInstructions.entrySet().iterator(); i.hasNext(); )
Carsten Ziegeler8fb2f052007-08-01 08:28:54 +0000288 {
Carsten Ziegeler82d87402015-03-04 13:26:21 +0000289 Map.Entry<String, String> e = i.next();
Carsten Ziegeler8fb2f052007-08-01 08:28:54 +0000290
Carsten Ziegeler82d87402015-03-04 13:26:21 +0000291 String key = e.getKey();
Stuart McCulloch5ae59142008-01-29 06:21:05 +0000292 if ( key.startsWith( "_" ) )
Carsten Ziegeler8fb2f052007-08-01 08:28:54 +0000293 {
Stuart McCulloch5ae59142008-01-29 06:21:05 +0000294 key = "-" + key.substring( 1 );
Carsten Ziegeler8fb2f052007-08-01 08:28:54 +0000295 }
296
Carsten Ziegeler82d87402015-03-04 13:26:21 +0000297 String value = e.getValue();
Stuart McCulloch5ae59142008-01-29 06:21:05 +0000298 if ( null == value )
Carsten Ziegeler8fb2f052007-08-01 08:28:54 +0000299 {
300 value = "";
301 }
Richard S. Hall6be327f2007-08-13 16:47:27 +0000302 else
303 {
Guillaume Nodet4eb49be2010-02-19 23:10:08 +0000304 value = value.replaceAll( "\\p{Blank}*[\r\n]\\p{Blank}*", "" );
Richard S. Hall6be327f2007-08-13 16:47:27 +0000305 }
Carsten Ziegeler8fb2f052007-08-01 08:28:54 +0000306
Stuart McCulloch85927eb2011-06-24 20:55:37 +0000307 if ( Analyzer.WAB.equals( key ) && value.length() == 0 )
308 {
309 // provide useful default
310 value = "src/main/webapp/";
311 }
312
Stuart McCulloch5ae59142008-01-29 06:21:05 +0000313 transformedInstructions.put( key, value );
Carsten Ziegeler8fb2f052007-08-01 08:28:54 +0000314 }
315 return transformedInstructions;
Richard S. Hall6cf6f0b2007-04-10 16:50:31 +0000316 }
Richard S. Hall6cf6f0b2007-04-10 16:50:31 +0000317
Stuart McCulloch5ae59142008-01-29 06:21:05 +0000318
Stuart McCulloch5fcbe4a2011-06-28 18:26:45 +0000319 protected boolean reportErrors( String prefix, Analyzer analyzer )
Stuart McCulloch1228d3f2011-06-28 16:14:52 +0000320 {
Carsten Ziegeler82d87402015-03-04 13:26:21 +0000321 List<String> errors = analyzer.getErrors();
322 List<String> warnings = analyzer.getWarnings();
Stuart McCulloch1228d3f2011-06-28 16:14:52 +0000323
Carsten Ziegeler82d87402015-03-04 13:26:21 +0000324 for ( Iterator<String> w = warnings.iterator(); w.hasNext(); )
Stuart McCulloch1228d3f2011-06-28 16:14:52 +0000325 {
Carsten Ziegeler82d87402015-03-04 13:26:21 +0000326 String msg = w.next();
Stuart McCulloch1228d3f2011-06-28 16:14:52 +0000327 getLog().warn( prefix + " : " + msg );
328 }
329
330 boolean hasErrors = false;
331 String fileNotFound = "Input file does not exist: ";
Carsten Ziegeler82d87402015-03-04 13:26:21 +0000332 for ( Iterator<String> e = errors.iterator(); e.hasNext(); )
Stuart McCulloch1228d3f2011-06-28 16:14:52 +0000333 {
Carsten Ziegeler82d87402015-03-04 13:26:21 +0000334 String msg = e.next();
Guillaume Nodetdfe0fe72015-07-09 19:45:35 +0000335 if ( msg.startsWith(fileNotFound) && msg.endsWith( "~" ) )
Stuart McCulloch1228d3f2011-06-28 16:14:52 +0000336 {
337 // treat as warning; this error happens when you have duplicate entries in Include-Resource
338 String duplicate = Processor.removeDuplicateMarker( msg.substring( fileNotFound.length() ) );
Stuart McCullochd98b02e2011-06-28 23:20:37 +0000339 getLog().warn( prefix + " : Duplicate path '" + duplicate + "' in Include-Resource" );
Stuart McCulloch1228d3f2011-06-28 16:14:52 +0000340 }
341 else
342 {
343 getLog().error( prefix + " : " + msg );
344 hasErrors = true;
345 }
346 }
347 return hasErrors;
348 }
349
350
Guillaume Nodeted7b1102015-07-09 19:45:09 +0000351 protected void execute( MavenProject currentProject, DependencyNode dependencyGraph, Map<String, String> originalInstructions, Properties properties,
Stuart McCulloch83e0da02008-01-29 08:25:27 +0000352 Jar[] classpath ) throws MojoExecutionException
Carsten Ziegeler8fb2f052007-08-01 08:28:54 +0000353 {
354 try
355 {
Stuart McCulloch9366a822008-01-29 07:45:57 +0000356 File jarFile = new File( getBuildDirectory(), getBundleName( currentProject ) );
Guillaume Nodeted7b1102015-07-09 19:45:09 +0000357 Builder builder = buildOSGiBundle( currentProject, dependencyGraph, originalInstructions, properties, classpath );
Stuart McCulloch1228d3f2011-06-28 16:14:52 +0000358 boolean hasErrors = reportErrors( "Bundle " + currentProject.getArtifact(), builder );
Stuart McCulloch737abc72011-06-25 19:53:50 +0000359 if ( hasErrors )
Stuart McCulloch6d3e62a2007-09-21 15:07:36 +0000360 {
Stuart McCulloch84bf81e2008-12-03 14:07:08 +0000361 String failok = builder.getProperty( "-failok" );
Stuart McCulloch5ae59142008-01-29 06:21:05 +0000362 if ( null == failok || "false".equalsIgnoreCase( failok ) )
Stuart McCulloch6d3e62a2007-09-21 15:07:36 +0000363 {
364 jarFile.delete();
365
Stuart McCulloch5ae59142008-01-29 06:21:05 +0000366 throw new MojoFailureException( "Error(s) found in bundle configuration" );
Stuart McCulloch6d3e62a2007-09-21 15:07:36 +0000367 }
368 }
369
Stuart McCulloch48fcb1e2008-01-30 06:58:34 +0000370 // attach bundle to maven project
Stuart McCulloch5ae59142008-01-29 06:21:05 +0000371 jarFile.getParentFile().mkdirs();
372 builder.getJar().write( jarFile );
Stuart McCulloch2d301732008-02-18 09:01:17 +0000373
374 Artifact mainArtifact = currentProject.getArtifact();
375
Stuart McCulloche68ebd22011-06-24 21:50:07 +0000376 if ( "bundle".equals( mainArtifact.getType() ) )
377 {
378 // workaround for MNG-1682: force maven to install artifact using the "jar" handler
379 mainArtifact.setArtifactHandler( m_artifactHandlerManager.getArtifactHandler( "jar" ) );
380 }
Stuart McCulloch2d301732008-02-18 09:01:17 +0000381
Stuart McCulloch01c93bd2013-06-07 18:23:07 +0000382 boolean customClassifier = null != classifier && classifier.trim().length() > 0;
383 boolean customPackaging = null != packaging && packaging.trim().length() > 0;
384
385 if ( customClassifier && customPackaging )
Stuart McCulloch2d301732008-02-18 09:01:17 +0000386 {
Stuart McCulloch01c93bd2013-06-07 18:23:07 +0000387 m_projectHelper.attachArtifact( currentProject, packaging, classifier, jarFile );
388 }
389 else if ( customClassifier )
390 {
391 m_projectHelper.attachArtifact( currentProject, jarFile, classifier );
392 }
393 else if ( customPackaging )
394 {
395 m_projectHelper.attachArtifact( currentProject, packaging, jarFile );
Stuart McCulloch2d301732008-02-18 09:01:17 +0000396 }
397 else
398 {
Stuart McCulloch01c93bd2013-06-07 18:23:07 +0000399 mainArtifact.setFile( jarFile );
Stuart McCulloch2d301732008-02-18 09:01:17 +0000400 }
Stuart McCulloch5ae59142008-01-29 06:21:05 +0000401
402 if ( unpackBundle )
Stuart McCullochdd0d9ba2007-12-07 08:22:20 +0000403 {
Stuart McCulloch48fcb1e2008-01-30 06:58:34 +0000404 unpackBundle( jarFile );
Stuart McCullochdd0d9ba2007-12-07 08:22:20 +0000405 }
406
Stuart McCulloch5ae59142008-01-29 06:21:05 +0000407 if ( manifestLocation != null )
Stuart McCulloch6d3e62a2007-09-21 15:07:36 +0000408 {
409 File outputFile = new File( manifestLocation, "MANIFEST.MF" );
410
411 try
412 {
Guillaume Nodetdfe0fe72015-07-09 19:45:35 +0000413 ManifestPlugin.writeManifest( builder, outputFile, niceManifest );
Stuart McCulloch6d3e62a2007-09-21 15:07:36 +0000414 }
415 catch ( IOException e )
416 {
417 getLog().error( "Error trying to write Manifest to file " + outputFile, e );
418 }
419 }
Stuart McCullochd8a04c52008-08-06 16:05:23 +0000420
421 // cleanup...
422 builder.close();
Carsten Ziegeler8fb2f052007-08-01 08:28:54 +0000423 }
Stuart McCulloch5ae59142008-01-29 06:21:05 +0000424 catch ( MojoFailureException e )
Stuart McCulloch6787ce42007-10-26 08:07:14 +0000425 {
426 getLog().error( e.getLocalizedMessage() );
427 throw new MojoExecutionException( "Error(s) found in bundle configuration", e );
428 }
Stuart McCulloch5ae59142008-01-29 06:21:05 +0000429 catch ( Exception e )
Carsten Ziegeler8fb2f052007-08-01 08:28:54 +0000430 {
Stuart McCulloch6787ce42007-10-26 08:07:14 +0000431 getLog().error( "An internal error occurred", e );
432 throw new MojoExecutionException( "Internal error in maven-bundle-plugin", e );
Carsten Ziegeler8fb2f052007-08-01 08:28:54 +0000433 }
434 }
Richard S. Hall6cf6f0b2007-04-10 16:50:31 +0000435
Stuart McCulloch5ae59142008-01-29 06:21:05 +0000436
Carsten Ziegeler82d87402015-03-04 13:26:21 +0000437 protected Builder getOSGiBuilder( MavenProject currentProject, Map<String, String> originalInstructions, Properties properties,
Stuart McCulloch1a42bfa2008-01-30 07:50:33 +0000438 Jar[] classpath ) throws Exception
439 {
440 properties.putAll( getDefaultProperties( currentProject ) );
Stuart McCulloch1a42bfa2008-01-30 07:50:33 +0000441 properties.putAll( transformDirectives( originalInstructions ) );
Carsten Ziegeler67c8ce32014-08-07 06:41:23 +0000442
443 // process overrides from project
Carsten Ziegeler82d87402015-03-04 13:26:21 +0000444 final Map<String, String> addProps = new HashMap<String, String>();
445 final Iterator<Map.Entry<Object, Object>> iter = currentProject.getProperties().entrySet().iterator();
Carsten Ziegeler67c8ce32014-08-07 06:41:23 +0000446 while ( iter.hasNext() )
447 {
Carsten Ziegeler82d87402015-03-04 13:26:21 +0000448 final Map.Entry<Object, Object> entry = iter.next();
Carsten Ziegeler67c8ce32014-08-07 06:41:23 +0000449 final String key = entry.getKey().toString();
Carsten Ziegeler66ff6052014-08-24 10:23:01 +0000450 if ( key.startsWith(BUNDLE_PLUGIN_EXTENSION) )
Carsten Ziegeler67c8ce32014-08-07 06:41:23 +0000451 {
Carsten Ziegeler66ff6052014-08-24 10:23:01 +0000452 final String oKey = key.substring(BUNDLE_PLUGIN_EXTENSION.length());
Carsten Ziegeler67c8ce32014-08-07 06:41:23 +0000453 final String currentValue = properties.getProperty(oKey);
454 if ( currentValue == null )
455 {
Carsten Ziegeler82d87402015-03-04 13:26:21 +0000456 addProps.put(oKey, entry.getValue().toString());
Carsten Ziegeler67c8ce32014-08-07 06:41:23 +0000457 }
458 else
459 {
Carsten Ziegeler22a60d52014-08-07 06:44:48 +0000460 addProps.put(oKey, currentValue + ',' + entry.getValue());
Carsten Ziegeler67c8ce32014-08-07 06:41:23 +0000461 }
Carsten Ziegeler67c8ce32014-08-07 06:41:23 +0000462 }
Guillaume Nodet04da5472015-03-04 12:08:38 +0000463 if ( key.startsWith(BUNDLE_PLUGIN_PREPEND_EXTENSION) )
464 {
465 final String oKey = key.substring(BUNDLE_PLUGIN_PREPEND_EXTENSION.length());
466 final String currentValue = properties.getProperty(oKey);
467 if ( currentValue == null )
468 {
Carsten Ziegeler82d87402015-03-04 13:26:21 +0000469 addProps.put(oKey, entry.getValue().toString());
Guillaume Nodet04da5472015-03-04 12:08:38 +0000470 }
471 else
472 {
473 addProps.put(oKey, entry.getValue() + "," + currentValue);
474 }
475 }
Carsten Ziegeler67c8ce32014-08-07 06:41:23 +0000476 }
Carsten Ziegeler22a60d52014-08-07 06:44:48 +0000477 properties.putAll( addProps );
Carsten Ziegeler82d87402015-03-04 13:26:21 +0000478 final Iterator<String> keyIter = addProps.keySet().iterator();
Carsten Ziegeler67c8ce32014-08-07 06:41:23 +0000479 while ( keyIter.hasNext() )
480 {
Guillaume Nodet04da5472015-03-04 12:08:38 +0000481 Object key = keyIter.next();
482 properties.remove(BUNDLE_PLUGIN_EXTENSION + key);
483 properties.remove(BUNDLE_PLUGIN_PREPEND_EXTENSION + key);
Carsten Ziegeler67c8ce32014-08-07 06:41:23 +0000484 }
485
Guillaume Nodet7bf509f2014-05-19 07:12:48 +0000486 if (properties.getProperty("Bundle-Activator") != null
487 && properties.getProperty("Bundle-Activator").isEmpty())
488 {
489 properties.remove("Bundle-Activator");
490 }
Guillaume Nodet5ddb13c2014-05-20 09:09:12 +0000491 if (properties.containsKey("-disable-plugin"))
492 {
493 String[] disabled = properties.remove("-disable-plugin").toString().replaceAll(" ", "").split(",");
494 String[] enabled = properties.getProperty(Analyzer.PLUGIN, "").replaceAll(" ", "").split(",");
495 Set<String> plugin = new LinkedHashSet<String>();
496 plugin.addAll(Arrays.asList(enabled));
497 plugin.removeAll(Arrays.asList(disabled));
498 StringBuilder sb = new StringBuilder();
499 for (String s : plugin)
500 {
501 if (sb.length() > 0)
502 {
503 sb.append(",");
504 }
Carsten Ziegeler70e05f72015-03-04 12:49:54 +0000505 sb.append(s);
Guillaume Nodet5ddb13c2014-05-20 09:09:12 +0000506 }
507 properties.setProperty(Analyzer.PLUGIN, sb.toString());
508 }
Stuart McCulloch1a42bfa2008-01-30 07:50:33 +0000509
Stuart McCulloch1a42bfa2008-01-30 07:50:33 +0000510 Builder builder = new Builder();
Carsten Ziegeler67c8ce32014-08-07 06:41:23 +0000511 synchronized ( BundlePlugin.class ) // protect setBase...getBndLastModified which uses static DateFormat
Stuart McCulloche1e06932013-06-07 17:32:51 +0000512 {
513 builder.setBase( getBase( currentProject ) );
514 }
Stuart McCulloch9e631952011-11-09 00:45:12 +0000515 builder.setProperties( sanitize( properties ) );
Stuart McCulloch5c9b67d02011-06-28 16:06:24 +0000516 if ( classpath != null )
517 {
518 builder.setClasspath( classpath );
519 }
Stuart McCulloch1a42bfa2008-01-30 07:50:33 +0000520
Stuart McCulloch5c9b67d02011-06-28 16:06:24 +0000521 return builder;
522 }
523
Stuart McCullochd98b02e2011-06-28 23:20:37 +0000524
Stuart McCulloch9e631952011-11-09 00:45:12 +0000525 protected static Properties sanitize( Properties properties )
526 {
527 // convert any non-String keys/values to Strings
528 Properties sanitizedEntries = new Properties();
Carsten Ziegeler82d87402015-03-04 13:26:21 +0000529 for ( Iterator<Map.Entry<Object,Object>> itr = properties.entrySet().iterator(); itr.hasNext(); )
Stuart McCulloch9e631952011-11-09 00:45:12 +0000530 {
Carsten Ziegeler82d87402015-03-04 13:26:21 +0000531 Map.Entry<Object,Object> entry = itr.next();
Stuart McCulloch9e631952011-11-09 00:45:12 +0000532 if ( entry.getKey() instanceof String == false )
533 {
Guillaume Nodetdfe0fe72015-07-09 19:45:35 +0000534 String key = sanitize(entry.getKey());
Stuart McCulloch9e631952011-11-09 00:45:12 +0000535 if ( !properties.containsKey( key ) )
536 {
537 sanitizedEntries.setProperty( key, sanitize( entry.getValue() ) );
538 }
539 itr.remove();
540 }
541 else if ( entry.getValue() instanceof String == false )
542 {
543 entry.setValue( sanitize( entry.getValue() ) );
544 }
545 }
546 properties.putAll( sanitizedEntries );
547 return properties;
548 }
549
550
551 protected static String sanitize( Object value )
552 {
553 if ( value instanceof String )
554 {
555 return ( String ) value;
556 }
557 else if ( value instanceof Iterable )
558 {
559 String delim = "";
560 StringBuilder buf = new StringBuilder();
561 for ( Object i : ( Iterable<?> ) value )
562 {
563 buf.append( delim ).append( i );
564 delim = ", ";
565 }
566 return buf.toString();
567 }
568 else if ( value.getClass().isArray() )
569 {
570 String delim = "";
571 StringBuilder buf = new StringBuilder();
572 for ( int i = 0, len = Array.getLength( value ); i < len; i++ )
573 {
574 buf.append( delim ).append( Array.get( value, i ) );
575 delim = ", ";
576 }
577 return buf.toString();
578 }
579 else
580 {
581 return String.valueOf( value );
582 }
583 }
584
585
Guillaume Nodeted7b1102015-07-09 19:45:09 +0000586 protected void addMavenInstructions( MavenProject currentProject, DependencyNode dependencyGraph, Builder builder ) throws Exception
Stuart McCulloch5c9b67d02011-06-28 16:06:24 +0000587 {
Stuart McCulloch5fcbe4a2011-06-28 18:26:45 +0000588 if ( currentProject.getBasedir() != null )
589 {
590 // update BND instructions to add included Maven resources
Guillaume Nodetdfe0fe72015-07-09 19:45:35 +0000591 includeMavenResources(currentProject, builder, getLog());
Stuart McCullocha8cfd1b2008-04-01 06:54:26 +0000592
Stuart McCulloch5fcbe4a2011-06-28 18:26:45 +0000593 // calculate default export/private settings based on sources
Guillaume Nodetdfe0fe72015-07-09 19:45:35 +0000594 addLocalPackages(outputDirectory, builder);
Stuart McCullochfe58ad52011-11-28 15:05:51 +0000595
596 // tell BND where the current project source resides
Guillaume Nodetdfe0fe72015-07-09 19:45:35 +0000597 addMavenSourcePath(currentProject, builder, getLog());
Stuart McCulloch5fcbe4a2011-06-28 18:26:45 +0000598 }
Stuart McCulloch9c4a94d2008-01-30 09:56:30 +0000599
Stuart McCulloch1a42bfa2008-01-30 07:50:33 +0000600 // update BND instructions to embed selected Maven dependencies
Guillaume Nodeted7b1102015-07-09 19:45:09 +0000601 Collection<Artifact> embeddableArtifacts = getEmbeddableArtifacts( currentProject, dependencyGraph, builder );
Guillaume Nodetdfe0fe72015-07-09 19:45:35 +0000602 new DependencyEmbedder( getLog(), dependencyGraph, embeddableArtifacts ).processHeaders(builder);
Stuart McCulloch1a42bfa2008-01-30 07:50:33 +0000603
Stuart McCulloch340a8dd2011-06-28 22:47:10 +0000604 if ( dumpInstructions != null || getLog().isDebugEnabled() )
605 {
606 StringBuilder buf = new StringBuilder();
607 getLog().debug( "BND Instructions:" + NL + dumpInstructions( builder.getProperties(), buf ) );
608 if ( dumpInstructions != null )
609 {
Stuart McCullochc5e7c352011-06-28 23:02:57 +0000610 getLog().info( "Writing BND instructions to " + dumpInstructions );
611 dumpInstructions.getParentFile().mkdirs();
612 FileUtils.fileWrite( dumpInstructions, "# BND instructions" + NL + buf );
Stuart McCulloch340a8dd2011-06-28 22:47:10 +0000613 }
614 }
615
616 if ( dumpClasspath != null || getLog().isDebugEnabled() )
617 {
618 StringBuilder buf = new StringBuilder();
Guillaume Nodetdfe0fe72015-07-09 19:45:35 +0000619 getLog().debug("BND Classpath:" + NL + dumpClasspath(builder.getClasspath(), buf));
Stuart McCulloch340a8dd2011-06-28 22:47:10 +0000620 if ( dumpClasspath != null )
621 {
Stuart McCullochc5e7c352011-06-28 23:02:57 +0000622 getLog().info( "Writing BND classpath to " + dumpClasspath );
623 dumpClasspath.getParentFile().mkdirs();
624 FileUtils.fileWrite( dumpClasspath, "# BND classpath" + NL + buf );
Stuart McCulloch340a8dd2011-06-28 22:47:10 +0000625 }
626 }
Stuart McCulloch5c9b67d02011-06-28 16:06:24 +0000627 }
628
Stuart McCulloch340a8dd2011-06-28 22:47:10 +0000629
Guillaume Nodeted7b1102015-07-09 19:45:09 +0000630 protected Builder buildOSGiBundle( MavenProject currentProject, DependencyNode dependencyGraph, Map<String, String> originalInstructions, Properties properties,
Stuart McCulloch5c9b67d02011-06-28 16:06:24 +0000631 Jar[] classpath ) throws Exception
632 {
633 Builder builder = getOSGiBuilder( currentProject, originalInstructions, properties, classpath );
634
Guillaume Nodeted7b1102015-07-09 19:45:09 +0000635 addMavenInstructions( currentProject, dependencyGraph, builder );
Stuart McCulloche8125182008-12-05 10:41:46 +0000636
Stuart McCulloch1a42bfa2008-01-30 07:50:33 +0000637 builder.build();
Stuart McCulloche8125182008-12-05 10:41:46 +0000638
Guillaume Nodetdfe0fe72015-07-09 19:45:35 +0000639 mergeMavenManifest(currentProject, dependencyGraph, builder);
Stuart McCulloch1a42bfa2008-01-30 07:50:33 +0000640
641 return builder;
642 }
643
644
Stuart McCulloch340a8dd2011-06-28 22:47:10 +0000645 protected static StringBuilder dumpInstructions( Properties properties, StringBuilder buf )
Stuart McCulloche8125182008-12-05 10:41:46 +0000646 {
Stuart McCulloch340a8dd2011-06-28 22:47:10 +0000647 try
Stuart McCulloche8125182008-12-05 10:41:46 +0000648 {
Stuart McCulloch340a8dd2011-06-28 22:47:10 +0000649 buf.append( "#-----------------------------------------------------------------------" + NL );
650 Properties stringProperties = new Properties();
Carsten Ziegeler82d87402015-03-04 13:26:21 +0000651 for ( Enumeration<String> e = (Enumeration<String>) properties.propertyNames(); e.hasMoreElements(); )
Stuart McCulloche8125182008-12-05 10:41:46 +0000652 {
Stuart McCulloch340a8dd2011-06-28 22:47:10 +0000653 // we can only store String properties
Carsten Ziegeler82d87402015-03-04 13:26:21 +0000654 String key = e.nextElement();
Stuart McCulloch340a8dd2011-06-28 22:47:10 +0000655 String value = properties.getProperty( key );
656 if ( value != null )
657 {
658 stringProperties.setProperty( key, value );
659 }
Stuart McCulloche8125182008-12-05 10:41:46 +0000660 }
Stuart McCulloch65271c82011-07-01 11:57:08 +0000661 ByteArrayOutputStream out = new ByteArrayOutputStream();
662 stringProperties.store( out, null ); // properties encoding is 8859_1
663 buf.append( out.toString( "8859_1" ) );
Stuart McCulloch340a8dd2011-06-28 22:47:10 +0000664 buf.append( "#-----------------------------------------------------------------------" + NL );
Stuart McCulloche8125182008-12-05 10:41:46 +0000665 }
Stuart McCulloch340a8dd2011-06-28 22:47:10 +0000666 catch ( Throwable e )
667 {
668 // ignore...
669 }
670 return buf;
Stuart McCulloche8125182008-12-05 10:41:46 +0000671 }
672
673
Carsten Ziegeler82d87402015-03-04 13:26:21 +0000674 protected static StringBuilder dumpClasspath( List<Jar> classpath, StringBuilder buf )
Stuart McCulloch53e42e12009-01-29 08:45:51 +0000675 {
Stuart McCulloch340a8dd2011-06-28 22:47:10 +0000676 try
Stuart McCulloch53e42e12009-01-29 08:45:51 +0000677 {
Guillaume Nodetdfe0fe72015-07-09 19:45:35 +0000678 buf.append("#-----------------------------------------------------------------------" + NL);
Stuart McCulloch340a8dd2011-06-28 22:47:10 +0000679 buf.append( "-classpath:\\" + NL );
Carsten Ziegeler82d87402015-03-04 13:26:21 +0000680 for ( Iterator<Jar> i = classpath.iterator(); i.hasNext(); )
Stuart McCulloch53e42e12009-01-29 08:45:51 +0000681 {
Carsten Ziegeler82d87402015-03-04 13:26:21 +0000682 File path = i.next().getSource();
Stuart McCulloch340a8dd2011-06-28 22:47:10 +0000683 if ( path != null )
684 {
685 buf.append( ' ' + path.toString() + ( i.hasNext() ? ",\\" : "" ) + NL );
686 }
Stuart McCulloch53e42e12009-01-29 08:45:51 +0000687 }
Stuart McCulloch340a8dd2011-06-28 22:47:10 +0000688 buf.append( "#-----------------------------------------------------------------------" + NL );
Stuart McCulloch53e42e12009-01-29 08:45:51 +0000689 }
Stuart McCulloch340a8dd2011-06-28 22:47:10 +0000690 catch ( Throwable e )
691 {
692 // ignore...
693 }
694 return buf;
Stuart McCulloch53e42e12009-01-29 08:45:51 +0000695 }
696
697
Stuart McCullochb3192b72014-06-23 12:07:29 +0000698 protected static StringBuilder dumpManifest( Manifest manifest, StringBuilder buf )
Stuart McCulloche8125182008-12-05 10:41:46 +0000699 {
Stuart McCulloch340a8dd2011-06-28 22:47:10 +0000700 try
Stuart McCulloche8125182008-12-05 10:41:46 +0000701 {
Stuart McCulloch340a8dd2011-06-28 22:47:10 +0000702 buf.append( "#-----------------------------------------------------------------------" + NL );
703 ByteArrayOutputStream out = new ByteArrayOutputStream();
Guillaume Nodetdfe0fe72015-07-09 19:45:35 +0000704 ManifestWriter.outputManifest(manifest, out, true); // manifest encoding is UTF8
Stuart McCulloch340a8dd2011-06-28 22:47:10 +0000705 buf.append( out.toString( "UTF8" ) );
706 buf.append( "#-----------------------------------------------------------------------" + NL );
Stuart McCulloche8125182008-12-05 10:41:46 +0000707 }
Stuart McCulloch340a8dd2011-06-28 22:47:10 +0000708 catch ( Throwable e )
709 {
710 // ignore...
711 }
712 return buf;
Stuart McCulloche8125182008-12-05 10:41:46 +0000713 }
714
715
Stuart McCulloch84bf81e2008-12-03 14:07:08 +0000716 protected static void includeMavenResources( MavenProject currentProject, Analyzer analyzer, Log log )
Stuart McCulloch48fcb1e2008-01-30 06:58:34 +0000717 {
718 // pass maven resource paths onto BND analyzer
Guillaume Nodet09194e62014-06-16 07:07:12 +0000719 final String mavenResourcePaths = getMavenResourcePaths( currentProject, false );
720 final String mavenTestResourcePaths = getMavenResourcePaths( currentProject, true );
721 final String includeResource = analyzer.getProperty( Analyzer.INCLUDE_RESOURCE );
Stuart McCulloch48fcb1e2008-01-30 06:58:34 +0000722 if ( includeResource != null )
723 {
Guillaume Nodet09194e62014-06-16 07:07:12 +0000724 if ( includeResource.contains( MAVEN_RESOURCES ) || includeResource.contains( MAVEN_TEST_RESOURCES ) )
Stuart McCulloch48fcb1e2008-01-30 06:58:34 +0000725 {
Guillaume Nodet09194e62014-06-16 07:07:12 +0000726 String combinedResource = StringUtils.replace( includeResource, MAVEN_RESOURCES, mavenResourcePaths );
727 combinedResource = StringUtils.replace( combinedResource, MAVEN_TEST_RESOURCES, mavenTestResourcePaths );
728 if ( combinedResource.length() > 0 )
Stuart McCulloch48fcb1e2008-01-30 06:58:34 +0000729 {
Guillaume Nodet09194e62014-06-16 07:07:12 +0000730 analyzer.setProperty( Analyzer.INCLUDE_RESOURCE, combinedResource );
Stuart McCulloch48fcb1e2008-01-30 06:58:34 +0000731 }
732 else
733 {
Guillaume Nodet09194e62014-06-16 07:07:12 +0000734 analyzer.unsetProperty( Analyzer.INCLUDE_RESOURCE );
Stuart McCulloch48fcb1e2008-01-30 06:58:34 +0000735 }
736 }
737 else if ( mavenResourcePaths.length() > 0 )
738 {
739 log.warn( Analyzer.INCLUDE_RESOURCE + ": overriding " + mavenResourcePaths + " with " + includeResource
Guillaume Nodet09194e62014-06-16 07:07:12 +0000740 + " (add " + MAVEN_RESOURCES + " if you want to include the maven resources)" );
Stuart McCulloch48fcb1e2008-01-30 06:58:34 +0000741 }
742 }
743 else if ( mavenResourcePaths.length() > 0 )
744 {
Stuart McCulloch84bf81e2008-12-03 14:07:08 +0000745 analyzer.setProperty( Analyzer.INCLUDE_RESOURCE, mavenResourcePaths );
Stuart McCulloch48fcb1e2008-01-30 06:58:34 +0000746 }
747 }
748
749
Guillaume Nodeted7b1102015-07-09 19:45:09 +0000750 protected void mergeMavenManifest( MavenProject currentProject, DependencyNode dependencyGraph, Builder builder ) throws Exception
Stuart McCulloch48fcb1e2008-01-30 06:58:34 +0000751 {
Stuart McCulloch5c9b67d02011-06-28 16:06:24 +0000752 Jar jar = builder.getJar();
753
Stuart McCulloch340a8dd2011-06-28 22:47:10 +0000754 if ( getLog().isDebugEnabled() )
755 {
756 getLog().debug( "BND Manifest:" + NL + dumpManifest( jar.getManifest(), new StringBuilder() ) );
757 }
Stuart McCulloch5c9b67d02011-06-28 16:06:24 +0000758
Stuart McCulloch5fcbe4a2011-06-28 18:26:45 +0000759 boolean addMavenDescriptor = currentProject.getBasedir() != null;
Stuart McCulloch378e76c2009-01-30 09:51:35 +0000760
Stuart McCulloch48fcb1e2008-01-30 06:58:34 +0000761 try
762 {
763 /*
764 * Grab customized manifest entries from the maven-jar-plugin configuration
765 */
766 MavenArchiveConfiguration archiveConfig = JarPluginConfiguration.getArchiveConfiguration( currentProject );
767 String mavenManifestText = new MavenArchiver().getManifest( currentProject, archiveConfig ).toString();
Stuart McCulloch5fcbe4a2011-06-28 18:26:45 +0000768 addMavenDescriptor = addMavenDescriptor && archiveConfig.isAddMavenDescriptor();
Stuart McCulloch378e76c2009-01-30 09:51:35 +0000769
Stuart McCulloch48fcb1e2008-01-30 06:58:34 +0000770 Manifest mavenManifest = new Manifest();
771
Stuart McCullochbc90bf82011-10-17 17:28:09 +0000772 // First grab the external manifest file (if specified and different to target location)
Stuart McCulloch48fcb1e2008-01-30 06:58:34 +0000773 File externalManifestFile = archiveConfig.getManifestFile();
Stuart McCulloche6cc8132013-06-07 21:45:18 +0000774 if ( null != externalManifestFile )
Stuart McCulloch6f241f02013-06-07 21:42:04 +0000775 {
Stuart McCulloche6cc8132013-06-07 21:45:18 +0000776 if ( !externalManifestFile.isAbsolute() )
777 {
778 externalManifestFile = new File( currentProject.getBasedir(), externalManifestFile.getPath() );
779 }
780 if ( externalManifestFile.exists() && !externalManifestFile.equals( new File( manifestLocation, "MANIFEST.MF" ) ) )
781 {
782 InputStream mis = new FileInputStream( externalManifestFile );
783 mavenManifest.read( mis );
784 mis.close();
785 }
Stuart McCulloch48fcb1e2008-01-30 06:58:34 +0000786 }
787
Stuart McCulloch340a8dd2011-06-28 22:47:10 +0000788 // Then apply customized entries from the jar plugin; note: manifest encoding is UTF8
789 mavenManifest.read( new ByteArrayInputStream( mavenManifestText.getBytes( "UTF8" ) ) );
Stuart McCulloch48fcb1e2008-01-30 06:58:34 +0000790
791 if ( !archiveConfig.isManifestSectionsEmpty() )
792 {
793 /*
794 * Add customized manifest sections (for some reason MavenArchiver doesn't do this for us)
795 */
Carsten Ziegeler82d87402015-03-04 13:26:21 +0000796 List<ManifestSection> sections = archiveConfig.getManifestSections();
797 for ( Iterator<ManifestSection> i = sections.iterator(); i.hasNext(); )
Stuart McCulloch48fcb1e2008-01-30 06:58:34 +0000798 {
Carsten Ziegeler82d87402015-03-04 13:26:21 +0000799 ManifestSection section = i.next();
Stuart McCulloch48fcb1e2008-01-30 06:58:34 +0000800 Attributes attributes = new Attributes();
801
802 if ( !section.isManifestEntriesEmpty() )
803 {
Carsten Ziegeler82d87402015-03-04 13:26:21 +0000804 Map<String, String> entries = section.getManifestEntries();
805 for ( Iterator<Map.Entry<String, String>> j = entries.entrySet().iterator(); j.hasNext(); )
Stuart McCulloch48fcb1e2008-01-30 06:58:34 +0000806 {
Carsten Ziegeler82d87402015-03-04 13:26:21 +0000807 Map.Entry<String, String> entry = j.next();
808 attributes.putValue( entry.getKey(), entry.getValue() );
Stuart McCulloch48fcb1e2008-01-30 06:58:34 +0000809 }
810 }
811
812 mavenManifest.getEntries().put( section.getName(), attributes );
813 }
814 }
815
Stuart McCulloche19d4092008-01-30 08:42:48 +0000816 Attributes mainMavenAttributes = mavenManifest.getMainAttributes();
817 mainMavenAttributes.putValue( "Created-By", "Apache Maven Bundle Plugin" );
818
Stuart McCulloch5c9b67d02011-06-28 16:06:24 +0000819 String[] removeHeaders = builder.getProperty( Constants.REMOVEHEADERS, "" ).split( "," );
820
Stuart McCulloche19d4092008-01-30 08:42:48 +0000821 // apply -removeheaders to the custom manifest
822 for ( int i = 0; i < removeHeaders.length; i++ )
823 {
Carsten Ziegeler82d87402015-03-04 13:26:21 +0000824 for ( Iterator<Object> j = mainMavenAttributes.keySet().iterator(); j.hasNext(); )
Stuart McCulloche19d4092008-01-30 08:42:48 +0000825 {
826 if ( j.next().toString().matches( removeHeaders[i].trim() ) )
827 {
828 j.remove();
829 }
830 }
831 }
832
Stuart McCulloch48fcb1e2008-01-30 06:58:34 +0000833 /*
834 * Overlay generated bundle manifest with customized entries
835 */
Guillaume Nodetdfe0fe72015-07-09 19:45:35 +0000836 Properties properties = builder.getProperties();
Stuart McCulloch48fcb1e2008-01-30 06:58:34 +0000837 Manifest bundleManifest = jar.getManifest();
Guillaume Nodetdfe0fe72015-07-09 19:45:35 +0000838 if ( properties.containsKey( "Merge-Headers" ) )
839 {
840 Instructions instructions = new Instructions( ExtList.from(builder.getProperty("Merge-Headers")) );
841 mergeManifest( instructions, bundleManifest, mavenManifest );
842 }
843 else
844 {
845 bundleManifest.getMainAttributes().putAll( mainMavenAttributes );
846 bundleManifest.getEntries().putAll( mavenManifest.getEntries() );
847 }
Hiram R. Chirino2d401a32011-01-27 20:58:44 +0000848
849 // adjust the import package attributes so that optional dependencies use
850 // optional resolution.
Stuart McCullochd98b02e2011-06-28 23:20:37 +0000851 String importPackages = bundleManifest.getMainAttributes().getValue( "Import-Package" );
852 if ( importPackages != null )
853 {
Guillaume Nodeted7b1102015-07-09 19:45:09 +0000854 Set optionalPackages = getOptionalPackages( currentProject, dependencyGraph );
Hiram R. Chirino2d401a32011-01-27 20:58:44 +0000855
Stuart McCullochf3173222012-06-07 21:57:32 +0000856 Map<String, ? extends Map<String, String>> values = new Analyzer().parseHeader( importPackages );
857 for ( Map.Entry<String, ? extends Map<String, String>> entry : values.entrySet() )
Stuart McCullochd98b02e2011-06-28 23:20:37 +0000858 {
Hiram R. Chirino2d401a32011-01-27 20:58:44 +0000859 String pkg = entry.getKey();
860 Map<String, String> options = entry.getValue();
Stuart McCullochd98b02e2011-06-28 23:20:37 +0000861 if ( !options.containsKey( "resolution:" ) && optionalPackages.contains( pkg ) )
862 {
863 options.put( "resolution:", "optional" );
Hiram R. Chirino2d401a32011-01-27 20:58:44 +0000864 }
865 }
Stuart McCulloch26e7a5a2011-10-17 10:31:43 +0000866 String result = Processor.printClauses( values );
Stuart McCullochd98b02e2011-06-28 23:20:37 +0000867 bundleManifest.getMainAttributes().putValue( "Import-Package", result );
Hiram R. Chirino2d401a32011-01-27 20:58:44 +0000868 }
869
Stuart McCulloch48fcb1e2008-01-30 06:58:34 +0000870 jar.setManifest( bundleManifest );
871 }
872 catch ( Exception e )
873 {
Stuart McCulloch5c9b67d02011-06-28 16:06:24 +0000874 getLog().warn( "Unable to merge Maven manifest: " + e.getLocalizedMessage() );
Stuart McCulloch48fcb1e2008-01-30 06:58:34 +0000875 }
Stuart McCulloch378e76c2009-01-30 09:51:35 +0000876
877 if ( addMavenDescriptor )
878 {
879 doMavenMetadata( currentProject, jar );
880 }
Stuart McCulloch5c9b67d02011-06-28 16:06:24 +0000881
Stuart McCulloch340a8dd2011-06-28 22:47:10 +0000882 if ( getLog().isDebugEnabled() )
883 {
884 getLog().debug( "Final Manifest:" + NL + dumpManifest( jar.getManifest(), new StringBuilder() ) );
885 }
Stuart McCulloch5c9b67d02011-06-28 16:06:24 +0000886
887 builder.setJar( jar );
Stuart McCulloch48fcb1e2008-01-30 06:58:34 +0000888 }
889
890
Guillaume Nodetdfe0fe72015-07-09 19:45:35 +0000891 protected static void mergeManifest( Instructions instructions, Manifest... manifests ) throws IOException
892 {
893 for ( int i = manifests.length - 2; i >= 0; i-- )
894 {
895 Manifest mergedManifest = manifests[i];
896 Manifest manifest = manifests[i + 1];
897 Attributes mergedMainAttributes = mergedManifest.getMainAttributes();
898 Attributes mainAttributes = manifest.getMainAttributes();
899 Attributes filteredMainAttributes = filterAttributes( instructions, mainAttributes, null );
900 if ( !filteredMainAttributes.isEmpty() )
901 {
902 mergeAttributes( mergedMainAttributes, filteredMainAttributes );
903 }
904 Map<String, Attributes> mergedEntries = mergedManifest.getEntries();
905 Map<String, Attributes> entries = manifest.getEntries();
906 for ( Map.Entry<String, Attributes> entry : entries.entrySet() )
907 {
908 String name = entry.getKey();
909 Attributes attributes = entry.getValue();
910 Attributes filteredAttributes = filterAttributes( instructions, attributes, null );
911 if ( !filteredAttributes.isEmpty() )
912 {
913 Attributes mergedAttributes = mergedManifest.getAttributes( name );
914 if ( mergedAttributes != null)
915 {
916 mergeAttributes(mergedAttributes, filteredAttributes);
917 }
918 else
919 {
920 mergedEntries.put(name, filteredAttributes);
921 }
922 }
923 }
924 }
925 }
926
927
928 /**
929 * @see Analyzer#filter
930 */
931 private static Attributes filterAttributes(Instructions instructions, Attributes source, Set<Instruction> nomatch) {
932 Attributes result = new Attributes();
933 Map<String, Object> keys = new TreeMap<String, Object>();
934 for ( Object key : source.keySet() )
935 {
936 keys.put( key.toString(), key );
937 }
938
939 List<Instruction> filters = new ArrayList<Instruction>( instructions.keySet() );
940 if (nomatch == null)
941 {
942 nomatch = Create.set();
943 }
944 for ( Instruction instruction : filters ) {
945 boolean match = false;
946 for (Iterator<Map.Entry<String, Object>> i = keys.entrySet().iterator(); i.hasNext();)
947 {
948 Map.Entry<String, Object> entry = i.next();
949 String key = entry.getKey();
950 if ( instruction.matches( key ) )
951 {
952 match = true;
953 if (!instruction.isNegated()) {
954 Object name = entry.getValue();
955 Object value = source.get( name );
956 result.put( name, value );
957 }
958 i.remove(); // Can never match again for another pattern
959 }
960 }
961 if (!match && !instruction.isAny())
962 nomatch.add(instruction);
963 }
964
965 /*
966 * Tricky. If we have umatched instructions they might indicate that we
967 * want to have multiple decorators for the same package. So we check
968 * the unmatched against the result list. If then then match and have
969 * actually interesting properties then we merge them
970 */
971
972 for (Iterator<Instruction> i = nomatch.iterator(); i.hasNext();) {
973 Instruction instruction = i.next();
974
975 // We assume the user knows what he is
976 // doing and inserted a literal. So
977 // we ignore any not matched literals
978 // #252, we should not be negated to make it a constant
979 if (instruction.isLiteral() && !instruction.isNegated()) {
980 Object key = keys.get( instruction.getLiteral() );
981 if ( key != null )
982 {
983 Object value = source.get( key );
984 result.put( key, value );
985 }
986 i.remove();
987 continue;
988 }
989
990 // Not matching a negated instruction looks
991 // like an error ... Though so, but
992 // in the second phase of Export-Package
993 // the !package will never match anymore.
994 if (instruction.isNegated()) {
995 i.remove();
996 continue;
997 }
998
999 // An optional instruction should not generate
1000 // an error
1001 if (instruction.isOptional()) {
1002 i.remove();
1003 continue;
1004 }
1005 }
1006 return result;
1007 }
1008
1009
1010 private static void mergeAttributes( Attributes... attributesArray ) throws IOException
1011 {
1012 for ( int i = attributesArray.length - 2; i >= 0; i-- )
1013 {
1014 Attributes mergedAttributes = attributesArray[i];
1015 Attributes attributes = attributesArray[i + 1];
1016 for ( Map.Entry<Object, Object> entry : attributes.entrySet() )
1017 {
1018 Object name = entry.getKey();
1019 String value = (String) entry.getValue();
1020 String oldValue = (String) mergedAttributes.put( name, value );
1021 if ( oldValue != null )
1022 {
1023 Parameters mergedClauses = OSGiHeader.parseHeader(oldValue);
1024 Parameters clauses = OSGiHeader.parseHeader( value );
1025 if ( !mergedClauses.isEqual( clauses) )
1026 {
1027 for ( Map.Entry<String, Attrs> clauseEntry : clauses.entrySet() )
1028 {
1029 String clause = clauseEntry.getKey();
1030 Attrs attrs = clauseEntry.getValue();
1031 Attrs mergedAttrs = mergedClauses.get( clause );
1032 if ( mergedAttrs == null)
1033 {
1034 mergedClauses.put( clause, attrs );
1035 }
1036 else if ( !mergedAttrs.isEqual(attrs) )
1037 {
1038 for ( Map.Entry<String,String> adentry : attrs.entrySet() )
1039 {
1040 String adname = adentry.getKey();
1041 String ad = adentry.getValue();
1042 if ( mergedAttrs.containsKey( adname ) )
1043 {
1044 Attrs.Type type = attrs.getType( adname );
1045 switch (type)
1046 {
1047 case VERSIONS:
1048 case STRINGS:
1049 case LONGS:
1050 case DOUBLES:
1051 ExtList<String> mergedAd = ExtList.from( mergedAttrs.get( adname ) );
1052 ExtList.from( ad ).addAll( ExtList.from( ad ) );
1053 mergedAttrs.put(adname, mergedAd.join() );
1054 break;
1055 }
1056 }
1057 else
1058 {
1059 mergedAttrs.put( adname, ad );
1060 }
1061 }
1062 }
1063 }
1064 mergedAttributes.put( name, Processor.printClauses( mergedClauses ) );
1065 }
1066 }
1067 }
1068 }
1069 }
1070
1071
Guillaume Nodeted7b1102015-07-09 19:45:09 +00001072 protected Set<String> getOptionalPackages( MavenProject currentProject, DependencyNode dependencyGraph ) throws IOException, MojoExecutionException
Hiram R. Chirino2d401a32011-01-27 20:58:44 +00001073 {
Carsten Ziegeler82d87402015-03-04 13:26:21 +00001074 ArrayList<Artifact> inscope = new ArrayList<Artifact>();
Guillaume Nodeted7b1102015-07-09 19:45:09 +00001075 final Collection<Artifact> artifacts = getSelectedDependencies( dependencyGraph, currentProject.getArtifacts() );
Carsten Ziegeler82d87402015-03-04 13:26:21 +00001076 for ( Iterator<Artifact> it = artifacts.iterator(); it.hasNext(); )
Hiram R. Chirino2d401a32011-01-27 20:58:44 +00001077 {
Carsten Ziegeler82d87402015-03-04 13:26:21 +00001078 Artifact artifact = it.next();
Hiram R. Chirino2d401a32011-01-27 20:58:44 +00001079 if ( artifact.getArtifactHandler().isAddedToClasspath() )
1080 {
Guillaume Nodeted7b1102015-07-09 19:45:09 +00001081 inscope.add( artifact );
Hiram R. Chirino2d401a32011-01-27 20:58:44 +00001082 }
1083 }
Hiram R. Chirino922498b2011-01-28 15:13:33 +00001084
Carsten Ziegeler82d87402015-03-04 13:26:21 +00001085 HashSet<String> optionalArtifactIds = new HashSet<String>();
1086 for ( Iterator<Artifact> it = inscope.iterator(); it.hasNext(); )
Hiram R. Chirino922498b2011-01-28 15:13:33 +00001087 {
Carsten Ziegeler82d87402015-03-04 13:26:21 +00001088 Artifact artifact = it.next();
Stuart McCullochd98b02e2011-06-28 23:20:37 +00001089 if ( artifact.isOptional() )
1090 {
Hiram R. Chirino922498b2011-01-28 15:13:33 +00001091 String id = artifact.toString();
Stuart McCullochd98b02e2011-06-28 23:20:37 +00001092 if ( artifact.getScope() != null )
1093 {
Hiram R. Chirino922498b2011-01-28 15:13:33 +00001094 // strip the scope...
Stuart McCullochd98b02e2011-06-28 23:20:37 +00001095 id = id.replaceFirst( ":[^:]*$", "" );
Hiram R. Chirino922498b2011-01-28 15:13:33 +00001096 }
Stuart McCullochd98b02e2011-06-28 23:20:37 +00001097 optionalArtifactIds.add( id );
Hiram R. Chirino922498b2011-01-28 15:13:33 +00001098 }
1099
1100 }
1101
Carsten Ziegeler82d87402015-03-04 13:26:21 +00001102 HashSet<String> required = new HashSet<String>();
1103 HashSet<String> optional = new HashSet<String>();
1104 for ( Iterator<Artifact> it = inscope.iterator(); it.hasNext(); )
Hiram R. Chirino922498b2011-01-28 15:13:33 +00001105 {
Carsten Ziegeler82d87402015-03-04 13:26:21 +00001106 Artifact artifact = it.next();
Hiram R. Chirino922498b2011-01-28 15:13:33 +00001107 File file = getFile( artifact );
1108 if ( file == null )
1109 {
1110 continue;
1111 }
1112
1113 Jar jar = new Jar( artifact.getArtifactId(), file );
Stuart McCullochd98b02e2011-06-28 23:20:37 +00001114 if ( isTransitivelyOptional( optionalArtifactIds, artifact ) )
1115 {
1116 optional.addAll( jar.getPackages() );
1117 }
1118 else
1119 {
1120 required.addAll( jar.getPackages() );
Hiram R. Chirino922498b2011-01-28 15:13:33 +00001121 }
1122 jar.close();
1123 }
1124
Stuart McCullochd98b02e2011-06-28 23:20:37 +00001125 optional.removeAll( required );
Hiram R. Chirino2d401a32011-01-27 20:58:44 +00001126 return optional;
1127 }
1128
Stuart McCullochd98b02e2011-06-28 23:20:37 +00001129
Hiram R. Chirino922498b2011-01-28 15:13:33 +00001130 /**
1131 * Check to see if any dependency along the dependency trail of
1132 * the artifact is optional.
1133 *
1134 * @param artifact
1135 */
Carsten Ziegeler82d87402015-03-04 13:26:21 +00001136 protected boolean isTransitivelyOptional( HashSet<String> optionalArtifactIds, Artifact artifact )
Stuart McCullochd98b02e2011-06-28 23:20:37 +00001137 {
Carsten Ziegeler82d87402015-03-04 13:26:21 +00001138 List<String> trail = artifact.getDependencyTrail();
1139 for ( Iterator<String> iterator = trail.iterator(); iterator.hasNext(); )
Stuart McCullochd98b02e2011-06-28 23:20:37 +00001140 {
Carsten Ziegeler82d87402015-03-04 13:26:21 +00001141 String next = iterator.next();
Stuart McCullochd98b02e2011-06-28 23:20:37 +00001142 if ( optionalArtifactIds.contains( next ) )
1143 {
Hiram R. Chirino922498b2011-01-28 15:13:33 +00001144 return true;
1145 }
1146 }
1147 return false;
1148 }
1149
Stuart McCullochd98b02e2011-06-28 23:20:37 +00001150
Stuart McCulloch48fcb1e2008-01-30 06:58:34 +00001151 private void unpackBundle( File jarFile )
1152 {
1153 File outputDir = getOutputDirectory();
1154 if ( null == outputDir )
1155 {
1156 outputDir = new File( getBuildDirectory(), "classes" );
1157 }
1158
1159 try
1160 {
1161 /*
1162 * this directory must exist before unpacking, otherwise the plexus
1163 * unarchiver decides to use the current working directory instead!
1164 */
1165 if ( !outputDir.exists() )
1166 {
1167 outputDir.mkdirs();
1168 }
1169
1170 UnArchiver unArchiver = m_archiverManager.getUnArchiver( "jar" );
1171 unArchiver.setDestDirectory( outputDir );
1172 unArchiver.setSourceFile( jarFile );
1173 unArchiver.extract();
1174 }
1175 catch ( Exception e )
1176 {
1177 getLog().error( "Problem unpacking " + jarFile + " to " + outputDir, e );
1178 }
1179 }
1180
1181
Stuart McCulloch5abb4c22008-01-29 11:26:33 +00001182 protected static String removeTagFromInstruction( String instruction, String tag )
Stuart McCulloch00b06942007-09-24 14:14:09 +00001183 {
1184 StringBuffer buf = new StringBuffer();
1185
Stuart McCulloch5abb4c22008-01-29 11:26:33 +00001186 String[] clauses = instruction.split( "," );
Stuart McCulloch5ae59142008-01-29 06:21:05 +00001187 for ( int i = 0; i < clauses.length; i++ )
Stuart McCulloch00b06942007-09-24 14:14:09 +00001188 {
1189 String clause = clauses[i].trim();
Stuart McCulloch5abb4c22008-01-29 11:26:33 +00001190 if ( !tag.equals( clause ) )
Stuart McCulloch00b06942007-09-24 14:14:09 +00001191 {
Stuart McCulloch5ae59142008-01-29 06:21:05 +00001192 if ( buf.length() > 0 )
Stuart McCulloch00b06942007-09-24 14:14:09 +00001193 {
Stuart McCulloch5ae59142008-01-29 06:21:05 +00001194 buf.append( ',' );
Stuart McCulloch00b06942007-09-24 14:14:09 +00001195 }
Stuart McCulloch5ae59142008-01-29 06:21:05 +00001196 buf.append( clause );
Stuart McCulloch00b06942007-09-24 14:14:09 +00001197 }
1198 }
1199
1200 return buf.toString();
1201 }
1202
Stuart McCulloch5ae59142008-01-29 06:21:05 +00001203
Carsten Ziegeler82d87402015-03-04 13:26:21 +00001204 private static Map<String, String> getProperties( Model projectModel, String prefix )
Carsten Ziegeler8fb2f052007-08-01 08:28:54 +00001205 {
Carsten Ziegeler82d87402015-03-04 13:26:21 +00001206 Map<String, String> properties = new LinkedHashMap<String, String>();
Carsten Ziegeler8fb2f052007-08-01 08:28:54 +00001207 Method methods[] = Model.class.getDeclaredMethods();
Stuart McCulloch5ae59142008-01-29 06:21:05 +00001208 for ( int i = 0; i < methods.length; i++ )
Carsten Ziegeler8fb2f052007-08-01 08:28:54 +00001209 {
1210 String name = methods[i].getName();
Stuart McCulloch5ae59142008-01-29 06:21:05 +00001211 if ( name.startsWith( "get" ) )
Carsten Ziegeler8fb2f052007-08-01 08:28:54 +00001212 {
1213 try
1214 {
Stuart McCulloch5ae59142008-01-29 06:21:05 +00001215 Object v = methods[i].invoke( projectModel, null );
Carsten Ziegeler8fb2f052007-08-01 08:28:54 +00001216 if ( v != null )
1217 {
Stuart McCulloch5ae59142008-01-29 06:21:05 +00001218 name = prefix + Character.toLowerCase( name.charAt( 3 ) ) + name.substring( 4 );
Carsten Ziegeler8fb2f052007-08-01 08:28:54 +00001219 if ( v.getClass().isArray() )
Stuart McCulloch5ae59142008-01-29 06:21:05 +00001220 properties.put( name, Arrays.asList( ( Object[] ) v ).toString() );
Carsten Ziegeler8fb2f052007-08-01 08:28:54 +00001221 else
Carsten Ziegeler82d87402015-03-04 13:26:21 +00001222 properties.put( name, v.toString() );
Richard S. Hall420d2782007-06-14 12:31:48 +00001223
Carsten Ziegeler8fb2f052007-08-01 08:28:54 +00001224 }
1225 }
Stuart McCulloch5ae59142008-01-29 06:21:05 +00001226 catch ( Exception e )
Carsten Ziegeler8fb2f052007-08-01 08:28:54 +00001227 {
1228 // too bad
1229 }
Stuart McCulloch5ae59142008-01-29 06:21:05 +00001230 }
Carsten Ziegeler8fb2f052007-08-01 08:28:54 +00001231 }
1232 return properties;
1233 }
Richard S. Hall46e7a852007-05-17 14:47:48 +00001234
Stuart McCulloch5ae59142008-01-29 06:21:05 +00001235
Carsten Ziegeler82d87402015-03-04 13:26:21 +00001236 private static StringBuffer printLicenses( List<License> licenses )
Carsten Ziegeler8fb2f052007-08-01 08:28:54 +00001237 {
Stuart McCulloch5ae59142008-01-29 06:21:05 +00001238 if ( licenses == null || licenses.size() == 0 )
Carsten Ziegeler8fb2f052007-08-01 08:28:54 +00001239 return null;
1240 StringBuffer sb = new StringBuffer();
1241 String del = "";
Carsten Ziegeler82d87402015-03-04 13:26:21 +00001242 for ( Iterator<License> i = licenses.iterator(); i.hasNext(); )
Carsten Ziegeler8fb2f052007-08-01 08:28:54 +00001243 {
Carsten Ziegeler82d87402015-03-04 13:26:21 +00001244 License l = i.next();
Carsten Ziegeler8fb2f052007-08-01 08:28:54 +00001245 String url = l.getUrl();
Stuart McCulloch5ae59142008-01-29 06:21:05 +00001246 if ( url == null )
1247 continue;
1248 sb.append( del );
1249 sb.append( url );
Carsten Ziegeler8fb2f052007-08-01 08:28:54 +00001250 del = ", ";
1251 }
Stuart McCulloch5ae59142008-01-29 06:21:05 +00001252 if ( sb.length() == 0 )
1253 return null;
Carsten Ziegeler8fb2f052007-08-01 08:28:54 +00001254 return sb;
1255 }
Richard S. Hall46e7a852007-05-17 14:47:48 +00001256
Stuart McCulloch5ae59142008-01-29 06:21:05 +00001257
Carsten Ziegeler8fb2f052007-08-01 08:28:54 +00001258 /**
1259 * @param jar
1260 * @throws IOException
1261 */
Stuart McCulloch9366a822008-01-29 07:45:57 +00001262 private void doMavenMetadata( MavenProject currentProject, Jar jar ) throws IOException
Stuart McCulloch5ae59142008-01-29 06:21:05 +00001263 {
Stuart McCulloch9366a822008-01-29 07:45:57 +00001264 String path = "META-INF/maven/" + currentProject.getGroupId() + "/" + currentProject.getArtifactId();
Stuart McCulloche79a18e2015-09-18 14:11:19 +00001265
1266 File pomFile = currentProject.getFile();
1267 if ( pomFile == null || !pomFile.exists() )
1268 {
1269 pomFile = new File( currentProject.getBasedir(), "pom.xml" );
1270 }
1271 if ( pomFile.exists() )
1272 {
1273 jar.putResource( path + "/pom.xml", new FileResource( pomFile ) );
1274 }
Richard S. Hall46e7a852007-05-17 14:47:48 +00001275
Carsten Ziegeler8fb2f052007-08-01 08:28:54 +00001276 Properties p = new Properties();
Stuart McCulloch9366a822008-01-29 07:45:57 +00001277 p.put( "version", currentProject.getVersion() );
1278 p.put( "groupId", currentProject.getGroupId() );
1279 p.put( "artifactId", currentProject.getArtifactId() );
Carsten Ziegeler8fb2f052007-08-01 08:28:54 +00001280 ByteArrayOutputStream out = new ByteArrayOutputStream();
Stuart McCulloch9366a822008-01-29 07:45:57 +00001281 p.store( out, "Generated by org.apache.felix.bundleplugin" );
Stuart McCullochd98b02e2011-06-28 23:20:37 +00001282 jar.putResource( path + "/pom.properties", new EmbeddedResource( out.toByteArray(), System.currentTimeMillis() ) );
Carsten Ziegeler8fb2f052007-08-01 08:28:54 +00001283 }
Richard S. Hall46e7a852007-05-17 14:47:48 +00001284
Stuart McCulloch5ae59142008-01-29 06:21:05 +00001285
Guillaume Nodeted7b1102015-07-09 19:45:09 +00001286 protected Jar[] getClasspath( MavenProject currentProject, DependencyNode dependencyGraph ) throws IOException, MojoExecutionException
Carsten Ziegeler8fb2f052007-08-01 08:28:54 +00001287 {
Carsten Ziegeler82d87402015-03-04 13:26:21 +00001288 List<Jar> list = new ArrayList<Jar>();
Richard S. Hall46e7a852007-05-17 14:47:48 +00001289
Stuart McCulloch9366a822008-01-29 07:45:57 +00001290 if ( getOutputDirectory() != null && getOutputDirectory().exists() )
Carsten Ziegeler8fb2f052007-08-01 08:28:54 +00001291 {
Stuart McCulloch9366a822008-01-29 07:45:57 +00001292 list.add( new Jar( ".", getOutputDirectory() ) );
Carsten Ziegeler8fb2f052007-08-01 08:28:54 +00001293 }
Richard S. Hall46e7a852007-05-17 14:47:48 +00001294
Guillaume Nodeted7b1102015-07-09 19:45:09 +00001295 final Collection<Artifact> artifacts = getSelectedDependencies( dependencyGraph, currentProject.getArtifacts() );
Carsten Ziegeler82d87402015-03-04 13:26:21 +00001296 for ( Iterator<Artifact> it = artifacts.iterator(); it.hasNext(); )
Carsten Ziegeler8fb2f052007-08-01 08:28:54 +00001297 {
Carsten Ziegeler82d87402015-03-04 13:26:21 +00001298 Artifact artifact = it.next();
Stuart McCulloch5ae59142008-01-29 06:21:05 +00001299 if ( artifact.getArtifactHandler().isAddedToClasspath() )
Carsten Ziegeler8fb2f052007-08-01 08:28:54 +00001300 {
Guillaume Nodeted7b1102015-07-09 19:45:09 +00001301 File file = getFile( artifact );
1302 if ( file == null )
Carsten Ziegeler8fb2f052007-08-01 08:28:54 +00001303 {
Guillaume Nodeted7b1102015-07-09 19:45:09 +00001304 getLog().warn(
1305 "File is not available for artifact " + artifact + " in project "
1306 + currentProject.getArtifact() );
1307 continue;
Carsten Ziegeler8fb2f052007-08-01 08:28:54 +00001308 }
Guillaume Nodeted7b1102015-07-09 19:45:09 +00001309 Jar jar = new Jar( artifact.getArtifactId(), file );
1310 list.add( jar );
Carsten Ziegeler8fb2f052007-08-01 08:28:54 +00001311 }
1312 }
1313 Jar[] cp = new Jar[list.size()];
Stuart McCulloch5ae59142008-01-29 06:21:05 +00001314 list.toArray( cp );
Carsten Ziegeler8fb2f052007-08-01 08:28:54 +00001315 return cp;
1316 }
Richard S. Hall46e7a852007-05-17 14:47:48 +00001317
Stuart McCulloch5ae59142008-01-29 06:21:05 +00001318
Guillaume Nodeted7b1102015-07-09 19:45:09 +00001319 private Collection<Artifact> getSelectedDependencies( DependencyNode dependencyGraph, Collection<Artifact> artifacts ) throws MojoExecutionException
Stuart McCulloch5ffc3fe2008-02-20 05:37:57 +00001320 {
1321 if ( null == excludeDependencies || excludeDependencies.length() == 0 )
1322 {
1323 return artifacts;
1324 }
1325 else if ( "true".equalsIgnoreCase( excludeDependencies ) )
1326 {
Carsten Ziegeler82d87402015-03-04 13:26:21 +00001327 return Collections.emptyList();
Stuart McCulloch5ffc3fe2008-02-20 05:37:57 +00001328 }
1329
Carsten Ziegeler82d87402015-03-04 13:26:21 +00001330 Collection<Artifact> selectedDependencies = new LinkedHashSet<Artifact>( artifacts );
Guillaume Nodeted7b1102015-07-09 19:45:09 +00001331 DependencyExcluder excluder = new DependencyExcluder( dependencyGraph, artifacts );
Stuart McCulloch888d6da2009-02-16 08:25:03 +00001332 excluder.processHeaders( excludeDependencies );
1333 selectedDependencies.removeAll( excluder.getExcludedArtifacts() );
Stuart McCulloch5ffc3fe2008-02-20 05:37:57 +00001334
Stuart McCulloch888d6da2009-02-16 08:25:03 +00001335 return selectedDependencies;
Stuart McCulloch5ffc3fe2008-02-20 05:37:57 +00001336 }
1337
1338
Carsten Ziegeler8fb2f052007-08-01 08:28:54 +00001339 /**
1340 * Get the file for an Artifact
1341 *
1342 * @param artifact
1343 */
Stuart McCulloch5ae59142008-01-29 06:21:05 +00001344 protected File getFile( Artifact artifact )
Carsten Ziegeler8fb2f052007-08-01 08:28:54 +00001345 {
1346 return artifact.getFile();
1347 }
Richard S. Hall46e7a852007-05-17 14:47:48 +00001348
Stuart McCulloch5ae59142008-01-29 06:21:05 +00001349
Stuart McCulloch9366a822008-01-29 07:45:57 +00001350 private static void header( Properties properties, String key, Object value )
Carsten Ziegeler8fb2f052007-08-01 08:28:54 +00001351 {
Stuart McCulloch5ae59142008-01-29 06:21:05 +00001352 if ( value == null )
Carsten Ziegeler8fb2f052007-08-01 08:28:54 +00001353 return;
Richard S. Hall46e7a852007-05-17 14:47:48 +00001354
Stuart McCulloch5ae59142008-01-29 06:21:05 +00001355 if ( value instanceof Collection && ( ( Collection ) value ).isEmpty() )
Carsten Ziegeler8fb2f052007-08-01 08:28:54 +00001356 return;
1357
Stuart McCulloch5ae59142008-01-29 06:21:05 +00001358 properties.put( key, value.toString().replaceAll( "[\r\n]", "" ) );
Carsten Ziegeler8fb2f052007-08-01 08:28:54 +00001359 }
1360
Stuart McCulloch5ae59142008-01-29 06:21:05 +00001361
Carsten Ziegeler8fb2f052007-08-01 08:28:54 +00001362 /**
1363 * Convert a Maven version into an OSGi compliant version
1364 *
1365 * @param version Maven version
1366 * @return the OSGi version
1367 */
Stuart McCulloch5ae59142008-01-29 06:21:05 +00001368 protected String convertVersionToOsgi( String version )
Carsten Ziegeler8fb2f052007-08-01 08:28:54 +00001369 {
Stuart McCulloch9366a822008-01-29 07:45:57 +00001370 return getMaven2OsgiConverter().getVersion( version );
Carsten Ziegeler8fb2f052007-08-01 08:28:54 +00001371 }
1372
Stuart McCulloch5ae59142008-01-29 06:21:05 +00001373
Carsten Ziegeler8fb2f052007-08-01 08:28:54 +00001374 /**
1375 * TODO this should return getMaven2Osgi().getBundleFileName( project.getArtifact() )
1376 */
Stuart McCulloch9366a822008-01-29 07:45:57 +00001377 protected String getBundleName( MavenProject currentProject )
Carsten Ziegeler8fb2f052007-08-01 08:28:54 +00001378 {
Stuart McCulloche68ebd22011-06-24 21:50:07 +00001379 String extension;
1380 try
1381 {
1382 extension = currentProject.getArtifact().getArtifactHandler().getExtension();
1383 }
1384 catch ( Throwable e )
1385 {
1386 extension = currentProject.getArtifact().getType();
1387 }
Stuart McCulloch5fcbe4a2011-06-28 18:26:45 +00001388 if ( StringUtils.isEmpty( extension ) || "bundle".equals( extension ) || "pom".equals( extension ) )
Stuart McCulloche68ebd22011-06-24 21:50:07 +00001389 {
1390 extension = "jar"; // just in case maven gets confused
1391 }
Stuart McCulloch0491afa2008-02-19 05:06:41 +00001392 if ( null != classifier && classifier.trim().length() > 0 )
1393 {
Stuart McCulloche68ebd22011-06-24 21:50:07 +00001394 return finalName + '-' + classifier + '.' + extension;
Stuart McCulloch0491afa2008-02-19 05:06:41 +00001395 }
Stuart McCulloche68ebd22011-06-24 21:50:07 +00001396 return finalName + '.' + extension;
Carsten Ziegeler8fb2f052007-08-01 08:28:54 +00001397 }
1398
Stuart McCulloch5ae59142008-01-29 06:21:05 +00001399
Stuart McCulloch1a862e92007-10-16 14:13:49 +00001400 protected String getBuildDirectory()
Carsten Ziegeler8fb2f052007-08-01 08:28:54 +00001401 {
Stuart McCulloch9366a822008-01-29 07:45:57 +00001402 return buildDirectory;
Carsten Ziegeler8fb2f052007-08-01 08:28:54 +00001403 }
1404
Stuart McCulloch5ae59142008-01-29 06:21:05 +00001405
Stuart McCulloch9366a822008-01-29 07:45:57 +00001406 protected void setBuildDirectory( String _buildirectory )
Carsten Ziegeler8fb2f052007-08-01 08:28:54 +00001407 {
Stuart McCulloch9366a822008-01-29 07:45:57 +00001408 buildDirectory = _buildirectory;
Carsten Ziegeler8fb2f052007-08-01 08:28:54 +00001409 }
1410
Stuart McCulloch5ae59142008-01-29 06:21:05 +00001411
Stuart McCulloch9366a822008-01-29 07:45:57 +00001412 protected Properties getDefaultProperties( MavenProject currentProject )
Carsten Ziegeler8fb2f052007-08-01 08:28:54 +00001413 {
1414 Properties properties = new Properties();
Stuart McCulloch02afa5f2007-10-04 17:23:30 +00001415
1416 String bsn;
1417 try
1418 {
Stuart McCulloch9366a822008-01-29 07:45:57 +00001419 bsn = getMaven2OsgiConverter().getBundleSymbolicName( currentProject.getArtifact() );
Stuart McCulloch02afa5f2007-10-04 17:23:30 +00001420 }
Stuart McCulloch5ae59142008-01-29 06:21:05 +00001421 catch ( Exception e )
Stuart McCulloch02afa5f2007-10-04 17:23:30 +00001422 {
Stuart McCulloch9366a822008-01-29 07:45:57 +00001423 bsn = currentProject.getGroupId() + "." + currentProject.getArtifactId();
Stuart McCulloch02afa5f2007-10-04 17:23:30 +00001424 }
1425
Carsten Ziegeler8fb2f052007-08-01 08:28:54 +00001426 // Setup defaults
Stuart McCulloch6d4c8372009-02-16 06:49:21 +00001427 properties.put( MAVEN_SYMBOLICNAME, bsn );
Stuart McCulloch5ae59142008-01-29 06:21:05 +00001428 properties.put( Analyzer.BUNDLE_SYMBOLICNAME, bsn );
1429 properties.put( Analyzer.IMPORT_PACKAGE, "*" );
Stuart McCullochd98b02e2011-06-28 23:20:37 +00001430 properties.put( Analyzer.BUNDLE_VERSION, getMaven2OsgiConverter().getVersion( currentProject.getVersion() ) );
Stuart McCulloch02afa5f2007-10-04 17:23:30 +00001431
Stuart McCullochc966ef62009-09-02 18:02:59 +00001432 // remove the extraneous Include-Resource and Private-Package entries from generated manifest
Richard S. Hall2c9e5922010-10-25 19:07:06 +00001433 properties.put( Constants.REMOVEHEADERS, Analyzer.INCLUDE_RESOURCE + ',' + Analyzer.PRIVATE_PACKAGE );
Stuart McCulloch8f21a4a2008-01-09 17:08:32 +00001434
Stuart McCulloch9366a822008-01-29 07:45:57 +00001435 header( properties, Analyzer.BUNDLE_DESCRIPTION, currentProject.getDescription() );
1436 StringBuffer licenseText = printLicenses( currentProject.getLicenses() );
Stuart McCulloch5ae59142008-01-29 06:21:05 +00001437 if ( licenseText != null )
Carsten Ziegeler8fb2f052007-08-01 08:28:54 +00001438 {
Stuart McCulloch9366a822008-01-29 07:45:57 +00001439 header( properties, Analyzer.BUNDLE_LICENSE, licenseText );
Stuart McCulloch5ae59142008-01-29 06:21:05 +00001440 }
Stuart McCulloch9366a822008-01-29 07:45:57 +00001441 header( properties, Analyzer.BUNDLE_NAME, currentProject.getName() );
Stuart McCulloch5ae59142008-01-29 06:21:05 +00001442
Stuart McCulloch9366a822008-01-29 07:45:57 +00001443 if ( currentProject.getOrganization() != null )
Stuart McCulloch5ae59142008-01-29 06:21:05 +00001444 {
Stuart McCulloch007f8c82011-06-24 12:45:17 +00001445 if ( currentProject.getOrganization().getName() != null )
1446 {
1447 String organizationName = currentProject.getOrganization().getName();
1448 header( properties, Analyzer.BUNDLE_VENDOR, organizationName );
1449 properties.put( "project.organization.name", organizationName );
1450 properties.put( "pom.organization.name", organizationName );
1451 }
Stuart McCulloch9366a822008-01-29 07:45:57 +00001452 if ( currentProject.getOrganization().getUrl() != null )
Carsten Ziegeler8fb2f052007-08-01 08:28:54 +00001453 {
Stuart McCulloch6dd4dd22009-09-02 22:45:33 +00001454 String organizationUrl = currentProject.getOrganization().getUrl();
1455 header( properties, Analyzer.BUNDLE_DOCURL, organizationUrl );
1456 properties.put( "project.organization.url", organizationUrl );
1457 properties.put( "pom.organization.url", organizationUrl );
Carsten Ziegeler8fb2f052007-08-01 08:28:54 +00001458 }
1459 }
1460
Stuart McCulloch9366a822008-01-29 07:45:57 +00001461 properties.putAll( currentProject.getProperties() );
1462 properties.putAll( currentProject.getModel().getProperties() );
Stuart McCulloch437f4872013-06-07 21:24:26 +00001463
Carsten Ziegeler82d87402015-03-04 13:26:21 +00001464 for ( Iterator<String> i = currentProject.getFilters().iterator(); i.hasNext(); )
Stuart McCulloch437f4872013-06-07 21:24:26 +00001465 {
Carsten Ziegeler82d87402015-03-04 13:26:21 +00001466 File filterFile = new File( i.next() );
Stuart McCulloch437f4872013-06-07 21:24:26 +00001467 if ( filterFile.isFile() )
1468 {
1469 properties.putAll( PropertyUtils.loadProperties( filterFile ) );
1470 }
1471 }
1472
Stuart McCullochcdad75f2011-06-28 00:03:15 +00001473 if ( m_mavenSession != null )
1474 {
Stuart McCulloche98965e2012-02-11 14:17:41 +00001475 try
1476 {
Stuart McCulloch8eb17522012-02-11 14:26:57 +00001477 // don't pass upper-case session settings to bnd as they end up in the manifest
Stuart McCulloche98965e2012-02-11 14:17:41 +00001478 Properties sessionProperties = m_mavenSession.getExecutionProperties();
Carsten Ziegeler82d87402015-03-04 13:26:21 +00001479 for ( Enumeration<String> e = (Enumeration<String>) sessionProperties.propertyNames(); e.hasMoreElements(); )
Stuart McCulloche98965e2012-02-11 14:17:41 +00001480 {
Carsten Ziegeler82d87402015-03-04 13:26:21 +00001481 String key = e.nextElement();
Stuart McCulloche98965e2012-02-11 14:17:41 +00001482 if ( key.length() > 0 && !Character.isUpperCase( key.charAt( 0 ) ) )
1483 {
1484 properties.put( key, sessionProperties.getProperty( key ) );
1485 }
1486 }
1487 }
1488 catch ( Exception e )
1489 {
1490 getLog().warn( "Problem with Maven session properties: " + e.getLocalizedMessage() );
1491 }
Stuart McCullochcdad75f2011-06-28 00:03:15 +00001492 }
1493
Stuart McCullochf806f862008-02-04 07:57:09 +00001494 properties.putAll( getProperties( currentProject.getModel(), "project.build." ) );
1495 properties.putAll( getProperties( currentProject.getModel(), "pom." ) );
1496 properties.putAll( getProperties( currentProject.getModel(), "project." ) );
Stuart McCullochcdad75f2011-06-28 00:03:15 +00001497
Stuart McCulloch5fcbe4a2011-06-28 18:26:45 +00001498 properties.put( "project.baseDir", getBase( currentProject ) );
Stuart McCulloch9366a822008-01-29 07:45:57 +00001499 properties.put( "project.build.directory", getBuildDirectory() );
1500 properties.put( "project.build.outputdirectory", getOutputDirectory() );
Carsten Ziegeler8fb2f052007-08-01 08:28:54 +00001501
Stuart McCulloch1d3a0a02008-04-30 05:38:03 +00001502 properties.put( "classifier", classifier == null ? "" : classifier );
1503
Guillaume Nodet459eaed2009-09-02 21:15:28 +00001504 // Add default plugins
Guillaume Nodet7bf509f2014-05-19 07:12:48 +00001505 header( properties, Analyzer.PLUGIN, ScrPlugin.class.getName() + ","
1506 + BlueprintPlugin.class.getName() + ","
1507 + SpringXMLType.class.getName() );
Guillaume Nodet459eaed2009-09-02 21:15:28 +00001508
Carsten Ziegeler8fb2f052007-08-01 08:28:54 +00001509 return properties;
1510 }
1511
Stuart McCulloch5ae59142008-01-29 06:21:05 +00001512
Stuart McCulloch5fcbe4a2011-06-28 18:26:45 +00001513 protected static File getBase( MavenProject currentProject )
1514 {
1515 return currentProject.getBasedir() != null ? currentProject.getBasedir() : new File( "" );
1516 }
1517
1518
Stuart McCulloch9366a822008-01-29 07:45:57 +00001519 protected File getOutputDirectory()
Carsten Ziegeler8fb2f052007-08-01 08:28:54 +00001520 {
Stuart McCulloch9366a822008-01-29 07:45:57 +00001521 return outputDirectory;
Carsten Ziegeler8fb2f052007-08-01 08:28:54 +00001522 }
1523
Stuart McCulloch5ae59142008-01-29 06:21:05 +00001524
Stuart McCulloch9366a822008-01-29 07:45:57 +00001525 protected void setOutputDirectory( File _outputDirectory )
Carsten Ziegeler8fb2f052007-08-01 08:28:54 +00001526 {
Stuart McCulloch9366a822008-01-29 07:45:57 +00001527 outputDirectory = _outputDirectory;
Carsten Ziegeler8fb2f052007-08-01 08:28:54 +00001528 }
1529
Stuart McCulloch5ae59142008-01-29 06:21:05 +00001530
Stuart McCulloch1648f402013-06-07 22:21:11 +00001531 private static void addLocalPackages( File outputDirectory, Analyzer analyzer ) throws IOException
Stuart McCulloch5341ef02009-02-16 09:44:47 +00001532 {
Stuart McCulloch1648f402013-06-07 22:21:11 +00001533 Packages packages = new Packages();
Stuart McCulloch5341ef02009-02-16 09:44:47 +00001534
Hiram R. Chirino4f5f2272011-01-27 18:32:03 +00001535 if ( outputDirectory != null && outputDirectory.isDirectory() )
Stuart McCulloch5341ef02009-02-16 09:44:47 +00001536 {
Hiram R. Chirino4f5f2272011-01-27 18:32:03 +00001537 // scan classes directory for potential packages
1538 DirectoryScanner scanner = new DirectoryScanner();
1539 scanner.setBasedir( outputDirectory );
1540 scanner.setIncludes( new String[]
1541 { "**/*.class" } );
1542
1543 scanner.addDefaultExcludes();
1544 scanner.scan();
1545
1546 String[] paths = scanner.getIncludedFiles();
1547 for ( int i = 0; i < paths.length; i++ )
Stuart McCullochb371e7e2009-02-17 11:58:12 +00001548 {
Stuart McCulloch1648f402013-06-07 22:21:11 +00001549 packages.put( analyzer.getPackageRef( getPackageName( paths[i] ) ) );
Stuart McCullochb371e7e2009-02-17 11:58:12 +00001550 }
Stuart McCulloch5341ef02009-02-16 09:44:47 +00001551 }
1552
Stuart McCulloch1648f402013-06-07 22:21:11 +00001553 Packages exportedPkgs = new Packages();
1554 Packages privatePkgs = new Packages();
Stuart McCullochd98b02e2011-06-28 23:20:37 +00001555
1556 boolean noprivatePackages = "!*".equals( analyzer.getProperty( Analyzer.PRIVATE_PACKAGE ) );
Stuart McCulloch5341ef02009-02-16 09:44:47 +00001557
Stuart McCulloch1648f402013-06-07 22:21:11 +00001558 for ( PackageRef pkg : packages.keySet() )
Stuart McCulloch5341ef02009-02-16 09:44:47 +00001559 {
Stuart McCullochb371e7e2009-02-17 11:58:12 +00001560 // mark all source packages as private by default (can be overridden by export list)
Stuart McCulloch1648f402013-06-07 22:21:11 +00001561 privatePkgs.put( pkg );
Stuart McCullochb371e7e2009-02-17 11:58:12 +00001562
Carsten Ziegeler67c8ce32014-08-07 06:41:23 +00001563 // we can't export the default package (".") and we shouldn't export internal packages
Stuart McCulloch1648f402013-06-07 22:21:11 +00001564 String fqn = pkg.getFQN();
1565 if ( noprivatePackages || !( ".".equals( fqn ) || fqn.contains( ".internal" ) || fqn.contains( ".impl" ) ) )
Stuart McCulloch5341ef02009-02-16 09:44:47 +00001566 {
Stuart McCulloch1648f402013-06-07 22:21:11 +00001567 exportedPkgs.put( pkg );
Stuart McCulloch5341ef02009-02-16 09:44:47 +00001568 }
1569 }
1570
Stuart McCulloch1648f402013-06-07 22:21:11 +00001571 Properties properties = analyzer.getProperties();
1572 String exported = properties.getProperty( Analyzer.EXPORT_PACKAGE );
1573 if ( exported == null )
Stuart McCullochb371e7e2009-02-17 11:58:12 +00001574 {
Stuart McCulloch1648f402013-06-07 22:21:11 +00001575 if ( !properties.containsKey( Analyzer.EXPORT_CONTENTS ) )
Stuart McCullochb371e7e2009-02-17 11:58:12 +00001576 {
1577 // no -exportcontents overriding the exports, so use our computed list
Stuart McCulloch1648f402013-06-07 22:21:11 +00001578 for ( Attrs attrs : exportedPkgs.values() )
1579 {
1580 attrs.put( Constants.SPLIT_PACKAGE_DIRECTIVE, "merge-first" );
1581 }
1582 properties.setProperty( Analyzer.EXPORT_PACKAGE, Processor.printClauses( exportedPkgs ) );
Stuart McCullochb371e7e2009-02-17 11:58:12 +00001583 }
1584 else
1585 {
1586 // leave Export-Package empty (but non-null) as we have -exportcontents
Stuart McCulloch1648f402013-06-07 22:21:11 +00001587 properties.setProperty( Analyzer.EXPORT_PACKAGE, "" );
Stuart McCullochb371e7e2009-02-17 11:58:12 +00001588 }
1589 }
Stuart McCulloch1648f402013-06-07 22:21:11 +00001590 else if ( exported.indexOf( LOCAL_PACKAGES ) >= 0 )
Guillaume Nodete5f5c7a2010-11-17 08:09:42 +00001591 {
Stuart McCulloch1648f402013-06-07 22:21:11 +00001592 String newExported = StringUtils.replace( exported, LOCAL_PACKAGES, Processor.printClauses( exportedPkgs ) );
1593 properties.setProperty( Analyzer.EXPORT_PACKAGE, newExported );
Guillaume Nodete5f5c7a2010-11-17 08:09:42 +00001594 }
Stuart McCullochb371e7e2009-02-17 11:58:12 +00001595
Stuart McCulloch1648f402013-06-07 22:21:11 +00001596 String internal = properties.getProperty( Analyzer.PRIVATE_PACKAGE );
Stuart McCullochba6fc122011-11-28 14:22:26 +00001597 if ( internal == null )
Stuart McCullochb371e7e2009-02-17 11:58:12 +00001598 {
Stuart McCulloch1648f402013-06-07 22:21:11 +00001599 if ( !privatePkgs.isEmpty() )
Stuart McCullochba6fc122011-11-28 14:22:26 +00001600 {
Stuart McCulloch1648f402013-06-07 22:21:11 +00001601 for ( Attrs attrs : privatePkgs.values() )
1602 {
1603 attrs.put( Constants.SPLIT_PACKAGE_DIRECTIVE, "merge-first" );
1604 }
1605 properties.setProperty( Analyzer.PRIVATE_PACKAGE, Processor.printClauses( privatePkgs ) );
Stuart McCullochba6fc122011-11-28 14:22:26 +00001606 }
1607 else
1608 {
1609 // if there are really no private packages then use "!*" as this will keep the Bnd Tool happy
Stuart McCulloch1648f402013-06-07 22:21:11 +00001610 properties.setProperty( Analyzer.PRIVATE_PACKAGE, "!*" );
Stuart McCullochba6fc122011-11-28 14:22:26 +00001611 }
1612 }
1613 else if ( internal.indexOf( LOCAL_PACKAGES ) >= 0 )
1614 {
Stuart McCulloch1648f402013-06-07 22:21:11 +00001615 String newInternal = StringUtils.replace( internal, LOCAL_PACKAGES, Processor.printClauses( privatePkgs ) );
1616 properties.setProperty( Analyzer.PRIVATE_PACKAGE, newInternal );
Stuart McCullochb371e7e2009-02-17 11:58:12 +00001617 }
Stuart McCulloch5341ef02009-02-16 09:44:47 +00001618 }
1619
1620
Stuart McCullochb371e7e2009-02-17 11:58:12 +00001621 private static String getPackageName( String filename )
Stuart McCulloch5341ef02009-02-16 09:44:47 +00001622 {
1623 int n = filename.lastIndexOf( File.separatorChar );
1624 return n < 0 ? "." : filename.substring( 0, n ).replace( File.separatorChar, '.' );
1625 }
1626
1627
Carsten Ziegeler82d87402015-03-04 13:26:21 +00001628 private static List<Resource> getMavenResources( MavenProject currentProject, boolean test )
Stuart McCulloche71aa492011-06-24 18:21:16 +00001629 {
Carsten Ziegeler82d87402015-03-04 13:26:21 +00001630 List<Resource> resources = new ArrayList<Resource>( test ? currentProject.getTestResources() : currentProject.getResources() );
Stuart McCulloche71aa492011-06-24 18:21:16 +00001631
Stuart McCulloch5fcbe4a2011-06-28 18:26:45 +00001632 if ( currentProject.getCompileSourceRoots() != null )
Stuart McCulloche71aa492011-06-24 18:21:16 +00001633 {
Stuart McCulloch1228d3f2011-06-28 16:14:52 +00001634 // also scan for any "packageinfo" files lurking in the source folders
Carsten Ziegeler82d87402015-03-04 13:26:21 +00001635 final List<String> packageInfoIncludes = Collections.singletonList( "**/packageinfo" );
1636 for ( Iterator<String> i = currentProject.getCompileSourceRoots().iterator(); i.hasNext(); )
Stuart McCulloch1228d3f2011-06-28 16:14:52 +00001637 {
Carsten Ziegeler82d87402015-03-04 13:26:21 +00001638 String sourceRoot = i.next();
Stuart McCulloch1228d3f2011-06-28 16:14:52 +00001639 Resource packageInfoResource = new Resource();
1640 packageInfoResource.setDirectory( sourceRoot );
1641 packageInfoResource.setIncludes( packageInfoIncludes );
1642 resources.add( packageInfoResource );
1643 }
Stuart McCulloche71aa492011-06-24 18:21:16 +00001644 }
1645
1646 return resources;
1647 }
1648
1649
Guillaume Nodet09194e62014-06-16 07:07:12 +00001650 protected static String getMavenResourcePaths( MavenProject currentProject, boolean test )
Carsten Ziegeler8fb2f052007-08-01 08:28:54 +00001651 {
Stuart McCulloch5fcbe4a2011-06-28 18:26:45 +00001652 final String basePath = currentProject.getBasedir().getAbsolutePath();
Carsten Ziegeler8fb2f052007-08-01 08:28:54 +00001653
Carsten Ziegeler82d87402015-03-04 13:26:21 +00001654 Set<String> pathSet = new LinkedHashSet<String>();
1655 for ( Iterator<Resource> i = getMavenResources( currentProject, test ).iterator(); i.hasNext(); )
Carsten Ziegeler8fb2f052007-08-01 08:28:54 +00001656 {
Carsten Ziegeler82d87402015-03-04 13:26:21 +00001657 Resource resource = i.next();
Carsten Ziegeler8fb2f052007-08-01 08:28:54 +00001658
1659 final String sourcePath = resource.getDirectory();
1660 final String targetPath = resource.getTargetPath();
1661
1662 // ignore empty or non-local resources
Stuart McCulloch5ae59142008-01-29 06:21:05 +00001663 if ( new File( sourcePath ).exists() && ( ( targetPath == null ) || ( targetPath.indexOf( ".." ) < 0 ) ) )
Carsten Ziegeler8fb2f052007-08-01 08:28:54 +00001664 {
Stuart McCulloch44deaef2007-11-18 04:36:21 +00001665 DirectoryScanner scanner = new DirectoryScanner();
Carsten Ziegeler8fb2f052007-08-01 08:28:54 +00001666
Stuart McCulloche71aa492011-06-24 18:21:16 +00001667 scanner.setBasedir( sourcePath );
Stuart McCulloch44deaef2007-11-18 04:36:21 +00001668 if ( resource.getIncludes() != null && !resource.getIncludes().isEmpty() )
Carsten Ziegeler8fb2f052007-08-01 08:28:54 +00001669 {
Stuart McCulloch5ae59142008-01-29 06:21:05 +00001670 scanner.setIncludes( ( String[] ) resource.getIncludes().toArray( EMPTY_STRING_ARRAY ) );
Carsten Ziegeler8fb2f052007-08-01 08:28:54 +00001671 }
1672 else
1673 {
Stuart McCulloch44deaef2007-11-18 04:36:21 +00001674 scanner.setIncludes( DEFAULT_INCLUDES );
Carsten Ziegeler8fb2f052007-08-01 08:28:54 +00001675 }
Stuart McCulloch44deaef2007-11-18 04:36:21 +00001676
1677 if ( resource.getExcludes() != null && !resource.getExcludes().isEmpty() )
1678 {
Stuart McCulloch5ae59142008-01-29 06:21:05 +00001679 scanner.setExcludes( ( String[] ) resource.getExcludes().toArray( EMPTY_STRING_ARRAY ) );
Stuart McCulloch44deaef2007-11-18 04:36:21 +00001680 }
1681
1682 scanner.addDefaultExcludes();
1683 scanner.scan();
1684
Carsten Ziegeler82d87402015-03-04 13:26:21 +00001685 List<String> includedFiles = Arrays.asList( scanner.getIncludedFiles() );
Stuart McCulloch44deaef2007-11-18 04:36:21 +00001686
Carsten Ziegeler82d87402015-03-04 13:26:21 +00001687 for ( Iterator<String> j = includedFiles.iterator(); j.hasNext(); )
Stuart McCulloch44deaef2007-11-18 04:36:21 +00001688 {
Carsten Ziegeler82d87402015-03-04 13:26:21 +00001689 String name = j.next();
Stuart McCulloch7c16d692007-11-18 05:02:09 +00001690 String path = sourcePath + '/' + name;
Stuart McCulloch44deaef2007-11-18 04:36:21 +00001691
1692 // make relative to project
Stuart McCulloch5ae59142008-01-29 06:21:05 +00001693 if ( path.startsWith( basePath ) )
Stuart McCulloch44deaef2007-11-18 04:36:21 +00001694 {
1695 if ( path.length() == basePath.length() )
1696 {
1697 path = ".";
1698 }
1699 else
1700 {
1701 path = path.substring( basePath.length() + 1 );
1702 }
1703 }
1704
1705 // replace windows backslash with a slash
1706 // this is a workaround for a problem with bnd 0.0.189
1707 if ( File.separatorChar != '/' )
1708 {
Stuart McCulloch5ae59142008-01-29 06:21:05 +00001709 name = name.replace( File.separatorChar, '/' );
1710 path = path.replace( File.separatorChar, '/' );
Stuart McCulloch44deaef2007-11-18 04:36:21 +00001711 }
1712
Stuart McCulloch7c16d692007-11-18 05:02:09 +00001713 // copy to correct place
1714 path = name + '=' + path;
Stuart McCulloch5ae59142008-01-29 06:21:05 +00001715 if ( targetPath != null )
Stuart McCulloch44deaef2007-11-18 04:36:21 +00001716 {
Stuart McCulloch7c16d692007-11-18 05:02:09 +00001717 path = targetPath + '/' + path;
Stuart McCulloch44deaef2007-11-18 04:36:21 +00001718 }
1719
Stuart McCulloch63682bf2009-07-13 10:59:39 +00001720 // use Bnd filtering?
Stuart McCulloch5ae59142008-01-29 06:21:05 +00001721 if ( resource.isFiltering() )
Stuart McCulloch44deaef2007-11-18 04:36:21 +00001722 {
Stuart McCulloch63682bf2009-07-13 10:59:39 +00001723 path = '{' + path + '}';
Stuart McCulloch44deaef2007-11-18 04:36:21 +00001724 }
Stuart McCulloch63682bf2009-07-13 10:59:39 +00001725
1726 pathSet.add( path );
Stuart McCulloch5ae59142008-01-29 06:21:05 +00001727 }
Carsten Ziegeler8fb2f052007-08-01 08:28:54 +00001728 }
1729 }
1730
Stuart McCulloch63682bf2009-07-13 10:59:39 +00001731 StringBuffer resourcePaths = new StringBuffer();
Carsten Ziegeler82d87402015-03-04 13:26:21 +00001732 for ( Iterator<String> i = pathSet.iterator(); i.hasNext(); )
Stuart McCulloch63682bf2009-07-13 10:59:39 +00001733 {
1734 resourcePaths.append( i.next() );
1735 if ( i.hasNext() )
1736 {
1737 resourcePaths.append( ',' );
1738 }
1739 }
1740
Carsten Ziegeler8fb2f052007-08-01 08:28:54 +00001741 return resourcePaths.toString();
1742 }
Stuart McCullochf7c44882007-08-23 08:10:03 +00001743
Stuart McCulloch5ae59142008-01-29 06:21:05 +00001744
Guillaume Nodeted7b1102015-07-09 19:45:09 +00001745 protected Collection<Artifact> getEmbeddableArtifacts( MavenProject currentProject, DependencyNode dependencyGraph, Analyzer analyzer )
Stuart McCulloch888d6da2009-02-16 08:25:03 +00001746 throws MojoExecutionException
Stuart McCullochf7c44882007-08-23 08:10:03 +00001747 {
Carsten Ziegeler82d87402015-03-04 13:26:21 +00001748 final Collection<Artifact> artifacts;
Stuart McCulloch888d6da2009-02-16 08:25:03 +00001749
Stuart McCulloch84bf81e2008-12-03 14:07:08 +00001750 String embedTransitive = analyzer.getProperty( DependencyEmbedder.EMBED_TRANSITIVE );
Stuart McCulloch5ae59142008-01-29 06:21:05 +00001751 if ( Boolean.valueOf( embedTransitive ).booleanValue() )
Stuart McCullochf7c44882007-08-23 08:10:03 +00001752 {
1753 // includes transitive dependencies
Stuart McCulloch5fcbe4a2011-06-28 18:26:45 +00001754 artifacts = currentProject.getArtifacts();
Stuart McCulloch888d6da2009-02-16 08:25:03 +00001755 }
1756 else
1757 {
1758 // only includes direct dependencies
Stuart McCulloch5fcbe4a2011-06-28 18:26:45 +00001759 artifacts = currentProject.getDependencyArtifacts();
Stuart McCullochf7c44882007-08-23 08:10:03 +00001760 }
Stuart McCullochf806f862008-02-04 07:57:09 +00001761
Guillaume Nodeted7b1102015-07-09 19:45:09 +00001762 return getSelectedDependencies( dependencyGraph, artifacts );
Stuart McCullochf7c44882007-08-23 08:10:03 +00001763 }
Stuart McCullochfe58ad52011-11-28 15:05:51 +00001764
1765
1766 protected static void addMavenSourcePath( MavenProject currentProject, Analyzer analyzer, Log log )
1767 {
1768 // pass maven source paths onto BND analyzer
1769 StringBuilder mavenSourcePaths = new StringBuilder();
Guillaume Nodet09194e62014-06-16 07:07:12 +00001770 StringBuilder mavenTestSourcePaths = new StringBuilder();
Carsten Ziegeler82d87402015-03-04 13:26:21 +00001771 Map<StringBuilder, List<String>> map = new HashMap<StringBuilder, List<String>>(2);
Guillaume Nodet09194e62014-06-16 07:07:12 +00001772 map.put(mavenSourcePaths, currentProject.getCompileSourceRoots() );
1773 map.put(mavenTestSourcePaths, currentProject.getTestCompileSourceRoots() );
Carsten Ziegeler82d87402015-03-04 13:26:21 +00001774 for ( Map.Entry<StringBuilder, List<String>> entry : map.entrySet() )
Stuart McCullochfe58ad52011-11-28 15:05:51 +00001775 {
Carsten Ziegeler82d87402015-03-04 13:26:21 +00001776 List<String> compileSourceRoots = entry.getValue();
Guillaume Nodet09194e62014-06-16 07:07:12 +00001777 if ( compileSourceRoots != null )
Stuart McCullochfe58ad52011-11-28 15:05:51 +00001778 {
Guillaume Nodet09194e62014-06-16 07:07:12 +00001779 StringBuilder sourcePaths = entry.getKey();
Carsten Ziegeler82d87402015-03-04 13:26:21 +00001780 for ( Iterator<String> i = compileSourceRoots.iterator(); i.hasNext(); )
Stuart McCullochfe58ad52011-11-28 15:05:51 +00001781 {
Guillaume Nodet09194e62014-06-16 07:07:12 +00001782 if ( sourcePaths.length() > 0 )
1783 {
1784 sourcePaths.append( ',' );
1785 }
Carsten Ziegeler82d87402015-03-04 13:26:21 +00001786 sourcePaths.append( i.next() );
Stuart McCullochfe58ad52011-11-28 15:05:51 +00001787 }
Stuart McCullochfe58ad52011-11-28 15:05:51 +00001788 }
1789 }
Guillaume Nodet09194e62014-06-16 07:07:12 +00001790 final String sourcePath = analyzer.getProperty( Analyzer.SOURCEPATH );
Stuart McCullochfe58ad52011-11-28 15:05:51 +00001791 if ( sourcePath != null )
1792 {
Guillaume Nodet09194e62014-06-16 07:07:12 +00001793 if ( sourcePath.contains(MAVEN_SOURCES) || sourcePath.contains(MAVEN_TEST_RESOURCES) )
Stuart McCullochfe58ad52011-11-28 15:05:51 +00001794 {
Guillaume Nodet09194e62014-06-16 07:07:12 +00001795 String combinedSource = StringUtils.replace( sourcePath, MAVEN_SOURCES, mavenSourcePaths.toString() );
1796 combinedSource = StringUtils.replace( combinedSource, MAVEN_TEST_SOURCES, mavenTestSourcePaths.toString() );
1797 if ( combinedSource.length() > 0 )
Stuart McCullochfe58ad52011-11-28 15:05:51 +00001798 {
Guillaume Nodet09194e62014-06-16 07:07:12 +00001799 analyzer.setProperty( Analyzer.SOURCEPATH, combinedSource );
Stuart McCullochfe58ad52011-11-28 15:05:51 +00001800 }
1801 else
1802 {
Guillaume Nodet09194e62014-06-16 07:07:12 +00001803 analyzer.unsetProperty( Analyzer.SOURCEPATH );
Stuart McCullochfe58ad52011-11-28 15:05:51 +00001804 }
1805 }
1806 else if ( mavenSourcePaths.length() > 0 )
1807 {
1808 log.warn( Analyzer.SOURCEPATH + ": overriding " + mavenSourcePaths + " with " + sourcePath + " (add "
1809 + MAVEN_SOURCES + " if you want to include the maven sources)" );
1810 }
Guillaume Nodet09194e62014-06-16 07:07:12 +00001811 else if ( mavenTestSourcePaths.length() > 0 )
1812 {
1813 log.warn( Analyzer.SOURCEPATH + ": overriding " + mavenTestSourcePaths + " with " + sourcePath + " (add "
1814 + MAVEN_TEST_SOURCES + " if you want to include the maven sources)" );
1815 }
Stuart McCullochfe58ad52011-11-28 15:05:51 +00001816 }
1817 else if ( mavenSourcePaths.length() > 0 )
1818 {
1819 analyzer.setProperty( Analyzer.SOURCEPATH, mavenSourcePaths.toString() );
1820 }
1821 }
Richard S. Hallf3120092006-10-31 17:32:16 +00001822}