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