1 /*
2 * Copyright (c) 2007, Ounce Labs, Inc.
3 * All rights reserved.
4 *
5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions are met:
7 * * Redistributions of source code must retain the above copyright
8 * notice, this list of conditions and the following disclaimer.
9 * * Redistributions in binary form must reproduce the above copyright
10 * notice, this list of conditions and the following disclaimer in the
11 * documentation and/or other materials provided with the distribution.
12 * * Neither the name of the <organization> nor the
13 * names of its contributors may be used to endorse or promote products
14 * derived from this software without specific prior written permission.
15 *
16 * THIS SOFTWARE IS PROVIDED BY OUNCE LABS, INC. ``AS IS'' AND ANY
17 * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
18 * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
19 * DISCLAIMED. IN NO EVENT SHALL OUNCE LABS, INC. BE LIABLE FOR ANY
20 * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
21 * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
22 * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
23 * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
24 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
25 * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
26 */
27 package org.codehaus.mojo.ounce;
28
29 import java.util.HashMap;
30 import java.util.Iterator;
31 import java.util.List;
32
33 import org.apache.maven.artifact.Artifact;
34 import org.apache.maven.artifact.DependencyResolutionRequiredException;
35 import org.apache.maven.artifact.repository.ArtifactRepository;
36 import org.apache.maven.plugin.MojoExecutionException;
37 import org.apache.maven.plugin.MojoFailureException;
38 import org.codehaus.mojo.ounce.core.OunceCore;
39 import org.codehaus.mojo.ounce.core.OunceCoreException;
40 import org.codehaus.mojo.ounce.utils.Utils;
41 import org.codehaus.plexus.component.repository.exception.ComponentLookupException;
42
43 /**
44 * This mojo generates an Ounce project file. It does not fork the build like the "project" mojo and is instead intended
45 * to be bound in a pom for automatic execution. If you would rather have the project generated on demand via the
46 * command line, use the project goal instead.
47 *
48 * @author <a href="mailto:brianf@apache.org">Brian Fox</a>
49 * @requiresDependencyResolution test
50 * @goal project-only
51 * @phase package
52 */
53 public class ProjectOnlyMojo
54 extends AbstractOunceMojo
55 {
56
57 public static final String PATH_SEPARATOR = ";";
58
59 public static final String M2_REPO = "M2_REPO";
60
61 /**
62 * The scope of the classpath used to analyze this project. <br/> Valid choices are: compile, test, runtime, or
63 * system. If includeTestSources is true, then the classpathScope reverts to test. Otherwise, the default is
64 * compile.
65 *
66 * @parameter default-value="compile" expression="${ounce.classpathScope}";
67 */
68 private String classpathScope;
69
70 /**
71 * JDK configuration known to Ounce Core.
72 *
73 * @parameter expression="${ounce.jdkName}"
74 */
75 private String jdkName;
76
77 /**
78 * Options to pass to the javac compiler.
79 *
80 * @parameter expression="${ounce.javaCompilerOptions}"
81 */
82 private String javaCompilerOptions;
83
84 /**
85 * If TestSources should be included in the compilable sources. If set, adds project.getTestSourceRoot() to the path
86 * and defaults the classpathScope to test.
87 *
88 * @parameter expression="${ounce.includeTestSources}" default-value="false"
89 */
90 protected boolean includeTestSources;
91
92 /**
93 * Whether the plugin should use the Ounce Automation Server to create any necessary variables (such as M2_REPO).
94 * Requires that the Ounce Automation Server be installed.
95 *
96 * @parameter expression="${ounce.createVariables}" default-value="true"
97 */
98 protected boolean createVariables;
99
100 /**
101 * The location of the Ounce client installation directory. Required if ounceauto is not on the path.
102 *
103 * @parameter expression="${ounce.installDir}"
104 */
105 String installDir;
106
107 /**
108 * The location of the web context root, if needed.
109 *
110 * @parameter expression="${project.build.directory}/${project.build.finalName}"
111 */
112 private String webappDirectory;
113
114 /**
115 * Whether to analyze the framework for a Struts application
116 *
117 * @parameter expression="${ounce.analyzeStrutsFramework}" default-value="false"
118 */
119 private boolean analyzeStrutsFramework;
120
121 /**
122 * Whether to import Struts validation routines
123 *
124 * @parameter expression="${ounce.importStrutsValidation}" default-value="false"
125 */
126 private boolean importStrutsValidation;
127
128 /**
129 * Location of the local repository.
130 *
131 * @parameter expression="${localRepository}"
132 * @readonly
133 * @required
134 */
135 protected ArtifactRepository local;
136
137 /*
138 * (non-Javadoc)
139 *
140 * @see org.apache.maven.plugin.Mojo#execute()
141 */
142 public void execute()
143 throws MojoExecutionException, MojoFailureException
144 {
145 if ( project.getPackaging() != "pom" || !skipPoms )
146 {
147 try
148 {
149
150 String classPath = buildClasspath();
151 List sourceRoots = getSourceRoots();
152
153 String projectRoot = getProjectRoot();
154
155 // make all paths relative
156
157 webappDirectory = Utils.convertToRelativePath( webappDirectory, projectRoot, "" );
158
159 // remove project root from the
160 // classpath
161 classPath = Utils.convertToRelativePath( classPath, projectRoot, "" );
162
163 // remove repo from the classpath
164 classPath = Utils.convertToRelativePath( classPath, local.getBasedir(), ProjectOnlyMojo.M2_REPO );
165
166 classPath = Utils.convertToVariablePath( classPath, pathVariableMap );
167
168 sourceRoots = Utils.convertToRelativePaths( sourceRoots, projectRoot, "" );
169
170 projectRoot = ".";
171
172 OunceCore core = getCore();
173
174 core.createProject( getProjectRoot(), name, projectRoot, sourceRoots, webappDirectory, classPath,
175 jdkName, javaCompilerOptions, project.getPackaging(), this.options,
176 analyzeStrutsFramework, importStrutsValidation, this.getLog() );
177
178 if ( createVariables )
179 {
180 if ( pathVariableMap == null )
181 {
182 pathVariableMap = new HashMap();
183 }
184 if ( pathVariableMap.get( ProjectOnlyMojo.M2_REPO ) == null )
185 {
186 pathVariableMap.put( ProjectOnlyMojo.M2_REPO, local.getBasedir() );
187 }
188 core.createPathVariables( pathVariableMap, installDir, this.getLog() );
189 }
190 }
191 catch ( ComponentLookupException e )
192 {
193 throw new MojoExecutionException( "Unable to lookup the core interface for hint: " + coreHint, e );
194 }
195 catch ( OunceCoreException e )
196 {
197 throw new MojoExecutionException( "Nested Ouncecore exception: " + e.getLocalizedMessage(), e );
198 }
199 }
200 else
201 {
202 getLog().info( "Skipping Pom project." );
203 }
204 }
205
206 /**
207 * This method gets the source roots from the project. Overrides the ProjectOnly:getSourceRoots() method because we
208 * don't have an executed project because the build wasn't forked.
209 *
210 * @return List of source roots.
211 */
212 protected List getSourceRoots()
213 {
214 List sourceRoots = project.getCompileSourceRoots();
215
216 if ( this.includeTestSources )
217 {
218 sourceRoots.addAll( project.getTestCompileSourceRoots() );
219 }
220 return sourceRoots;
221 }
222
223 /**
224 * Gets the classpath elements and returns a properly formatted classpath.
225 *
226 * @return
227 * @throws MojoExecutionException
228 */
229 protected String buildClasspath()
230 throws MojoExecutionException
231 {
232
233 List classpathElements = getClasspathElements();
234
235 StringBuffer sb = new StringBuffer();
236 Iterator i = classpathElements.iterator();
237
238 if ( i.hasNext() )
239 {
240 // first one, no separator needed
241 sb.append( Utils.convertToUnixStylePath( (String) i.next() ) );
242
243 // separate the rest of them with pathSeparator
244 while ( i.hasNext() )
245 {
246 sb.append( ProjectOnlyMojo.PATH_SEPARATOR );
247 sb.append( Utils.convertToUnixStylePath( (String) i.next() ) );
248 }
249 }
250
251 return sb.toString();
252
253 }
254
255 /**
256 * Gets the properly scoped classpathElements from the Maven Project
257 *
258 * @return List of classpath strings.
259 * @throws MojoExecutionException
260 */
261 protected List getClasspathElements()
262 throws MojoExecutionException
263 {
264 List classpathElements = null;
265
266 try
267 {
268 // checking if test sources are included. If so,
269 // then we want the classpath to be test
270 // (includes everything)
271 if ( Artifact.SCOPE_TEST.equalsIgnoreCase( this.classpathScope ) || this.includeTestSources )
272 {
273 classpathElements = project.getTestClasspathElements();
274 }
275 else if ( Artifact.SCOPE_COMPILE.equalsIgnoreCase( this.classpathScope ) )
276 {
277 classpathElements = project.getCompileClasspathElements();
278 }
279 else if ( Artifact.SCOPE_RUNTIME.equalsIgnoreCase( this.classpathScope ) )
280 {
281 classpathElements = project.getRuntimeClasspathElements();
282 }
283 else if ( Artifact.SCOPE_SYSTEM.equalsIgnoreCase( this.classpathScope ) )
284 {
285 classpathElements = project.getSystemClasspathElements();
286 }
287 else
288 {
289 throw new MojoExecutionException( "Invalid classpathScope: " + this.classpathScope +
290 " valid values are: compile, test, runtime, system." );
291 }
292 }
293 catch ( DependencyResolutionRequiredException e )
294 {
295 throw new MojoExecutionException( e.getLocalizedMessage(), e );
296 }
297
298 return classpathElements;
299 }
300
301 /**
302 * @return the classpathScope
303 */
304 protected String getClasspathScope()
305 {
306 return this.classpathScope;
307 }
308
309 /**
310 * @param theClasspathScope the classpathScope to set
311 */
312 protected void setClasspathScope( String theClasspathScope )
313 {
314 this.classpathScope = theClasspathScope;
315 }
316
317 /**
318 * @return the jdkName
319 */
320 protected String getJdkName()
321 {
322 return this.jdkName;
323 }
324
325 /**
326 * @param theJdkName the jdkName to set
327 */
328 protected void setJdkName( String theJdkName )
329 {
330 this.jdkName = theJdkName;
331 }
332
333 /**
334 * @return the includeTestSources
335 */
336 protected boolean isIncludeTestSources()
337 {
338 return this.includeTestSources;
339 }
340
341 /**
342 * @param theIncludeTestSources the includeTestSources to set
343 */
344 protected void setIncludeTestSources( boolean theIncludeTestSources )
345 {
346 this.includeTestSources = theIncludeTestSources;
347 }
348
349 /**
350 * @return the java compiler options
351 */
352 protected String getJavaCompilerOptions()
353 {
354 return javaCompilerOptions;
355 }
356
357 /**
358 * @param theJavaCompilerOptions the java compiler options
359 */
360 protected void setJavaCompilerOptions( String theJavaCompilerOptions )
361 {
362 this.javaCompilerOptions = theJavaCompilerOptions;
363 }
364
365 /**
366 * @return the webappDirectory
367 */
368 protected String getWebappDirectory()
369 {
370 return this.webappDirectory;
371 }
372
373 /**
374 * @param theWebappDirectory the webappDirectory to set
375 */
376 protected void setWebappDirectory( String theWebappDirectory )
377 {
378 this.webappDirectory = theWebappDirectory;
379 }
380
381 /**
382 * @return whether to analyze Struts framework
383 */
384 protected boolean getAnalyzeStrutsFramework() {
385 return this.analyzeStrutsFramework;
386 }
387
388 /**
389 * @param toAnalyzeStrutsFramework whether to analyze Struts Framework
390 */
391 protected void setAnalyzeStrutsFramework(boolean analyzeStrutsFramework) {
392 this.analyzeStrutsFramework = analyzeStrutsFramework;
393 }
394
395 /**
396 * @return whether to import Struts validation
397 */
398 protected boolean getImportStrutsValidation() {
399 return this.importStrutsValidation;
400 }
401
402 /**
403 * @param importStrutsValidation whether to import Struts validation
404 */
405 protected void setImportStrutsValidation(boolean importStrutsValidation) {
406 this.importStrutsValidation = importStrutsValidation;
407 }
408
409 /**
410 * @return the local
411 */
412 public ArtifactRepository getLocal()
413 {
414 return this.local;
415 }
416
417 /**
418 * @param theLocal the local to set
419 */
420 public void setLocal( ArtifactRepository theLocal )
421 {
422 this.local = theLocal;
423 }
424
425 }