1 package org.apache.maven.plugin.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.codehaus.plexus.util.StringUtils;
29
30 /**
31 * Provides a convenient facade around the <code>invoker.properties</code>.
32 *
33 * @author Benjamin Bentmann
34 * @version $Id: InvokerProperties.java 1671476 2015-04-06 03:53:29Z dantran $
35 */
36 class InvokerProperties
37 {
38
39 private enum InvocationProperty
40 {
41 PROJECT( "invoker.project" ),
42 GOALS( "invoker.goals" ),
43 PROFILES( "invoker.profiles" ),
44 MAVEN_OPTS( "invoker.mavenOpts" ),
45 FAILURE_BEHAVIOR( "invoker.failureBehavior" ),
46 NON_RECURSIVE( "invoker.nonRecursive" ),
47 OFFLINE( "invoker.offline" ),
48 SYSTEM_PROPERTIES_FILE( "invoker.systemPropertiesFile" ),
49 DEBUG( "invoker.debug" );
50
51 private final String key;
52
53 private InvocationProperty( final String s )
54 {
55 this.key = s;
56 }
57
58 @Override
59 public String toString()
60 {
61 return key;
62 }
63 }
64
65 /**
66 * The invoker properties being wrapped.
67 */
68 private final Properties properties;
69
70 /**
71 * Creates a new facade for the specified invoker properties. The properties will not be copied, so any changes to
72 * them will be reflected by the facade.
73 *
74 * @param properties The invoker properties to wrap, may be <code>null</code> if none.
75 */
76 public InvokerProperties( Properties properties )
77 {
78 this.properties = ( properties != null ) ? properties : new Properties();
79 }
80
81 /**
82 * Gets the invoker properties being wrapped.
83 *
84 * @return The invoker properties being wrapped, never <code>null</code>.
85 */
86 public Properties getProperties()
87 {
88 return this.properties;
89 }
90
91 /**
92 * Gets the name of the corresponding build job.
93 *
94 * @return The name of the build job or an empty string if not set.
95 */
96 public String getJobName()
97 {
98 return this.properties.getProperty( "invoker.name", "" );
99 }
100
101 /**
102 * Gets the description of the corresponding build job.
103 *
104 * @return The description of the build job or an empty string if not set.
105 */
106 public String getJobDescription()
107 {
108 return this.properties.getProperty( "invoker.description", "" );
109 }
110
111 /**
112 * Gets the specification of JRE versions on which this build job should be run.
113 *
114 * @return The specification of JRE versions or an empty string if not set.
115 */
116 public String getJreVersion()
117 {
118 return this.properties.getProperty( "invoker.java.version", "" );
119 }
120
121 /**
122 * Gets the specification of Maven versions on which this build job should be run.
123 *
124 * @return The specification of Maven versions on which this build job should be run.
125 * @since 1.5
126 */
127 public String getMavenVersion()
128 {
129 return this.properties.getProperty( "invoker.maven.version", "" );
130 }
131
132 /**
133 * Gets the specification of OS families on which this build job should be run.
134 *
135 * @return The specification of OS families or an empty string if not set.
136 */
137 public String getOsFamily()
138 {
139 return this.properties.getProperty( "invoker.os.family", "" );
140 }
141
142 /**
143 * Determines whether these invoker properties contain a build definition for the specified invocation index.
144 *
145 * @param index The one-based index of the invocation to check for, must not be negative.
146 * @return <code>true</code> if the invocation with the specified index is defined, <code>false</code> otherwise.
147 */
148 public boolean isInvocationDefined( int index )
149 {
150 for ( InvocationProperty prop : InvocationProperty.values() )
151 {
152 if ( properties.getProperty( prop.toString() + '.' + index ) != null )
153 {
154 return true;
155 }
156 }
157 return false;
158 }
159
160 /**
161 * Configures the specified invocation request from these invoker properties. Settings not present in the invoker
162 * properties will be left unchanged in the invocation request.
163 *
164 * @param request The invocation request to configure, must not be <code>null</code>.
165 * @param index The one-based index of the invocation to configure, must not be negative.
166 */
167 public void configureInvocation( InvocationRequest request, int index )
168 {
169 String project = get( InvocationProperty.PROJECT, index );
170 if ( project != null )
171 {
172 File file = new File( request.getBaseDirectory(), project );
173 if ( file.isFile() )
174 {
175 request.setBaseDirectory( file.getParentFile() );
176 request.setPomFile( file );
177 }
178 else
179 {
180 request.setBaseDirectory( file );
181 request.setPomFile( null );
182 }
183 }
184
185 String goals = get( InvocationProperty.GOALS, index );
186 if ( goals != null )
187 {
188 request.setGoals( new ArrayList<String>( Arrays.asList( StringUtils.split( goals, ", \t\n\r\f" ) ) ) );
189 }
190
191 String profiles = get( InvocationProperty.PROFILES, index );
192 if ( profiles != null )
193 {
194 // CHECKSTYLE_OFF: LineLength
195 request.setProfiles( new ArrayList<String>( Arrays.asList( StringUtils.split( profiles, ", \t\n\r\f" ) ) ) );
196 // CHECKSTYLE_ON: LineLength
197 }
198
199 String mvnOpts = get( InvocationProperty.MAVEN_OPTS, index );
200 if ( mvnOpts != null )
201 {
202 request.setMavenOpts( mvnOpts );
203 }
204
205 String failureBehavior = get( InvocationProperty.FAILURE_BEHAVIOR, index );
206 if ( failureBehavior != null )
207 {
208 request.setFailureBehavior( failureBehavior );
209 }
210
211 String nonRecursive = get( InvocationProperty.NON_RECURSIVE, index );
212 if ( nonRecursive != null )
213 {
214 request.setRecursive( !Boolean.valueOf( nonRecursive ) );
215 }
216
217 String offline = get( InvocationProperty.OFFLINE, index );
218 if ( offline != null )
219 {
220 request.setOffline( Boolean.valueOf( offline ) );
221 }
222
223 String debug = get( InvocationProperty.DEBUG, index );
224 if ( debug != null )
225 {
226 request.setDebug( Boolean.valueOf( debug ) );
227 }
228 }
229
230 /**
231 * Checks whether the specified exit code matches the one expected for the given invocation.
232 *
233 * @param exitCode The exit code of the Maven invocation to check.
234 * @param index The index of the invocation for which to check the exit code, must not be negative.
235 * @return <code>true</code> if the exit code is zero and a success was expected or if the exit code is non-zero and
236 * a failue was expected, <code>false</code> otherwise.
237 */
238 public boolean isExpectedResult( int exitCode, int index )
239 {
240 boolean nonZeroExit = "failure".equalsIgnoreCase( get( "invoker.buildResult", index ) );
241 return ( exitCode != 0 ) == nonZeroExit;
242 }
243
244 /**
245 * Gets the path to the properties file used to set the system properties for the specified invocation.
246 *
247 * @param index The index of the invocation for which to check the exit code, must not be negative.
248 * @return The path to the properties file or <code>null</code> if not set.
249 */
250 public String getSystemPropertiesFile( int index )
251 {
252 return get( InvocationProperty.SYSTEM_PROPERTIES_FILE, index );
253 }
254
255 /**
256 * Gets a value from the invoker properties. The invoker properties are intended to describe the invocation settings
257 * for multiple builds of the same project. For this reason, the properties are indexed. First, a property named
258 * <code>key.index</code> will be queried. If this property does not exist, the value of the property named
259 * <code>key</code> will finally be returned.
260 *
261 * @param key The (base) key for the invoker property to lookup, must not be <code>null</code>.
262 * @param index The index of the invocation for which to retrieve the value, must not be negative.
263 * @return The value for the requested invoker property or <code>null</code> if not defined.
264 */
265 String get( String key, int index )
266 {
267 if ( index < 0 )
268 {
269 throw new IllegalArgumentException( "invalid invocation index: " + index );
270 }
271
272 String value = properties.getProperty( key + '.' + index );
273 if ( value == null )
274 {
275 value = properties.getProperty( key );
276 }
277 return value;
278 }
279
280 private String get( InvocationProperty prop, int index )
281 {
282 return get( prop.toString(), index );
283 }
284 }