View Javadoc

1   package org.apache.maven.plugin.assembly.utils;
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 org.apache.maven.artifact.Artifact;
23  import org.apache.maven.execution.MavenSession;
24  import org.apache.maven.plugin.assembly.AssemblerConfigurationSource;
25  import org.apache.maven.plugin.assembly.format.AssemblyFormattingException;
26  import org.apache.maven.plugin.assembly.model.Assembly;
27  import org.apache.maven.project.MavenProject;
28  import org.codehaus.plexus.interpolation.InterpolationException;
29  import org.codehaus.plexus.interpolation.PrefixedObjectValueSource;
30  import org.codehaus.plexus.interpolation.PrefixedPropertiesValueSource;
31  import org.codehaus.plexus.interpolation.PropertiesBasedValueSource;
32  import org.codehaus.plexus.interpolation.StringSearchInterpolator;
33  import org.codehaus.plexus.util.StringUtils;
34  import org.codehaus.plexus.util.cli.CommandLineUtils;
35  
36  import java.io.IOException;
37  import java.util.ArrayList;
38  import java.util.Arrays;
39  import java.util.Collections;
40  import java.util.List;
41  import java.util.ListIterator;
42  import java.util.Properties;
43  
44  /**
45   * @version $Id: AssemblyFormatUtils.java 1074695 2011-02-25 20:44:36Z jdcasey $
46   */
47  public final class AssemblyFormatUtils
48  {
49  
50      private AssemblyFormatUtils()
51      {
52      }
53  
54      /**
55       * Get the full name of the distribution artifact
56       * 
57       * @param assembly
58       * @return the distribution name
59       */
60      public static String getDistributionName( final Assembly assembly, final AssemblerConfigurationSource configSource )
61      {
62          final String finalName = configSource.getFinalName();
63          final boolean appendAssemblyId = configSource.isAssemblyIdAppended();
64          final String classifier = configSource.getClassifier();
65  
66          String distributionName = finalName;
67          if ( appendAssemblyId )
68          {
69              if ( !StringUtils.isEmpty( assembly.getId() ) )
70              {
71                  distributionName = finalName + "-" + assembly.getId();
72              }
73          }
74          else if ( classifier != null )
75          {
76              distributionName = finalName + "-" + classifier;
77          }
78  
79          return distributionName;
80      }
81  
82      /**
83       * @deprecated Use
84       *             {@link AssemblyFormatUtils#getOutputDirectory(String, MavenProject, MavenProject, String, AssemblerConfigurationSource)}
85       *             instead.
86       */
87      @Deprecated
88      public static String getOutputDirectory( final String output, final MavenProject mainProject,
89                                               final MavenProject artifactProject, final String finalName )
90          throws AssemblyFormattingException
91      {
92          return getOutputDirectory( output, mainProject, null, artifactProject, finalName, null );
93      }
94  
95      public static String getOutputDirectory( final String output, final MavenProject mainProject,
96                                               final MavenProject artifactProject, final String finalName,
97                                               final AssemblerConfigurationSource configSource )
98          throws AssemblyFormattingException
99      {
100         return getOutputDirectory( output, mainProject, null, artifactProject, finalName, configSource );
101     }
102 
103     /**
104      * ORDER OF INTERPOLATION PRECEDENCE:
105      * <ol>
106      * <li>Support for special expressions, like ${finalName} (use the assembly plugin configuration not the build
107      * config)</li>
108      * <li>prefixed with "module." if moduleProject is non-null
109      * <ol>
110      * <li>MavenProject instance for module being assembled</li>
111      * </ol>
112      * </li>
113      * <li>prefixed with "artifact." if artifactProject is non-null
114      * <ol>
115      * <li>MavenProject instance for artifact</li>
116      * </ol>
117      * </li>
118      * <li>user-defined properties from the command line</li>
119      * <li>prefixed with "pom." or "project.", or no prefix at all
120      * <ol>
121      * <li>MavenProject instance from current build</li>
122      * </ol>
123      * </li>
124      * <li>properties from main project</li>
125      * <li>system properties, from the MavenSession instance (to support IDEs)</li>
126      * <li>environment variables.</li>
127      * </ol>
128      */
129     public static String getOutputDirectory( final String output, final MavenProject mainProject,
130                                              final MavenProject moduleProject, final MavenProject artifactProject,
131                                              final String finalName, final AssemblerConfigurationSource configSource )
132         throws AssemblyFormattingException
133     {
134         String value = output;
135         if ( value == null )
136         {
137             value = "";
138         }
139 
140         final StringSearchInterpolator interpolator = new StringSearchInterpolator();
141 
142         final Properties specialExpressionOverrides = new Properties();
143 
144         if ( finalName != null )
145         {
146             specialExpressionOverrides.setProperty( "finalName", finalName );
147             specialExpressionOverrides.setProperty( "build.finalName", finalName );
148         }
149 
150         // 1
151         interpolator.addValueSource( new PropertiesBasedValueSource( specialExpressionOverrides ) );
152 
153         if ( moduleProject != null )
154         {
155             // 2
156             interpolator.addValueSource( new PrefixedObjectValueSource( "module.", moduleProject ) );
157             interpolator.addValueSource( new PrefixedPropertiesValueSource( "module.properties.",
158                                                                             moduleProject.getProperties() ) );
159             if ( moduleProject.getArtifact() != null )
160             {
161                 interpolator.addValueSource( new PrefixedObjectValueSource( "module.", moduleProject.getArtifact() ) );
162             }
163         }
164 
165         if ( artifactProject != null )
166         {
167             // 3
168             interpolator.addValueSource( new PrefixedObjectValueSource( "artifact.", artifactProject ) );
169             interpolator.addValueSource( new PrefixedPropertiesValueSource( "artifact.properties.",
170                                                                             artifactProject.getProperties() ) );
171             if ( artifactProject.getArtifact() != null )
172             {
173                 interpolator.addValueSource( new PrefixedObjectValueSource( "artifact.", artifactProject.getArtifact() ) );
174             }
175         }
176 
177         MavenSession session = null;
178 
179         if ( configSource != null )
180         {
181             session = configSource.getMavenSession();
182 
183             if ( session != null )
184             {
185                 Properties userProperties = null;
186                 try
187                 {
188                     userProperties = session.getExecutionProperties();
189                 }
190                 catch ( final NoSuchMethodError nsmer )
191                 {
192                     // OK, so user is using Maven <= 2.0.8. No big deal.
193                 }
194 
195                 if ( userProperties != null )
196                 {
197                     // 4
198                     interpolator.addValueSource( new PropertiesBasedValueSource( userProperties ) );
199                 }
200             }
201         }
202 
203         if ( mainProject != null )
204         {
205             // 5
206             interpolator.addValueSource( new PrefixedObjectValueSource( InterpolationConstants.PROJECT_PREFIXES,
207                                                                         mainProject, true ) );
208 
209             // 6
210             interpolator.addValueSource( new PrefixedPropertiesValueSource(
211                                                                             InterpolationConstants.PROJECT_PROPERTIES_PREFIXES,
212                                                                             mainProject.getProperties(), true ) );
213         }
214 
215         Properties commandLineProperties = System.getProperties();
216         if ( session != null )
217         {
218             commandLineProperties = new Properties();
219             if ( session.getExecutionProperties() != null )
220             {
221                 commandLineProperties.putAll( session.getExecutionProperties() );
222             }
223 
224             if ( session.getUserProperties() != null )
225             {
226                 commandLineProperties.putAll( session.getUserProperties() );
227             }
228         }
229 
230         // 7
231         interpolator.addValueSource( new PropertiesBasedValueSource( commandLineProperties ) );
232 
233         try
234         {
235             // 8
236             interpolator.addValueSource( new PrefixedPropertiesValueSource( Collections.singletonList( "env." ),
237                                                                             CommandLineUtils.getSystemEnvVars( false ),
238                                                                             true ) );
239         }
240         catch ( final IOException e )
241         {
242             throw new AssemblyFormattingException( "Failed to retrieve OS environment variables. Reason: "
243                             + e.getMessage(), e );
244         }
245 
246         try
247         {
248             value = interpolator.interpolate( value );
249         }
250         catch ( final InterpolationException e )
251         {
252             throw new AssemblyFormattingException( "Failed to interpolate output directory. Reason: " + e.getMessage(),
253                                                    e );
254         }
255 
256         if ( ( value.length() > 0 ) && !value.endsWith( "/" ) && !value.endsWith( "\\" ) )
257         {
258             value += "/";
259         }
260 
261         if ( ( value.length() > 0 ) && ( value.startsWith( "/" ) || value.startsWith( "\\" ) ) )
262         {
263             value = value.substring( 1 );
264         }
265 
266         value = StringUtils.replace( value, "//", "/" );
267         value = StringUtils.replace( value, "\\\\", "\\" );
268         value = fixRelativeRefs( value );
269 
270         return value;
271     }
272 
273     /**
274      * @deprecated Use
275      *             {@link AssemblyFormatUtils#evaluateFileNameMapping(String, Artifact, MavenProject, MavenProject, AssemblerConfigurationSource)}
276      *             instead.
277      */
278     @Deprecated
279     public static String evaluateFileNameMapping( final String expression, final Artifact artifact,
280                                                   final MavenProject mainProject, final MavenProject artifactProject )
281         throws AssemblyFormattingException
282     {
283         return evaluateFileNameMapping( expression, artifact, mainProject, null, null, artifactProject, null );
284     }
285 
286     public static String evaluateFileNameMapping( final String expression, final Artifact artifact,
287                                                   final MavenProject mainProject, final MavenProject artifactProject,
288                                                   final AssemblerConfigurationSource configSource )
289         throws AssemblyFormattingException
290     {
291         return evaluateFileNameMapping( expression, artifact, mainProject, null, null, artifactProject, configSource );
292     }
293 
294     /**
295      * ORDER OF INTERPOLATION PRECEDENCE:
296      * <ol>
297      * <li>prefixed with "module.", if moduleProject != null
298      * <ol>
299      * <li>Artifact instance for module, if moduleArtifact != null</li>
300      * <li>ArtifactHandler instance for module, if moduleArtifact != null</li>
301      * <li>MavenProject instance for module</li>
302      * </ol>
303      * </li>
304      * <li>prefixed with "artifact."
305      * <ol>
306      * <li>Artifact instance</li>
307      * <li>ArtifactHandler instance for artifact</li>
308      * <li>MavenProject instance for artifact</li>
309      * </ol>
310      * </li>
311      * <li>prefixed with "pom." or "project."
312      * <ol>
313      * <li>MavenProject instance from current build</li>
314      * </ol>
315      * </li>
316      * <li>no prefix, using main project instance
317      * <ol>
318      * <li>MavenProject instance from current build</li>
319      * </ol>
320      * </li>
321      * <li>Support for special expressions, like ${dashClassifier?}</li>
322      * <li>user-defined properties from the command line</li>
323      * <li>properties from main project</li>
324      * <li>system properties, from the MavenSession instance (to support IDEs)</li>
325      * <li>environment variables.</li>
326      * </ol>
327      */
328     public static String evaluateFileNameMapping( final String expression, final Artifact artifact,
329                                                   final MavenProject mainProject, final MavenProject moduleProject,
330                                                   final Artifact moduleArtifact, final MavenProject artifactProject,
331                                                   final AssemblerConfigurationSource configSource )
332         throws AssemblyFormattingException
333     {
334         String value = expression;
335 
336         // TODO: This is BAD! Accessors SHOULD NOT change the behavior of the object.
337         // [jdcasey; 16-Aug-1007] This is fixed in SVN, just waiting for it to pass out of legacy.
338         artifact.isSnapshot();
339 
340         final StringSearchInterpolator interpolator = new StringSearchInterpolator();
341 
342         if ( moduleArtifact != null )
343         {
344             // 1A
345             interpolator.addValueSource( new PrefixedObjectValueSource( "module.", moduleArtifact ) );
346 
347             // 1B
348             interpolator.addValueSource( new PrefixedObjectValueSource( "module.", moduleArtifact.getArtifactHandler() ) );
349             interpolator.addValueSource( new PrefixedObjectValueSource( "module.handler.",
350                                                                         moduleArtifact.getArtifactHandler() ) );
351         }
352 
353         // 1C
354         if ( moduleProject != null )
355         {
356             interpolator.addValueSource( new PrefixedObjectValueSource( "module.", moduleProject ) );
357             interpolator.addValueSource( new PrefixedPropertiesValueSource( "module.properties.",
358                                                                             moduleProject.getProperties() ) );
359             if ( moduleProject.getArtifact() != null )
360             {
361                 interpolator.addValueSource( new PrefixedObjectValueSource( "module.", moduleProject.getArtifact() ) );
362             }
363         }
364 
365         // 2A
366         interpolator.addValueSource( new PrefixedObjectValueSource( "artifact.", artifact ) );
367 
368         // 2B
369         interpolator.addValueSource( new PrefixedObjectValueSource( "artifact.", artifact.getArtifactHandler() ) );
370         interpolator.addValueSource( new PrefixedObjectValueSource( "artifact.handler.", artifact.getArtifactHandler() ) );
371 
372         // 2C
373         if ( artifactProject != null )
374         {
375             interpolator.addValueSource( new PrefixedObjectValueSource( "artifact.", artifactProject ) );
376             interpolator.addValueSource( new PrefixedPropertiesValueSource( "artifact.properties.",
377                                                                             artifactProject.getProperties() ) );
378             if ( artifactProject.getArtifact() != null )
379             {
380                 interpolator.addValueSource( new PrefixedObjectValueSource( "artifact.", artifactProject.getArtifact() ) );
381             }
382         }
383 
384         if ( mainProject != null )
385         {
386             // 3
387             // 4
388             interpolator.addValueSource( new PrefixedObjectValueSource( InterpolationConstants.PROJECT_PREFIXES,
389                                                                         mainProject, true ) );
390         }
391 
392         final Properties specialRules = new Properties();
393 
394         final String classifier = artifact.getClassifier();
395         if ( classifier != null )
396         {
397             specialRules.setProperty( "dashClassifier?", "-" + classifier );
398             specialRules.setProperty( "dashClassifier", "-" + classifier );
399         }
400         else
401         {
402             specialRules.setProperty( "dashClassifier?", "" );
403             specialRules.setProperty( "dashClassifier", "" );
404         }
405 
406         // 5
407         interpolator.addValueSource( new PropertiesBasedValueSource( specialRules ) );
408 
409         MavenSession session = null;
410         if ( configSource != null )
411         {
412             session = configSource.getMavenSession();
413 
414             if ( session != null )
415             {
416                 Properties userProperties = null;
417                 try
418                 {
419                     userProperties = session.getExecutionProperties();
420                 }
421                 catch ( final NoSuchMethodError nsmer )
422                 {
423                     // OK, so user is using Maven <= 2.0.8. No big deal.
424                 }
425 
426                 if ( userProperties != null )
427                 {
428                     // 6
429                     interpolator.addValueSource( new PropertiesBasedValueSource( userProperties ) );
430                 }
431             }
432         }
433 
434         if ( mainProject != null )
435         {
436             // 7
437             interpolator.addValueSource( new PrefixedPropertiesValueSource(
438                                                                             InterpolationConstants.PROJECT_PROPERTIES_PREFIXES,
439                                                                             mainProject.getProperties(), true ) );
440         }
441 
442         Properties commandLineProperties = System.getProperties();
443         if ( session != null )
444         {
445             commandLineProperties = new Properties();
446             if ( session.getExecutionProperties() != null )
447             {
448                 commandLineProperties.putAll( session.getExecutionProperties() );
449             }
450 
451             if ( session.getUserProperties() != null )
452             {
453                 commandLineProperties.putAll( session.getUserProperties() );
454             }
455         }
456 
457         // 8
458         interpolator.addValueSource( new PropertiesBasedValueSource( commandLineProperties ) );
459 
460         try
461         {
462             // 9
463             interpolator.addValueSource( new PrefixedPropertiesValueSource( Collections.singletonList( "env." ),
464                                                                             CommandLineUtils.getSystemEnvVars( false ),
465                                                                             true ) );
466         }
467         catch ( final IOException e )
468         {
469             throw new AssemblyFormattingException( "Failed to retrieve OS environment variables. Reason: "
470                             + e.getMessage(), e );
471         }
472 
473         try
474         {
475             value = interpolator.interpolate( value );
476         }
477         catch ( final InterpolationException e )
478         {
479             throw new AssemblyFormattingException( "Failed to interpolate output filename mapping. Reason: "
480                             + e.getMessage(), e );
481         }
482 
483         value = StringUtils.replace( value, "//", "/" );
484         value = StringUtils.replace( value, "\\\\", "\\" );
485         value = fixRelativeRefs( value );
486 
487         return value;
488     }
489 
490     public static String fixRelativeRefs( String src )
491     {
492         String value = src;
493         
494         String[] separators = {
495             "/", "\\"
496         };
497         
498         String finalSep = null;
499         for ( String sep : separators )
500         {
501             if ( value.endsWith( sep ) )
502             {
503                 finalSep = sep;
504             }
505             
506             if ( value.indexOf( "." + sep ) > -1 )
507             {
508                 List<String> parts = new ArrayList<String>();
509                 parts.addAll( Arrays.asList( value.split( sep ) ) );
510                 
511                 for ( ListIterator<String> it = parts.listIterator(); it.hasNext(); )
512                 {
513                     String part = it.next();
514                     if ( ".".equals( part ) )
515                     {
516                         it.remove();
517                     }
518                     else if ( "..".equals( part ) )
519                     {
520                         it.remove();
521                         if ( it.hasPrevious() )
522                         {
523                             it.previous();
524                             it.remove();
525                         }
526                     }
527                 }
528                 
529                 value = StringUtils.join( parts.iterator(), sep );
530             }
531         }
532         
533         if ( finalSep != null && value.length() > 0 && !value.endsWith( finalSep ) )
534         {
535             value += finalSep;
536         }
537         
538         return value;
539     }
540 }