View Javadoc

1   /**
2    * Pyx4me framework
3    * Copyright (C) 2006-2008 pyx4j.com.
4    * 
5    * Licensed under the Apache License, Version 2.0 (the "License");
6    * you may not use this file except in compliance with the License.
7    * 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,
12   * software distributed under the License is distributed on an
13   * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
14   * KIND, either express or implied.  See the License for the
15   * specific language governing permissions and limitations
16   * under the License.
17   * 
18   * @author vlads
19   * @version $Id: ProGuardMojo.java 3205 2009-03-28 23:42:55Z vlads $
20   */
21  package com.pyx4me.maven.proguard;
22  
23  import java.io.File;
24  import java.net.URL;
25  import java.util.ArrayList;
26  import java.util.HashSet;
27  import java.util.Iterator;
28  import java.util.List;
29  import java.util.Set;
30  
31  import org.apache.maven.archiver.MavenArchiveConfiguration;
32  import org.apache.maven.archiver.MavenArchiver;
33  import org.apache.maven.artifact.Artifact;
34  import org.apache.maven.model.Dependency;
35  import org.apache.maven.plugin.AbstractMojo;
36  import org.apache.maven.plugin.MojoExecutionException;
37  import org.apache.maven.plugin.MojoFailureException;
38  import org.apache.maven.plugin.logging.Log;
39  import org.apache.maven.project.MavenProject;
40  import org.apache.maven.project.MavenProjectHelper;
41  import org.apache.tools.ant.DefaultLogger;
42  import org.apache.tools.ant.Project;
43  import org.apache.tools.ant.taskdefs.Java;
44  import org.codehaus.plexus.archiver.jar.JarArchiver;
45  
46  /**
47   * 
48   * <p>
49   * The Obfuscate task provides a stand-alone obfuscation task
50   * </p>
51   * 
52   * @goal proguard
53   * @phase package
54   * @description Create small jar files using ProGuard
55   * @requiresDependencyResolution compile
56   */
57  
58  public class ProGuardMojo extends AbstractMojo {
59  
60  	/**
61  	 * Set this to 'true' to bypass ProGuard processing entirely.
62  	 * 
63  	 * @parameter expression="${proguard.skip}"
64  	 */
65  	private boolean skip;
66  
67  	/**
68  	 * Recursively reads configuration options from the given file filename
69  	 * 
70  	 * @parameter default-value="${basedir}/proguard.conf"
71  	 */
72  	private File proguardInclude;
73  
74  	/**
75  	 * Select specific ProGuard version from plugin dependencies
76  	 * 
77  	 * @parameter
78  	 */
79  	private String proguardVersion;
80  
81  	/**
82  	 * ProGuard configuration options
83  	 * 
84  	 * @parameter
85  	 */
86  	private String[] options;
87  
88  	/**
89  	 * Specifies not to obfuscate the input class files.
90  	 * 
91  	 * @parameter default-value="true"
92  	 */
93  	private boolean obfuscate;
94  
95  	/**
96  	 * Specifies that project compile dependencies be added as -libraryjars to proguard arguments. Dependency itself is
97  	 * not included in resulting jar
98  	 * 
99  	 * @parameter default-value="true"
100 	 */
101 	private boolean includeDependency;
102 
103 	/**
104 	 * Bundle project dependency to resulting jar. Specifies list of artifact inclusions
105 	 * 
106 	 * @parameter
107 	 */
108 	private Assembly assembly;
109 
110 	/**
111 	 * Additional -libraryjars e.g. ${java.home}/lib/rt.jar Project compile dependency are added automatically. See
112 	 * exclusions
113 	 * 
114 	 * @parameter
115 	 */
116 	private List libs;
117 
118 	/**
119 	 * List of dependency exclusions
120 	 * 
121 	 * @parameter
122 	 */
123 	private List exclusions;
124 
125 	/**
126      * Specifies the input jar name (or wars, ears, zips) of the application to be
127      * processed.
128      * 
129      * You may specify a classes directory e.g. 'classes'. This way plugin will processed
130      * the classes instead of jar. You would need to bind the execution to phase 'compile'
131      * or 'process-classes' in this case.
132      * 
133      * @parameter expression="${project.build.finalName}.jar"
134      * @required
135      */
136     protected String injar;
137 
138 	/**
139 	 * Set this to 'true' to bypass ProGuard processing when injar does not exists.
140 	 * 
141 	 * @parameter default-value="false"
142 	 */
143 	private boolean injarNotExistsSkip;
144 
145 	/**
146 	 * Apply ProGuard classpathentry Filters to input jar. e.g. <code>!**.gif,!**&#47;tests&#47;**'</code>
147 	 * 
148 	 * @parameter
149 	 */
150 	protected String inFilter;
151 
152 	/**
153 	 * Specifies the names of the output jars. If attach=true the value ignored and name constructed base on classifier
154 	 * If empty input jar would be overdriven.
155 	 * 
156 	 * @parameter
157 	 */
158 	protected String outjar;
159 
160 	/**
161 	 * Specifies whether or not to attach the created artifact to the project
162 	 * 
163 	 * @parameter default-value="false"
164 	 */
165 	private boolean attach = false;
166 
167 	/**
168 	 * Specifies attach artifact type
169 	 * 
170 	 * @parameter default-value="jar"
171 	 */
172 	private String attachArtifactType;
173 
174 	/**
175 	 * Specifies attach artifact Classifier, Ignored if attach=false
176 	 * 
177 	 * @parameter default-value="small"
178 	 */
179 	private String attachArtifactClassifier;
180 
181 	/**
182 	 * Set to false to exclude the attachArtifactClassifier from the Artifact final name. Default value is true.
183 	 * 
184 	 * @parameter default-value="true"
185 	 */
186 	private boolean appendClassifier;
187 
188 	/**
189 	 * Set to true to include META-INF/maven/** maven descriptord
190 	 * 
191 	 * @parameter default-value="false"
192 	 */
193 	private boolean addMavenDescriptor;
194 
195 	/**
196 	 * Directory containing the input and generated JAR.
197 	 * 
198 	 * @parameter expression="${project.build.directory}"
199 	 * @required
200 	 */
201 	protected File outputDirectory;
202 
203 	/**
204 	 * The Maven project reference where the plugin is currently being executed. The default value is populated from
205 	 * maven.
206 	 * 
207 	 * @parameter expression="${project}"
208 	 * @readonly
209 	 * @required
210 	 */
211 	protected MavenProject mavenProject;
212 
213 	/**
214 	 * The plugin dependencies.
215 	 * 
216 	 * @parameter expression="${plugin.artifacts}"
217 	 * @required
218 	 * @readonly
219 	 */
220 	protected List pluginArtifacts;
221 
222 	/**
223 	 * @component
224 	 */
225 	private MavenProjectHelper projectHelper;
226 
227 	/**
228 	 * The Jar archiver.
229 	 * 
230 	 * @parameter expression="${component.org.codehaus.plexus.archiver.Archiver#jar}"
231 	 * @required
232 	 */
233 	private JarArchiver jarArchiver;
234 
235 	/**
236 	 * The maven archive configuration to use. only if assembly is used.
237 	 * 
238 	 * @parameter
239 	 */
240 	protected MavenArchiveConfiguration archive = new MavenArchiveConfiguration();
241 
242 	/**
243 	 * The max memory the forked java process should use, e.g. 256m
244 	 * 
245 	 * @parameter
246 	 */
247 	protected String maxMemory;
248 
249 	/**
250 	 * ProGuard main class name.
251 	 * 
252 	 * @parameter default-value="proguard.ProGuard"
253 	 */
254 	protected String proguardMainClass = "proguard.ProGuard";
255 
256 	private Log log;
257 
258 	/**
259 	 * ProGuard docs: Names with special characters like spaces and parentheses must be quoted with single or double
260 	 * quotes.
261 	 */
262 	private static String fileNameToString(String fileName) {
263 		return "'" + fileName + "'";
264 	}
265 
266 	private static String fileToString(File file) {
267 		return fileNameToString(file.toString());
268 	}
269 
270 	private boolean useArtifactClassifier() {
271 		return appendClassifier && ((attachArtifactClassifier != null) && (attachArtifactClassifier.length() > 0));
272 	}
273 
274 	public void execute() throws MojoExecutionException, MojoFailureException {
275 
276 		log = getLog();
277 
278 		if (skip) {
279 			log.info("Bypass ProGuard processing because \"proguard.skip=true\"");
280 			return;
281 		}
282 
283 		boolean mainIsJar = mavenProject.getPackaging().equals("jar");
284 		boolean mainIsPom = mavenProject.getPackaging().equals("pom");
285 
286 		File inJarFile = new File(outputDirectory, injar);
287 		if (mainIsJar && (!inJarFile.exists())) {
288 			if (injarNotExistsSkip) {
289 				log.info("Bypass ProGuard processing because \"injar\" dos not exist");
290 				return;
291 			}
292 			throw new MojoFailureException("Can't find file " + inJarFile);
293 		}
294 
295 		if (mainIsPom && (!inJarFile.exists()) && injarNotExistsSkip) {
296 			log.info("Bypass ProGuard processing because \"injar\" dos not exist");
297 			return;
298 		}
299 
300 		if (!outputDirectory.exists()) {
301 			if (!outputDirectory.mkdirs()) {
302 				throw new MojoFailureException("Can't create " + outputDirectory);
303 			}
304 		}
305 
306 		File outJarFile;
307 		boolean sameArtifact;
308 
309 		if (attach) {
310 			outjar = nameNoType(injar);
311 			if (useArtifactClassifier()) {
312 				outjar += "-" + attachArtifactClassifier;
313 			}
314 			outjar += "." + attachArtifactType;
315 		}
316 
317 		if ((outjar != null) && (!outjar.equals(injar))) {
318 			sameArtifact = false;
319 			outJarFile = (new File(outputDirectory, outjar)).getAbsoluteFile();
320 			if (outJarFile.exists()) {
321 			    if (!deleteFileOrDirectory(outJarFile)) {
322 					throw new MojoFailureException("Can't delete " + outJarFile);
323 				}
324 			}
325 		} else {
326 			sameArtifact = true;
327 			outJarFile = inJarFile.getAbsoluteFile();
328 			File baseFile;
329 			if (inJarFile.isDirectory()) {
330 			    baseFile = new File(outputDirectory, nameNoType(injar) + "_proguard_base");
331 			} else {
332 			    baseFile = new File(outputDirectory, nameNoType(injar) + "_proguard_base.jar");
333 		    }
334 			if (baseFile.exists()) {
335 				if (!deleteFileOrDirectory(baseFile)) {
336 					throw new MojoFailureException("Can't delete " + baseFile);
337 				}
338 			}
339 			if (inJarFile.exists()) {
340 				if (!inJarFile.renameTo(baseFile)) {
341 					throw new MojoFailureException("Can't rename " + inJarFile);
342 				}
343 			}
344 			inJarFile = baseFile;
345 		}
346 
347 		ArrayList args = new ArrayList();
348 
349 		if (log.isDebugEnabled()) {
350 			List dependancy = mavenProject.getCompileArtifacts();
351 			for (Iterator i = dependancy.iterator(); i.hasNext();) {
352 				Artifact artifact = (Artifact) i.next();
353 				log.debug("--- compile artifact " + artifact.getGroupId() + ":" + artifact.getArtifactId() + ":"
354 						+ artifact.getType() + ":" + artifact.getClassifier() + " Scope:" + artifact.getScope());
355 			}
356 			for (Iterator i = mavenProject.getArtifacts().iterator(); i.hasNext();) {
357 				Artifact artifact = (Artifact) i.next();
358 				log.debug("--- artifact " + artifact.getGroupId() + ":" + artifact.getArtifactId() + ":"
359 						+ artifact.getType() + ":" + artifact.getClassifier() + " Scope:" + artifact.getScope());
360 			}
361 			for (Iterator i = mavenProject.getDependencies().iterator(); i.hasNext();) {
362 				Dependency artifact = (Dependency) i.next();
363 				log.debug("--- dependency " + artifact.getGroupId() + ":" + artifact.getArtifactId() + ":"
364 						+ artifact.getType() + ":" + artifact.getClassifier() + " Scope:" + artifact.getScope());
365 			}
366 		}
367 
368 		Set inPath = new HashSet();
369 		boolean hasInclusionLibrary = false;
370 		if (assembly != null) {
371 			for (Iterator iter = assembly.inclusions.iterator(); iter.hasNext();) {
372 				Inclusion inc = (Inclusion) iter.next();
373 				if (!inc.library) {
374 					File file = getClasspathElement(getDependancy(inc, mavenProject), mavenProject);
375 					inPath.add(file.toString());
376 					log.debug("--- ADD injars:" + inc.artifactId);
377 					StringBuffer filter = new StringBuffer(fileToString(file));
378 					filter.append("(!META-INF/MANIFEST.MF");
379 					if (!addMavenDescriptor) {
380 						filter.append(",");
381 						filter.append("!META-INF/maven/**");
382 					}
383 					if (inc.filter != null) {
384 						filter.append(",").append(inc.filter);
385 					}
386 					filter.append(")");
387 					args.add("-injars");
388 					args.add(filter.toString());
389 				} else {
390 					hasInclusionLibrary = true;
391 					log.debug("--- ADD libraryjars:" + inc.artifactId);
392 					// This may not be CompileArtifacts, maven 2.0.6 bug
393 					File file = getClasspathElement(getDependancy(inc, mavenProject), mavenProject);
394 					inPath.add(file.toString());
395 					args.add("-libraryjars");
396 					args.add(fileToString(file));
397 				}
398 			}
399 		}
400 
401 		if ((!mainIsPom) && inJarFile.exists()) {
402 			args.add("-injars");
403 			StringBuffer filter = new StringBuffer(fileToString(inJarFile));
404 			if ((inFilter != null) || (!addMavenDescriptor)) {
405 				filter.append("(");
406 				boolean coma = false;
407 
408 				if (!addMavenDescriptor) {
409 					coma = true;
410 					filter.append("!META-INF/maven/**");
411 				}
412 
413 				if (inFilter != null) {
414 					if (coma) {
415 						filter.append(",");
416 					}
417 					filter.append(inFilter);
418 				}
419 
420 				filter.append(")");
421 			}
422 			args.add(filter.toString());
423 		}
424 		args.add("-outjars");
425 		args.add(fileToString(outJarFile));
426 
427 		if (!obfuscate) {
428 			args.add("-dontobfuscate");
429 		}
430 
431 		if (proguardInclude != null) {
432 			if (proguardInclude.exists()) {
433 				args.add("-include");
434 				args.add(fileToString(proguardInclude));
435 				log.debug("proguardInclude " + proguardInclude);
436 			} else {
437 				log.debug("proguardInclude config does not exists " + proguardInclude);
438 			}
439 		}
440 
441 		if (includeDependency) {
442 			List dependency = this.mavenProject.getCompileArtifacts();
443 			for (Iterator i = dependency.iterator(); i.hasNext();) {
444 				Artifact artifact = (Artifact) i.next();
445 				// dependency filter
446 				if (isExclusion(artifact)) {
447 					continue;
448 				}
449 				File file = getClasspathElement(artifact, mavenProject);
450 
451 				if (inPath.contains(file.toString())) {
452 					log.debug("--- ignore libraryjars since one in injar:" + artifact.getArtifactId());
453 					continue;
454 				}
455 				log.debug("--- ADD libraryjars:" + artifact.getArtifactId());
456 				args.add("-libraryjars");
457 				args.add(fileToString(file));
458 			}
459 		}
460 
461 		if (libs != null) {
462 			for (Iterator i = libs.iterator(); i.hasNext();) {
463 				Object lib = i.next();
464 				args.add("-libraryjars");
465 				args.add(fileNameToString(lib.toString()));
466 			}
467 		}
468 
469 		args.add("-printmapping");
470 		args.add(fileToString((new File(outputDirectory, "proguard_map.txt").getAbsoluteFile())));
471 
472 		args.add("-printseeds");
473 		args.add(fileToString((new File(outputDirectory, "proguard_seeds.txt").getAbsoluteFile())));
474 
475 		if (log.isDebugEnabled()) {
476 			args.add("-verbose");
477 		}
478 
479 		if (options != null) {
480 			for (int i = 0; i < options.length; i++) {
481 				args.add(options[i]);
482 			}
483 		}
484 
485 		log.info("execute ProGuard " + args.toString());
486 		proguardMain(getProguardJar(this), args, this);
487 
488 		if ((assembly != null) && (hasInclusionLibrary)) {
489 
490 			log.info("creating assembly");
491 
492 			File baseFile = new File(outputDirectory, nameNoType(injar) + "_proguard_result.jar");
493 			if (baseFile.exists()) {
494 				if (!baseFile.delete()) {
495 					throw new MojoFailureException("Can't delete " + baseFile);
496 				}
497 			}
498 			File archiverFile = outJarFile.getAbsoluteFile();
499 			if (!outJarFile.renameTo(baseFile)) {
500 				throw new MojoFailureException("Can't rename " + outJarFile);
501 			}
502 
503 			MavenArchiver archiver = new MavenArchiver();
504 			archiver.setArchiver(jarArchiver);
505 			archiver.setOutputFile(archiverFile);
506 			archive.setAddMavenDescriptor(addMavenDescriptor);
507 
508 			try {
509 				jarArchiver.addArchivedFileSet(baseFile);
510 
511 				for (Iterator iter = assembly.inclusions.iterator(); iter.hasNext();) {
512 					Inclusion inc = (Inclusion) iter.next();
513 					if (inc.library) {
514 						File file;
515 						Artifact artifact = getDependancy(inc, mavenProject);
516 						file = getClasspathElement(artifact, mavenProject);
517 						if (file.isDirectory()) {
518 							getLog().info("merge project: " + artifact.getArtifactId() + " " + file);
519 							jarArchiver.addDirectory(file);
520 						} else {
521 							getLog().info("merge artifact: " + artifact.getArtifactId());
522 							jarArchiver.addArchivedFileSet(file);
523 						}
524 					}
525 				}
526 
527 				archiver.createArchive(mavenProject, archive);
528 
529 			} catch (Exception e) {
530 				throw new MojoExecutionException("Unable to create jar", e);
531 			}
532 
533 		}
534 
535 		if (attach && !sameArtifact) {
536 			if (useArtifactClassifier()) {
537 				projectHelper.attachArtifact(mavenProject, attachArtifactType, attachArtifactClassifier, outJarFile);
538 			} else {
539 				projectHelper.attachArtifact(mavenProject, attachArtifactType, null, outJarFile);
540 			}
541 		}
542 	}
543 
544 	private static File getProguardJar(ProGuardMojo mojo) throws MojoExecutionException {
545 
546 		Artifact proguardArtifact = null;
547 		int proguardArtifactDistance = -1;
548 		// This should be solved in Maven 2.1
549 		for (Iterator i = mojo.pluginArtifacts.iterator(); i.hasNext();) {
550 			Artifact artifact = (Artifact) i.next();
551 			mojo.getLog().debug("pluginArtifact: " + artifact.getFile());
552 			if ("proguard".equals(artifact.getArtifactId())) {
553 				int distance = artifact.getDependencyTrail().size();
554 				mojo.getLog().debug("proguard DependencyTrail: " + distance);
555 				if ((mojo.proguardVersion != null) && (mojo.proguardVersion.equals(artifact.getVersion()))) {
556 					proguardArtifact = artifact;
557 					break;
558 				} else if (proguardArtifactDistance == -1) {
559 					proguardArtifact = artifact;
560 					proguardArtifactDistance = distance;
561 				} else if (distance < proguardArtifactDistance) {
562 					proguardArtifact = artifact;
563 					proguardArtifactDistance = distance;
564 				}
565 			}
566 		}
567 		if (proguardArtifact != null) {
568 			mojo.getLog().debug("proguardArtifact: " + proguardArtifact.getFile());
569 			return proguardArtifact.getFile().getAbsoluteFile();
570 		}
571 		mojo.getLog().info("proguard jar not found in pluginArtifacts");
572 
573 		ClassLoader cl;
574 		cl = mojo.getClass().getClassLoader();
575 		// cl = Thread.currentThread().getContextClassLoader();
576 		String classResource = "/" + mojo.proguardMainClass.replace('.', '/') + ".class";
577 		URL url = cl.getResource(classResource);
578 		if (url == null) {
579 			throw new MojoExecutionException("Obfuscation failed ProGuard (" + mojo.proguardMainClass
580 					+ ") not found in classpath");
581 		}
582 		String proguardJar = url.toExternalForm();
583 		if (proguardJar.startsWith("jar:file:")) {
584 			proguardJar = proguardJar.substring("jar:file:".length());
585 			proguardJar = proguardJar.substring(0, proguardJar.indexOf('!'));
586 		} else {
587 			throw new MojoExecutionException("Unrecognized location (" + proguardJar + ") in classpath");
588 		}
589 		return new File(proguardJar);
590 	}
591 
592 	private static void proguardMain(File proguardJar, ArrayList argsList, ProGuardMojo mojo)
593 			throws MojoExecutionException {
594 
595 		Java java = new Java();
596 
597 		Project antProject = new Project();
598 		antProject.setName(mojo.mavenProject.getName());
599 		antProject.init();
600 
601 		DefaultLogger antLogger = new DefaultLogger();
602 		antLogger.setOutputPrintStream(System.out);
603 		antLogger.setErrorPrintStream(System.err);
604 		antLogger.setMessageOutputLevel(mojo.log.isDebugEnabled() ? Project.MSG_DEBUG : Project.MSG_INFO);
605 
606 		antProject.addBuildListener(antLogger);
607 		antProject.setBaseDir(mojo.mavenProject.getBasedir());
608 
609 		java.setProject(antProject);
610 		java.setTaskName("proguard");
611 
612 		mojo.getLog().info("proguard jar: " + proguardJar);
613 
614 		java.createClasspath().setLocation(proguardJar);
615 		// java.createClasspath().setPath(System.getProperty("java.class.path"));
616 		java.setClassname(mojo.proguardMainClass);
617 
618 		java.setFailonerror(true);
619 
620 		java.setFork(true);
621 
622 		// get the maxMemory setting
623 		if (mojo.maxMemory != null) {
624 			java.setMaxmemory(mojo.maxMemory);
625 		}
626 
627 		for (Iterator i = argsList.iterator(); i.hasNext();) {
628 			java.createArg().setValue(i.next().toString());
629 		}
630 
631 		int result = java.executeJava();
632 		if (result != 0) {
633 			throw new MojoExecutionException("Obfuscation failed (result=" + result + ")");
634 		}
635 	}
636 
637 	private static String nameNoType(String fileName) {
638 	    int extStart = fileName.lastIndexOf('.');
639 	    if (extStart == -1) {
640 	        return fileName;
641 	    }
642 		return fileName.substring(0, extStart);
643 	}
644 	
645 	private static boolean deleteFileOrDirectory(File path) throws MojoFailureException {
646         if (path.isDirectory()) {
647             File[] files = path.listFiles();
648             for (int i = 0; i < files.length; i++) {
649                 if (files[i].isDirectory()) {
650                     if (!deleteFileOrDirectory(files[i])) {
651                         throw new MojoFailureException("Can't delete dir " + files[i]);    
652                     }
653                 } else {
654                     if (!files[i].delete()) {
655                         throw new MojoFailureException("Can't delete file " + files[i]);  
656                     }
657                 }
658             }
659             return path.delete();
660         } else {
661             return path.delete();
662         }
663     }
664 
665 
666 	private static Artifact getDependancy(Inclusion inc, MavenProject mavenProject) throws MojoExecutionException {
667 		Set dependancy = mavenProject.getArtifacts();
668 		for (Iterator i = dependancy.iterator(); i.hasNext();) {
669 			Artifact artifact = (Artifact) i.next();
670 			if (inc.match(artifact)) {
671 				return artifact;
672 			}
673 		}
674 		throw new MojoExecutionException("artifactId Not found " + inc.artifactId);
675 	}
676 
677 	private boolean isExclusion(Artifact artifact) {
678 		if (exclusions == null) {
679 			return false;
680 		}
681 		for (Iterator iter = exclusions.iterator(); iter.hasNext();) {
682 			Exclusion excl = (Exclusion) iter.next();
683 			if (excl.match(artifact)) {
684 				return true;
685 			}
686 		}
687 		return false;
688 	}
689 
690 	private static File getClasspathElement(Artifact artifact, MavenProject mavenProject) throws MojoExecutionException {
691 		if (artifact.getClassifier() != null) {
692 			return artifact.getFile();
693 		}
694 		String refId = artifact.getGroupId() + ":" + artifact.getArtifactId();
695 		MavenProject project = (MavenProject) mavenProject.getProjectReferences().get(refId);
696 		if (project != null) {
697 			return new File(project.getBuild().getOutputDirectory());
698 		} else {
699 			File file = artifact.getFile();
700 			if ((file == null) || (!file.exists())) {
701 				throw new MojoExecutionException("Dependency Resolution Required " + artifact);
702 			}
703 			return file;
704 		}
705 	}
706 }