Clover Coverage Report - Maven Eclipse Formatter Plugin 1.1
Coverage timestamp: Wed Dec 31 1969 19:00:00 EST
../../../../img/srcFileCovDistChart0.png 0% of files have more coverage
203   585   82   8.46
92   366   0.4   24
24     3.42  
1    
 
  ExecMojo       Line # 60 203 0% 82 319 0% 0.0
 
No Tests
 
1    package org.codehaus.mojo.exec;
2   
3    /*
4    * Licensed to the Apache Software Foundation (ASF) under one or more contributor license agreements. See the NOTICE
5    * file distributed with this work for additional information regarding copyright ownership. The ASF licenses this file
6    * to you under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the
7    * License. You may obtain a copy of the License at
8    *
9    * http://www.apache.org/licenses/LICENSE-2.0
10    *
11    * Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on
12    * an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the
13    * specific language governing permissions and limitations under the License.
14    */
15   
16    import java.io.File;
17    import java.io.FileOutputStream;
18    import java.io.IOException;
19    import java.io.OutputStream;
20    import java.io.PrintStream;
21    import java.util.ArrayList;
22    import java.util.Arrays;
23    import java.util.Collection;
24    import java.util.HashMap;
25    import java.util.Iterator;
26    import java.util.List;
27    import java.util.Locale;
28    import java.util.Map;
29    import java.util.Properties;
30    import java.util.jar.JarEntry;
31    import java.util.jar.JarOutputStream;
32    import java.util.jar.Manifest;
33   
34    import org.apache.commons.exec.CommandLine;
35    import org.apache.commons.exec.DefaultExecutor;
36    import org.apache.commons.exec.ExecuteException;
37    import org.apache.commons.exec.Executor;
38    import org.apache.commons.exec.OS;
39    import org.apache.commons.exec.PumpStreamHandler;
40    import org.apache.maven.artifact.Artifact;
41    import org.apache.maven.artifact.resolver.filter.AndArtifactFilter;
42    import org.apache.maven.artifact.resolver.filter.IncludesArtifactFilter;
43    import org.apache.maven.execution.MavenSession;
44    import org.apache.maven.plugin.MojoExecutionException;
45    import org.apache.maven.plugin.logging.Log;
46    import org.apache.maven.project.MavenProject;
47    import org.apache.maven.toolchain.Toolchain;
48    import org.apache.maven.toolchain.ToolchainManager;
49    import org.codehaus.plexus.component.repository.exception.ComponentLookupException;
50    import org.codehaus.plexus.util.StringUtils;
51    import org.codehaus.plexus.util.cli.CommandLineUtils;
52   
53    /**
54    * A Plugin for executing external programs.
55    *
56    * @author Jerome Lacoste <jerome@coffeebreaks.org>
57    * @version $Id: ExecMojo.java 12386 2010-07-16 22:10:38Z rfscholte $
58    * @since 1.0
59    */
 
60    public class ExecMojo extends AbstractExecMojo {
61    /**
62    * The executable. Can be a full path or a the name executable. In the latter case, the executable must be in the
63    * PATH for the execution to work.
64    */
65    private String executable;
66   
67    /**
68    * The current working directory. Optional. If not specified, basedir will be used.
69    */
70    private File workingDirectory;
71   
72    /**
73    * Program standard and error output will be redirected to the file specified by this optional field. If not
74    * specified the standard maven logging is used.
75    */
76    private File outputFile;
77   
78    /**
79    * Can be of type <code>&lt;argument&gt;</code> or <code>&lt;classpath&gt;</code> Can be overridden using
80    * "exec.args" env. variable
81    */
82    private List arguments;
83   
84    /**
85    * @parameter expression="${basedir}"
86    * @required
87    * @readonly
88    * @since 1.0
89    */
90    private File basedir;
91   
92    /**
93    * Environment variables to pass to the executed program.
94    */
95    private Map environmentVariables = new HashMap();
96   
97    /**
98    * The current build session instance. This is used for toolchain manager API calls.
99    *
100    * @parameter expression="${session}"
101    * @required
102    * @readonly
103    */
104    private MavenSession session;
105   
106    /**
107    * Exit codes to be resolved as successful execution for non-compliant applications (applications not returning 0
108    * for success).
109    */
110    private List successCodes;
111   
112    /**
113    * If set to true the classpath and the main class will be written to a MANIFEST.MF file and wrapped into a jar.
114    * Instead of '-classpath/-cp CLASSPATH mainClass' the exec plugin executes '-jar maven-exec.jar'.
115    */
116    private boolean longClasspath;
117   
118    public static final String CLASSPATH_TOKEN = "%classpath";
119   
120    /**
121    * priority in the execute method will be to use System properties arguments over the pom specification.
122    *
123    * @throws MojoExecutionException
124    * if a failure happens
125    */
 
126  0 toggle @Override
127    public void execute() throws MojoExecutionException {
128  0 try {
129  0 if (isSkip()) {
130  0 getLog().info("skipping execute as per configuraion");
131  0 return;
132    }
133   
134  0 if (basedir == null) {
135  0 throw new IllegalStateException("basedir is null. Should not be possible.");
136    }
137   
138  0 String argsProp = getSystemProperty("exec.args");
139   
140  0 List commandArguments = new ArrayList();
141   
142  0 if (hasCommandlineArgs()) {
143  0 String[] args = parseCommandlineArgs();
144  0 for (int i = 0; i < args.length; i++) {
145  0 if (isLongClassPathArgument(args[i])) {
146    // it is assumed that starting from -cp or -classpath the arguments
147    // are: -classpath/-cp %classpath mainClass
148    // the arguments are replaced with: -jar $TMP/maven-exec.jar
149    // NOTE: the jar will contain the classpath and the main class
150  0 commandArguments.add("-jar");
151  0 File tmpFile = createJar(computeClasspath(null), args[i + 2]);
152  0 commandArguments.add(tmpFile.getAbsolutePath());
153  0 i += 2;
154  0 } else if (CLASSPATH_TOKEN.equals(args[i])) {
155  0 commandArguments.add(computeClasspathString(null));
156    } else {
157  0 commandArguments.add(args[i]);
158    }
159    }
160  0 } else if (!isEmpty(argsProp)) {
161  0 getLog().debug("got arguments from system properties: " + argsProp);
162   
163  0 try {
164  0 String[] args = CommandLineUtils.translateCommandline(argsProp);
165  0 commandArguments.addAll(Arrays.asList(args));
166    } catch (Exception e) {
167  0 throw new MojoExecutionException("Couldn't parse systemproperty 'exec.args'");
168    }
169    } else {
170  0 if (arguments != null) {
171  0 for (int i = 0; i < arguments.size(); i++) {
172  0 Object argument = arguments.get(i);
173  0 String arg;
174  0 if (argument == null) {
175  0 throw new MojoExecutionException("Misconfigured argument, value is null. "
176    + "Set the argument to an empty value if this is the required behaviour.");
177  0 } else if (argument instanceof String && isLongClassPathArgument((String) argument)) {
178    // it is assumed that starting from -cp or -classpath the arguments
179    // are: -classpath/-cp %classpath mainClass
180    // the arguments are replaced with: -jar $TMP/maven-exec.jar
181    // NOTE: the jar will contain the classpath and the main class
182  0 commandArguments.add("-jar");
183  0 File tmpFile = createJar(computeClasspath((Classpath) arguments.get(i + 1)),
184    (String) arguments.get(i + 2));
185  0 commandArguments.add(tmpFile.getAbsolutePath());
186  0 i += 2;
187  0 } else if (argument instanceof Classpath) {
188  0 Classpath specifiedClasspath = (Classpath) argument;
189   
190  0 arg = computeClasspathString(specifiedClasspath);
191  0 commandArguments.add(arg);
192    } else {
193  0 arg = argument.toString();
194  0 commandArguments.add(arg);
195    }
196    }
197    }
198    }
199   
200  0 Map enviro = new HashMap();
201  0 try {
202  0 Properties systemEnvVars = CommandLineUtils.getSystemEnvVars();
203  0 enviro.putAll(systemEnvVars);
204    } catch (IOException x) {
205  0 getLog().error("Could not assign default system enviroment variables.", x);
206    }
207   
208  0 if (environmentVariables != null) {
209  0 Iterator iter = environmentVariables.keySet().iterator();
210  0 while (iter.hasNext()) {
211  0 String key = (String) iter.next();
212  0 String value = (String) environmentVariables.get(key);
213  0 enviro.put(key, value);
214    }
215    }
216   
217  0 if (workingDirectory == null) {
218  0 workingDirectory = basedir;
219    }
220   
221  0 if (!workingDirectory.exists()) {
222  0 getLog().debug("Making working directory '" + workingDirectory.getAbsolutePath() + "'.");
223  0 if (!workingDirectory.mkdirs()) {
224  0 throw new MojoExecutionException("Could not make working directory: '"
225    + workingDirectory.getAbsolutePath() + "'");
226    }
227    }
228   
229  0 CommandLine commandLine = getExecutablePath(enviro, workingDirectory);
230   
231  0 String[] args = new String[commandArguments.size()];
232  0 for (int i = 0; i < commandArguments.size(); i++) {
233  0 args[i] = (String) commandArguments.get(i);
234    }
235   
236  0 commandLine.addArguments(args, false);
237   
238  0 Executor exec = getExecutor();
239   
240  0 exec.setWorkingDirectory(workingDirectory);
241   
242    // this code ensures the output gets logged vai maven logging, but at the same time prevents
243    // partial line output, like input prompts.
244    // final Log outputLog = getExecOutputLog();
245    // LogOutputStream stdout = new LogOutputStream()
246    // {
247    // protected void processLine( String line, int level )
248    // {
249    // outputLog.info( line );
250    // }
251    // };
252    //
253    // LogOutputStream stderr = new LogOutputStream()
254    // {
255    // protected void processLine( String line, int level )
256    // {
257    // outputLog.info( line );
258    // }
259    // };
260  0 OutputStream stdout = System.out;
261  0 OutputStream stderr = System.err;
262   
263  0 try {
264  0 getLog().debug("Executing command line: " + commandLine);
265   
266  0 int resultCode = executeCommandLine(exec, commandLine, enviro, stdout, stderr);
267   
268  0 if (isResultCodeAFailure(resultCode)) {
269  0 throw new MojoExecutionException("Result of " + commandLine + " execution is: '" + resultCode
270    + "'.");
271    }
272    } catch (ExecuteException e) {
273  0 throw new MojoExecutionException("Command execution failed.", e);
274   
275    } catch (IOException e) {
276  0 throw new MojoExecutionException("Command execution failed.", e);
277    }
278   
279  0 registerSourceRoots();
280    } catch (IOException e) {
281  0 throw new MojoExecutionException("I/O Error", e);
282    }
283    }
284   
 
285  0 toggle protected Executor getExecutor() {
286  0 DefaultExecutor exec = new DefaultExecutor();
287   
288  0 if (successCodes != null) {
289  0 int size = successCodes.size();
290  0 int[] exitValues = new int[size];
291  0 for (int i = 0; i < size; i++) {
292  0 exitValues[i] = new Integer(successCodes.get(i) + "");
293    }
294  0 exec.setExitValues(exitValues);
295    }
296  0 return exec;
297    }
298   
 
299  0 toggle boolean isResultCodeAFailure(int result) {
300  0 if (successCodes == null || successCodes.size() == 0) {
301  0 return result != 0;
302    }
303  0 for (Iterator it = successCodes.iterator(); it.hasNext();) {
304  0 int code = Integer.parseInt((String) it.next());
305  0 if (code == result) {
306  0 return false;
307    }
308    }
309  0 return true;
310    }
311   
 
312  0 toggle private boolean isLongClassPathArgument(String arg) {
313  0 return longClasspath && ("-classpath".equals(arg) || "-cp".equals(arg));
314    }
315   
 
316  0 toggle private Log getExecOutputLog() {
317  0 Log log = getLog();
318  0 if (outputFile != null) {
319  0 try {
320  0 if (!outputFile.getParentFile().exists() && !outputFile.getParentFile().mkdirs()) {
321  0 getLog().warn("Could not create non existing parent directories for log file: " + outputFile);
322    }
323  0 PrintStream stream = new PrintStream(new FileOutputStream(outputFile));
324   
325  0 log = new StreamLog(stream);
326    } catch (Exception e) {
327  0 getLog().warn("Could not open " + outputFile + ". Using default log", e);
328    }
329    }
330   
331  0 return log;
332    }
333   
334    /**
335    * Compute the classpath from the specified Classpath. The computed classpath is based on the classpathScope. The
336    * plugin cannot know from maven the phase it is executed in. So we have to depend on the user to tell us he wants
337    * the scope in which the plugin is expected to be executed.
338    *
339    * @param specifiedClasspath
340    * Non null when the user restricted the dependenceis, null otherwise (the default classpath will be
341    * used)
342    * @return a platform specific String representation of the classpath
343    */
 
344  0 toggle private String computeClasspathString(Classpath specifiedClasspath) {
345  0 List resultList = computeClasspath(specifiedClasspath);
346  0 StringBuffer theClasspath = new StringBuffer();
347   
348  0 for (Iterator it = resultList.iterator(); it.hasNext();) {
349  0 String str = (String) it.next();
350  0 addToClasspath(theClasspath, str);
351    }
352   
353  0 return theClasspath.toString();
354    }
355   
356    /**
357    * Compute the classpath from the specified Classpath. The computed classpath is based on the classpathScope. The
358    * plugin cannot know from maven the phase it is executed in. So we have to depend on the user to tell us he wants
359    * the scope in which the plugin is expected to be executed.
360    *
361    * @param specifiedClasspath
362    * Non null when the user restricted the dependenceis, null otherwise (the default classpath will be
363    * used)
364    * @return a list of class path elements
365    */
 
366  0 toggle private List computeClasspath(Classpath specifiedClasspath) {
367  0 List artifacts = new ArrayList();
368  0 List theClasspathFiles = new ArrayList();
369  0 List resultList = new ArrayList();
370   
371  0 collectProjectArtifactsAndClasspath(artifacts, theClasspathFiles);
372   
373  0 if ((specifiedClasspath != null) && (specifiedClasspath.getDependencies() != null)) {
374  0 artifacts = filterArtifacts(artifacts, specifiedClasspath.getDependencies());
375    }
376   
377  0 for (Iterator it = theClasspathFiles.iterator(); it.hasNext();) {
378  0 File f = (File) it.next();
379  0 resultList.add(f.getAbsolutePath());
380    }
381   
382  0 for (Iterator it = artifacts.iterator(); it.hasNext();) {
383  0 Artifact artifact = (Artifact) it.next();
384  0 getLog().debug("dealing with " + artifact);
385  0 resultList.add(artifact.getFile().getAbsolutePath());
386    }
387   
388  0 return resultList;
389    }
390   
 
391  0 toggle private static void addToClasspath(StringBuffer theClasspath, String toAdd) {
392  0 if (theClasspath.length() > 0) {
393  0 theClasspath.append(File.pathSeparator);
394    }
395  0 theClasspath.append(toAdd);
396    }
397   
 
398  0 toggle private List filterArtifacts(List artifacts, Collection dependencies) {
399  0 AndArtifactFilter filter = new AndArtifactFilter();
400   
401  0 filter.add(new IncludesArtifactFilter(new ArrayList(dependencies))); // gosh
402   
403  0 List filteredArtifacts = new ArrayList();
404  0 for (Iterator it = artifacts.iterator(); it.hasNext();) {
405  0 Artifact artifact = (Artifact) it.next();
406  0 if (filter.include(artifact)) {
407  0 getLog().debug("filtering in " + artifact);
408  0 filteredArtifacts.add(artifact);
409    }
410    }
411  0 return filteredArtifacts;
412    }
413   
 
414  0 toggle CommandLine getExecutablePath(Map enviro, File dir) {
415  0 File execFile = new File(executable);
416  0 String exec = null;
417  0 if (execFile.exists()) {
418  0 getLog().debug("Toolchains are ignored, 'executable' parameter is set to " + executable);
419  0 exec = execFile.getAbsolutePath();
420    } else {
421  0 Toolchain tc = getToolchain();
422   
423    // if the file doesn't exist & toolchain is null, the exec is probably in the PATH...
424    // we should probably also test for isFile and canExecute, but the second one is only
425    // available in SDK 6.
426  0 if (tc != null) {
427  0 getLog().info("Toolchain in exec-maven-plugin: " + tc);
428  0 exec = tc.findTool(executable);
429    } else {
430  0 if (OS.isFamilyWindows()) {
431  0 String ex = executable.indexOf(".") < 0 ? executable + ".bat" : executable;
432  0 File f = new File(dir, ex);
433  0 if (f.exists()) {
434  0 exec = ex;
435    } else {
436    // now try to figure the path from PATH, PATHEXT env vars
437    // if bat file, wrap in cmd /c
438  0 String path = (String) enviro.get("PATH");
439  0 if (path != null) {
440  0 String[] elems = StringUtils.split(path, File.pathSeparator);
441  0 for (int i = 0; i < elems.length; i++) {
442  0 f = new File(new File(elems[i]), ex);
443  0 if (f.exists()) {
444  0 exec = ex;
445  0 break;
446    }
447    }
448    }
449    }
450    }
451    }
452    }
453   
454  0 if (exec == null) {
455  0 exec = executable;
456    }
457   
458  0 CommandLine toRet;
459  0 if (OS.isFamilyWindows() && exec.toLowerCase(Locale.getDefault()).endsWith(".bat")) {
460  0 toRet = new CommandLine("cmd");
461  0 toRet.addArgument("/c");
462  0 toRet.addArgument(exec);
463    } else {
464  0 toRet = new CommandLine(exec);
465    }
466   
467  0 return toRet;
468    }
469   
470    // private String[] DEFAULT_PATH_EXT = new String[] {
471    // .COM; .EXE; .BAT; .CMD; .VBS; .VBE; .JS; .JSE; .WSF; .WSH
472    // ".COM", ".EXE", ".BAT", ".CMD"
473    // };
474   
 
475  0 toggle private static boolean isEmpty(String string) {
476  0 return string == null || string.length() == 0;
477    }
478   
479    //
480    // methods used for tests purposes - allow mocking and simulate automatic setters
481    //
482   
 
483  0 toggle protected int executeCommandLine(Executor exec, CommandLine commandLine, Map enviro, OutputStream out,
484    OutputStream err) throws IOException {
485  0 exec.setStreamHandler(new PumpStreamHandler(out, err, System.in));
486  0 return exec.execute(commandLine, enviro);
487    }
488   
 
489  0 toggle void setExecutable(String executable) {
490  0 this.executable = executable;
491    }
492   
 
493  0 toggle String getExecutable() {
494  0 return executable;
495    }
496   
 
497  0 toggle void setWorkingDirectory(String workingDir) {
498  0 setWorkingDirectory(new File(workingDir));
499    }
500   
 
501  0 toggle void setWorkingDirectory(File workingDir) {
502  0 this.workingDirectory = workingDir;
503    }
504   
 
505  0 toggle void setArguments(List arguments) {
506  0 this.arguments = arguments;
507    }
508   
 
509  0 toggle void setBasedir(File basedir) {
510  0 this.basedir = basedir;
511    }
512   
 
513  0 toggle void setProject(MavenProject project) {
514  0 this.project = project;
515    }
516   
 
517  0 toggle protected String getSystemProperty(String key) {
518  0 return System.getProperty(key);
519    }
520   
 
521  0 toggle public void setSuccessCodes(List list) {
522  0 this.successCodes = list;
523    }
524   
 
525  0 toggle public List getSuccessCodes() {
526  0 return successCodes;
527    }
528   
 
529  0 toggle private Toolchain getToolchain() {
530  0 Toolchain tc = null;
531   
532  0 try {
533  0 if (session != null) { // session is null in tests..
534  0 ToolchainManager toolchainManager = (ToolchainManager) session.getContainer().lookup(
535    ToolchainManager.ROLE);
536   
537  0 if (toolchainManager != null) {
538  0 tc = toolchainManager.getToolchainFromBuildContext("jdk", session);
539    }
540    }
541    } catch (ComponentLookupException componentLookupException) {
542    // just ignore, could happen in pre-2.0.9 builds..
543    }
544  0 return tc;
545    }
546   
547    /**
548    * Create a jar with just a manifest containing a Main-Class entry for SurefireBooter and a Class-Path entry for all
549    * classpath elements. Copied from surefire (ForkConfiguration#createJar())
550    *
551    * @param classPath
552    * List&lt;String> of all classpath elements.
553    * @return
554    * @throws IOException
555    */
 
556  0 toggle private File createJar(List classPath, String mainClass) throws IOException {
557  0 File file = File.createTempFile("maven-exec", ".jar");
558  0 file.deleteOnExit();
559  0 FileOutputStream fos = new FileOutputStream(file);
560  0 JarOutputStream jos = new JarOutputStream(fos);
561  0 jos.setLevel(JarOutputStream.STORED);
562  0 JarEntry je = new JarEntry("META-INF/MANIFEST.MF");
563  0 jos.putNextEntry(je);
564   
565  0 Manifest man = new Manifest();
566   
567    // we can't use StringUtils.join here since we need to add a '/' to
568    // the end of directory entries - otherwise the jvm will ignore them.
569  0 String cp = "";
570  0 for (Iterator it = classPath.iterator(); it.hasNext();) {
571  0 String el = (String) it.next();
572    // NOTE: if File points to a directory, this entry MUST end in '/'.
573  0 cp += UrlUtils.getURL(new File(el)).toExternalForm() + " ";
574    }
575   
576  0 man.getMainAttributes().putValue("Manifest-Version", "1.0");
577  0 man.getMainAttributes().putValue("Class-Path", cp.trim());
578  0 man.getMainAttributes().putValue("Main-Class", mainClass);
579   
580  0 man.write(jos);
581  0 jos.close();
582   
583  0 return file;
584    }
585    }