View Javadoc
1   package org.apache.maven.plugin.ear;
2   
3   /*
4    * Licensed to the Apache Software Foundation (ASF) under one
5    * or more contributor license agreements.  See the NOTICE file
6    * distributed with this work for additional information
7    * regarding copyright ownership.  The ASF licenses this file
8    * to you under the Apache License, Version 2.0 (the
9    * "License"); you may not use this file except in compliance
10   * with the License.  You may obtain a copy of the License at
11   *
12   *  http://www.apache.org/licenses/LICENSE-2.0
13   *
14   * Unless required by applicable law or agreed to in writing,
15   * software distributed under the License is distributed on an
16   * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
17   * KIND, either express or implied.  See the License for the
18   * specific language governing permissions and limitations
19   * under the License.
20   */
21  
22  import java.io.File;
23  import java.util.ArrayList;
24  import java.util.List;
25  import java.util.Set;
26  
27  import org.apache.maven.artifact.Artifact;
28  import org.apache.maven.artifact.resolver.filter.ScopeArtifactFilter;
29  import org.apache.maven.plugin.AbstractMojo;
30  import org.apache.maven.plugin.MojoExecutionException;
31  import org.apache.maven.plugin.MojoFailureException;
32  import org.apache.maven.plugin.ear.util.ArtifactTypeMappingService;
33  import org.apache.maven.plugin.ear.util.JavaEEVersion;
34  import org.apache.maven.plugins.annotations.Component;
35  import org.apache.maven.plugins.annotations.Parameter;
36  import org.apache.maven.project.MavenProject;
37  import org.apache.maven.shared.filtering.MavenResourcesFiltering;
38  import org.codehaus.plexus.configuration.PlexusConfiguration;
39  import org.codehaus.plexus.configuration.PlexusConfigurationException;
40  
41  /**
42   * A base class for EAR-processing related tasks.
43   * 
44   * @author <a href="snicoll@apache.org">Stephane Nicoll</a>
45   * @version $Id: AbstractEarMojo.java 1648051 2014-12-27 12:55:58Z khmarbaise $
46   */
47  public abstract class AbstractEarMojo
48      extends AbstractMojo
49  {
50      /**
51       * The application XML URI {@code META-INF/application.xml}
52       */
53      public static final String APPLICATION_XML_URI = "META-INF/application.xml";
54  
55      /**
56       * The {@code META-INF} folder.
57       */
58      public static final String META_INF = "META-INF";
59  
60      /**
61       * UTF-8 encoding constant.
62       */
63      public static final String UTF_8 = "UTF-8";
64  
65      /**
66       * The version of the application.xml to generate. Valid values are 1.3, 1.4, 5, 6 and 7.
67       */
68      @Parameter( defaultValue = "1.3" )
69      protected String version;
70  
71      /**
72       * Character encoding for the auto-generated deployment file(s).
73       */
74      @Parameter( defaultValue = "UTF-8" )
75      protected String encoding;
76  
77      /**
78       * Directory where the deployment descriptor file(s) will be auto-generated.
79       */
80      @Parameter( defaultValue = "${project.build.directory}" )
81      protected String generatedDescriptorLocation;
82  
83      /**
84       * The maven project.
85       */
86      @Parameter( defaultValue = "${project}", readonly = true, required = true )
87      protected MavenProject project;
88  
89      /**
90       * The ear modules configuration.
91       */
92      @Parameter
93      private EarModule[] modules;
94  
95      /**
96       * The artifact type mappings.
97       */
98      @Parameter
99      protected PlexusConfiguration artifactTypeMappings;
100 
101     /**
102      * The default bundle dir for libraries.
103      */
104     @Parameter
105     protected String defaultLibBundleDir;
106 
107     /**
108      * Should libraries be added in application.xml
109      */
110     @Parameter( defaultValue = "false" )
111     private Boolean includeLibInApplicationXml = Boolean.FALSE;
112 
113     /**
114      * The file name mapping to use for all dependencies included in the EAR file.
115      * The following values are valid {@code standard}, {code no-version}, {@code full}, {@code no-version-for-ejb}.
116      * The {@code standard} means the filename is the artifactId incl. the version of the artifact.
117      * The {@code no-version} means the files is only the artifactId without the version.
118      * The {@code full} means the filename is the groupId+artifactId+version of the artifact.
119      * The {@code no-version-for-ejb} means the filename is the artifactId without the version in case of {@code EJB}
120      * type.
121      */
122     @Parameter
123     private String fileNameMapping;
124 
125     /**
126      * When using a {@link #fileNameMapping} with versions, either use the {@code baseVersion} or the {@code version}.
127      * When the artifact is a SNAPSHOT, {@code version} will always return a value with a {@code -SNAPSHOT} postfix
128      * instead of the possible timestamped value.
129      * 
130      * @since 2.9
131      */
132     @Parameter
133     private Boolean useBaseVersion;
134 
135     /**
136      * Directory that resources are copied to during the build.
137      */
138     @Parameter( defaultValue = "${project.build.directory}/${project.build.finalName}", required = true )
139     private File workDirectory;
140 
141     /**
142      * The JBoss specific configuration.
143      * 
144      * @parameter
145      */
146     @Parameter
147     private PlexusConfiguration jboss;
148 
149     /**
150      * The id to use to define the main artifact (e.g. the artifact without a classifier) when there is multiple
151      * candidates.
152      * 
153      * @parameter
154      */
155     @Parameter
156     private String mainArtifactId = "none";
157 
158     /**
159      * temp folder location.
160      */
161     @Parameter( defaultValue = "${project.build.directory}", required = true )
162     private File tempFolder;
163 
164     @Component
165     private MavenResourcesFiltering mavenResourcesFiltering;
166     
167     private List<EarModule> earModules;
168 
169     private List<EarModule> allModules;
170 
171     private JbossConfiguration jbossConfiguration;
172 
173     /** {@inheritDoc} */
174     public void execute()
175         throws MojoExecutionException, MojoFailureException
176     {
177         final JavaEEVersion javaEEVersion = JavaEEVersion.getJavaEEVersion( version );
178         getLog().debug( "Resolving artifact type mappings ..." );
179         ArtifactTypeMappingService typeMappingService;
180         try
181         {
182             typeMappingService = new ArtifactTypeMappingService();
183             typeMappingService.configure( artifactTypeMappings );
184         }
185         catch ( EarPluginException e )
186         {
187             throw new MojoExecutionException( "Failed to initialize artifact type mappings", e );
188         }
189         catch ( PlexusConfigurationException e )
190         {
191             throw new MojoExecutionException( "Invalid artifact type mappings configuration", e );
192         }
193 
194         getLog().debug( "Initializing JBoss configuration if necessary ..." );
195         try
196         {
197             initializeJbossConfiguration();
198         }
199         catch ( EarPluginException e )
200         {
201             throw new MojoExecutionException( "Failed to initialize JBoss configuration", e );
202         }
203 
204         getLog().debug( "Initializing ear execution context" );
205         EarExecutionContext earExecutionContext =
206             new EarExecutionContext( project, mainArtifactId, defaultLibBundleDir, jbossConfiguration, fileNameMapping,
207                                      typeMappingService );
208 
209         if ( useBaseVersion != null )
210         {
211             earExecutionContext.getFileNameMapping().setUseBaseVersion( useBaseVersion );
212         }
213 
214         getLog().debug( "Resolving ear modules ..." );
215         allModules = new ArrayList<EarModule>();
216         try
217         {
218             if ( modules != null && modules.length > 0 )
219             {
220                 // Let's validate user-defined modules
221                 EarModule module;
222 
223                 for ( EarModule module1 : modules )
224                 {
225                     module = module1;
226                     getLog().debug( "Resolving ear module[" + module + "]" );
227                     module.setEarExecutionContext( earExecutionContext );
228                     module.resolveArtifact( project.getArtifacts() );
229                     allModules.add( module );
230                 }
231             }
232 
233             // Let's add other modules
234             Set<Artifact> artifacts = project.getArtifacts();
235             for ( Artifact artifact : artifacts )
236             {
237                 // If the artifact's type is POM, ignore and continue
238                 // since it's used for transitive deps only.
239                 if ( "pom".equals( artifact.getType() ) )
240                 {
241                     continue;
242                 }
243 
244                 // Artifact is not yet registered and it has neither test, nor a
245                 // provided scope, not is it optional
246                 ScopeArtifactFilter filter = new ScopeArtifactFilter( Artifact.SCOPE_RUNTIME );
247                 if ( !isArtifactRegistered( artifact, allModules ) && !artifact.isOptional()
248                     && filter.include( artifact ) )
249                 {
250                     EarModule module =
251                         EarModuleFactory.newEarModule( artifact, javaEEVersion, defaultLibBundleDir,
252                                                        includeLibInApplicationXml, typeMappingService );
253                     module.setEarExecutionContext( earExecutionContext );
254                     allModules.add( module );
255                 }
256             }
257         }
258         catch ( EarPluginException e )
259         {
260             throw new MojoExecutionException( "Failed to initialize ear modules", e );
261         }
262 
263         // Now we have everything let's built modules which have not been excluded
264         earModules = new ArrayList<EarModule>();
265         for ( EarModule earModule : allModules )
266         {
267             if ( earModule.isExcluded() )
268             {
269                 getLog().debug( "Skipping ear module[" + earModule + "]" );
270             }
271             else
272             {
273                 earModules.add( earModule );
274             }
275         }
276 
277     }
278 
279     /**
280      * @return The list of {@link #earModules}.
281      */
282     protected List<EarModule> getModules()
283     {
284         if ( earModules == null )
285         {
286             throw new IllegalStateException( "Ear modules have not been initialized" );
287         }
288         return earModules;
289     }
290 
291     /**
292      * @return {@link MavenProject}
293      */
294     protected MavenProject getProject()
295     {
296         return project;
297     }
298 
299     /**
300      * @return {@link #workDirectory}
301      */
302     protected File getWorkDirectory()
303     {
304         return workDirectory;
305     }
306 
307     /**
308      * @return {@link #jbossConfiguration}
309      */
310     protected JbossConfiguration getJbossConfiguration()
311     {
312         return jbossConfiguration;
313     }
314 
315     /**
316      * @return {@link #tempFolder}
317      */
318     public File getTempFolder()
319     {
320         return tempFolder;
321     }
322 
323     private static boolean isArtifactRegistered( Artifact a, List<EarModule> currentList )
324     {
325         for ( EarModule em : currentList )
326         {
327             if ( em.getArtifact().equals( a ) )
328             {
329                 return true;
330             }
331         }
332         return false;
333     }
334 
335     /**
336      * Initializes the JBoss configuration.
337      * 
338      * @throws EarPluginException if the configuration is invalid
339      */
340     private void initializeJbossConfiguration()
341         throws EarPluginException
342     {
343         if ( jboss == null )
344         {
345             jbossConfiguration = null;
346         }
347         else
348         {
349             try
350             {
351                 String childVersion = jboss.getChild( JbossConfiguration.VERSION ).getValue();
352                 if ( childVersion == null )
353                 {
354                     getLog().info( "JBoss version not set, using JBoss 4 by default" );
355                     childVersion = JbossConfiguration.VERSION_4;
356                 }
357                 final String securityDomain = jboss.getChild( JbossConfiguration.SECURITY_DOMAIN ).getValue();
358                 final String unauthenticatedPrincipal =
359                     jboss.getChild( JbossConfiguration.UNAUHTHENTICTED_PRINCIPAL ).getValue();
360 
361                 final PlexusConfiguration loaderRepositoryEl = jboss.getChild( JbossConfiguration.LOADER_REPOSITORY );
362                 final String loaderRepository = loaderRepositoryEl.getValue();
363                 final String loaderRepositoryClass =
364                     loaderRepositoryEl.getAttribute( JbossConfiguration.LOADER_REPOSITORY_CLASS_ATTRIBUTE );
365                 final PlexusConfiguration loaderRepositoryConfigEl =
366                     jboss.getChild( JbossConfiguration.LOADER_REPOSITORY_CONFIG );
367                 final String loaderRepositoryConfig = loaderRepositoryConfigEl.getValue();
368                 final String configParserClass =
369                     loaderRepositoryConfigEl.getAttribute( JbossConfiguration.CONFIG_PARSER_CLASS_ATTRIBUTE );
370 
371                 final String jmxName = jboss.getChild( JbossConfiguration.JMX_NAME ).getValue();
372                 final String moduleOrder = jboss.getChild( JbossConfiguration.MODULE_ORDER ).getValue();
373 
374                 final List<String> dataSources = new ArrayList<String>();
375                 final PlexusConfiguration dataSourcesEl = jboss.getChild( JbossConfiguration.DATASOURCES );
376                 if ( dataSourcesEl != null )
377                 {
378 
379                     final PlexusConfiguration[] dataSourcesConfig =
380                         dataSourcesEl.getChildren( JbossConfiguration.DATASOURCE );
381                     for ( PlexusConfiguration dataSourceConfig : dataSourcesConfig )
382                     {
383                         dataSources.add( dataSourceConfig.getValue() );
384 
385                     }
386                 }
387                 final String libraryDirectory = jboss.getChild( JbossConfiguration.LIBRARY_DIRECTORY ).getValue();
388                 jbossConfiguration =
389                     new JbossConfiguration( childVersion, securityDomain, unauthenticatedPrincipal, jmxName,
390                                             loaderRepository, moduleOrder, dataSources, libraryDirectory,
391                                             loaderRepositoryConfig, loaderRepositoryClass, configParserClass );
392             }
393             catch ( PlexusConfigurationException e )
394             {
395                 throw new EarPluginException( "Invalid JBoss configuration", e );
396             }
397         }
398     }
399 }