diff --git a/pom.xml b/pom.xml
index d8bdf4a45..68e4aa6a2 100644
--- a/pom.xml
+++ b/pom.xml
@@ -78,6 +78,7 @@
teavm-html4j
teavm-samples
teavm-platform
+ teavm-cli
diff --git a/teavm-cli/.gitignore b/teavm-cli/.gitignore
new file mode 100644
index 000000000..c708c363d
--- /dev/null
+++ b/teavm-cli/.gitignore
@@ -0,0 +1,4 @@
+/target
+/.settings
+/.classpath
+/.project
diff --git a/teavm-cli/pom.xml b/teavm-cli/pom.xml
new file mode 100644
index 000000000..cca0a2556
--- /dev/null
+++ b/teavm-cli/pom.xml
@@ -0,0 +1,55 @@
+
+
+ 4.0.0
+
+
+ org.teavm
+ teavm
+ 0.2-SNAPSHOT
+
+ teavm-cli
+
+ TeaVM CLI
+ TeaVM command line tools
+
+
+
+ org.teavm
+ teavm-core
+ ${project.version}
+
+
+ commons-cli
+ commons-cli
+ 1.2
+
+
+
+
+
+
+ org.apache.maven.plugins
+ maven-source-plugin
+
+
+ org.apache.maven.plugins
+ maven-javadoc-plugin
+
+
+
+
\ No newline at end of file
diff --git a/teavm-cli/src/main/java/org/teavm/cli/ConsoleTeaVMToolLog.java b/teavm-cli/src/main/java/org/teavm/cli/ConsoleTeaVMToolLog.java
new file mode 100644
index 000000000..2105333ea
--- /dev/null
+++ b/teavm-cli/src/main/java/org/teavm/cli/ConsoleTeaVMToolLog.java
@@ -0,0 +1,68 @@
+/*
+ * 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.cli;
+
+import org.teavm.tooling.TeaVMToolLog;
+
+/**
+ *
+ * @author Alexey Andreev
+ */
+class ConsoleTeaVMToolLog implements TeaVMToolLog {
+ @Override
+ public void info(String text) {
+ System.out.println("INFO: " + text);
+ }
+
+ @Override
+ public void debug(String text) {
+ System.out.println("DEBUG: " + text);
+ }
+
+ @Override
+ public void warning(String text) {
+ System.out.println("WARNING: " + text);
+ }
+
+ @Override
+ public void error(String text) {
+ System.out.println("ERROR: " + text);
+ }
+
+ @Override
+ public void info(String text, Throwable e) {
+ System.out.println("INFO: " + text);
+ e.printStackTrace(System.out);
+ }
+
+ @Override
+ public void debug(String text, Throwable e) {
+ System.out.println("DEBUG: " + text);
+ e.printStackTrace(System.out);
+ }
+
+ @Override
+ public void warning(String text, Throwable e) {
+ System.out.println("WARNING: " + text);
+ e.printStackTrace(System.out);
+ }
+
+ @Override
+ public void error(String text, Throwable e) {
+ System.out.println("ERROR: " + text);
+ e.printStackTrace(System.out);
+ }
+}
diff --git a/teavm-cli/src/main/java/org/teavm/cli/TeaVMRunner.java b/teavm-cli/src/main/java/org/teavm/cli/TeaVMRunner.java
new file mode 100644
index 000000000..be4ddbf0a
--- /dev/null
+++ b/teavm-cli/src/main/java/org/teavm/cli/TeaVMRunner.java
@@ -0,0 +1,146 @@
+/*
+ * 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.cli;
+
+import java.io.File;
+import org.apache.commons.cli.*;
+import org.teavm.tooling.RuntimeCopyOperation;
+import org.teavm.tooling.TeaVMTool;
+
+/**
+ *
+ * @author Alexey Andreev
+ */
+public class TeaVMRunner {
+ @SuppressWarnings("static-access")
+ public static void main(String[] args) {
+ Options options = new Options();
+ options.addOption(OptionBuilder
+ .withArgName("directory")
+ .hasArg()
+ .withDescription("a directory where to put generated files (current directory by default)")
+ .withLongOpt("targetdir")
+ .create('d'));
+ options.addOption(OptionBuilder
+ .withArgName("file")
+ .hasArg()
+ .withDescription("a file where to put decompiled classes (classes.js by default)")
+ .withLongOpt("targetfile")
+ .create('f'));
+ options.addOption(OptionBuilder
+ .withDescription("causes TeaVM to generate minimized JavaScript file")
+ .withLongOpt("minify")
+ .create("m"));
+ options.addOption(OptionBuilder
+ .withArgName("separate|merge|none")
+ .hasArg()
+ .withDescription("how to attach runtime. Possible values are: separate|merge|none")
+ .withLongOpt("runtime")
+ .create("r"));
+ options.addOption(OptionBuilder
+ .withDescription("causes TeaVM to include default main page")
+ .withLongOpt("mainpage")
+ .create());
+ options.addOption(OptionBuilder
+ .withDescription("causes TeaVM to log bytecode")
+ .create("logbytecode"));
+ options.addOption(OptionBuilder
+ .withArgName("number")
+ .hasArg()
+ .withDescription("how many threads should TeaVM run")
+ .withLongOpt("threads")
+ .create("t"));
+
+ if (args.length == 0) {
+ printUsage(options);
+ return;
+ }
+ CommandLineParser parser = new PosixParser();
+ CommandLine commandLine;
+ try {
+ commandLine = parser.parse(options, args);
+ } catch (ParseException e) {
+ printUsage(options);
+ return;
+ }
+
+ TeaVMTool tool = new TeaVMTool();
+ tool.setBytecodeLogging(commandLine.hasOption("logbytecode"));
+ if (commandLine.hasOption("d")) {
+ tool.setTargetDirectory(new File(commandLine.getOptionValue("d")));
+ }
+ if (commandLine.hasOption("f")) {
+ tool.setTargetFileName(commandLine.getOptionValue("f"));
+ }
+ if (commandLine.hasOption("m")) {
+ tool.setMinifying(true);
+ } else {
+ tool.setMinifying(false);
+ }
+ if (commandLine.hasOption("r")) {
+ switch (commandLine.getOptionValue("r")) {
+ case "separate":
+ tool.setRuntime(RuntimeCopyOperation.SEPARATE);
+ break;
+ case "merge":
+ tool.setRuntime(RuntimeCopyOperation.MERGED);
+ break;
+ case "none":
+ tool.setRuntime(RuntimeCopyOperation.NONE);
+ break;
+ default:
+ System.err.println("Wrong parameter for -r option specified");
+ printUsage(options);
+ return;
+ }
+ }
+ if (commandLine.hasOption("mainpage")) {
+ tool.setMainPageIncluded(true);
+ }
+ if (commandLine.hasOption("t")) {
+ try {
+ tool.setNumThreads(Integer.parseInt(commandLine.getOptionValue("t")));
+ } catch (NumberFormatException e) {
+ System.err.println("Wrong parameter for -t option specified");
+ printUsage(options);
+ return;
+ }
+ }
+ args = commandLine.getArgs();
+ if (args.length > 1) {
+ System.err.println("Unexpected arguments");
+ printUsage(options);
+ return;
+ } else if (args.length == 1) {
+ tool.setMainClass(args[0]);
+ }
+ tool.setLog(new ConsoleTeaVMToolLog());
+ tool.getProperties().putAll(System.getProperties());
+
+ try {
+ tool.generate();
+ } catch (Exception e) {
+ e.printStackTrace(System.err);
+ System.exit(-2);
+ }
+ }
+
+ private static void printUsage(Options options) {
+ HelpFormatter formatter = new HelpFormatter();
+ formatter.printHelp("java " + TeaVMRunner.class.getName() + " [OPTIONS] [qualified.main.Class]", options);
+ System.exit(-1);
+ }
+}
diff --git a/teavm-cli/src/main/java/org/teavm/cli/TeaVMTestRunner.java b/teavm-cli/src/main/java/org/teavm/cli/TeaVMTestRunner.java
new file mode 100644
index 000000000..988d18858
--- /dev/null
+++ b/teavm-cli/src/main/java/org/teavm/cli/TeaVMTestRunner.java
@@ -0,0 +1,183 @@
+package org.teavm.cli;
+
+import java.io.File;
+import java.lang.reflect.Constructor;
+import java.lang.reflect.InvocationTargetException;
+import java.util.Arrays;
+import org.apache.commons.cli.*;
+import org.teavm.model.ClassHolderTransformer;
+import org.teavm.testing.TestAdapter;
+import org.teavm.tooling.TeaVMTestTool;
+import org.teavm.tooling.TeaVMToolException;
+
+/**
+ *
+ * @author Alexey Andreev
+ */
+public class TeaVMTestRunner {
+ @SuppressWarnings("static-access")
+ public static void main(String[] args) {
+ Options options = new Options();
+ options.addOption(OptionBuilder
+ .withArgName("directory")
+ .hasArg()
+ .withDescription("a directory where to put generated files (current directory by default)")
+ .withLongOpt("targetdir")
+ .create('d'));
+ options.addOption(OptionBuilder
+ .withDescription("causes TeaVM to generate minimized JavaScript file")
+ .withLongOpt("minify")
+ .create("m"));
+ options.addOption(OptionBuilder
+ .withArgName("number")
+ .hasArg()
+ .withDescription("how many threads should TeaVM run")
+ .withLongOpt("threads")
+ .create("t"));
+ options.addOption(OptionBuilder
+ .withArgName("class name")
+ .hasArg()
+ .withDescription("qualified class name of test adapter")
+ .withLongOpt("adapter")
+ .create("a"));
+ options.addOption(OptionBuilder
+ .hasArg()
+ .hasOptionalArgs()
+ .withArgName("class name")
+ .withDescription("qualified class names of transformers")
+ .withLongOpt("transformers")
+ .create("T"));
+
+ if (args.length == 0) {
+ printUsage(options);
+ return;
+ }
+ CommandLineParser parser = new PosixParser();
+ CommandLine commandLine;
+ try {
+ commandLine = parser.parse(options, args);
+ } catch (ParseException e) {
+ printUsage(options);
+ return;
+ }
+
+ TeaVMTestTool tool = new TeaVMTestTool();
+ tool.setOutputDir(new File(commandLine.getOptionValue("d", ".")));
+ tool.setMinifying(commandLine.hasOption("m"));
+ try {
+ tool.setNumThreads(Integer.parseInt(commandLine.getOptionValue("t", "1")));
+ } catch (NumberFormatException e) {
+ System.err.println("Invalid number specified for -t option");
+ printUsage(options);
+ return;
+ }
+ if (commandLine.hasOption("a")) {
+ tool.setAdapter(instantiateAdapter(commandLine.getOptionValue("a")));
+ }
+ if (commandLine.hasOption("T")) {
+ for (String transformerType : commandLine.getOptionValues("T")) {
+ tool.getTransformers().add(instantiateTransformer(transformerType));
+ }
+ }
+ args = commandLine.getArgs();
+ if (args.length == 0) {
+ System.err.println("You did not specify any test classes");
+ printUsage(options);
+ return;
+ }
+ tool.getTestClasses().addAll(Arrays.asList(args));
+
+ tool.setLog(new ConsoleTeaVMToolLog());
+ tool.getProperties().putAll(System.getProperties());
+ long start = System.currentTimeMillis();
+ try {
+ tool.generate();
+ } catch (TeaVMToolException e) {
+ e.printStackTrace(System.err);
+ System.exit(-2);
+ }
+ System.out.println("Operation took " + (System.currentTimeMillis() - start) + " milliseconds");
+ }
+
+ private static TestAdapter instantiateAdapter(String adapterName) {
+ Class> adapterClass;
+ try {
+ adapterClass = Class.forName(adapterName, true, TeaVMTestRunner.class.getClassLoader());
+ } catch (ClassNotFoundException e) {
+ System.err.println("Adapter not found: " + adapterName);
+ System.exit(-1);
+ return null;
+ }
+ if (!TestAdapter.class.isAssignableFrom(adapterClass)) {
+ System.err.println("Adapter class does not implement TestAdapter: " + adapterName);
+ System.exit(-1);
+ return null;
+ }
+ Constructor> cons;
+ try {
+ cons = adapterClass.getConstructor();
+ } catch (NoSuchMethodException e) {
+ System.err.println("Adapter class does not contain no-arg constructor: " + adapterName);
+ System.exit(-1);
+ return null;
+ }
+
+ try {
+ return (TestAdapter)cons.newInstance();
+ } catch (IllegalAccessException | InstantiationException e) {
+ System.err.println("Error instantiating adapter: " + adapterName);
+ e.printStackTrace(System.err);
+ System.exit(-1);
+ return null;
+ } catch (InvocationTargetException e) {
+ System.err.println("Error instantiating adapter: " + adapterName);
+ e.getTargetException().printStackTrace(System.err);
+ System.exit(-1);
+ return null;
+ }
+ }
+
+ private static ClassHolderTransformer instantiateTransformer(String transformerName) {
+ Class> adapterClass;
+ try {
+ adapterClass = Class.forName(transformerName, true, TeaVMTestRunner.class.getClassLoader());
+ } catch (ClassNotFoundException e) {
+ System.err.println("Transformer not found: " + transformerName);
+ System.exit(-1);
+ return null;
+ }
+ if (!ClassHolderTransformer.class.isAssignableFrom(adapterClass)) {
+ System.err.println("Transformer class does not implement ClassHolderTransformer: " + transformerName);
+ System.exit(-1);
+ return null;
+ }
+ Constructor> cons;
+ try {
+ cons = adapterClass.getConstructor();
+ } catch (NoSuchMethodException e) {
+ System.err.println("Transformer class does not contain no-arg constructor: " + transformerName);
+ System.exit(-1);
+ return null;
+ }
+
+ try {
+ return (ClassHolderTransformer)cons.newInstance();
+ } catch (IllegalAccessException | InstantiationException e) {
+ System.err.println("Error instantiating transformer: " + transformerName);
+ e.printStackTrace(System.err);
+ System.exit(-1);
+ return null;
+ } catch (InvocationTargetException e) {
+ System.err.println("Error instantiating transformer: " + transformerName);
+ e.getTargetException().printStackTrace(System.err);
+ System.exit(-1);
+ return null;
+ }
+ }
+
+ private static void printUsage(Options options) {
+ HelpFormatter formatter = new HelpFormatter();
+ formatter.printHelp("java " + TeaVMTestRunner.class.getName() + " [OPTIONS] test_name {test_name}", options);
+ System.exit(-1);
+ }
+}
diff --git a/teavm-maven-plugin/src/main/java/org/teavm/maven/ClassAlias.java b/teavm-core/src/main/java/org/teavm/tooling/ClassAlias.java
similarity index 97%
rename from teavm-maven-plugin/src/main/java/org/teavm/maven/ClassAlias.java
rename to teavm-core/src/main/java/org/teavm/tooling/ClassAlias.java
index 29aefd6b0..f5fe8a5e9 100644
--- a/teavm-maven-plugin/src/main/java/org/teavm/maven/ClassAlias.java
+++ b/teavm-core/src/main/java/org/teavm/tooling/ClassAlias.java
@@ -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;
/**
*
diff --git a/teavm-core/src/main/java/org/teavm/tooling/EmptyTeaVMToolLog.java b/teavm-core/src/main/java/org/teavm/tooling/EmptyTeaVMToolLog.java
new file mode 100644
index 000000000..917e73fb4
--- /dev/null
+++ b/teavm-core/src/main/java/org/teavm/tooling/EmptyTeaVMToolLog.java
@@ -0,0 +1,54 @@
+/*
+ * 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;
+
+/**
+ *
+ * @author Alexey Andreev
+ */
+public class EmptyTeaVMToolLog implements TeaVMToolLog {
+ @Override
+ public void info(String text) {
+ }
+
+ @Override
+ public void debug(String text) {
+ }
+
+ @Override
+ public void warning(String text) {
+ }
+
+ @Override
+ public void error(String text) {
+ }
+
+ @Override
+ public void info(String text, Throwable e) {
+ }
+
+ @Override
+ public void debug(String text, Throwable e) {
+ }
+
+ @Override
+ public void warning(String text, Throwable e) {
+ }
+
+ @Override
+ public void error(String text, Throwable e) {
+ }
+}
diff --git a/teavm-maven-plugin/src/main/java/org/teavm/maven/MethodAlias.java b/teavm-core/src/main/java/org/teavm/tooling/MethodAlias.java
similarity index 98%
rename from teavm-maven-plugin/src/main/java/org/teavm/maven/MethodAlias.java
rename to teavm-core/src/main/java/org/teavm/tooling/MethodAlias.java
index 1e477d35c..58a6bdadb 100644
--- a/teavm-maven-plugin/src/main/java/org/teavm/maven/MethodAlias.java
+++ b/teavm-core/src/main/java/org/teavm/tooling/MethodAlias.java
@@ -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;
/**
*
diff --git a/teavm-maven-plugin/src/main/java/org/teavm/maven/RuntimeCopyOperation.java b/teavm-core/src/main/java/org/teavm/tooling/RuntimeCopyOperation.java
similarity index 96%
rename from teavm-maven-plugin/src/main/java/org/teavm/maven/RuntimeCopyOperation.java
rename to teavm-core/src/main/java/org/teavm/tooling/RuntimeCopyOperation.java
index 7e8f0f598..aa3b493d7 100644
--- a/teavm-maven-plugin/src/main/java/org/teavm/maven/RuntimeCopyOperation.java
+++ b/teavm-core/src/main/java/org/teavm/tooling/RuntimeCopyOperation.java
@@ -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;
/**
*
diff --git a/teavm-core/src/main/java/org/teavm/tooling/TeaVMTestTool.java b/teavm-core/src/main/java/org/teavm/tooling/TeaVMTestTool.java
new file mode 100644
index 000000000..9d70eca42
--- /dev/null
+++ b/teavm-core/src/main/java/org/teavm/tooling/TeaVMTestTool.java
@@ -0,0 +1,359 @@
+/*
+ * 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.*;
+import org.apache.commons.io.IOUtils;
+import org.teavm.common.FiniteExecutor;
+import org.teavm.common.SimpleFiniteExecutor;
+import org.teavm.common.ThreadPoolFiniteExecutor;
+import org.teavm.model.*;
+import org.teavm.parsing.ClasspathClassHolderSource;
+import org.teavm.testing.JUnitTestAdapter;
+import org.teavm.testing.TestAdapter;
+import org.teavm.vm.DirectoryBuildTarget;
+import org.teavm.vm.TeaVM;
+import org.teavm.vm.TeaVMBuilder;
+
+/**
+ *
+ * @author Alexey Andreev
+ */
+public class TeaVMTestTool {
+ private Map> groupedMethods = new HashMap<>();
+ private Map fileNames = new HashMap<>();
+ private List testMethods = new ArrayList<>();
+ private File outputDir = new File(".");
+ private boolean minifying = true;
+ private int numThreads = 1;
+ private TestAdapter adapter = new JUnitTestAdapter();
+ private List transformers = new ArrayList<>();
+ private List additionalScripts = new ArrayList<>();
+ private List additionalScriptLocalPaths = new ArrayList<>();
+ private Properties properties = new Properties();
+ private List testClasses = new ArrayList<>();
+ private ClassLoader classLoader = TeaVMTestTool.class.getClassLoader();
+ private TeaVMToolLog log = new EmptyTeaVMToolLog();
+
+ public File getOutputDir() {
+ return outputDir;
+ }
+
+ public void setOutputDir(File outputDir) {
+ this.outputDir = outputDir;
+ }
+
+ public boolean isMinifying() {
+ return minifying;
+ }
+
+ public void setMinifying(boolean minifying) {
+ this.minifying = minifying;
+ }
+
+ public int getNumThreads() {
+ return numThreads;
+ }
+
+ public void setNumThreads(int numThreads) {
+ this.numThreads = numThreads;
+ }
+
+ public TestAdapter getAdapter() {
+ return adapter;
+ }
+
+ public void setAdapter(TestAdapter adapter) {
+ this.adapter = adapter;
+ }
+
+ public List getTransformers() {
+ return transformers;
+ }
+
+ public List getAdditionalScripts() {
+ return additionalScripts;
+ }
+
+ public Properties getProperties() {
+ return properties;
+ }
+
+ public List getTestClasses() {
+ return testClasses;
+ }
+
+ public ClassLoader getClassLoader() {
+ return classLoader;
+ }
+
+ public void setClassLoader(ClassLoader classLoader) {
+ this.classLoader = classLoader;
+ }
+
+ public TeaVMToolLog getLog() {
+ return log;
+ }
+
+ public void setLog(TeaVMToolLog log) {
+ this.log = log;
+ }
+
+ public void generate() throws TeaVMToolException {
+ Runnable finalizer = null;
+ try {
+ new File(outputDir, "tests").mkdirs();
+ new File(outputDir, "res").mkdirs();
+ resourceToFile("org/teavm/javascript/runtime.js", "res/runtime.js");
+ String prefix = "org/teavm/tooling/test";
+ resourceToFile(prefix + "/res/junit-support.js", "res/junit-support.js");
+ resourceToFile(prefix + "/res/junit.css", "res/junit.css");
+ resourceToFile(prefix + "/res/class_obj.png", "res/class_obj.png");
+ resourceToFile(prefix + "/res/control-000-small.png", "res/control-000-small.png");
+ resourceToFile(prefix + "/res/methpub_obj.png", "res/methpub_obj.png");
+ resourceToFile(prefix + "/res/package_obj.png", "res/package_obj.png");
+ resourceToFile(prefix + "/res/tick-small-red.png", "res/tick-small-red.png");
+ resourceToFile(prefix + "/res/tick-small.png", "res/tick-small.png");
+ resourceToFile(prefix + "/res/toggle-small-expand.png", "res/toggle-small-expand.png");
+ resourceToFile(prefix + "/res/toggle-small.png", "res/toggle-small.png");
+ resourceToFile(prefix + "/junit.html", "junit.html");
+ final ClassHolderSource classSource = new ClasspathClassHolderSource(classLoader);
+ for (String testClass : testClasses) {
+ ClassHolder classHolder = classSource.get(testClass);
+ if (classHolder == null) {
+ throw new TeaVMToolException("Could not find class " + testClass);
+ }
+ findTests(classHolder);
+ }
+
+ includeAdditionalScripts(classLoader);
+ File allTestsFile = new File(outputDir, "tests/all.js");
+ try (Writer allTestsWriter = new OutputStreamWriter(new FileOutputStream(allTestsFile), "UTF-8")) {
+ allTestsWriter.write("prepare = function() {\n");
+ allTestsWriter.write(" return new JUnitServer(document.body).readTests([");
+ boolean first = true;
+ for (String testClass : testClasses) {
+ Collection methods = groupedMethods.get(testClass);
+ if (methods == null) {
+ continue;
+ }
+ if (!first) {
+ allTestsWriter.append(",");
+ }
+ first = false;
+ allTestsWriter.append("\n { name : \"").append(testClass).append("\", methods : [");
+ boolean firstMethod = true;
+ for (MethodReference methodRef : methods) {
+ String scriptName = "tests/" + fileNames.size() + ".js";
+ fileNames.put(methodRef, scriptName);
+ if (!firstMethod) {
+ allTestsWriter.append(",");
+ }
+ firstMethod = false;
+ allTestsWriter.append("\n { name : \"" + methodRef.getName() + "\", script : \"" +
+ scriptName + "\", expected : [");
+ MethodHolder methodHolder = classSource.get(testClass).getMethod(
+ methodRef.getDescriptor());
+ boolean firstException = true;
+ for (String exception : adapter.getExpectedExceptions(methodHolder)) {
+ if (!firstException) {
+ allTestsWriter.append(", ");
+ }
+ firstException = false;
+ allTestsWriter.append("\"" + exception + "\"");
+ }
+ allTestsWriter.append("], additionalScripts : [");
+ for (int i = 0; i < additionalScriptLocalPaths.size(); ++i) {
+ if (i > 0) {
+ allTestsWriter.append(", ");
+ }
+ escapeString(additionalScriptLocalPaths.get(i), allTestsWriter);
+ }
+ allTestsWriter.append("] }");
+ }
+ allTestsWriter.append("] }");
+ }
+ allTestsWriter.write("], function() {}); }");
+ }
+ int methodsGenerated = 0;
+ log.info("Generating test files");
+ FiniteExecutor executor = new SimpleFiniteExecutor();
+ if (numThreads != 1) {
+ int threads = numThreads != 0 ? numThreads : Runtime.getRuntime().availableProcessors();
+ final ThreadPoolFiniteExecutor threadedExecutor = new ThreadPoolFiniteExecutor(threads);
+ finalizer = new Runnable() {
+ @Override public void run() {
+ threadedExecutor.stop();
+ }
+ };
+ executor = threadedExecutor;
+ }
+ for (final MethodReference method : testMethods) {
+ executor.execute(new Runnable() {
+ @Override public void run() {
+ log.debug("Building test for " + method);
+ try {
+ decompileClassesForTest(classLoader, new CopyClassHolderSource(classSource), method,
+ fileNames.get(method), new SimpleFiniteExecutor());
+ } catch (IOException e) {
+ log.error("Error generating JavaScript", e);
+ }
+ }
+ });
+ ++methodsGenerated;
+ }
+ executor.complete();
+ log.info("Test files successfully generated for " + methodsGenerated + " method(s).");
+ } catch (IOException e) {
+ throw new TeaVMToolException("IO error occured generating JavaScript files", e);
+ } finally {
+ if (finalizer != null) {
+ finalizer.run();
+ }
+ }
+ }
+
+ private void resourceToFile(String resource, String fileName) throws IOException {
+ try (InputStream input = TeaVMTestTool.class.getClassLoader().getResourceAsStream(resource)) {
+ try (OutputStream output = new FileOutputStream(new File(outputDir, fileName))) {
+ IOUtils.copy(input, output);
+ }
+ }
+ }
+
+ private void findTests(ClassHolder cls) {
+ for (MethodHolder method : cls.getMethods()) {
+ if (adapter.acceptMethod(method)) {
+ MethodReference ref = new MethodReference(cls.getName(), method.getDescriptor());
+ testMethods.add(ref);
+ List group = groupedMethods.get(cls.getName());
+ if (group == null) {
+ group = new ArrayList<>();
+ groupedMethods.put(cls.getName(), group);
+ }
+ group.add(ref);
+ }
+ }
+ }
+
+ private void includeAdditionalScripts(ClassLoader classLoader) throws TeaVMToolException {
+ if (additionalScripts == null) {
+ return;
+ }
+ for (String script : additionalScripts) {
+ String simpleName = script.substring(script.lastIndexOf('/') + 1);
+ additionalScriptLocalPaths.add("tests/" + simpleName);
+ if (classLoader.getResource(script) == null) {
+ throw new TeaVMToolException("Additional script " + script + " was not found");
+ }
+ File file = new File(outputDir, "tests/" + simpleName);
+ try (InputStream in = classLoader.getResourceAsStream(script)) {
+ if (!file.exists()) {
+ file.createNewFile();
+ }
+ try(OutputStream out = new FileOutputStream(file)) {
+ IOUtils.copy(in, out);
+ }
+ } catch (IOException e) {
+ throw new TeaVMToolException("Error copying additional script " + script, e);
+ }
+ }
+ }
+
+ private void decompileClassesForTest(ClassLoader classLoader, ClassHolderSource classSource,
+ MethodReference methodRef, String targetName, FiniteExecutor executor) throws IOException {
+ TeaVM vm = new TeaVMBuilder()
+ .setClassLoader(classLoader)
+ .setClassSource(classSource)
+ .setExecutor(executor)
+ .build();
+ vm.setProperties(properties);
+ vm.setMinifying(minifying);
+ vm.installPlugins();
+ new TestExceptionPlugin().install(vm);
+ for (ClassHolderTransformer transformer : transformers) {
+ vm.add(transformer);
+ }
+ File file = new File(outputDir, targetName);
+ try (Writer innerWriter = new OutputStreamWriter(new FileOutputStream(file), "UTF-8")) {
+ MethodReference cons = new MethodReference(methodRef.getClassName(),
+ new MethodDescriptor("", ValueType.VOID));
+ MethodReference exceptionMsg = new MethodReference("java.lang.Throwable", "getMessage",
+ ValueType.object("java.lang.String"));
+ vm.entryPoint("initInstance", cons);
+ vm.entryPoint("runTest", methodRef).withValue(0, cons.getClassName());
+ vm.entryPoint("extractException", exceptionMsg);
+ vm.exportType("TestClass", cons.getClassName());
+ vm.build(innerWriter, new DirectoryBuildTarget(outputDir));
+ if (!vm.hasMissingItems()) {
+ innerWriter.append("\n");
+ innerWriter.append("\nJUnitClient.run();");
+ innerWriter.close();
+ } else {
+ innerWriter.append("JUnitClient.reportError(\n");
+ StringBuilder sb = new StringBuilder();
+ vm.showMissingItems(sb);
+ escapeStringLiteral(sb.toString(), innerWriter);
+ innerWriter.append(");");
+ log.warning("Error building test " + methodRef);
+ log.warning(sb.toString());
+ }
+ }
+ }
+
+ private void escapeStringLiteral(String text, Writer writer) throws IOException {
+ int index = 0;
+ while (true) {
+ int next = text.indexOf('\n', index);
+ if (next < 0) {
+ break;
+ }
+ escapeString(text.substring(index, next + 1), writer);
+ writer.append(" +\n");
+ index = next + 1;
+ }
+ escapeString(text.substring(index), writer);
+ }
+
+ private void escapeString(String string, Writer writer) throws IOException {
+ writer.append('\"');
+ for (int i = 0; i < string.length(); ++i) {
+ char c = string.charAt(i);
+ switch (c) {
+ case '"':
+ writer.append("\\\"");
+ break;
+ case '\\':
+ writer.append("\\\\");
+ break;
+ case '\n':
+ writer.append("\\n");
+ break;
+ case '\r':
+ writer.append("\\r");
+ break;
+ case '\t':
+ writer.append("\\t");
+ break;
+ default:
+ writer.append(c);
+ break;
+ }
+ }
+ writer.append('\"');
+ }
+}
diff --git a/teavm-core/src/main/java/org/teavm/tooling/TeaVMTool.java b/teavm-core/src/main/java/org/teavm/tooling/TeaVMTool.java
new file mode 100644
index 000000000..75a909243
--- /dev/null
+++ b/teavm-core/src/main/java/org/teavm/tooling/TeaVMTool.java
@@ -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
+ */
+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 transformers = new ArrayList<>();
+ private List classAliases = new ArrayList<>();
+ private List 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 getTransformers() {
+ return transformers;
+ }
+
+ public List getClassAliases() {
+ return classAliases;
+ }
+
+ public List 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/tooling/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");
+ }
+ }
+}
diff --git a/teavm-core/src/main/java/org/teavm/tooling/TeaVMToolException.java b/teavm-core/src/main/java/org/teavm/tooling/TeaVMToolException.java
new file mode 100644
index 000000000..510006be6
--- /dev/null
+++ b/teavm-core/src/main/java/org/teavm/tooling/TeaVMToolException.java
@@ -0,0 +1,36 @@
+/*
+ * 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;
+
+/**
+ *
+ * @author Alexey Andreev
+ */
+public class TeaVMToolException extends Exception {
+ private static final long serialVersionUID = 579149191624783241L;
+
+ public TeaVMToolException(String message, Throwable cause) {
+ super(message, cause);
+ }
+
+ public TeaVMToolException(String message) {
+ super(message);
+ }
+
+ public TeaVMToolException(Throwable cause) {
+ super(cause);
+ }
+}
diff --git a/teavm-core/src/main/java/org/teavm/tooling/TeaVMToolLog.java b/teavm-core/src/main/java/org/teavm/tooling/TeaVMToolLog.java
new file mode 100644
index 000000000..bc1ee5b81
--- /dev/null
+++ b/teavm-core/src/main/java/org/teavm/tooling/TeaVMToolLog.java
@@ -0,0 +1,38 @@
+/*
+ * 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;
+
+/**
+ *
+ * @author Alexey Andreev
+ */
+public interface TeaVMToolLog {
+ void info(String text);
+
+ void debug(String text);
+
+ void warning(String text);
+
+ void error(String text);
+
+ void info(String text, Throwable e);
+
+ void debug(String text, Throwable e);
+
+ void warning(String text, Throwable e);
+
+ void error(String text, Throwable e);
+}
diff --git a/teavm-core/src/main/java/org/teavm/tooling/TestExceptionDependency.java b/teavm-core/src/main/java/org/teavm/tooling/TestExceptionDependency.java
new file mode 100644
index 000000000..bf447b030
--- /dev/null
+++ b/teavm-core/src/main/java/org/teavm/tooling/TestExceptionDependency.java
@@ -0,0 +1,69 @@
+/*
+ * 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 org.teavm.dependency.*;
+import org.teavm.model.ClassReader;
+import org.teavm.model.ClassReaderSource;
+import org.teavm.model.MethodReference;
+import org.teavm.model.ValueType;
+
+/**
+ *
+ * @author Alexey Andreev
+ */
+class TestExceptionDependency implements DependencyListener {
+ private MethodReference getMessageRef = new MethodReference("java.lang.Throwable", "getMessage",
+ ValueType.object("java.lang.String"));
+ private DependencyNode allClasses;
+
+ @Override
+ public void started(DependencyAgent agent) {
+ allClasses = agent.createNode();
+ }
+
+ @Override
+ public void classAchieved(DependencyAgent agent, String className) {
+ if (isException(agent.getClassSource(), className)) {
+ allClasses.propagate(className);
+ }
+ }
+
+ private boolean isException(ClassReaderSource classSource, String className) {
+ while (className != null) {
+ if (className.equals("java.lang.Throwable")) {
+ return true;
+ }
+ ClassReader cls = classSource.get(className);
+ if (cls == null) {
+ return false;
+ }
+ className = cls.getParent();
+ }
+ return false;
+ }
+
+ @Override
+ public void methodAchieved(DependencyAgent agent, MethodDependency method) {
+ if (method.getReference().equals(getMessageRef)) {
+ allClasses.connect(method.getVariable(0));
+ }
+ }
+
+ @Override
+ public void fieldAchieved(DependencyAgent agent, FieldDependency field) {
+ }
+}
diff --git a/teavm-core/src/main/java/org/teavm/tooling/TestExceptionPlugin.java b/teavm-core/src/main/java/org/teavm/tooling/TestExceptionPlugin.java
new file mode 100644
index 000000000..2ec7136c6
--- /dev/null
+++ b/teavm-core/src/main/java/org/teavm/tooling/TestExceptionPlugin.java
@@ -0,0 +1,30 @@
+/*
+ * 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 org.teavm.vm.spi.TeaVMHost;
+import org.teavm.vm.spi.TeaVMPlugin;
+
+/**
+ *
+ * @author Alexey Andreev
+ */
+class TestExceptionPlugin implements TeaVMPlugin {
+ @Override
+ public void install(TeaVMHost host) {
+ host.add(new TestExceptionDependency());
+ }
+}
diff --git a/teavm-maven-plugin/src/main/resources/org/teavm/maven/main.html b/teavm-core/src/main/resources/org/teavm/tooling/main.html
similarity index 100%
rename from teavm-maven-plugin/src/main/resources/org/teavm/maven/main.html
rename to teavm-core/src/main/resources/org/teavm/tooling/main.html
diff --git a/teavm-maven-plugin/src/main/resources/org/teavm/maven/junit.html b/teavm-core/src/main/resources/org/teavm/tooling/test/junit.html
similarity index 100%
rename from teavm-maven-plugin/src/main/resources/org/teavm/maven/junit.html
rename to teavm-core/src/main/resources/org/teavm/tooling/test/junit.html
diff --git a/teavm-maven-plugin/src/main/resources/org/teavm/maven/res/class_obj.png b/teavm-core/src/main/resources/org/teavm/tooling/test/res/class_obj.png
similarity index 100%
rename from teavm-maven-plugin/src/main/resources/org/teavm/maven/res/class_obj.png
rename to teavm-core/src/main/resources/org/teavm/tooling/test/res/class_obj.png
diff --git a/teavm-maven-plugin/src/main/resources/org/teavm/maven/res/control-000-small.png b/teavm-core/src/main/resources/org/teavm/tooling/test/res/control-000-small.png
similarity index 100%
rename from teavm-maven-plugin/src/main/resources/org/teavm/maven/res/control-000-small.png
rename to teavm-core/src/main/resources/org/teavm/tooling/test/res/control-000-small.png
diff --git a/teavm-maven-plugin/src/main/resources/org/teavm/maven/res/junit-support.js b/teavm-core/src/main/resources/org/teavm/tooling/test/res/junit-support.js
similarity index 100%
rename from teavm-maven-plugin/src/main/resources/org/teavm/maven/res/junit-support.js
rename to teavm-core/src/main/resources/org/teavm/tooling/test/res/junit-support.js
diff --git a/teavm-maven-plugin/src/main/resources/org/teavm/maven/res/junit.css b/teavm-core/src/main/resources/org/teavm/tooling/test/res/junit.css
similarity index 100%
rename from teavm-maven-plugin/src/main/resources/org/teavm/maven/res/junit.css
rename to teavm-core/src/main/resources/org/teavm/tooling/test/res/junit.css
diff --git a/teavm-maven-plugin/src/main/resources/org/teavm/maven/res/methpub_obj.png b/teavm-core/src/main/resources/org/teavm/tooling/test/res/methpub_obj.png
similarity index 100%
rename from teavm-maven-plugin/src/main/resources/org/teavm/maven/res/methpub_obj.png
rename to teavm-core/src/main/resources/org/teavm/tooling/test/res/methpub_obj.png
diff --git a/teavm-maven-plugin/src/main/resources/org/teavm/maven/res/package_obj.png b/teavm-core/src/main/resources/org/teavm/tooling/test/res/package_obj.png
similarity index 100%
rename from teavm-maven-plugin/src/main/resources/org/teavm/maven/res/package_obj.png
rename to teavm-core/src/main/resources/org/teavm/tooling/test/res/package_obj.png
diff --git a/teavm-maven-plugin/src/main/resources/org/teavm/maven/res/runtime.js b/teavm-core/src/main/resources/org/teavm/tooling/test/res/runtime.js
similarity index 100%
rename from teavm-maven-plugin/src/main/resources/org/teavm/maven/res/runtime.js
rename to teavm-core/src/main/resources/org/teavm/tooling/test/res/runtime.js
diff --git a/teavm-maven-plugin/src/main/resources/org/teavm/maven/res/tick-small-red.png b/teavm-core/src/main/resources/org/teavm/tooling/test/res/tick-small-red.png
similarity index 100%
rename from teavm-maven-plugin/src/main/resources/org/teavm/maven/res/tick-small-red.png
rename to teavm-core/src/main/resources/org/teavm/tooling/test/res/tick-small-red.png
diff --git a/teavm-maven-plugin/src/main/resources/org/teavm/maven/res/tick-small.png b/teavm-core/src/main/resources/org/teavm/tooling/test/res/tick-small.png
similarity index 100%
rename from teavm-maven-plugin/src/main/resources/org/teavm/maven/res/tick-small.png
rename to teavm-core/src/main/resources/org/teavm/tooling/test/res/tick-small.png
diff --git a/teavm-maven-plugin/src/main/resources/org/teavm/maven/res/toggle-small-expand.png b/teavm-core/src/main/resources/org/teavm/tooling/test/res/toggle-small-expand.png
similarity index 100%
rename from teavm-maven-plugin/src/main/resources/org/teavm/maven/res/toggle-small-expand.png
rename to teavm-core/src/main/resources/org/teavm/tooling/test/res/toggle-small-expand.png
diff --git a/teavm-maven-plugin/src/main/resources/org/teavm/maven/res/toggle-small.png b/teavm-core/src/main/resources/org/teavm/tooling/test/res/toggle-small.png
similarity index 100%
rename from teavm-maven-plugin/src/main/resources/org/teavm/maven/res/toggle-small.png
rename to teavm-core/src/main/resources/org/teavm/tooling/test/res/toggle-small.png
diff --git a/teavm-maven-plugin/src/main/java/org/teavm/maven/BuildJavascriptMojo.java b/teavm-maven-plugin/src/main/java/org/teavm/maven/BuildJavascriptMojo.java
index b414e0cfb..a5f57c210 100644
--- a/teavm-maven-plugin/src/main/java/org/teavm/maven/BuildJavascriptMojo.java
+++ b/teavm-maven-plugin/src/main/java/org/teavm/maven/BuildJavascriptMojo.java
@@ -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 instantiateTransformers(ClassLoader classLoader)
throws MojoExecutionException {
List 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");
- }
- }
}
diff --git a/teavm-maven-plugin/src/main/java/org/teavm/maven/BuildJavascriptTestMojo.java b/teavm-maven-plugin/src/main/java/org/teavm/maven/BuildJavascriptTestMojo.java
index 1bb62251d..6702cc11c 100644
--- a/teavm-maven-plugin/src/main/java/org/teavm/maven/BuildJavascriptTestMojo.java
+++ b/teavm-maven-plugin/src/main/java/org/teavm/maven/BuildJavascriptTestMojo.java
@@ -15,7 +15,8 @@
*/
package org.teavm.maven;
-import java.io.*;
+import java.io.File;
+import java.io.IOException;
import java.lang.reflect.Constructor;
import java.lang.reflect.InvocationTargetException;
import java.net.MalformedURLException;
@@ -25,7 +26,6 @@ import java.util.*;
import java.util.jar.JarEntry;
import java.util.jar.JarFile;
import org.apache.commons.io.FilenameUtils;
-import org.apache.commons.io.IOUtils;
import org.apache.maven.artifact.Artifact;
import org.apache.maven.plugin.AbstractMojo;
import org.apache.maven.plugin.MojoExecutionException;
@@ -36,16 +36,11 @@ 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.FiniteExecutor;
-import org.teavm.common.SimpleFiniteExecutor;
-import org.teavm.common.ThreadPoolFiniteExecutor;
-import org.teavm.model.*;
-import org.teavm.parsing.ClasspathClassHolderSource;
+import org.teavm.model.ClassHolderTransformer;
import org.teavm.testing.JUnitTestAdapter;
import org.teavm.testing.TestAdapter;
-import org.teavm.vm.DirectoryBuildTarget;
-import org.teavm.vm.TeaVM;
-import org.teavm.vm.TeaVMBuilder;
+import org.teavm.tooling.TeaVMTestTool;
+import org.teavm.tooling.TeaVMToolException;
/**
*
@@ -57,11 +52,6 @@ public class BuildJavascriptTestMojo extends AbstractMojo {
private static Set testScopes = new HashSet<>(Arrays.asList(
Artifact.SCOPE_COMPILE, Artifact.SCOPE_TEST, Artifact.SCOPE_SYSTEM, Artifact.SCOPE_RUNTIME,
Artifact.SCOPE_PROVIDED));
- private Map> groupedMethods = new HashMap<>();
- private Map fileNames = new HashMap<>();
- private List testMethods = new ArrayList<>();
- private List testClasses = new ArrayList<>();
- private TestAdapter adapter;
@Component
private MavenProject project;
@@ -93,16 +83,14 @@ public class BuildJavascriptTestMojo extends AbstractMojo {
@Parameter
private String[] transformers;
- private List transformerInstances;
-
@Parameter
private String[] additionalScripts;
- private List additionalScriptLocalPaths = new ArrayList<>();
-
@Parameter
private Properties properties;
+ private TeaVMTestTool tool = new TeaVMTestTool();
+
public void setProject(MavenProject project) {
this.project = project;
}
@@ -154,124 +142,33 @@ public class BuildJavascriptTestMojo extends AbstractMojo {
getLog().info("Tests build skipped as specified by system property");
return;
}
- Runnable finalizer = null;
try {
final ClassLoader classLoader = prepareClassLoader();
- createAdapter(classLoader);
getLog().info("Searching for tests in the directory `" + testFiles.getAbsolutePath() + "'");
+ tool.setClassLoader(classLoader);
+ tool.setAdapter(createAdapter(classLoader));
findTestClasses(classLoader, testFiles, "");
if (scanDependencies) {
findTestsInDependencies(classLoader);
}
- final Log log = getLog();
- new File(outputDir, "tests").mkdirs();
- new File(outputDir, "res").mkdirs();
- resourceToFile("org/teavm/javascript/runtime.js", "res/runtime.js");
- resourceToFile("org/teavm/maven/res/junit-support.js", "res/junit-support.js");
- resourceToFile("org/teavm/maven/res/junit.css", "res/junit.css");
- resourceToFile("org/teavm/maven/res/class_obj.png", "res/class_obj.png");
- resourceToFile("org/teavm/maven/res/control-000-small.png", "res/control-000-small.png");
- resourceToFile("org/teavm/maven/res/methpub_obj.png", "res/methpub_obj.png");
- resourceToFile("org/teavm/maven/res/package_obj.png", "res/package_obj.png");
- resourceToFile("org/teavm/maven/res/tick-small-red.png", "res/tick-small-red.png");
- resourceToFile("org/teavm/maven/res/tick-small.png", "res/tick-small.png");
- resourceToFile("org/teavm/maven/res/toggle-small-expand.png", "res/toggle-small-expand.png");
- resourceToFile("org/teavm/maven/res/toggle-small.png", "res/toggle-small.png");
- resourceToFile("org/teavm/maven/junit.html", "junit.html");
- final ClassHolderSource classSource = new ClasspathClassHolderSource(classLoader);
- for (String testClass : testClasses) {
- ClassHolder classHolder = classSource.get(testClass);
- if (classHolder == null) {
- throw new MojoFailureException("Could not find class " + testClass);
- }
- findTests(classHolder);
+ tool.getTransformers().addAll(instantiateTransformers(classLoader));
+ tool.setLog(new MavenTeaVMToolLog(getLog()));
+ tool.setOutputDir(outputDir);
+ tool.setNumThreads(numThreads);
+ tool.setMinifying(minifying);
+ if (properties != null) {
+ tool.getProperties().putAll(properties);
}
-
- transformerInstances = instantiateTransformers(classLoader);
- includeAdditionalScripts(classLoader);
- File allTestsFile = new File(outputDir, "tests/all.js");
- try (Writer allTestsWriter = new OutputStreamWriter(new FileOutputStream(allTestsFile), "UTF-8")) {
- allTestsWriter.write("prepare = function() {\n");
- allTestsWriter.write(" return new JUnitServer(document.body).readTests([");
- boolean first = true;
- for (String testClass : testClasses) {
- if (!first) {
- allTestsWriter.append(",");
- }
- first = false;
- allTestsWriter.append("\n { name : \"").append(testClass).append("\", methods : [");
- boolean firstMethod = true;
- for (MethodReference methodRef : groupedMethods.get(testClass)) {
- String scriptName = "tests/" + fileNames.size() + ".js";
- fileNames.put(methodRef, scriptName);
- if (!firstMethod) {
- allTestsWriter.append(",");
- }
- firstMethod = false;
- allTestsWriter.append("\n { name : \"" + methodRef.getName() + "\", script : \"" +
- scriptName + "\", expected : [");
- MethodHolder methodHolder = classSource.get(testClass).getMethod(
- methodRef.getDescriptor());
- boolean firstException = true;
- for (String exception : adapter.getExpectedExceptions(methodHolder)) {
- if (!firstException) {
- allTestsWriter.append(", ");
- }
- firstException = false;
- allTestsWriter.append("\"" + exception + "\"");
- }
- allTestsWriter.append("], additionalScripts : [");
- for (int i = 0; i < additionalScriptLocalPaths.size(); ++i) {
- if (i > 0) {
- allTestsWriter.append(", ");
- }
- escapeString(additionalScriptLocalPaths.get(i), allTestsWriter);
- }
- allTestsWriter.append("] }");
- }
- allTestsWriter.append("] }");
- }
- allTestsWriter.write("], function() {}); }");
- }
- int methodsGenerated = 0;
- log.info("Generating test files");
- FiniteExecutor executor = new SimpleFiniteExecutor();
- if (numThreads != 1) {
- int threads = numThreads != 0 ? numThreads : Runtime.getRuntime().availableProcessors();
- final ThreadPoolFiniteExecutor threadedExecutor = new ThreadPoolFiniteExecutor(threads);
- finalizer = new Runnable() {
- @Override public void run() {
- threadedExecutor.stop();
- }
- };
- executor = threadedExecutor;
- }
- for (final MethodReference method : testMethods) {
- executor.execute(new Runnable() {
- @Override public void run() {
- log.debug("Building test for " + method);
- try {
- decompileClassesForTest(classLoader, new CopyClassHolderSource(classSource), method,
- fileNames.get(method), new SimpleFiniteExecutor());
- } catch (IOException e) {
- log.error("Error generating JavaScript", e);
- }
- }
- });
- ++methodsGenerated;
- }
- executor.complete();
- log.info("Test files successfully generated for " + methodsGenerated + " method(s).");
- } catch (IOException e) {
- throw new MojoFailureException("IO error occured generating JavaScript files", e);
- } finally {
- if (finalizer != null) {
- finalizer.run();
+ if (additionalScripts != null) {
+ tool.getAdditionalScripts().addAll(Arrays.asList(additionalScripts));
}
+ tool.generate();
+ } catch (TeaVMToolException e) {
+ throw new MojoFailureException("Error occured generating JavaScript files", e);
}
}
- private void createAdapter(ClassLoader classLoader) throws MojoExecutionException {
+ private TestAdapter createAdapter(ClassLoader classLoader) throws MojoExecutionException {
Class> adapterClsRaw;
try {
adapterClsRaw = Class.forName(adapterClass, true, classLoader);
@@ -290,7 +187,7 @@ public class BuildJavascriptTestMojo extends AbstractMojo {
throw new MojoExecutionException("No default constructor found for test adapter " + adapterClass, e);
}
try {
- adapter = cons.newInstance();
+ return cons.newInstance();
} catch (IllegalAccessException | InstantiationException e) {
throw new MojoExecutionException("Error creating test adapter", e);
} catch (InvocationTargetException e) {
@@ -330,89 +227,6 @@ public class BuildJavascriptTestMojo extends AbstractMojo {
}
}
- private void decompileClassesForTest(ClassLoader classLoader, ClassHolderSource classSource,
- MethodReference methodRef, String targetName, FiniteExecutor executor) throws IOException {
- TeaVM vm = new TeaVMBuilder()
- .setClassLoader(classLoader)
- .setClassSource(classSource)
- .setExecutor(executor)
- .build();
- vm.setProperties(properties);
- vm.setMinifying(minifying);
- vm.installPlugins();
- new TestExceptionPlugin().install(vm);
- for (ClassHolderTransformer transformer : transformerInstances) {
- vm.add(transformer);
- }
- File file = new File(outputDir, targetName);
- try (Writer innerWriter = new OutputStreamWriter(new FileOutputStream(file), "UTF-8")) {
- MethodReference cons = new MethodReference(methodRef.getClassName(),
- new MethodDescriptor("", ValueType.VOID));
- MethodReference exceptionMsg = new MethodReference("java.lang.Throwable", "getMessage",
- ValueType.object("java.lang.String"));
- vm.entryPoint("initInstance", cons);
- vm.entryPoint("runTest", methodRef).withValue(0, cons.getClassName());
- vm.entryPoint("extractException", exceptionMsg);
- vm.exportType("TestClass", cons.getClassName());
- vm.build(innerWriter, new DirectoryBuildTarget(outputDir));
- if (!vm.hasMissingItems()) {
- innerWriter.append("\n");
- innerWriter.append("\nJUnitClient.run();");
- innerWriter.close();
- } else {
- innerWriter.append("JUnitClient.reportError(\n");
- StringBuilder sb = new StringBuilder();
- vm.showMissingItems(sb);
- escapeStringLiteral(sb.toString(), innerWriter);
- innerWriter.append(");");
- getLog().warn("Error building test " + methodRef);
- getLog().warn(sb);
- }
- }
- }
-
- private void escapeStringLiteral(String text, Writer writer) throws IOException {
- int index = 0;
- while (true) {
- int next = text.indexOf('\n', index);
- if (next < 0) {
- break;
- }
- escapeString(text.substring(index, next + 1), writer);
- writer.append(" +\n");
- index = next + 1;
- }
- escapeString(text.substring(index), writer);
- }
-
- private void escapeString(String string, Writer writer) throws IOException {
- writer.append('\"');
- for (int i = 0; i < string.length(); ++i) {
- char c = string.charAt(i);
- switch (c) {
- case '"':
- writer.append("\\\"");
- break;
- case '\\':
- writer.append("\\\\");
- break;
- case '\n':
- writer.append("\\n");
- break;
- case '\r':
- writer.append("\\r");
- break;
- case '\t':
- writer.append("\\t");
- break;
- default:
- writer.append(c);
- break;
- }
- }
- writer.append('\"');
- }
-
private void findTestsInDependencies(ClassLoader classLoader) throws MojoExecutionException {
try {
Log log = getLog();
@@ -477,8 +291,8 @@ public class BuildJavascriptTestMojo extends AbstractMojo {
}
try {
Class> candidate = Class.forName(className, true, classLoader);
- if (adapter.acceptClass(candidate)) {
- testClasses.add(candidate.getName());
+ if (tool.getAdapter().acceptClass(candidate)) {
+ tool.getTestClasses().add(candidate.getName());
getLog().info("Test class detected: " + candidate.getName());
}
} catch (ClassNotFoundException e) {
@@ -486,28 +300,6 @@ public class BuildJavascriptTestMojo extends AbstractMojo {
}
}
- private void findTests(ClassHolder cls) {
- for (MethodHolder method : cls.getMethods()) {
- if (adapter.acceptMethod(method)) {
- MethodReference ref = new MethodReference(cls.getName(), method.getDescriptor());
- testMethods.add(ref);
- List group = groupedMethods.get(cls.getName());
- if (group == null) {
- group = new ArrayList<>();
- groupedMethods.put(cls.getName(), group);
- }
- group.add(ref);
- }
- }
- }
-
- private void resourceToFile(String resource, String fileName) throws IOException {
- try (InputStream input = BuildJavascriptTestMojo.class.getClassLoader().getResourceAsStream(resource)) {
- try (OutputStream output = new FileOutputStream(new File(outputDir, fileName))) {
- IOUtils.copy(input, output);
- }
- }
- }
private List instantiateTransformers(ClassLoader classLoader)
throws MojoExecutionException {
@@ -543,29 +335,4 @@ public class BuildJavascriptTestMojo extends AbstractMojo {
}
return transformerInstances;
}
-
- private void includeAdditionalScripts(ClassLoader classLoader) throws MojoExecutionException {
- if (additionalScripts == null) {
- return;
- }
- for (String script : additionalScripts) {
- String simpleName = script.substring(script.lastIndexOf('/') + 1);
- additionalScriptLocalPaths.add("tests/" + simpleName);
- if (classLoader.getResource(script) == null) {
- throw new MojoExecutionException("Additional script " + script + " was not found");
- }
- File file = new File(outputDir, "tests/" + simpleName);
- try (InputStream in = classLoader.getResourceAsStream(script)) {
- if (!file.exists()) {
- file.createNewFile();
- }
- try(OutputStream out = new FileOutputStream(file)) {
- IOUtils.copy(in, out);
- }
- } catch (IOException e) {
- throw new MojoExecutionException("Error copying additional script " + script, e);
- }
- }
- }
}
-
diff --git a/teavm-maven-plugin/src/main/java/org/teavm/maven/MavenTeaVMToolLog.java b/teavm-maven-plugin/src/main/java/org/teavm/maven/MavenTeaVMToolLog.java
new file mode 100644
index 000000000..657e69e28
--- /dev/null
+++ b/teavm-maven-plugin/src/main/java/org/teavm/maven/MavenTeaVMToolLog.java
@@ -0,0 +1,56 @@
+package org.teavm.maven;
+
+import org.apache.maven.plugin.logging.Log;
+import org.teavm.tooling.TeaVMToolLog;
+
+/**
+ *
+ * @author Alexey Andreev
+ */
+public class MavenTeaVMToolLog implements TeaVMToolLog {
+ private Log log;
+
+ public MavenTeaVMToolLog(Log log) {
+ this.log = log;
+ }
+
+ @Override
+ public void info(String text) {
+ log.info(text);
+ }
+
+ @Override
+ public void debug(String text) {
+ log.debug(text);
+ }
+
+ @Override
+ public void warning(String text) {
+ log.warn(text);
+ }
+
+ @Override
+ public void error(String text) {
+ log.error(text);
+ }
+
+ @Override
+ public void info(String text, Throwable e) {
+ log.info(text, e);
+ }
+
+ @Override
+ public void debug(String text, Throwable e) {
+ log.debug(text, e);
+ }
+
+ @Override
+ public void warning(String text, Throwable e) {
+ log.warn(text, e);
+ }
+
+ @Override
+ public void error(String text, Throwable e) {
+ log.error(text, e);
+ }
+}