1 package org.apache.maven.plugin.testing;
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19 import org.apache.maven.monitor.logging.DefaultLog;
20 import org.apache.maven.plugin.Mojo;
21 import org.apache.maven.plugin.logging.Log;
22 import org.codehaus.plexus.PlexusTestCase;
23 import org.codehaus.plexus.component.configurator.ComponentConfigurator;
24 import org.codehaus.plexus.component.configurator.expression.ExpressionEvaluator;
25 import org.codehaus.plexus.configuration.PlexusConfiguration;
26 import org.codehaus.plexus.configuration.xml.XmlPlexusConfiguration;
27 import org.codehaus.plexus.util.ReflectionUtils;
28 import org.codehaus.plexus.util.xml.Xpp3Dom;
29 import org.codehaus.plexus.util.xml.Xpp3DomBuilder;
30
31 import java.io.File;
32 import java.io.FileReader;
33 import java.io.Reader;
34 import java.util.Map;
35 import java.util.HashMap;
36 import java.lang.reflect.Field;
37 import java.lang.reflect.AccessibleObject;
38
39
40
41
42
43
44
45
46
47 public abstract class AbstractMojoTestCase
48 extends PlexusTestCase
49 {
50 private ComponentConfigurator configurator;
51
52
53
54
55
56
57
58
59 protected void setUp()
60 throws Exception
61 {
62 super.setUp();
63
64 configurator = (ComponentConfigurator) getContainer().lookup( ComponentConfigurator.ROLE );
65
66
67 }
68
69 /**
70 * lookup the mojo leveraging the subproject pom
71 *
72 */
73 protected Mojo lookupMojo( String goal, String pluginPom ) throws Exception
74 {
75 return lookupMojo( goal, new File( pluginPom ) );
76 }
77
78 /**
79 * lookup an empty mojo
80 */
81 protected Mojo lookupEmptyMojo( String goal, String pluginPom ) throws Exception
82 {
83 return lookupEmptyMojo( goal, new File( pluginPom ) );
84 }
85
86
87 /**
88 * lookup the mojo leveraging the actual subprojects pom
89 *
90 * @param goal
91 * @param pom
92 * @return
93 * @throws Exception
94 */
95 protected Mojo lookupMojo( String goal, File pom )
96 throws Exception
97 {
98 File pluginPom = new File( getBasedir(), "pom.xml" );
99
100 Xpp3Dom pluginPomDom = Xpp3DomBuilder.build( new FileReader( pluginPom ) );
101
102 String artifactId = pluginPomDom.getChild( "artifactId" ).getValue();
103
104 String groupId = resolveFromRootThenParent( pluginPomDom, "groupId" );
105
106 String version = resolveFromRootThenParent( pluginPomDom, "version" );
107
108 PlexusConfiguration pluginConfiguration = extractPluginConfiguration( artifactId, pom );
109
110 return lookupMojo( groupId, artifactId, version, goal, pluginConfiguration );
111 }
112
113 /**
114 * lookup the mojo leveraging the actual subprojects pom
115 *
116 * @param goal
117 * @param pom
118 * @return
119 * @throws Exception
120 */
121 protected Mojo lookupEmptyMojo( String goal, File pom )
122 throws Exception
123 {
124 File pluginPom = new File( getBasedir(), "pom.xml" );
125
126 Xpp3Dom pluginPomDom = Xpp3DomBuilder.build( new FileReader( pluginPom ) );
127
128 String artifactId = pluginPomDom.getChild( "artifactId" ).getValue();
129
130 String groupId = resolveFromRootThenParent( pluginPomDom, "groupId" );
131
132 String version = resolveFromRootThenParent( pluginPomDom, "version" );
133
134 return lookupMojo( groupId, artifactId, version, goal, null );
135 }
136
137
138
139
140
141
142
143
144
145
146 /**
147 * lookup the mojo while we have all of the relavent information
148 *
149 * @param groupId
150 * @param artifactId
151 * @param version
152 * @param goal
153 * @param pluginConfiguration
154 * @return
155 * @throws Exception
156 */
157 protected Mojo lookupMojo( String groupId, String artifactId, String version, String goal, PlexusConfiguration pluginConfiguration )
158 throws Exception
159 {
160 validateContainerStatus();
161
162
163
164 Mojo mojo = (Mojo) lookup( Mojo.ROLE, groupId + ":" + artifactId + ":" + version + ":" + goal );
165
166 Log mojoLogger = new DefaultLog( container.getLoggerManager().getLoggerForComponent( Mojo.ROLE ) );
167
168 mojo.setLog( mojoLogger );
169
170 if ( pluginConfiguration != null )
171 {
172
173
174
175 ExpressionEvaluator evaluator = new ResolverExpressionEvaluatorStub();
176
177 configurator.configureComponent( mojo, pluginConfiguration, evaluator, getContainer().getContainerRealm() );
178 }
179
180 return mojo;
181 }
182
183
184 protected PlexusConfiguration extractPluginConfiguration( String artifactId, File pom )
185 throws Exception
186 {
187 Reader reader = new FileReader( pom );
188
189 Xpp3Dom pomDom = Xpp3DomBuilder.build( reader );
190
191 return extractPluginConfiguration( artifactId, pomDom );
192 }
193
194 protected PlexusConfiguration extractPluginConfiguration( String artifactId, Xpp3Dom pomDom )
195 throws Exception
196 {
197 Xpp3Dom pluginConfigurationElement = null;
198
199 Xpp3Dom buildElement = pomDom.getChild( "build" );
200 if ( buildElement != null )
201 {
202 Xpp3Dom pluginsRootElement = buildElement.getChild( "plugins" );
203
204 if ( pluginsRootElement != null )
205 {
206 Xpp3Dom[] pluginElements = pluginsRootElement.getChildren();
207
208 for ( int i = 0; i < pluginElements.length; i++ )
209 {
210 Xpp3Dom pluginElement = pluginElements[i];
211
212 String pluginElementArtifactId = pluginElement.getChild( "artifactId" ).getValue();
213
214 if ( pluginElementArtifactId.equals( artifactId ) )
215 {
216 pluginConfigurationElement = pluginElement.getChild( "configuration" );
217
218 break;
219 }
220 }
221 }
222 }
223
224 if ( pluginConfigurationElement == null )
225 {
226 throw new ConfigurationException( "Cannot find a configuration element for a plugin with an artifactId of "
227 + artifactId + "." );
228 }
229
230 return new XmlPlexusConfiguration( pluginConfigurationElement );
231 }
232
233 protected Mojo configureMojo( Mojo mojo, String artifactId, File pom )
234 throws Exception
235 {
236 validateContainerStatus();
237
238 PlexusConfiguration pluginConfiguration = extractPluginConfiguration( artifactId, pom );
239
240 ExpressionEvaluator evaluator = new ResolverExpressionEvaluatorStub();
241
242
243 configurator.configureComponent( mojo, pluginConfiguration, evaluator, getContainer().getContainerRealm() );
244
245 return mojo;
246 }
247
248 /**
249 * configure the mojo with the given plexus configuration
250 *
251 * @param mojo
252 * @param pluginConfiguration
253 * @return
254 * @throws Exception
255 */
256 protected Mojo configureMojo( Mojo mojo, PlexusConfiguration pluginConfiguration )
257 throws Exception
258 {
259 validateContainerStatus();
260
261 ExpressionEvaluator evaluator = new ResolverExpressionEvaluatorStub();
262
263 configurator.configureComponent( mojo, pluginConfiguration, evaluator, getContainer().getContainerRealm() );
264
265 return mojo;
266 }
267
268
269 /**
270 * convience method to obtain the value of a variable on a mojo that might not have a getter.
271 *
272 * NOTE: the caller is responsible for casting to to what the desired type is.
273 *
274 * @param object
275 * @param variable
276 * @return object value of variable
277 * @throws IllegalArgumentException
278 */
279 protected Object getVariableValueFromObject( Object object, String variable )
280 throws IllegalAccessException
281 {
282 Field field = ReflectionUtils.getFieldByNameIncludingSuperclasses( variable, object.getClass() );
283
284 field.setAccessible( true );
285
286 return field.get( object );
287 }
288
289
290 /**
291 * convience method to obtain all variables and values from the mojo (including its superclasses)
292 *
293 * Note: the values in the map are of type Object so the caller is responsible for casting to desired types.
294 *
295 * @param object
296 * @return map of variable names and values
297 */
298 protected Map getVariablesAndValuesFromObject( Object object )
299 throws IllegalAccessException
300 {
301 return getVariablesAndValuesFromObject( object.getClass(), object );
302 }
303
304 /**
305 * convience method to obtain all variables and values from the mojo (including its superclasses)
306 *
307 * Note: the values in the map are of type Object so the caller is responsible for casting to desired types.
308 *
309 * @param clazz
310 * @param object
311 * @return map of variable names and values
312 */
313 protected Map getVariablesAndValuesFromObject( Class clazz, Object object )
314 throws IllegalAccessException
315 {
316 Map map = new HashMap();
317
318 Field[] fields = clazz.getDeclaredFields();
319
320 AccessibleObject.setAccessible( fields, true);
321
322 for (int i = 0; i < fields.length; ++i)
323 {
324 Field field = fields[i];
325
326 map.put( field.getName(), field.get( object ) );
327
328 }
329
330 Class superclass = clazz.getSuperclass();
331
332 if ( !Object.class.equals( superclass ) )
333 {
334 map.putAll( getVariablesAndValuesFromObject( superclass, object ) );
335 }
336
337 return map;
338 }
339
340
341 /**
342 * convience method to set values to variables in objects that don't have setters
343 * @param object
344 * @param variable
345 * @param value
346 * @throws IllegalAccessException
347 */
348 protected void setVariableValueToObject( Object object, String variable, Object value )
349 throws IllegalAccessException
350 {
351 Field field = ReflectionUtils.getFieldByNameIncludingSuperclasses( variable, object.getClass() );
352
353 field.setAccessible( true );
354
355 field.set(object, value );
356 }
357 /**
358 * sometimes the parent element might contain the correct value so generalize that access
359 *
360 * TODO find out where this is probably done elsewhere
361 *
362 * @param pluginPomDom
363 * @param element
364 * @return
365 * @throws Exception
366 */
367
368 private String resolveFromRootThenParent( Xpp3Dom pluginPomDom, String element ) throws Exception
369 {
370 Xpp3Dom elementDom = pluginPomDom.getChild( element );
371
372
373 if ( elementDom == null )
374 {
375 Xpp3Dom pluginParentDom = pluginPomDom.getChild("parent");
376
377 if (pluginParentDom != null )
378 {
379 elementDom = pluginParentDom.getChild( element );
380
381 if ( elementDom == null )
382 {
383 throw new Exception ( "unable to determine " + element );
384 }
385 else
386 {
387 return elementDom.getValue();
388 }
389 }
390 else
391 {
392 throw new Exception ( "unable to determine " + element );
393 }
394 }
395 else
396 {
397 return elementDom.getValue();
398 }
399 }
400
401
402
403
404
405
406
407
408
409
410 private void validateContainerStatus() throws Exception {
411 if (container != null)
412 {
413 return;
414 }
415 else
416 {
417 throw new Exception("container is null, make sure super.setUp() is called");
418 }
419 }
420 }