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