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.util.Set;
23  
24  import org.apache.maven.artifact.Artifact;
25  import org.apache.maven.plugin.MojoFailureException;
26  import org.apache.maven.plugin.ear.output.FileNameMappingFactory;
27  import org.apache.maven.plugin.ear.util.ArtifactRepository;
28  import org.codehaus.plexus.util.xml.XMLWriter;
29  
30  /**
31   * A base implementation of an {@link EarModule}.
32   * 
33   * @author <a href="snicoll@apache.org">Stephane Nicoll</a>
34   * @version $Id: AbstractEarModule.java 1645331 2014-12-13 17:31:09Z khmarbaise $
35   */
36  public abstract class AbstractEarModule
37      implements EarModule
38  {
39  
40      /**
41       * The module element.
42       */
43      protected static final String MODULE_ELEMENT = "module";
44  
45      /**
46       * The java module.
47       */
48      protected static final String JAVA_MODULE = "java";
49  
50      /**
51       * The alt-dd module.
52       */
53      protected static final String ALT_DD = "alt-dd";
54  
55      private Artifact artifact;
56  
57      // Those are set by the configuration
58  
59      private String groupId;
60  
61      private String artifactId;
62  
63      private String classifier;
64  
65      /**
66       * The bundleDir.
67       */
68      protected String bundleDir;
69  
70      /**
71       * The bundleFileName.
72       */
73      protected String bundleFileName;
74  
75      /**
76       * excluded by default {@code false}.
77       */
78      protected Boolean excluded = Boolean.FALSE;
79  
80      private String uri;
81  
82      /**
83       * unpack
84       */
85      protected Boolean unpack = null;
86  
87      /**
88       * The alternate deployment descriptor.
89       */
90      protected String altDeploymentDescriptor;
91  
92      private String moduleId;
93  
94      // This is injected once the module has been built.
95  
96      /**
97       * The {@link EarExecutionContext}
98       */
99      protected EarExecutionContext earExecutionContext;
100 
101     /**
102      * Empty constructor to be used when the module is built based on the configuration.
103      */
104     public AbstractEarModule()
105     {
106     }
107 
108     /**
109      * Creates an ear module from the artifact.
110      * 
111      * @param a the artifact
112      */
113     public AbstractEarModule( Artifact a )
114     {
115         this.artifact = a;
116         this.groupId = a.getGroupId();
117         this.artifactId = a.getArtifactId();
118         this.classifier = a.getClassifier();
119         this.bundleDir = null;
120     }
121 
122     /**
123      * {@inheritDoc}
124      */
125     public void setEarExecutionContext( EarExecutionContext earExecutionContext )
126     {
127         this.earExecutionContext = earExecutionContext;
128     }
129 
130     /** {@inheritDoc} */
131     public void resolveArtifact( Set<Artifact> artifacts )
132         throws EarPluginException, MojoFailureException
133     {
134         // If the artifact is already set no need to resolve it
135         if ( artifact == null )
136         {
137             // Make sure that at least the groupId and the artifactId are specified
138             if ( groupId == null || artifactId == null )
139             {
140                 throw new MojoFailureException( "Could not resolve artifact[" + groupId + ":" + artifactId + ":"
141                     + getType() + "]" );
142             }
143             final ArtifactRepository ar = earExecutionContext.getArtifactRepository();
144             artifact = ar.getUniqueArtifact( groupId, artifactId, getType(), classifier );
145             // Artifact has not been found
146             if ( artifact == null )
147             {
148                 Set<Artifact> candidates = ar.getArtifacts( groupId, artifactId, getType() );
149                 if ( candidates.size() > 1 )
150                 {
151                     throw new MojoFailureException( "Artifact[" + this + "] has " + candidates.size()
152                         + " candidates, please provide a classifier." );
153                 }
154                 else
155                 {
156                     throw new MojoFailureException( "Artifact[" + this + "] is not a dependency of the project." );
157                 }
158             }
159         }
160     }
161 
162     /**
163      * @return {@link #artifact}
164      */
165     public Artifact getArtifact()
166     {
167         return artifact;
168     }
169 
170     /**
171      * @return {@link #moduleId}
172      */
173     public String getModuleId()
174     {
175         return moduleId;
176     }
177 
178     /**
179      * @return Return the URI.
180      */
181     public String getUri()
182     {
183         if ( uri == null )
184         {
185             if ( getBundleDir() == null )
186             {
187                 uri = getBundleFileName();
188             }
189             else
190             {
191                 uri = getBundleDir() + getBundleFileName();
192             }
193         }
194         return uri;
195     }
196 
197     /**
198      * Returns the artifact's groupId.
199      * 
200      * @return {@link #groupId}
201      */
202     public String getGroupId()
203     {
204         return groupId;
205     }
206 
207     /**
208      * Returns the artifact's Id.
209      * 
210      * @return {@link #artifactId}
211      */
212     public String getArtifactId()
213     {
214         return artifactId;
215     }
216 
217     /**
218      * Returns the artifact's classifier.
219      * 
220      * @return the artifact classifier
221      */
222     public String getClassifier()
223     {
224         return classifier;
225     }
226 
227     /**
228      * Returns the bundle directory. If null, the module is bundled in the root of the EAR.
229      * 
230      * @return the custom bundle directory
231      */
232     public String getBundleDir()
233     {
234         if ( bundleDir != null )
235         {
236             bundleDir = cleanBundleDir( bundleDir );
237         }
238         return bundleDir;
239     }
240 
241     /**
242      * Returns the bundle file name. If null, the artifact's file name is returned.
243      * 
244      * @return the bundle file name
245      */
246     public String getBundleFileName()
247     {
248         if ( bundleFileName == null )
249         {
250             bundleFileName = earExecutionContext.getFileNameMapping().mapFileName( artifact );
251         }
252         return bundleFileName;
253     }
254 
255     /**
256      * Based on MEAR-189 we need to get back
257      * the original file name under any circumstances.
258      * 
259      * @return The original file name.
260      */
261     public String getOriginalBundleFileName()
262     {
263         return FileNameMappingFactory.getDefaultFileNameMapping().mapFileName( artifact );
264     }
265 
266     /**
267      * The alt-dd element specifies an optional URI to the post-assembly version of the deployment descriptor file for a
268      * particular Java EE module. The URI must specify the full pathname of the deployment descriptor file relative to
269      * the application's root directory.
270      * 
271      * @return the alternative deployment descriptor for this module
272      */
273     public String getAltDeploymentDescriptor()
274     {
275         return altDeploymentDescriptor;
276     }
277 
278     /**
279      * Specify whether this module should be excluded or not.
280      * 
281      * @return true if this module should be skipped, false otherwise
282      */
283     public boolean isExcluded()
284     {
285         return excluded;
286     }
287 
288     /**
289      * @return {@link #unpack}
290      */
291     public Boolean shouldUnpack()
292     {
293         return unpack;
294     }
295 
296     /**
297      * Writes the alternative deployment descriptor if necessary.
298      * 
299      * @param writer the writer to use
300      * @param version the java EE version in use
301      */
302     protected void writeAltDeploymentDescriptor( XMLWriter writer, String version )
303     {
304         if ( getAltDeploymentDescriptor() != null )
305         {
306             writer.startElement( ALT_DD );
307             writer.writeText( getAltDeploymentDescriptor() );
308             writer.endElement();
309         }
310     }
311 
312     /**
313      * Starts a new {@link #MODULE_ELEMENT} on the specified writer, possibly including an id attribute.
314      * 
315      * @param writer the XML writer.
316      * @param generateId whether an id should be generated
317      */
318     protected void startModuleElement( XMLWriter writer, Boolean generateId )
319     {
320         writer.startElement( MODULE_ELEMENT );
321 
322         // If a moduleId is specified, always include it
323         if ( getModuleId() != null )
324         {
325             writer.addAttribute( "id", getModuleId() );
326         }
327         else if ( generateId )
328         {
329             // No module id was specified but one should be generated.
330             Artifact theArtifact = getArtifact();
331             String generatedId =
332                 theArtifact.getType().toUpperCase() + "_" + theArtifact.getGroupId() + "."
333                     + theArtifact.getArtifactId();
334             if ( null != theArtifact.getClassifier() && theArtifact.getClassifier().trim().length() > 0 )
335             {
336                 generatedId += "-" + theArtifact.getClassifier().trim();
337             }
338             writer.addAttribute( "id", generatedId );
339         }
340     }
341 
342     /**
343      * {@inheritDoc}
344      */
345     public String toString()
346     {
347         StringBuilder sb = new StringBuilder();
348         sb.append( getType() ).append( ":" ).append( groupId ).append( ":" ).append( artifactId );
349         if ( classifier != null )
350         {
351             sb.append( ":" ).append( classifier );
352         }
353         if ( artifact != null )
354         {
355             sb.append( ":" ).append( artifact.getVersion() );
356         }
357         return sb.toString();
358     }
359 
360     /**
361      * Cleans the bundle directory so that it might be used properly.
362      * 
363      * @param bundleDir the bundle directory to clean
364      * @return the cleaned bundle directory
365      */
366     static String cleanBundleDir( String bundleDir )
367     {
368         if ( bundleDir == null )
369         {
370             return null;
371         }
372 
373         // Using slashes
374         bundleDir = bundleDir.replace( '\\', '/' );
375 
376         // Remove '/' prefix if any so that directory is a relative path
377         if ( bundleDir.startsWith( "/" ) )
378         {
379             bundleDir = bundleDir.substring( 1, bundleDir.length() );
380         }
381 
382         if ( bundleDir.length() > 0 && !bundleDir.endsWith( "/" ) )
383         {
384             // Adding '/' suffix to specify a directory structure if it is not empty
385             bundleDir = bundleDir + "/";
386         }
387 
388         return bundleDir;
389     }
390 
391     /**
392      * Specify if the objects are both null or both equal.
393      * 
394      * @param first the first object
395      * @param second the second object
396      * @return true if parameters are either both null or equal
397      */
398     static boolean areNullOrEqual( Object first, Object second )
399     {
400         if ( first != null )
401         {
402             return first.equals( second );
403         }
404         else
405         {
406             return second == null;
407         }
408     }
409 
410     /**
411      * Sets the URI of the module explicitly for testing purposes.
412      * 
413      * @param uri the uri
414      */
415     void setUri( String uri )
416     {
417         this.uri = uri;
418 
419     }
420 
421     /**
422      * @return always {@code true}
423      */
424     public boolean changeManifestClasspath()
425     {
426         return true;
427     }
428 
429     /**
430      * @return always {@code null}
431      */
432     public String getLibDir()
433     {
434         return null;
435     }
436 }