Transfers much of BuildJavaScriptMojo logic to the common TeaVMTool.

This commit is contained in:
konsoletyper 2014-06-22 11:52:15 +04:00
parent 4866a6d52f
commit c459f3779a
6 changed files with 281 additions and 114 deletions

View File

@ -76,6 +76,7 @@
<module>teavm-dom</module>
<module>teavm-jso</module>
<module>teavm-html4j</module>
<module>teavm-samples</module>
</modules>
<dependencyManagement>

View File

@ -13,7 +13,7 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.teavm.maven;
package org.teavm.tooling;
/**
*

View File

@ -13,7 +13,7 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.teavm.maven;
package org.teavm.tooling;
/**
*

View File

@ -13,7 +13,7 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.teavm.maven;
package org.teavm.tooling;
/**
*

View File

@ -0,0 +1,256 @@
/*
* Copyright 2014 Alexey Andreev.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.teavm.tooling;
import java.io.*;
import java.util.ArrayList;
import java.util.List;
import java.util.Properties;
import org.apache.commons.io.IOUtils;
import org.teavm.common.ThreadPoolFiniteExecutor;
import org.teavm.javascript.RenderingContext;
import org.teavm.model.ClassHolderTransformer;
import org.teavm.model.MethodDescriptor;
import org.teavm.model.MethodReference;
import org.teavm.model.ValueType;
import org.teavm.parsing.ClasspathClassHolderSource;
import org.teavm.vm.*;
import org.teavm.vm.spi.AbstractRendererListener;
/**
*
* @author Alexey Andreev <konsoletyper@gmail.com>
*/
public class TeaVMTool {
private File targetDirectory = new File(".");
private String targetFileName = "classes.js";
private boolean minifying = true;
private String mainClass;
private RuntimeCopyOperation runtime = RuntimeCopyOperation.SEPARATE;
private Properties properties = new Properties();
private boolean mainPageIncluded;
private boolean bytecodeLogging;
private int numThreads = 1;
private List<ClassHolderTransformer> transformers = new ArrayList<>();
private List<ClassAlias> classAliases = new ArrayList<>();
private List<MethodAlias> methodAliases = new ArrayList<>();
private TeaVMToolLog log = new EmptyTeaVMToolLog();
private ClassLoader classLoader = TeaVMTool.class.getClassLoader();
public File getTargetDirectory() {
return targetDirectory;
}
public void setTargetDirectory(File targetDirectory) {
this.targetDirectory = targetDirectory;
}
public String getTargetFileName() {
return targetFileName;
}
public void setTargetFileName(String targetFileName) {
this.targetFileName = targetFileName;
}
public boolean isMinifying() {
return minifying;
}
public void setMinifying(boolean minifying) {
this.minifying = minifying;
}
public String getMainClass() {
return mainClass;
}
public void setMainClass(String mainClass) {
this.mainClass = mainClass;
}
public RuntimeCopyOperation getRuntime() {
return runtime;
}
public void setRuntime(RuntimeCopyOperation runtime) {
this.runtime = runtime;
}
public boolean isMainPageIncluded() {
return mainPageIncluded;
}
public void setMainPageIncluded(boolean mainPageIncluded) {
this.mainPageIncluded = mainPageIncluded;
}
public boolean isBytecodeLogging() {
return bytecodeLogging;
}
public void setBytecodeLogging(boolean bytecodeLogging) {
this.bytecodeLogging = bytecodeLogging;
}
public int getNumThreads() {
return numThreads;
}
public void setNumThreads(int numThreads) {
this.numThreads = numThreads;
}
public Properties getProperties() {
return properties;
}
public List<ClassHolderTransformer> getTransformers() {
return transformers;
}
public List<ClassAlias> getClassAliases() {
return classAliases;
}
public List<MethodAlias> getMethodAliases() {
return methodAliases;
}
public TeaVMToolLog getLog() {
return log;
}
public void setLog(TeaVMToolLog log) {
this.log = log;
}
public ClassLoader getClassLoader() {
return classLoader;
}
public void setClassLoader(ClassLoader classLoader) {
this.classLoader = classLoader;
}
public void generate() throws TeaVMToolException {
Runnable finalizer = null;
try {
log.info("Building JavaScript file");
TeaVMBuilder vmBuilder = new TeaVMBuilder();
vmBuilder.setClassLoader(classLoader).setClassSource(new ClasspathClassHolderSource(classLoader));
if (numThreads != 1) {
int threads = numThreads != 0 ? numThreads : Runtime.getRuntime().availableProcessors();
final ThreadPoolFiniteExecutor executor = new ThreadPoolFiniteExecutor(threads);
finalizer = new Runnable() {
@Override public void run() {
executor.stop();
}
};
vmBuilder.setExecutor(executor);
}
TeaVM vm = vmBuilder.build();
vm.setMinifying(minifying);
vm.setBytecodeLogging(bytecodeLogging);
vm.setProperties(properties);
vm.installPlugins();
for (ClassHolderTransformer transformer : transformers) {
vm.add(transformer);
}
if (mainClass != null) {
MethodDescriptor mainMethodDesc = new MethodDescriptor("main", ValueType.arrayOf(
ValueType.object("java.lang.String")), ValueType.VOID);
vm.entryPoint("main", new MethodReference(mainClass, mainMethodDesc))
.withValue(1, "java.lang.String");
}
for (ClassAlias alias : classAliases) {
vm.exportType(alias.getAlias(), alias.getClassName());
}
for (MethodAlias methodAlias : methodAliases) {
MethodReference ref = new MethodReference(methodAlias.getClassName(), methodAlias.getMethodName(),
MethodDescriptor.parseSignature(methodAlias.getDescriptor()));
TeaVMEntryPoint entryPoint = vm.entryPoint(methodAlias.getAlias(), ref);
if (methodAlias.getTypes() != null) {
for (int i = 0; i < methodAlias.getTypes().length; ++i) {
String types = methodAlias.getTypes()[i];
if (types != null) {
for (String type : types.split(" +")) {
type = type.trim();
if (!type.isEmpty()) {
entryPoint.withValue(i, type);
}
}
}
}
}
}
targetDirectory.mkdirs();
try (FileWriter writer = new FileWriter(new File(targetDirectory, targetFileName))) {
if (runtime == RuntimeCopyOperation.MERGED) {
vm.add(runtimeInjector);
}
vm.build(writer, new DirectoryBuildTarget(targetDirectory));
vm.checkForMissingItems();
log.info("JavaScript file successfully built");
}
if (runtime == RuntimeCopyOperation.SEPARATE) {
resourceToFile("org/teavm/javascript/runtime.js", "runtime.js");
}
if (mainPageIncluded) {
String text;
try (Reader reader = new InputStreamReader(classLoader.getResourceAsStream(
"org/teavm/maven/main.html"), "UTF-8")) {
text = IOUtils.toString(reader).replace("${classes.js}", targetFileName);
}
File mainPageFile = new File(targetDirectory, "main.html");
try (Writer writer = new OutputStreamWriter(new FileOutputStream(mainPageFile), "UTF-8")) {
writer.append(text);
}
}
} catch (IOException e) {
throw new TeaVMToolException("IO error occured", e);
} finally {
if (finalizer != null) {
finalizer.run();
}
}
}
private AbstractRendererListener runtimeInjector = new AbstractRendererListener() {
@Override
public void begin(RenderingContext context, BuildTarget buildTarget) throws IOException {
@SuppressWarnings("resource")
StringWriter writer = new StringWriter();
resourceToWriter("org/teavm/javascript/runtime.js", writer);
writer.close();
context.getWriter().append(writer.toString()).newLine();
}
};
private void resourceToFile(String resource, String fileName) throws IOException {
try (InputStream input = TeaVMTool.class.getClassLoader().getResourceAsStream(resource)) {
try (OutputStream output = new FileOutputStream(new File(targetDirectory, fileName))) {
IOUtils.copy(input, output);
}
}
}
private void resourceToWriter(String resource, Writer writer) throws IOException {
try (InputStream input = TeaVMTool.class.getClassLoader().getResourceAsStream(resource)) {
IOUtils.copy(input, writer, "UTF-8");
}
}
}

View File

@ -15,14 +15,13 @@
*/
package org.teavm.maven;
import java.io.*;
import java.io.File;
import java.lang.reflect.Constructor;
import java.lang.reflect.InvocationTargetException;
import java.net.MalformedURLException;
import java.net.URL;
import java.net.URLClassLoader;
import java.util.*;
import org.apache.commons.io.IOUtils;
import org.apache.maven.artifact.Artifact;
import org.apache.maven.plugin.AbstractMojo;
import org.apache.maven.plugin.MojoExecutionException;
@ -32,15 +31,8 @@ import org.apache.maven.plugins.annotations.Mojo;
import org.apache.maven.plugins.annotations.Parameter;
import org.apache.maven.plugins.annotations.ResolutionScope;
import org.apache.maven.project.MavenProject;
import org.teavm.common.ThreadPoolFiniteExecutor;
import org.teavm.javascript.RenderingContext;
import org.teavm.model.ClassHolderTransformer;
import org.teavm.model.MethodDescriptor;
import org.teavm.model.MethodReference;
import org.teavm.model.ValueType;
import org.teavm.parsing.ClasspathClassHolderSource;
import org.teavm.vm.*;
import org.teavm.vm.spi.AbstractRendererListener;
import org.teavm.tooling.*;
/**
*
@ -94,6 +86,8 @@ public class BuildJavascriptMojo extends AbstractMojo {
@Parameter
private MethodAlias[] methodAliases;
private TeaVMTool tool = new TeaVMTool();
public void setProject(MavenProject project) {
this.project = project;
}
@ -153,106 +147,36 @@ public class BuildJavascriptMojo extends AbstractMojo {
@Override
public void execute() throws MojoExecutionException {
Log log = getLog();
Runnable finalizer = null;
tool.setLog(new MavenTeaVMToolLog(log));
try {
ClassLoader classLoader = prepareClassLoader();
log.info("Building JavaScript file");
TeaVMBuilder vmBuilder = new TeaVMBuilder();
vmBuilder.setClassLoader(classLoader).setClassSource(new ClasspathClassHolderSource(classLoader));
if (numThreads != 1) {
int threads = numThreads != 0 ? numThreads : Runtime.getRuntime().availableProcessors();
final ThreadPoolFiniteExecutor executor = new ThreadPoolFiniteExecutor(threads);
finalizer = new Runnable() {
@Override public void run() {
executor.stop();
}
};
vmBuilder.setExecutor(executor);
}
TeaVM vm = vmBuilder.build();
vm.setMinifying(minifying);
vm.setBytecodeLogging(bytecodeLogging);
vm.setProperties(properties);
vm.installPlugins();
for (ClassHolderTransformer transformer : instantiateTransformers(classLoader)) {
vm.add(transformer);
}
if (mainClass != null) {
MethodDescriptor mainMethodDesc = new MethodDescriptor("main", ValueType.arrayOf(
ValueType.object("java.lang.String")), ValueType.VOID);
vm.entryPoint("main", new MethodReference(mainClass, mainMethodDesc))
.withValue(1, "java.lang.String");
}
tool.setClassLoader(classLoader);
tool.setBytecodeLogging(bytecodeLogging);
tool.setMainClass(mainClass);
tool.setMainPageIncluded(mainPageIncluded);
tool.setMinifying(minifying);
tool.setNumThreads(numThreads);
tool.setRuntime(runtime);
tool.setTargetDirectory(targetDirectory);
tool.setTargetFileName(targetFileName);
tool.getTransformers().addAll(instantiateTransformers(classLoader));
if (classAliases != null) {
for (ClassAlias alias : classAliases) {
vm.exportType(alias.getAlias(), alias.getClassName());
}
tool.getClassAliases().addAll(Arrays.asList(classAliases));
}
if (methodAliases != null) {
for (MethodAlias methodAlias : methodAliases) {
MethodReference ref = new MethodReference(methodAlias.getClassName(), methodAlias.getMethodName(),
MethodDescriptor.parseSignature(methodAlias.getDescriptor()));
TeaVMEntryPoint entryPoint = vm.entryPoint(methodAlias.getAlias(), ref);
if (methodAlias.getTypes() != null) {
for (int i = 0; i < methodAlias.getTypes().length; ++i) {
String types = methodAlias.getTypes()[i];
if (types != null) {
for (String type : types.split(" +")) {
type = type.trim();
if (!type.isEmpty()) {
entryPoint.withValue(i, type);
}
}
}
}
}
}
tool.getMethodAliases().addAll(Arrays.asList(methodAliases));
}
targetDirectory.mkdirs();
try (FileWriter writer = new FileWriter(new File(targetDirectory, targetFileName))) {
if (runtime == RuntimeCopyOperation.MERGED) {
vm.add(runtimeInjector);
}
vm.build(writer, new DirectoryBuildTarget(targetDirectory));
vm.checkForMissingItems();
log.info("JavaScript file successfully built");
}
if (runtime == RuntimeCopyOperation.SEPARATE) {
resourceToFile("org/teavm/javascript/runtime.js", "runtime.js");
}
if (mainPageIncluded) {
String text;
try (Reader reader = new InputStreamReader(classLoader.getResourceAsStream(
"org/teavm/maven/main.html"), "UTF-8")) {
text = IOUtils.toString(reader).replace("${classes.js}", targetFileName);
}
File mainPageFile = new File(targetDirectory, "main.html");
try (Writer writer = new OutputStreamWriter(new FileOutputStream(mainPageFile), "UTF-8")) {
writer.append(text);
}
if (properties != null) {
tool.getProperties().putAll(properties);
}
tool.generate();
} catch (RuntimeException e) {
throw new MojoExecutionException("Unexpected error occured", e);
} catch (IOException e) {
} catch (TeaVMToolException e) {
throw new MojoExecutionException("IO error occured", e);
} finally {
if (finalizer != null) {
finalizer.run();
}
}
}
private AbstractRendererListener runtimeInjector = new AbstractRendererListener() {
@Override
public void begin(RenderingContext context, BuildTarget buildTarget) throws IOException {
@SuppressWarnings("resource")
StringWriter writer = new StringWriter();
resourceToWriter("org/teavm/javascript/runtime.js", writer);
writer.close();
context.getWriter().append(writer.toString()).newLine();
}
};
private List<ClassHolderTransformer> instantiateTransformers(ClassLoader classLoader)
throws MojoExecutionException {
List<ClassHolderTransformer> transformerInstances = new ArrayList<>();
@ -316,18 +240,4 @@ public class BuildJavascriptMojo extends AbstractMojo {
throw new MojoExecutionException("Error gathering classpath information", e);
}
}
private void resourceToFile(String resource, String fileName) throws IOException {
try (InputStream input = BuildJavascriptMojo.class.getClassLoader().getResourceAsStream(resource)) {
try (OutputStream output = new FileOutputStream(new File(targetDirectory, fileName))) {
IOUtils.copy(input, output);
}
}
}
private void resourceToWriter(String resource, Writer writer) throws IOException {
try (InputStream input = BuildJavascriptMojo.class.getClassLoader().getResourceAsStream(resource)) {
IOUtils.copy(input, writer, "UTF-8");
}
}
}