Maven mojo to generate the Javascript during compilation phase
authorJaroslav Tulach <jaroslav.tulach@apidesign.org>
Tue, 16 Oct 2012 16:51:22 +0200
changeset 109b19d12a9e6d5
parent 108 7e3f72897a83
child 110 2428122fb24d
Maven mojo to generate the Javascript during compilation phase
htmlpage/pom.xml
mojo/pom.xml
mojo/src/main/java/org/apidesign/bck2brwsr/mojo/Bck2BrswrMojo.java
pom.xml
vm/src/main/java/org/apidesign/vm4brwsr/GenJS.java
     1.1 --- a/htmlpage/pom.xml	Tue Oct 16 13:23:04 2012 +0200
     1.2 +++ b/htmlpage/pom.xml	Tue Oct 16 16:51:22 2012 +0200
     1.3 @@ -7,7 +7,7 @@
     1.4      <artifactId>bck2brwsr</artifactId>
     1.5      <version>1.0-SNAPSHOT</version>
     1.6    </parent>
     1.7 -  <groupId>org.apidesign</groupId>
     1.8 +  <groupId>org.apidesign.bck2brwsr</groupId>
     1.9    <artifactId>htmlpage</artifactId>
    1.10    <version>1.0-SNAPSHOT</version>
    1.11    <name>htmlpage</name>
     2.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
     2.2 +++ b/mojo/pom.xml	Tue Oct 16 16:51:22 2012 +0200
     2.3 @@ -0,0 +1,66 @@
     2.4 +<?xml version="1.0"?>
     2.5 +<project xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd" xmlns="http://maven.apache.org/POM/4.0.0"
     2.6 +    xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
     2.7 +  <modelVersion>4.0.0</modelVersion>
     2.8 +  <parent>
     2.9 +    <groupId>org.apidesign</groupId>
    2.10 +    <artifactId>bck2brwsr</artifactId>
    2.11 +    <version>1.0-SNAPSHOT</version>
    2.12 +  </parent>
    2.13 +  <groupId>org.apidesign.bck2brwsr</groupId>
    2.14 +  <artifactId>mojo</artifactId>
    2.15 +  <version>1.0-SNAPSHOT</version>
    2.16 +  <packaging>maven-plugin</packaging>
    2.17 +  <name>Maven Mojo to Compile to JavaScript</name>
    2.18 +  <url>http://maven.apache.org</url>
    2.19 +      <build>
    2.20 +        <plugins>
    2.21 +            <plugin>
    2.22 +                <groupId>org.apache.maven.plugins</groupId>
    2.23 +                <artifactId>maven-plugin-plugin</artifactId>
    2.24 +                <version>3.1</version>
    2.25 +                <configuration>
    2.26 +                    <extractors>
    2.27 +                        <extractor>java-annotations</extractor>
    2.28 +                    </extractors>
    2.29 +                    <skipErrorNoDescriptorsFound>true</skipErrorNoDescriptorsFound>
    2.30 +                 </configuration>
    2.31 +                <executions>
    2.32 +                    <execution>
    2.33 +                        <id>mojo-descriptor</id>
    2.34 +                        <phase>process-classes</phase>
    2.35 +                        <goals>
    2.36 +                            <goal>descriptor</goal>
    2.37 +                        </goals>
    2.38 +                    </execution>
    2.39 +                </executions>
    2.40 +            </plugin>
    2.41 +        </plugins>
    2.42 +      </build>
    2.43 +      
    2.44 +<dependencies>
    2.45 +    <dependency>
    2.46 +      <groupId>org.apache.maven</groupId>
    2.47 +      <artifactId>maven-plugin-api</artifactId>
    2.48 +      <version>3.0.4</version>
    2.49 +      <type>jar</type>
    2.50 +    </dependency>
    2.51 +    <dependency>
    2.52 +      <groupId>org.apache.maven.plugin-tools</groupId>
    2.53 +      <artifactId>maven-plugin-annotations</artifactId>
    2.54 +      <version>3.0</version>
    2.55 +      <type>jar</type>
    2.56 +    </dependency>
    2.57 +    <dependency>
    2.58 +      <groupId>${project.groupId}</groupId>
    2.59 +      <artifactId>vm4brwsr</artifactId>
    2.60 +      <version>0.1-SNAPSHOT</version>
    2.61 +    </dependency>
    2.62 +    <dependency>
    2.63 +        <groupId>org.apache.maven</groupId>
    2.64 +        <artifactId>maven-core</artifactId>
    2.65 +      <version>3.0.2</version>
    2.66 +      <type>jar</type>
    2.67 +    </dependency>
    2.68 +</dependencies>
    2.69 +</project>
     3.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
     3.2 +++ b/mojo/src/main/java/org/apidesign/bck2brwsr/mojo/Bck2BrswrMojo.java	Tue Oct 16 16:51:22 2012 +0200
     3.3 @@ -0,0 +1,100 @@
     3.4 +package org.apidesign.bck2brwsr.mojo;
     3.5 +
     3.6 +import org.apache.maven.plugin.AbstractMojo;
     3.7 +
     3.8 +import java.io.File;
     3.9 +import java.io.FileWriter;
    3.10 +import java.lang.reflect.Method;
    3.11 +import java.net.MalformedURLException;
    3.12 +import java.net.URL;
    3.13 +import java.net.URLClassLoader;
    3.14 +import java.util.ArrayList;
    3.15 +import java.util.Collection;
    3.16 +import java.util.List;
    3.17 +import org.apache.maven.artifact.Artifact;
    3.18 +import org.apache.maven.model.Dependency;
    3.19 +import org.apache.maven.plugin.MojoExecutionException;
    3.20 +import org.apache.maven.plugins.annotations.Component;
    3.21 +import org.apache.maven.plugins.annotations.LifecyclePhase;
    3.22 +import org.apache.maven.plugins.annotations.Mojo;
    3.23 +import org.apache.maven.plugins.annotations.Parameter;
    3.24 +import org.apache.maven.project.MavenProject;
    3.25 +
    3.26 +/** Compiles classes into JavaScript. */
    3.27 +@Mojo(name="j2js", defaultPhase=LifecyclePhase.PROCESS_CLASSES)
    3.28 +public class Bck2BrswrMojo extends AbstractMojo {
    3.29 +    public Bck2BrswrMojo() {
    3.30 +    }
    3.31 +    /** Root of the class files */
    3.32 +    @Parameter(defaultValue="${project.build.directory}/classes")
    3.33 +    private File classes;
    3.34 +    /** File to generate. Defaults bootjava.js in the first non-empty 
    3.35 +     package under the classes directory */
    3.36 +    @Parameter
    3.37 +    private File javascript;
    3.38 +    
    3.39 +    @Parameter(defaultValue="${project}")
    3.40 +    private MavenProject prj;
    3.41 +    
    3.42 +    
    3.43 +
    3.44 +    @Override
    3.45 +    public void execute() throws MojoExecutionException {
    3.46 +        if (!classes.isDirectory()) {
    3.47 +            throw new MojoExecutionException("Can't find " + classes);
    3.48 +        }
    3.49 +
    3.50 +        if (javascript == null) {
    3.51 +            javascript = new File(findNonEmptyFolder(classes), "bootjava.js");
    3.52 +        }
    3.53 +
    3.54 +        List<String> arr = new ArrayList<String>();
    3.55 +        collectAllClasses("", classes, arr);
    3.56 +        
    3.57 +        
    3.58 +
    3.59 +        try {
    3.60 +            URLClassLoader url = buildClassLoader(classes, prj.getDependencyArtifacts());
    3.61 +            
    3.62 +            Class<?> c = Class.forName("org.apidesign.vm4brwsr.GenJS");
    3.63 +            Method m = c.getDeclaredMethod("compile", ClassLoader.class, Appendable.class, List.class);
    3.64 +            m.setAccessible(true);
    3.65 +            FileWriter w = new FileWriter(javascript);
    3.66 +            m.invoke(null, url, w, arr);
    3.67 +            w.close();
    3.68 +        } catch (Exception ex) {
    3.69 +            throw new MojoExecutionException("Can't compile", ex);
    3.70 +        }
    3.71 +    }
    3.72 +
    3.73 +    private static File findNonEmptyFolder(File dir) throws MojoExecutionException {
    3.74 +        if (!dir.isDirectory()) {
    3.75 +            throw new MojoExecutionException("Not a directory " + dir);
    3.76 +        }
    3.77 +        File[] arr = dir.listFiles();
    3.78 +        if (arr.length == 1 && arr[0].isDirectory()) {
    3.79 +            return findNonEmptyFolder(arr[0]);
    3.80 +        }
    3.81 +        return dir;
    3.82 +    }
    3.83 +
    3.84 +    private static void collectAllClasses(String prefix, File toCheck, List<String> arr) {
    3.85 +        File[] files = toCheck.listFiles();
    3.86 +        if (files != null) {
    3.87 +            for (File f : files) {
    3.88 +                collectAllClasses(prefix + f.getName() + "/", f, arr);
    3.89 +            }
    3.90 +        } else if (toCheck.getName().endsWith(".class")) {
    3.91 +            arr.add(prefix.substring(0, prefix.length() - 7));
    3.92 +        }
    3.93 +    }
    3.94 +
    3.95 +    private static URLClassLoader buildClassLoader(File root, Collection<Artifact> deps) throws MalformedURLException {
    3.96 +        List<URL> arr = new ArrayList<URL>();
    3.97 +        arr.add(root.toURI().toURL());
    3.98 +        for (Artifact a : deps) {
    3.99 +            arr.add(a.getFile().toURI().toURL());
   3.100 +        }
   3.101 +        return new URLClassLoader(arr.toArray(new URL[0]), Bck2BrswrMojo.class.getClassLoader());
   3.102 +    }
   3.103 +}
     4.1 --- a/pom.xml	Tue Oct 16 13:23:04 2012 +0200
     4.2 +++ b/pom.xml	Tue Oct 16 16:51:22 2012 +0200
     4.3 @@ -11,6 +11,7 @@
     4.4      <module>htmlpage</module>
     4.5      <module>emul</module>
     4.6      <module>core</module>
     4.7 +    <module>mojo</module>
     4.8    </modules>
     4.9    <licenses>
    4.10        <license>
     5.1 --- a/vm/src/main/java/org/apidesign/vm4brwsr/GenJS.java	Tue Oct 16 13:23:04 2012 +0200
     5.2 +++ b/vm/src/main/java/org/apidesign/vm4brwsr/GenJS.java	Tue Oct 16 16:51:22 2012 +0200
     5.3 @@ -55,6 +55,9 @@
     5.4          compile(out, Arrays.asList(names));
     5.5      }
     5.6      static void compile(Appendable out, List<String> names) throws IOException {
     5.7 +        compile(GenJS.class.getClassLoader(), out, names);
     5.8 +    }
     5.9 +    static void compile(ClassLoader l, Appendable out, List<String> names) throws IOException {
    5.10          for (String baseClass : names) {
    5.11              Map<String,String> processed = new HashMap<String, String>();
    5.12              LinkedList<String> toProcess = new LinkedList<String>();
    5.13 @@ -92,7 +95,7 @@
    5.14                      processed.put(name, "");
    5.15                      continue;
    5.16                  }            
    5.17 -                InputStream is = loadClass(name);
    5.18 +                InputStream is = loadClass(l, name);
    5.19                  if (is == null) {
    5.20                      throw new IOException("Can't find class " + name); 
    5.21                  }
    5.22 @@ -119,7 +122,10 @@
    5.23                      }
    5.24                  }
    5.25                  for (String resource : scripts) {
    5.26 -                    InputStream emul = GenJS.class.getResourceAsStream(resource);
    5.27 +                    while (resource.startsWith("/")) {
    5.28 +                        resource = resource.substring(1);
    5.29 +                    }
    5.30 +                    InputStream emul = l.getResourceAsStream(resource);
    5.31                      if (emul == null) {
    5.32                          throw new IOException("Can't find " + resource);
    5.33                      }
    5.34 @@ -183,12 +189,13 @@
    5.35          }
    5.36      }
    5.37  
    5.38 -    private static InputStream loadClass(String name) throws IOException {
    5.39 -        Enumeration<URL> en = ClassLoader.getSystemClassLoader().getResources(name + ".class");
    5.40 +    private static InputStream loadClass(ClassLoader l, String name) throws IOException {
    5.41 +        Enumeration<URL> en = l.getResources(name + ".class");
    5.42          URL u = null;
    5.43          while (en.hasMoreElements()) {
    5.44              u = en.nextElement();
    5.45          }
    5.46 +        System.err.println("loader: " + l + " url : " + u);
    5.47          if (u == null) {
    5.48              throw new IOException("Can't find " + name);
    5.49          }