View Javadoc
1   package org.apache.maven.plugins.invoker;
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.Arrays;
25  import java.util.Properties;
26  
27  import org.apache.maven.shared.invoker.InvocationRequest;
28  import org.apache.maven.shared.invoker.InvocationRequest.ReactorFailureBehavior;
29  import org.codehaus.plexus.util.StringUtils;
30  
31  /**
32   * Provides a convenient facade around the <code>invoker.properties</code>.
33   *
34   * @author Benjamin Bentmann
35   * @version $Id: InvokerProperties.java 1779250 2017-01-17 20:20:02Z rfscholte $
36   */
37  class InvokerProperties
38  {
39      private static final String SELECTOR_PREFIX = "selector.";
40  
41      private enum InvocationProperty
42      {
43          PROJECT( "invoker.project" ),
44          GOALS( "invoker.goals" ),
45          PROFILES( "invoker.profiles" ),
46          MAVEN_OPTS( "invoker.mavenOpts" ),
47          FAILURE_BEHAVIOR( "invoker.failureBehavior" ),
48          NON_RECURSIVE( "invoker.nonRecursive" ),
49          OFFLINE( "invoker.offline" ),
50          SYSTEM_PROPERTIES_FILE( "invoker.systemPropertiesFile" ),
51          DEBUG( "invoker.debug" ),
52          SETTINGS_FILE ( "invoker.settingsFile" );
53  
54          private final String key;
55  
56          private InvocationProperty( final String s )
57          {
58              this.key = s;
59          }
60  
61          @Override
62          public String toString()
63          {
64              return key;
65          }
66      }
67      
68      private enum SelectorProperty
69      {
70          JAVA_VERSION( ".java.version" ),
71          MAVEN_VERSION( ".maven.version" ),
72          OS_FAMLY( ".os.family" );
73          
74          private final String suffix;
75          
76          private SelectorProperty( String suffix )
77          {
78              this.suffix = suffix;
79          }
80          
81          @Override
82          public String toString()
83          {
84              return suffix;
85          }
86      }
87  
88      /**
89       * The invoker properties being wrapped.
90       */
91      private final Properties properties;
92  
93      /**
94       * Creates a new facade for the specified invoker properties. The properties will not be copied, so any changes to
95       * them will be reflected by the facade.
96       *
97       * @param properties The invoker properties to wrap, may be <code>null</code> if none.
98       */
99      public InvokerProperties( Properties properties )
100     {
101         this.properties = ( properties != null ) ? properties : new Properties();
102     }
103 
104     /**
105      * Gets the invoker properties being wrapped.
106      *
107      * @return The invoker properties being wrapped, never <code>null</code>.
108      */
109     public Properties getProperties()
110     {
111         return this.properties;
112     }
113 
114     /**
115      * Gets the name of the corresponding build job.
116      *
117      * @return The name of the build job or an empty string if not set.
118      */
119     public String getJobName()
120     {
121         return this.properties.getProperty( "invoker.name", "" );
122     }
123 
124     /**
125      * Gets the description of the corresponding build job.
126      *
127      * @return The description of the build job or an empty string if not set.
128      */
129     public String getJobDescription()
130     {
131         return this.properties.getProperty( "invoker.description", "" );
132     }
133 
134     /**
135      * Gets the specification of JRE versions on which this build job should be run.
136      *
137      * @return The specification of JRE versions or an empty string if not set.
138      */
139     public String getJreVersion()
140     {
141         return this.properties.getProperty( "invoker.java.version", "" );
142     }
143 
144     /**
145      * Gets the specification of JRE versions on which this build job should be run.
146      *
147      * @return The specification of JRE versions or an empty string if not set.
148      */
149     public String getJreVersion( int index )
150     {
151         return this.properties.getProperty( SELECTOR_PREFIX + index + SelectorProperty.JAVA_VERSION.suffix,
152                                             getJreVersion() );
153     }
154 
155     /**
156      * Gets the specification of Maven versions on which this build job should be run.
157      *
158      * @return The specification of Maven versions on which this build job should be run.
159      * @since 1.5
160      */
161     public String getMavenVersion()
162     {
163         return this.properties.getProperty( "invoker.maven.version", "" );
164     }
165     
166     /**
167      * 
168      * @param index the selector index
169      * @return The specification of Maven versions on which this build job should be run.
170      * @since 3.0.0
171      */
172     public String getMavenVersion( int index )
173     {
174         return this.properties.getProperty( SELECTOR_PREFIX + index + SelectorProperty.MAVEN_VERSION.suffix,
175                                             getMavenVersion() );
176     }
177 
178     /**
179      * Gets the specification of OS families on which this build job should be run.
180      *
181      * @return The specification of OS families or an empty string if not set.
182      */
183     public String getOsFamily()
184     {
185         return this.properties.getProperty( "invoker.os.family", "" );
186     }
187     
188     /**
189      * Gets the specification of OS families on which this build job should be run.
190      *
191      * @param index the selector index
192      * @return The specification of OS families or an empty string if not set.
193      * @since 3.0.0
194      */
195     public String getOsFamily( int index )
196     {
197         return this.properties.getProperty( SELECTOR_PREFIX + index + SelectorProperty.OS_FAMLY.suffix,
198                                             getOsFamily() );
199     }   
200     
201 
202     /**
203      * Determines whether these invoker properties contain a build definition for the specified invocation index.
204      *
205      * @param index The one-based index of the invocation to check for, must not be negative.
206      * @return <code>true</code> if the invocation with the specified index is defined, <code>false</code> otherwise.
207      */
208     public boolean isInvocationDefined( int index )
209     {
210         for ( InvocationProperty prop : InvocationProperty.values() )
211         {
212             if ( properties.getProperty( prop.toString() + '.' + index ) != null )
213             {
214                 return true;
215             }
216         }
217         return false;
218     }
219     
220     /**
221      * Determines whether these invoker properties contain a build definition for the specified selector index.
222      * 
223      * @param index the index
224      * @return <code>true</code> if the selector with the specified index is defined, <code>false</code> otherwise.
225      * @since 3.0.0
226      */
227     public boolean isSelectorDefined( int index )
228     {
229         for ( SelectorProperty prop : SelectorProperty.values() )
230         {
231             if ( properties.getProperty( SELECTOR_PREFIX + index + prop.suffix ) != null )
232             {
233                 return true;
234             }
235         }
236         return false;
237     }
238 
239     /**
240      * Configures the specified invocation request from these invoker properties. Settings not present in the invoker
241      * properties will be left unchanged in the invocation request.
242      *
243      * @param request The invocation request to configure, must not be <code>null</code>.
244      * @param index The one-based index of the invocation to configure, must not be negative.
245      */
246     public void configureInvocation( InvocationRequest request, int index )
247     {
248         String project = get( InvocationProperty.PROJECT, index );
249         if ( project != null )
250         {
251             File file = new File( request.getBaseDirectory(), project );
252             if ( file.isFile() )
253             {
254                 request.setBaseDirectory( file.getParentFile() );
255                 request.setPomFile( file );
256             }
257             else
258             {
259                 request.setBaseDirectory( file );
260                 request.setPomFile( null );
261             }
262         }
263 
264         String goals = get( InvocationProperty.GOALS, index );
265         if ( goals != null )
266         {
267             request.setGoals( new ArrayList<String>( Arrays.asList( StringUtils.split( goals, ", \t\n\r\f" ) ) ) );
268         }
269 
270         String profiles = get( InvocationProperty.PROFILES, index );
271         if ( profiles != null )
272         {
273             // CHECKSTYLE_OFF: LineLength
274             request.setProfiles( new ArrayList<String>( Arrays.asList( StringUtils.split( profiles,
275                                                                                           ", \t\n\r\f" ) ) ) );
276             // CHECKSTYLE_ON: LineLength
277         }
278 
279         String mvnOpts = get( InvocationProperty.MAVEN_OPTS, index );
280         if ( mvnOpts != null )
281         {
282             request.setMavenOpts( mvnOpts );
283         }
284 
285         String failureBehavior = get( InvocationProperty.FAILURE_BEHAVIOR, index );
286         if ( failureBehavior != null )
287         {
288             ReactorFailureBehavior valueOf =
289                 InvocationRequest.ReactorFailureBehavior.valueOfByLongOption( failureBehavior );
290             request.setReactorFailureBehavior( valueOf );
291         }
292 
293         String nonRecursive = get( InvocationProperty.NON_RECURSIVE, index );
294         if ( nonRecursive != null )
295         {
296             request.setRecursive( !Boolean.valueOf( nonRecursive ) );
297         }
298 
299         String offline = get( InvocationProperty.OFFLINE, index );
300         if ( offline != null )
301         {
302             request.setOffline( Boolean.valueOf( offline ) );
303         }
304 
305         String debug = get( InvocationProperty.DEBUG, index );
306         if ( debug != null )
307         {
308             request.setDebug( Boolean.valueOf( debug ) );
309         }
310     }
311 
312     /**
313      * Checks whether the specified exit code matches the one expected for the given invocation.
314      *
315      * @param exitCode The exit code of the Maven invocation to check.
316      * @param index The index of the invocation for which to check the exit code, must not be negative.
317      * @return <code>true</code> if the exit code is zero and a success was expected or if the exit code is non-zero and
318      *         a failue was expected, <code>false</code> otherwise.
319      */
320     public boolean isExpectedResult( int exitCode, int index )
321     {
322         boolean nonZeroExit = "failure".equalsIgnoreCase( get( "invoker.buildResult", index ) );
323         return ( exitCode != 0 ) == nonZeroExit;
324     }
325 
326     /**
327      * Gets the path to the properties file used to set the system properties for the specified invocation.
328      *
329      * @param index The index of the invocation, must not be negative.
330      * @return The path to the properties file or <code>null</code> if not set.
331      */
332     public String getSystemPropertiesFile( int index )
333     {
334         return get( InvocationProperty.SYSTEM_PROPERTIES_FILE, index );
335     }
336 
337     /**
338      * Gets the settings file used for the specified invocation.
339      * 
340      * @param index The index of the invocation, must not be negative.
341      * @return the value for the settings file or <code>null</code> if not set.
342      */
343     public String getSettingsFile( int index )
344     {
345         return get( InvocationProperty.SETTINGS_FILE, index );
346     }
347 
348     /**
349      * Gets a value from the invoker properties. The invoker properties are intended to describe the invocation settings
350      * for multiple builds of the same project. For this reason, the properties are indexed. First, a property named
351      * <code>key.index</code> will be queried. If this property does not exist, the value of the property named
352      * <code>key</code> will finally be returned.
353      *
354      * @param key The (base) key for the invoker property to lookup, must not be <code>null</code>.
355      * @param index The index of the invocation for which to retrieve the value, must not be negative.
356      * @return The value for the requested invoker property or <code>null</code> if not defined.
357      */
358     String get( String key, int index )
359     {
360         if ( index < 0 )
361         {
362             throw new IllegalArgumentException( "invalid invocation index: " + index );
363         }
364 
365         String value = properties.getProperty( key + '.' + index );
366         if ( value == null )
367         {
368             value = properties.getProperty( key );
369         }
370         return value;
371     }
372 
373     private String get( InvocationProperty prop, int index )
374     {
375         return get( prop.toString(), index );
376     }
377 }