View Javadoc

1   package org.apache.maven.plugin.assembly.interpolation;
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.execution.MavenSession;
23  import org.apache.maven.plugin.assembly.AssemblerConfigurationSource;
24  import org.apache.maven.plugin.assembly.model.Assembly;
25  import org.apache.maven.plugin.assembly.utils.AssemblyFileUtils;
26  import org.apache.maven.plugin.assembly.utils.InterpolationConstants;
27  import org.apache.maven.project.MavenProject;
28  import org.codehaus.plexus.interpolation.InterpolationException;
29  import org.codehaus.plexus.interpolation.InterpolationPostProcessor;
30  import org.codehaus.plexus.interpolation.Interpolator;
31  import org.codehaus.plexus.interpolation.PrefixAwareRecursionInterceptor;
32  import org.codehaus.plexus.interpolation.PrefixedObjectValueSource;
33  import org.codehaus.plexus.interpolation.PrefixedPropertiesValueSource;
34  import org.codehaus.plexus.interpolation.PropertiesBasedValueSource;
35  import org.codehaus.plexus.interpolation.RecursionInterceptor;
36  import org.codehaus.plexus.interpolation.StringSearchInterpolator;
37  import org.codehaus.plexus.interpolation.object.FieldBasedObjectInterpolator;
38  import org.codehaus.plexus.interpolation.object.ObjectInterpolationWarning;
39  import org.codehaus.plexus.logging.AbstractLogEnabled;
40  import org.codehaus.plexus.logging.Logger;
41  import org.codehaus.plexus.logging.console.ConsoleLogger;
42  import org.codehaus.plexus.util.cli.CommandLineUtils;
43  
44  import java.io.File;
45  import java.io.IOException;
46  import java.util.Collections;
47  import java.util.HashSet;
48  import java.util.Iterator;
49  import java.util.List;
50  import java.util.Properties;
51  import java.util.Set;
52  
53  /**
54   * @version $Id: AssemblyInterpolator.java 1074695 2011-02-25 20:44:36Z jdcasey $
55   */
56  public class AssemblyInterpolator
57      extends AbstractLogEnabled
58  {
59      private static final Set<String> INTERPOLATION_BLACKLIST;
60  
61      private static final Properties ENVIRONMENT_VARIABLES;
62  
63      static
64      {
65          final Set<String> blacklist = new HashSet<String>();
66  
67          blacklist.add( "outputFileNameMapping" );
68          blacklist.add( "outputDirectoryMapping" );
69          blacklist.add( "outputDirectory" );
70  
71          INTERPOLATION_BLACKLIST = blacklist;
72  
73          Properties environmentVariables;
74          try
75          {
76              environmentVariables = CommandLineUtils.getSystemEnvVars( false );
77          }
78          catch ( final IOException e )
79          {
80              environmentVariables = new Properties();
81          }
82  
83          ENVIRONMENT_VARIABLES = environmentVariables;
84      }
85  
86      public AssemblyInterpolator()
87          throws IOException
88      {
89      }
90  
91      public Assembly interpolate( final Assembly assembly, final MavenProject project,
92                                   final AssemblerConfigurationSource configSource )
93          throws AssemblyInterpolationException
94      {
95          @SuppressWarnings( "unchecked" )
96          final Set<String> blacklistFields =
97              new HashSet<String>( FieldBasedObjectInterpolator.DEFAULT_BLACKLISTED_FIELD_NAMES );
98          blacklistFields.addAll( INTERPOLATION_BLACKLIST );
99  
100         @SuppressWarnings( "unchecked" )
101         final Set<String> blacklistPkgs = FieldBasedObjectInterpolator.DEFAULT_BLACKLISTED_PACKAGE_PREFIXES;
102 
103         final FieldBasedObjectInterpolator objectInterpolator =
104             new FieldBasedObjectInterpolator( blacklistFields, blacklistPkgs );
105         final Interpolator interpolator = buildInterpolator( project, configSource );
106 
107         // TODO: Will this adequately detect cycles between prefixed property references and prefixed project
108         // references??
109         final RecursionInterceptor interceptor =
110             new PrefixAwareRecursionInterceptor( InterpolationConstants.PROJECT_PREFIXES, true );
111 
112         try
113         {
114             objectInterpolator.interpolate( assembly, interpolator, interceptor );
115         }
116         catch ( final InterpolationException e )
117         {
118             throw new AssemblyInterpolationException( "Failed to interpolate assembly with ID: " + assembly.getId()
119                             + ". Reason: " + e.getMessage(), e );
120         }
121         finally
122         {
123             interpolator.clearAnswers();
124         }
125 
126         if ( objectInterpolator.hasWarnings() && getLogger().isDebugEnabled() )
127         {
128             final StringBuffer sb = new StringBuffer();
129 
130             sb.append( "One or more minor errors occurred while interpolating the assembly with ID: "
131                             + assembly.getId() + ":\n" );
132 
133             @SuppressWarnings( "unchecked" )
134             final List<ObjectInterpolationWarning> warnings = objectInterpolator.getWarnings();
135             for ( final Iterator<ObjectInterpolationWarning> it = warnings.iterator(); it.hasNext(); )
136             {
137                 final ObjectInterpolationWarning warning = it.next();
138 
139                 sb.append( '\n' ).append( warning );
140             }
141 
142             sb.append( "\n\nThese values were SKIPPED, but the assembly process will continue.\n" );
143 
144             getLogger().debug( sb.toString() );
145         }
146 
147         return assembly;
148     }
149 
150     public static Interpolator buildInterpolator( final MavenProject project,
151                                                   final AssemblerConfigurationSource configSource )
152     {
153         final StringSearchInterpolator interpolator = new StringSearchInterpolator();
154         interpolator.setCacheAnswers( true );
155 
156         final MavenSession session = configSource.getMavenSession();
157 
158         if ( session != null )
159         {
160             Properties userProperties = null;
161             try
162             {
163                 userProperties = session.getExecutionProperties();
164             }
165             catch ( final NoSuchMethodError nsmer )
166             {
167                 // OK, so user is using Maven <= 2.0.8. No big deal.
168             }
169 
170             if ( userProperties != null )
171             {
172                 // 4
173                 interpolator.addValueSource( new PropertiesBasedValueSource( userProperties ) );
174             }
175         }
176 
177         interpolator.addValueSource( new PrefixedPropertiesValueSource(
178                                                                         InterpolationConstants.PROJECT_PROPERTIES_PREFIXES,
179                                                                         project.getProperties(), true ) );
180         interpolator.addValueSource( new PrefixedObjectValueSource( InterpolationConstants.PROJECT_PREFIXES, project,
181                                                                     true ) );
182 
183         final Properties settingsProperties = new Properties();
184         if ( configSource.getLocalRepository() != null )
185         {
186             settingsProperties.setProperty( "localRepository", configSource.getLocalRepository().getBasedir() );
187             settingsProperties.setProperty( "settings.localRepository", configSource.getLocalRepository().getBasedir() );
188         }
189         else if ( session != null && session.getSettings() != null )
190         {
191             settingsProperties.setProperty( "localRepository", session.getSettings().getLocalRepository() );
192             settingsProperties.setProperty( "settings.localRepository", configSource.getLocalRepository().getBasedir() );
193         }
194 
195         interpolator.addValueSource( new PropertiesBasedValueSource( settingsProperties ) );
196 
197         Properties commandLineProperties = System.getProperties();
198         if ( session != null )
199         {
200             commandLineProperties = new Properties();
201             if ( session.getExecutionProperties() != null )
202             {
203                 commandLineProperties.putAll( session.getExecutionProperties() );
204             }
205             
206             if ( session.getUserProperties() != null )
207             {
208                 commandLineProperties.putAll( session.getUserProperties() );
209             }
210         }
211 
212         // 7
213         interpolator.addValueSource( new PropertiesBasedValueSource( commandLineProperties ) );
214         interpolator.addValueSource( new PrefixedPropertiesValueSource( Collections.singletonList( "env." ),
215                                                                         ENVIRONMENT_VARIABLES, true ) );
216 
217         interpolator.addPostProcessor( new PathTranslatingPostProcessor( project.getBasedir() ) );
218         return interpolator;
219     }
220 
221     @Override
222     protected Logger getLogger()
223     {
224         Logger logger = super.getLogger();
225 
226         if ( logger == null )
227         {
228             logger = new ConsoleLogger( Logger.LEVEL_INFO, "interpolator-internal" );
229 
230             enableLogging( logger );
231         }
232 
233         return logger;
234     }
235 
236     private static final class PathTranslatingPostProcessor
237         implements InterpolationPostProcessor
238     {
239 
240         private final File basedir;
241 
242         public PathTranslatingPostProcessor( final File basedir )
243         {
244             this.basedir = basedir;
245         }
246 
247         public Object execute( final String expression, final Object value )
248         {
249             final String path = String.valueOf( value );
250             return AssemblyFileUtils.makePathRelativeTo( path, basedir );
251         }
252 
253     }
254 }