Can process 'provided' dependencies and include their modified classes in the projects classes output directory
1.1 --- a/html4j-maven-plugin/src/main/java/org/apidesign/html/mojo/ProcessJsAnnotationsMojo.java Mon Nov 25 09:44:59 2013 +0100
1.2 +++ b/html4j-maven-plugin/src/main/java/org/apidesign/html/mojo/ProcessJsAnnotationsMojo.java Mon Nov 25 13:33:48 2013 +0100
1.3 @@ -22,8 +22,16 @@
1.4
1.5 import java.io.File;
1.6 import java.io.FileInputStream;
1.7 +import java.io.FileNotFoundException;
1.8 import java.io.FileOutputStream;
1.9 import java.io.IOException;
1.10 +import java.io.InputStream;
1.11 +import java.util.Enumeration;
1.12 +import java.util.HashMap;
1.13 +import java.util.Map;
1.14 +import java.util.zip.ZipEntry;
1.15 +import java.util.zip.ZipFile;
1.16 +import org.apache.maven.artifact.Artifact;
1.17 import org.apache.maven.plugin.AbstractMojo;
1.18 import org.apache.maven.plugin.MojoExecutionException;
1.19 import org.apache.maven.plugin.MojoFailureException;
1.20 @@ -36,7 +44,7 @@
1.21
1.22 @Mojo(
1.23 name="process-js-annotations",
1.24 - requiresDependencyResolution = ResolutionScope.RUNTIME,
1.25 + requiresDependencyResolution = ResolutionScope.COMPILE_PLUS_RUNTIME,
1.26 defaultPhase= LifecyclePhase.PROCESS_CLASSES
1.27 )
1.28 public final class ProcessJsAnnotationsMojo extends AbstractMojo {
1.29 @@ -45,6 +53,13 @@
1.30
1.31 @Parameter(defaultValue = "${project.build.directory}/classes")
1.32 private File classes;
1.33 +
1.34 + /** Checks all "provided" dependency JAR files and if they contain
1.35 + * usage of JavaScriptXXX annotation, their classes are expanded into the
1.36 + * <code>classes</code> directory.
1.37 + */
1.38 + @Parameter(defaultValue = "false")
1.39 + private boolean processProvided;
1.40
1.41 public ProcessJsAnnotationsMojo() {
1.42 }
1.43 @@ -52,18 +67,34 @@
1.44 @Override
1.45 public void execute() throws MojoExecutionException, MojoFailureException {
1.46 try {
1.47 - processClasess(classes);
1.48 + processClasses(classes);
1.49 } catch (IOException ex) {
1.50 throw new MojoExecutionException("Problem converting JavaScriptXXX annotations", ex);
1.51 }
1.52 +
1.53 + if (processProvided) {
1.54 + for (Artifact a : prj.getArtifacts()) {
1.55 + if (!"provided".equals(a.getScope())) {
1.56 + continue;
1.57 + }
1.58 + final File f = a.getFile();
1.59 + if (f != null) {
1.60 + try {
1.61 + processClasses(f, classes);
1.62 + } catch (IOException ex) {
1.63 + throw new MojoExecutionException("Problem converting JavaScriptXXX annotations in " + f, ex);
1.64 + }
1.65 + }
1.66 + }
1.67 + }
1.68 }
1.69
1.70 - private void processClasess(File f) throws IOException, MojoExecutionException {
1.71 + private void processClasses(File f) throws IOException, MojoExecutionException {
1.72 if (f.isDirectory()) {
1.73 File[] arr = f.listFiles();
1.74 if (arr != null) {
1.75 for (File file : arr) {
1.76 - processClasess(file);
1.77 + processClasses(file);
1.78 }
1.79 }
1.80 return;
1.81 @@ -79,14 +110,7 @@
1.82 byte[] arr = new byte[(int)f.length()];
1.83 FileInputStream is = new FileInputStream(f);
1.84 try {
1.85 - int off = 0;
1.86 - while (off< arr.length) {
1.87 - int read = is.read(arr, off, arr.length - off);
1.88 - if (read == -1) {
1.89 - break;
1.90 - }
1.91 - off += read;
1.92 - }
1.93 + readArr(arr, is);
1.94 } finally {
1.95 is.close();
1.96 }
1.97 @@ -95,9 +119,71 @@
1.98 if (newArr == null || newArr == arr) {
1.99 return;
1.100 }
1.101 + getLog().info("Processing " + f);
1.102 + writeArr(f, newArr);
1.103 + }
1.104 +
1.105 + private void writeArr(File f, byte[] newArr) throws IOException, FileNotFoundException {
1.106 + FileOutputStream os = new FileOutputStream(f);
1.107 + try {
1.108 + os.write(newArr);
1.109 + } finally {
1.110 + os.close();
1.111 + }
1.112 + }
1.113 +
1.114 + private static void readArr(byte[] arr, InputStream is) throws IOException {
1.115 + int off = 0;
1.116 + while (off< arr.length) {
1.117 + int read = is.read(arr, off, arr.length - off);
1.118 + if (read == -1) {
1.119 + break;
1.120 + }
1.121 + off += read;
1.122 + }
1.123 + }
1.124 +
1.125 + private void processClasses(File jar, File target) throws IOException {
1.126 + ZipFile zf = new ZipFile(jar);
1.127 + Enumeration<? extends ZipEntry> en = zf.entries();
1.128 + Map<String,byte[]> waiting = new HashMap<String, byte[]>();
1.129 + boolean found = false;
1.130 + while (en.hasMoreElements()) {
1.131 + ZipEntry ze = en.nextElement();
1.132 + if (ze.getName().endsWith("/")) {
1.133 + continue;
1.134 + }
1.135 + byte[] arr = new byte[(int)ze.getSize()];
1.136 + InputStream is = zf.getInputStream(ze);
1.137 + try {
1.138 + readArr(arr, is);
1.139 + } finally {
1.140 + is.close();
1.141 + }
1.142 + if (ze.getName().endsWith(".class")) {
1.143 + byte[] newArr = FnUtils.transform(arr, null);
1.144 + if (newArr == null || newArr == arr) {
1.145 + waiting.put(ze.getName(), arr);
1.146 + continue;
1.147 + }
1.148 + File t = new File(target, ze.getName().replace('/', File.separatorChar));
1.149 + t.getParentFile().mkdirs();
1.150 + writeArr(t, newArr);
1.151 + found = true;
1.152 + getLog().info("Found " + ze.getName() + " in " + jar + " - will copy all classes");
1.153 + } else {
1.154 + waiting.put(ze.getName(), arr);
1.155 + }
1.156 + }
1.157
1.158 - FileOutputStream os = new FileOutputStream(f);
1.159 - os.write(newArr);
1.160 - os.close();
1.161 + if (found) {
1.162 + for (Map.Entry<String, byte[]> entry : waiting.entrySet()) {
1.163 + String name = entry.getKey();
1.164 + byte[] arr = entry.getValue();
1.165 + File t = new File(target, name.replace('/', File.separatorChar));
1.166 + t.getParentFile().mkdirs();
1.167 + writeArr(t, arr);
1.168 + }
1.169 + }
1.170 }
1.171 }