diff --git a/src/main/java/com/github/wvengen/maven/proguard/ProGuardMojo.java b/src/main/java/com/github/wvengen/maven/proguard/ProGuardMojo.java
index 7413b15e..a2af570f 100644
--- a/src/main/java/com/github/wvengen/maven/proguard/ProGuardMojo.java
+++ b/src/main/java/com/github/wvengen/maven/proguard/ProGuardMojo.java
@@ -20,15 +20,6 @@
*/
package com.github.wvengen.maven.proguard;
-import java.io.File;
-import java.io.IOException;
-import java.net.URL;
-import java.util.ArrayList;
-import java.util.Collections;
-import java.util.HashSet;
-import java.util.List;
-import java.util.Set;
-
import org.apache.maven.archiver.MavenArchiveConfiguration;
import org.apache.maven.archiver.MavenArchiver;
import org.apache.maven.artifact.Artifact;
@@ -41,10 +32,18 @@
import org.apache.maven.project.MavenProjectHelper;
import org.apache.tools.ant.DefaultLogger;
import org.apache.tools.ant.Project;
+import org.apache.tools.ant.Target;
+import org.apache.tools.ant.taskdefs.Expand;
import org.apache.tools.ant.taskdefs.Java;
import org.codehaus.plexus.archiver.jar.JarArchiver;
import org.codehaus.plexus.util.FileUtils;
+import java.io.File;
+import java.io.FilenameFilter;
+import java.io.IOException;
+import java.net.URL;
+import java.util.*;
+
/**
*
*
@@ -238,6 +237,36 @@ public class ProGuardMojo extends AbstractMojo {
*/
private boolean appendClassifier;
+ /**
+ * Specifies attach proguard map artifact type
+ *
+ * @parameter default-value="txt"
+ */
+ private String attachMapArtifactType = "txt";
+
+ /**
+ * Specifies attach proguard seed artifact type
+ *
+ * @parameter default-value="txt"
+ */
+ private String attachSeedArtifactType = "txt";
+
+ /**
+ * Specifies attach artifact Classifier, ignored if attachMap=false
+ *
+ * @parameter default-value="proguard-map"
+ */
+ private String attachMapArtifactClassifier = "proguard-map";
+
+ /**
+ * Specifies attach artifact Classifier, ignored if attachSeed=false
+ *
+ * @parameter default-value="proguard-seed"
+ */
+ private String attachSeedArtifactClassifier = "proguard-seed";
+
+
+
/**
* Set to true to include META-INF/maven/** maven descriptord
*
@@ -307,6 +336,13 @@ public class ProGuardMojo extends AbstractMojo {
*/
protected String proguardMainClass = "proguard.ProGuard";
+ /**
+ * Specifies whether or not to pass war's WEB-INF/classes/ directory to Proguard.
+ *
+ * @parameter default-value="true"
+ */
+ private boolean processWarClassesDir = true;
+
/**
* Sets the name of the ProGuard mapping file.
*
@@ -354,6 +390,14 @@ private boolean useArtifactClassifier() {
return appendClassifier && ((attachArtifactClassifier != null) && (attachArtifactClassifier.length() > 0));
}
+ private boolean useMapArtifactClassifier() {
+ return ((attachMapArtifactClassifier != null) && (attachMapArtifactClassifier.length() > 0));
+ }
+
+ private boolean useSeedArtifactClassifier() {
+ return ((attachSeedArtifactClassifier != null) && (attachSeedArtifactClassifier.length() > 0));
+ }
+
public void execute() throws MojoExecutionException, MojoFailureException {
log = getLog();
@@ -375,6 +419,35 @@ public void execute() throws MojoExecutionException, MojoFailureException {
}
}
+ // check and extract war
+ boolean processingWar = false;
+ boolean mainIsWar = mavenProject.getPackaging().equals("war");
+ File expandedDir = null;
+ File priorityLibsDir = null;
+ if (mainIsWar) {
+ processingWar = injar.endsWith(".war");
+ if (processingWar) {
+ expandedDir = (new File(outputDirectory, nameNoType(injar) + "_war_proguard_expanded")).getAbsoluteFile();
+ if (expandedDir.exists()) {
+ if (!deleteFileOrDirectory(expandedDir)) {
+ throw new MojoFailureException("Can't delete " + expandedDir);
+ }
+ }
+ if (!expandedDir.mkdirs()) {
+ throw new MojoFailureException("Can't create " + outputDirectory);
+ }
+
+ try {
+ unzip(inJarFile, expandedDir);
+ } catch (IOException e) {
+ throw new MojoFailureException("Can't extract " + inJarFile, e);
+ }
+
+ priorityLibsDir = new File(expandedDir, "WEB-INF/lib");
+ }
+ }
+
+
if (!outputDirectory.exists()) {
if (!outputDirectory.mkdirs()) {
throw new MojoFailureException("Can't create " + outputDirectory);
@@ -392,7 +465,20 @@ public void execute() throws MojoExecutionException, MojoFailureException {
outjar += "." + attachArtifactType;
}
- if ((outjar != null) && (!outjar.equals(injar))) {
+ if (processingWar) {
+ // When processing war, we update outJarFile to point to proguarded jar
+ if (outjar == null) {
+ outjar = injar;
+ }
+ String outJarName = nameNoType(outjar) + ".jar";
+ outJarFile = (new File(priorityLibsDir, outJarName)).getAbsoluteFile();
+ if (outJarFile.exists()) {
+ if (!deleteFileOrDirectory(outJarFile)) {
+ throw new MojoFailureException("Can't delete " + outJarFile);
+ }
+ }
+ sameArtifact = (outjar != null) && (outjar.equals(injar));
+ } else if ((outjar != null) && (!outjar.equals(injar))) {
sameArtifact = false;
outJarFile = (new File(outputDirectory, outjar)).getAbsoluteFile();
if (outJarFile.exists()) {
@@ -447,66 +533,80 @@ public void execute() throws MojoExecutionException, MojoFailureException {
}
}
+ Set inFiles = new HashSet();
+
+ if (processingWar) {
+ File classesDir = new File(expandedDir, "WEB-INF/classes");
+ if (processWarClassesDir) {
+ File classesDirInput = new File(expandedDir, "WEB-INF/classes_input");
+ classesDir.renameTo(classesDirInput);
+
+ args.add("-injars");
+ args.add(fileToString(classesDirInput));
+ inFiles.add(classesDirInput);
+
+ // class files are processes separately!
+ args.add("-outjars");
+ args.add(fileToString(classesDir));
+
+ } else {
+ args.add("-libraryjars");
+ args.add(fileToString(classesDir));
+ }
+ }
+
Set inPath = new HashSet();
boolean hasInclusionLibrary = false;
if (assembly != null && assembly.inclusions != null) {
@SuppressWarnings("unchecked")
final List inclusions = assembly.inclusions;
for (Inclusion inc : inclusions) {
- if (!inc.library) {
- File file = getClasspathElement(getDependency(inc, mavenProject), mavenProject);
- inPath.add(file.toString());
- log.debug("--- ADD injars:" + inc.artifactId);
- StringBuilder filter = new StringBuilder(fileToString(file));
- filter.append("(!META-INF/MANIFEST.MF");
- if (!addMavenDescriptor) {
- filter.append(",");
- filter.append("!META-INF/maven/**");
- }
- if (inc.filter != null) {
- filter.append(",").append(inc.filter);
- }
- filter.append(")");
- args.add("-injars");
- args.add(filter.toString());
- } else {
- hasInclusionLibrary = true;
- log.debug("--- ADD libraryjars:" + inc.artifactId);
- // This may not be CompileArtifacts, maven 2.0.6 bug
- File file = getClasspathElement(getDependency(inc, mavenProject), mavenProject);
- inPath.add(file.toString());
- if(putLibraryJarsInTempDir){
- libraryJars.add(file);
+ Set deps = getDependancies(inc, mavenProject); // get all matching dependencies as wildcard may have been used
+ for (Artifact artifact : deps) {
+ if (!inc.library) {
+ File file = getClasspathElement(artifact, mavenProject, priorityLibsDir);
+ if (processingWar && "*".equals(inc.artifactId) && !priorityLibsDir.equals(file.getParentFile())) {
+ log.debug("Wildcard matching artifact will be included as a library (as does not belong to enclosed libs): " + file);
+ inPath.add(file.toString());
+ args.add("-libraryjars");
+ args.add(fileToString(file));
+ continue;
+ }
+ inPath.add(file.toString());
+ log.debug("--- ADD injars:" + inc.artifactId);
+ StringBuffer filter = new StringBuffer(fileToString(file));
+ filter.append("(!META-INF/MANIFEST.MF");
+ if (!addMavenDescriptor) {
+ filter.append(",");
+ filter.append("!META-INF/maven/**");
+ }
+ if (inc.filter != null) {
+ filter.append(",").append(inc.filter);
+ }
+ filter.append(")");
+ inFiles.add(file);
+ args.add("-injars");
+ args.add(filter.toString());
} else {
- args.add("-libraryjars");
- args.add(fileToString(file));
+ hasInclusionLibrary = true;
+ log.debug("--- ADD libraryjars:" + inc.artifactId);
+ // This may not be CompileArtifacts, maven 2.0.6 bug
+ File file = getClasspathElement(artifact, mavenProject, priorityLibsDir);
+ inPath.add(file.toString());
+ if(putLibraryJarsInTempDir){
+ libraryJars.add(file);
+ } else {
+ args.add("-libraryjars");
+ args.add(fileToString(file));
+ }
}
}
}
}
- if (inJarFile.exists()) {
+ if (inJarFile.exists() && !processingWar) {
args.add("-injars");
- StringBuilder filter = new StringBuilder(fileToString(inJarFile));
- if ((inFilter != null) || (!addMavenDescriptor)) {
- filter.append("(");
- boolean coma = false;
-
- if (!addMavenDescriptor) {
- coma = true;
- filter.append("!META-INF/maven/**");
- }
-
- if (inFilter != null) {
- if (coma) {
- filter.append(",");
- }
- filter.append(inFilter);
- }
-
- filter.append(")");
- }
- args.add(filter.toString());
+ args.add(buildJarReference(inJarFile, inFilter));
}
@@ -518,7 +618,7 @@ public void execute() throws MojoExecutionException, MojoFailureException {
if (isExclusion(artifact)) {
continue;
}
- File file = getClasspathElement(artifact, mavenProject);
+ File file = getClasspathElement(artifact, mavenProject, priorityLibsDir);
if (inPath.contains(file.toString())) {
log.debug("--- ignore library since one in injar:" + artifact.getArtifactId());
@@ -526,6 +626,7 @@ public void execute() throws MojoExecutionException, MojoFailureException {
}
if (includeDependencyInjar) {
log.debug("--- ADD library as injars:" + artifact.getArtifactId());
+ inFiles.add(file);
args.add("-injars");
args.add(fileToString(file));
} else {
@@ -542,12 +643,8 @@ public void execute() throws MojoExecutionException, MojoFailureException {
if (args.contains("-injars")) {
args.add("-outjars");
- StringBuilder filter = new StringBuilder(fileToString(outJarFile));
- if (outFilter != null) {
- filter.append("(").append(outFilter).append(")");
- }
- args.add(filter.toString());
- }
+ args.add(buildJarReference(outJarFile, outFilter));
+ }
if (!obfuscate) {
args.add("-dontobfuscate");
@@ -599,11 +696,13 @@ public void execute() throws MojoExecutionException, MojoFailureException {
args.add(fileToString(tempLibraryjarsDir));
}
+ File proguardMapFile = (new File(outputDirectory, mappingFileName).getAbsoluteFile());
args.add("-printmapping");
- args.add(fileToString((new File(outputDirectory, mappingFileName).getAbsoluteFile())));
+ args.add(fileToString(proguardMapFile));
+ File proguardSeedFile = (new File(outputDirectory, seedFileName).getAbsoluteFile());
args.add("-printseeds");
- args.add(fileToString((new File(outputDirectory,seedFileName).getAbsoluteFile())));
+ args.add(fileToString(proguardSeedFile));
if (log.isDebugEnabled()) {
args.add("-verbose");
@@ -613,9 +712,24 @@ public void execute() throws MojoExecutionException, MojoFailureException {
Collections.addAll(args, options);
}
- log.info("execute ProGuard " + args.toString());
+ log.debug("Run Proguard with options" + args.toString());
proguardMain(getProguardJar(this), args, this);
+ if (processingWar) {
+ for (File f : inFiles) {
+ if (f.isDirectory()) {
+ log.info("Removing proguarded: " + f);
+ if (!deleteFileOrDirectory(f)) {
+ throw new MojoFailureException("Can't delete " + f);
+ }
+ } else if (priorityLibsDir.equals(f.getParentFile())) {
+ log.info("Removing proguarded: " + f);
+ if (!deleteFileOrDirectory(f)) {
+ throw new MojoFailureException("Can't delete " + f);
+ }
+ }
+ }
+ }
if (!libraryJars.isEmpty()) {
deleteFileOrDirectory(tempLibraryjarsDir);
@@ -648,8 +762,8 @@ public void execute() throws MojoExecutionException, MojoFailureException {
for (Inclusion inc : inclusions) {
if (inc.library) {
File file;
- Artifact artifact = getDependency(inc, mavenProject);
- file = getClasspathElement(artifact, mavenProject);
+ Artifact artifact = getDependancy(inc, mavenProject);
+ file = getClasspathElement(artifact, mavenProject, priorityLibsDir);
if (file.isDirectory()) {
getLog().info("merge project: " + artifact.getArtifactId() + " " + file);
jarArchiver.addDirectory(file);
@@ -662,12 +776,37 @@ public void execute() throws MojoExecutionException, MojoFailureException {
archiver.createArchive(mavenProject, archive);
+ // delete baseFile right away so we don't include it in war
+ if (!baseFile.delete()) {
+ throw new MojoFailureException("Can't delete " + baseFile);
+ }
+
} catch (Exception e) {
throw new MojoExecutionException("Unable to create jar", e);
}
}
+ if (processingWar) {
+ File outputWar = new File(outputDirectory, outjar);
+ if (outputWar.exists()) {
+ if (!outputWar.delete()) {
+ throw new MojoFailureException("Can't delete " + outputWar);
+ }
+ }
+ MavenArchiver archiver = new MavenArchiver();
+ archiver.setArchiver(jarArchiver);
+ archiver.setOutputFile(outputWar);
+ archive.setAddMavenDescriptor(addMavenDescriptor);
+ try {
+ jarArchiver.addDirectory(expandedDir);
+ archiver.createArchive(mavenProject, archive);
+ } catch (Exception e) {
+ throw new MojoExecutionException("Unable to create war", e);
+ }
+ outJarFile = outputWar;
+ }
+
if (attach) {
if (!sameArtifact) {
final String classifier;
@@ -689,6 +828,28 @@ public void execute() throws MojoExecutionException, MojoFailureException {
attachTextFile(new File(buildOutput, seedFileName), mainClassifier, "seed");
}
}
+
+ if (attachMap && attach) {
+ if (!proguardMapFile.exists()) {
+ log.warn("Cannot attach proguard map artifact as file does nto exist.");
+ } else if (useMapArtifactClassifier()) {
+ projectHelper.attachArtifact(mavenProject, attachMapArtifactType, attachMapArtifactClassifier, proguardMapFile);
+ } else {
+ throw new MojoExecutionException("Map artifact classifier cannot be empty");
+// projectHelper.attachArtifact(mavenProject, attachMapArtifactType, null, proguardMapFile);
+ }
+ }
+
+ if (attachSeed && attach) {
+ if (!proguardSeedFile.exists()) {
+ log.warn("Cannot attach proguard seed artifact as file does nto exist.");
+ } else if (useSeedArtifactClassifier()) {
+ projectHelper.attachArtifact(mavenProject, attachSeedArtifactType, attachSeedArtifactClassifier, proguardSeedFile);
+ } else {
+ throw new MojoExecutionException("Seed artifact classifier cannot be empty");
+// projectHelper.attachArtifact(mavenProject, attachSeedArtifactType, null, proguardSeedFile);
+ }
+ }
}
private void attachTextFile(File theFile, String mainClassifier, String suffix) {
@@ -845,8 +1006,21 @@ private boolean deleteFileOrDirectory(File path) throws MojoFailureException {
}
}
+ private static Set getDependancies(Inclusion inc, MavenProject mavenProject) throws MojoExecutionException {
+ @SuppressWarnings("unchecked")
+ Set artifacts = mavenProject.getArtifacts();
+ Set dependencies = new HashSet();
+ for (Artifact artifact: artifacts) {
+ if (inc.match(artifact)) {
+ dependencies.add(artifact);
+ }
+ }
+ if (dependencies.size() == 0)
+ throw new MojoExecutionException("artifactId Not found " + inc.artifactId);
+ return dependencies;
+ }
- private Artifact getDependency(Inclusion inc, MavenProject mavenProject) throws MojoExecutionException {
+ private static Artifact getDependancy(Inclusion inc, MavenProject mavenProject) throws MojoExecutionException {
@SuppressWarnings("unchecked")
Set dependency = mavenProject.getArtifacts();
for (Artifact artifact : dependency) {
@@ -869,7 +1043,7 @@ private boolean isExclusion(Artifact artifact) {
return false;
}
- private File getClasspathElement(Artifact artifact, MavenProject mavenProject) throws MojoExecutionException {
+ private File getClasspathElement(Artifact artifact, MavenProject mavenProject, File libsDir) throws MojoExecutionException {
if (artifact.getClassifier() != null) {
return artifact.getFile();
}
@@ -878,6 +1052,25 @@ private File getClasspathElement(Artifact artifact, MavenProject mavenProject) t
if (project != null) {
return new File(project.getBuild().getOutputDirectory());
} else {
+
+ if (libsDir != null) {
+ final String filenameBase = artifact.getArtifactId() + "-";
+ File[] artifactFilesInLib = libsDir.listFiles(new FilenameFilter() {
+ public boolean accept(File dir, String name) {
+ if (name.startsWith(filenameBase) && name.length() > filenameBase.length() + 4) {
+ // check if the first char after base name is a digit (assuming version number)
+ boolean digitFound = Character.isDigit(name.charAt(filenameBase.length()));
+ return digitFound;
+ }
+ return false;
+ }
+ });
+ if (artifactFilesInLib.length > 1)
+ System.out.println("Warn: Found more than one library for artifact " + artifact + ": " + artifactFilesInLib);
+ if (artifactFilesInLib.length > 0)
+ return artifactFilesInLib[0];
+ }
+
File file = artifact.getFile();
if ((file == null) || (!file.exists())) {
throw new MojoExecutionException("Dependency Resolution Required " + artifact);
@@ -885,4 +1078,46 @@ private File getClasspathElement(Artifact artifact, MavenProject mavenProject) t
return file;
}
}
+
+ /**
+ * Unzips archive from the given path to the given destination dir.
+ */
+ private static void unzip(File archiveFile, File destDir) throws IOException, MojoFailureException {
+ final class Expander extends Expand {
+ public Expander() {
+ project = new Project();
+ project.init();
+ taskType = "unzip";
+ taskName = "unzip";
+ target = new Target();
+ }
+ }
+ Expander expander = new Expander();
+ expander.setSrc(archiveFile);
+ expander.setDest(destDir);
+ expander.execute();
+ }
+
+ private String buildJarReference(File jarFile, String jarFilter) {
+ StringBuffer filter = new StringBuffer(fileToString(jarFile));
+ if ((jarFilter != null) || (!addMavenDescriptor)) {
+ filter.append("(");
+ boolean coma = false;
+
+ if (!addMavenDescriptor) {
+ coma = true;
+ filter.append("!META-INF/maven/**");
+ }
+
+ if (jarFilter != null) {
+ if (coma) {
+ filter.append(",");
+ }
+ filter.append(jarFilter);
+ }
+
+ filter.append(")");
+ }
+ return filter.toString();
+ }
}