Merge branch 'cli' into date2
Conflicts: pom.xml
1
pom.xml
|
@ -78,6 +78,7 @@
|
||||||
<module>teavm-html4j</module>
|
<module>teavm-html4j</module>
|
||||||
<module>teavm-samples</module>
|
<module>teavm-samples</module>
|
||||||
<module>teavm-platform</module>
|
<module>teavm-platform</module>
|
||||||
|
<module>teavm-cli</module>
|
||||||
</modules>
|
</modules>
|
||||||
|
|
||||||
<dependencyManagement>
|
<dependencyManagement>
|
||||||
|
|
4
teavm-cli/.gitignore
vendored
Normal file
|
@ -0,0 +1,4 @@
|
||||||
|
/target
|
||||||
|
/.settings
|
||||||
|
/.classpath
|
||||||
|
/.project
|
55
teavm-cli/pom.xml
Normal file
|
@ -0,0 +1,55 @@
|
||||||
|
<!--
|
||||||
|
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.
|
||||||
|
-->
|
||||||
|
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
|
||||||
|
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
|
||||||
|
<modelVersion>4.0.0</modelVersion>
|
||||||
|
|
||||||
|
<parent>
|
||||||
|
<groupId>org.teavm</groupId>
|
||||||
|
<artifactId>teavm</artifactId>
|
||||||
|
<version>0.2-SNAPSHOT</version>
|
||||||
|
</parent>
|
||||||
|
<artifactId>teavm-cli</artifactId>
|
||||||
|
|
||||||
|
<name>TeaVM CLI</name>
|
||||||
|
<description>TeaVM command line tools</description>
|
||||||
|
|
||||||
|
<dependencies>
|
||||||
|
<dependency>
|
||||||
|
<groupId>org.teavm</groupId>
|
||||||
|
<artifactId>teavm-core</artifactId>
|
||||||
|
<version>${project.version}</version>
|
||||||
|
</dependency>
|
||||||
|
<dependency>
|
||||||
|
<groupId>commons-cli</groupId>
|
||||||
|
<artifactId>commons-cli</artifactId>
|
||||||
|
<version>1.2</version>
|
||||||
|
</dependency>
|
||||||
|
</dependencies>
|
||||||
|
|
||||||
|
<build>
|
||||||
|
<plugins>
|
||||||
|
<plugin>
|
||||||
|
<groupId>org.apache.maven.plugins</groupId>
|
||||||
|
<artifactId>maven-source-plugin</artifactId>
|
||||||
|
</plugin>
|
||||||
|
<plugin>
|
||||||
|
<groupId>org.apache.maven.plugins</groupId>
|
||||||
|
<artifactId>maven-javadoc-plugin</artifactId>
|
||||||
|
</plugin>
|
||||||
|
</plugins>
|
||||||
|
</build>
|
||||||
|
</project>
|
|
@ -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 <konsoletyper@gmail.com>
|
||||||
|
*/
|
||||||
|
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);
|
||||||
|
}
|
||||||
|
}
|
146
teavm-cli/src/main/java/org/teavm/cli/TeaVMRunner.java
Normal file
|
@ -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 <konsoletyper@gmail.com>
|
||||||
|
*/
|
||||||
|
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);
|
||||||
|
}
|
||||||
|
}
|
183
teavm-cli/src/main/java/org/teavm/cli/TeaVMTestRunner.java
Normal file
|
@ -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);
|
||||||
|
}
|
||||||
|
}
|
|
@ -13,7 +13,7 @@
|
||||||
* See the License for the specific language governing permissions and
|
* See the License for the specific language governing permissions and
|
||||||
* limitations under the License.
|
* limitations under the License.
|
||||||
*/
|
*/
|
||||||
package org.teavm.maven;
|
package org.teavm.tooling;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
*
|
*
|
|
@ -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 <konsoletyper@gmail.com>
|
||||||
|
*/
|
||||||
|
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) {
|
||||||
|
}
|
||||||
|
}
|
|
@ -13,7 +13,7 @@
|
||||||
* See the License for the specific language governing permissions and
|
* See the License for the specific language governing permissions and
|
||||||
* limitations under the License.
|
* limitations under the License.
|
||||||
*/
|
*/
|
||||||
package org.teavm.maven;
|
package org.teavm.tooling;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
*
|
*
|
|
@ -13,7 +13,7 @@
|
||||||
* See the License for the specific language governing permissions and
|
* See the License for the specific language governing permissions and
|
||||||
* limitations under the License.
|
* limitations under the License.
|
||||||
*/
|
*/
|
||||||
package org.teavm.maven;
|
package org.teavm.tooling;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
*
|
*
|
359
teavm-core/src/main/java/org/teavm/tooling/TeaVMTestTool.java
Normal file
|
@ -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 <konsoletyper@gmail.com>
|
||||||
|
*/
|
||||||
|
public class TeaVMTestTool {
|
||||||
|
private Map<String, List<MethodReference>> groupedMethods = new HashMap<>();
|
||||||
|
private Map<MethodReference, String> fileNames = new HashMap<>();
|
||||||
|
private List<MethodReference> testMethods = new ArrayList<>();
|
||||||
|
private File outputDir = new File(".");
|
||||||
|
private boolean minifying = true;
|
||||||
|
private int numThreads = 1;
|
||||||
|
private TestAdapter adapter = new JUnitTestAdapter();
|
||||||
|
private List<ClassHolderTransformer> transformers = new ArrayList<>();
|
||||||
|
private List<String> additionalScripts = new ArrayList<>();
|
||||||
|
private List<String> additionalScriptLocalPaths = new ArrayList<>();
|
||||||
|
private Properties properties = new Properties();
|
||||||
|
private List<String> 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<ClassHolderTransformer> getTransformers() {
|
||||||
|
return transformers;
|
||||||
|
}
|
||||||
|
|
||||||
|
public List<String> getAdditionalScripts() {
|
||||||
|
return additionalScripts;
|
||||||
|
}
|
||||||
|
|
||||||
|
public Properties getProperties() {
|
||||||
|
return properties;
|
||||||
|
}
|
||||||
|
|
||||||
|
public List<String> 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<MethodReference> 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<MethodReference> 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("<init>", 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('\"');
|
||||||
|
}
|
||||||
|
}
|
256
teavm-core/src/main/java/org/teavm/tooling/TeaVMTool.java
Normal 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/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");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
|
@ -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 <konsoletyper@gmail.com>
|
||||||
|
*/
|
||||||
|
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);
|
||||||
|
}
|
||||||
|
}
|
38
teavm-core/src/main/java/org/teavm/tooling/TeaVMToolLog.java
Normal file
|
@ -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 <konsoletyper@gmail.com>
|
||||||
|
*/
|
||||||
|
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);
|
||||||
|
}
|
|
@ -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) {
|
||||||
|
}
|
||||||
|
}
|
|
@ -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());
|
||||||
|
}
|
||||||
|
}
|
Before Width: | Height: | Size: 774 B After Width: | Height: | Size: 774 B |
Before Width: | Height: | Size: 297 B After Width: | Height: | Size: 297 B |
Before Width: | Height: | Size: 325 B After Width: | Height: | Size: 325 B |
Before Width: | Height: | Size: 345 B After Width: | Height: | Size: 345 B |
Before Width: | Height: | Size: 1.2 KiB After Width: | Height: | Size: 1.2 KiB |
Before Width: | Height: | Size: 321 B After Width: | Height: | Size: 321 B |
Before Width: | Height: | Size: 418 B After Width: | Height: | Size: 418 B |
Before Width: | Height: | Size: 394 B After Width: | Height: | Size: 394 B |
|
@ -15,14 +15,13 @@
|
||||||
*/
|
*/
|
||||||
package org.teavm.maven;
|
package org.teavm.maven;
|
||||||
|
|
||||||
import java.io.*;
|
import java.io.File;
|
||||||
import java.lang.reflect.Constructor;
|
import java.lang.reflect.Constructor;
|
||||||
import java.lang.reflect.InvocationTargetException;
|
import java.lang.reflect.InvocationTargetException;
|
||||||
import java.net.MalformedURLException;
|
import java.net.MalformedURLException;
|
||||||
import java.net.URL;
|
import java.net.URL;
|
||||||
import java.net.URLClassLoader;
|
import java.net.URLClassLoader;
|
||||||
import java.util.*;
|
import java.util.*;
|
||||||
import org.apache.commons.io.IOUtils;
|
|
||||||
import org.apache.maven.artifact.Artifact;
|
import org.apache.maven.artifact.Artifact;
|
||||||
import org.apache.maven.plugin.AbstractMojo;
|
import org.apache.maven.plugin.AbstractMojo;
|
||||||
import org.apache.maven.plugin.MojoExecutionException;
|
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.Parameter;
|
||||||
import org.apache.maven.plugins.annotations.ResolutionScope;
|
import org.apache.maven.plugins.annotations.ResolutionScope;
|
||||||
import org.apache.maven.project.MavenProject;
|
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.ClassHolderTransformer;
|
||||||
import org.teavm.model.MethodDescriptor;
|
import org.teavm.tooling.*;
|
||||||
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;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
*
|
*
|
||||||
|
@ -94,6 +86,8 @@ public class BuildJavascriptMojo extends AbstractMojo {
|
||||||
@Parameter
|
@Parameter
|
||||||
private MethodAlias[] methodAliases;
|
private MethodAlias[] methodAliases;
|
||||||
|
|
||||||
|
private TeaVMTool tool = new TeaVMTool();
|
||||||
|
|
||||||
public void setProject(MavenProject project) {
|
public void setProject(MavenProject project) {
|
||||||
this.project = project;
|
this.project = project;
|
||||||
}
|
}
|
||||||
|
@ -153,105 +147,35 @@ public class BuildJavascriptMojo extends AbstractMojo {
|
||||||
@Override
|
@Override
|
||||||
public void execute() throws MojoExecutionException {
|
public void execute() throws MojoExecutionException {
|
||||||
Log log = getLog();
|
Log log = getLog();
|
||||||
Runnable finalizer = null;
|
tool.setLog(new MavenTeaVMToolLog(log));
|
||||||
try {
|
try {
|
||||||
ClassLoader classLoader = prepareClassLoader();
|
ClassLoader classLoader = prepareClassLoader();
|
||||||
log.info("Building JavaScript file");
|
tool.setClassLoader(classLoader);
|
||||||
TeaVMBuilder vmBuilder = new TeaVMBuilder();
|
tool.setBytecodeLogging(bytecodeLogging);
|
||||||
vmBuilder.setClassLoader(classLoader).setClassSource(new ClasspathClassHolderSource(classLoader));
|
tool.setMainClass(mainClass);
|
||||||
if (numThreads != 1) {
|
tool.setMainPageIncluded(mainPageIncluded);
|
||||||
int threads = numThreads != 0 ? numThreads : Runtime.getRuntime().availableProcessors();
|
tool.setMinifying(minifying);
|
||||||
final ThreadPoolFiniteExecutor executor = new ThreadPoolFiniteExecutor(threads);
|
tool.setNumThreads(numThreads);
|
||||||
finalizer = new Runnable() {
|
tool.setRuntime(runtime);
|
||||||
@Override public void run() {
|
tool.setTargetDirectory(targetDirectory);
|
||||||
executor.stop();
|
tool.setTargetFileName(targetFileName);
|
||||||
}
|
tool.getTransformers().addAll(instantiateTransformers(classLoader));
|
||||||
};
|
|
||||||
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");
|
|
||||||
}
|
|
||||||
if (classAliases != null) {
|
if (classAliases != null) {
|
||||||
for (ClassAlias alias : classAliases) {
|
tool.getClassAliases().addAll(Arrays.asList(classAliases));
|
||||||
vm.exportType(alias.getAlias(), alias.getClassName());
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
if (methodAliases != null) {
|
if (methodAliases != null) {
|
||||||
for (MethodAlias methodAlias : methodAliases) {
|
tool.getMethodAliases().addAll(Arrays.asList(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);
|
|
||||||
}
|
}
|
||||||
|
if (properties != null) {
|
||||||
|
tool.getProperties().putAll(properties);
|
||||||
}
|
}
|
||||||
|
tool.generate();
|
||||||
} catch (RuntimeException e) {
|
} catch (RuntimeException e) {
|
||||||
throw new MojoExecutionException("Unexpected error occured", e);
|
throw new MojoExecutionException("Unexpected error occured", e);
|
||||||
} catch (IOException e) {
|
} catch (TeaVMToolException e) {
|
||||||
throw new MojoExecutionException("IO error occured", 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)
|
private List<ClassHolderTransformer> instantiateTransformers(ClassLoader classLoader)
|
||||||
throws MojoExecutionException {
|
throws MojoExecutionException {
|
||||||
|
@ -316,18 +240,4 @@ public class BuildJavascriptMojo extends AbstractMojo {
|
||||||
throw new MojoExecutionException("Error gathering classpath information", e);
|
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");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -15,7 +15,8 @@
|
||||||
*/
|
*/
|
||||||
package org.teavm.maven;
|
package org.teavm.maven;
|
||||||
|
|
||||||
import java.io.*;
|
import java.io.File;
|
||||||
|
import java.io.IOException;
|
||||||
import java.lang.reflect.Constructor;
|
import java.lang.reflect.Constructor;
|
||||||
import java.lang.reflect.InvocationTargetException;
|
import java.lang.reflect.InvocationTargetException;
|
||||||
import java.net.MalformedURLException;
|
import java.net.MalformedURLException;
|
||||||
|
@ -25,7 +26,6 @@ import java.util.*;
|
||||||
import java.util.jar.JarEntry;
|
import java.util.jar.JarEntry;
|
||||||
import java.util.jar.JarFile;
|
import java.util.jar.JarFile;
|
||||||
import org.apache.commons.io.FilenameUtils;
|
import org.apache.commons.io.FilenameUtils;
|
||||||
import org.apache.commons.io.IOUtils;
|
|
||||||
import org.apache.maven.artifact.Artifact;
|
import org.apache.maven.artifact.Artifact;
|
||||||
import org.apache.maven.plugin.AbstractMojo;
|
import org.apache.maven.plugin.AbstractMojo;
|
||||||
import org.apache.maven.plugin.MojoExecutionException;
|
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.Parameter;
|
||||||
import org.apache.maven.plugins.annotations.ResolutionScope;
|
import org.apache.maven.plugins.annotations.ResolutionScope;
|
||||||
import org.apache.maven.project.MavenProject;
|
import org.apache.maven.project.MavenProject;
|
||||||
import org.teavm.common.FiniteExecutor;
|
import org.teavm.model.ClassHolderTransformer;
|
||||||
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.JUnitTestAdapter;
|
||||||
import org.teavm.testing.TestAdapter;
|
import org.teavm.testing.TestAdapter;
|
||||||
import org.teavm.vm.DirectoryBuildTarget;
|
import org.teavm.tooling.TeaVMTestTool;
|
||||||
import org.teavm.vm.TeaVM;
|
import org.teavm.tooling.TeaVMToolException;
|
||||||
import org.teavm.vm.TeaVMBuilder;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
*
|
*
|
||||||
|
@ -57,11 +52,6 @@ public class BuildJavascriptTestMojo extends AbstractMojo {
|
||||||
private static Set<String> testScopes = new HashSet<>(Arrays.asList(
|
private static Set<String> testScopes = new HashSet<>(Arrays.asList(
|
||||||
Artifact.SCOPE_COMPILE, Artifact.SCOPE_TEST, Artifact.SCOPE_SYSTEM, Artifact.SCOPE_RUNTIME,
|
Artifact.SCOPE_COMPILE, Artifact.SCOPE_TEST, Artifact.SCOPE_SYSTEM, Artifact.SCOPE_RUNTIME,
|
||||||
Artifact.SCOPE_PROVIDED));
|
Artifact.SCOPE_PROVIDED));
|
||||||
private Map<String, List<MethodReference>> groupedMethods = new HashMap<>();
|
|
||||||
private Map<MethodReference, String> fileNames = new HashMap<>();
|
|
||||||
private List<MethodReference> testMethods = new ArrayList<>();
|
|
||||||
private List<String> testClasses = new ArrayList<>();
|
|
||||||
private TestAdapter adapter;
|
|
||||||
|
|
||||||
@Component
|
@Component
|
||||||
private MavenProject project;
|
private MavenProject project;
|
||||||
|
@ -93,16 +83,14 @@ public class BuildJavascriptTestMojo extends AbstractMojo {
|
||||||
@Parameter
|
@Parameter
|
||||||
private String[] transformers;
|
private String[] transformers;
|
||||||
|
|
||||||
private List<ClassHolderTransformer> transformerInstances;
|
|
||||||
|
|
||||||
@Parameter
|
@Parameter
|
||||||
private String[] additionalScripts;
|
private String[] additionalScripts;
|
||||||
|
|
||||||
private List<String> additionalScriptLocalPaths = new ArrayList<>();
|
|
||||||
|
|
||||||
@Parameter
|
@Parameter
|
||||||
private Properties properties;
|
private Properties properties;
|
||||||
|
|
||||||
|
private TeaVMTestTool tool = new TeaVMTestTool();
|
||||||
|
|
||||||
public void setProject(MavenProject project) {
|
public void setProject(MavenProject project) {
|
||||||
this.project = project;
|
this.project = project;
|
||||||
}
|
}
|
||||||
|
@ -154,124 +142,33 @@ public class BuildJavascriptTestMojo extends AbstractMojo {
|
||||||
getLog().info("Tests build skipped as specified by system property");
|
getLog().info("Tests build skipped as specified by system property");
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
Runnable finalizer = null;
|
|
||||||
try {
|
try {
|
||||||
final ClassLoader classLoader = prepareClassLoader();
|
final ClassLoader classLoader = prepareClassLoader();
|
||||||
createAdapter(classLoader);
|
|
||||||
getLog().info("Searching for tests in the directory `" + testFiles.getAbsolutePath() + "'");
|
getLog().info("Searching for tests in the directory `" + testFiles.getAbsolutePath() + "'");
|
||||||
|
tool.setClassLoader(classLoader);
|
||||||
|
tool.setAdapter(createAdapter(classLoader));
|
||||||
findTestClasses(classLoader, testFiles, "");
|
findTestClasses(classLoader, testFiles, "");
|
||||||
if (scanDependencies) {
|
if (scanDependencies) {
|
||||||
findTestsInDependencies(classLoader);
|
findTestsInDependencies(classLoader);
|
||||||
}
|
}
|
||||||
final Log log = getLog();
|
tool.getTransformers().addAll(instantiateTransformers(classLoader));
|
||||||
new File(outputDir, "tests").mkdirs();
|
tool.setLog(new MavenTeaVMToolLog(getLog()));
|
||||||
new File(outputDir, "res").mkdirs();
|
tool.setOutputDir(outputDir);
|
||||||
resourceToFile("org/teavm/javascript/runtime.js", "res/runtime.js");
|
tool.setNumThreads(numThreads);
|
||||||
resourceToFile("org/teavm/maven/res/junit-support.js", "res/junit-support.js");
|
tool.setMinifying(minifying);
|
||||||
resourceToFile("org/teavm/maven/res/junit.css", "res/junit.css");
|
if (properties != null) {
|
||||||
resourceToFile("org/teavm/maven/res/class_obj.png", "res/class_obj.png");
|
tool.getProperties().putAll(properties);
|
||||||
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);
|
if (additionalScripts != null) {
|
||||||
}
|
tool.getAdditionalScripts().addAll(Arrays.asList(additionalScripts));
|
||||||
|
|
||||||
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();
|
|
||||||
}
|
}
|
||||||
|
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;
|
Class<?> adapterClsRaw;
|
||||||
try {
|
try {
|
||||||
adapterClsRaw = Class.forName(adapterClass, true, classLoader);
|
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);
|
throw new MojoExecutionException("No default constructor found for test adapter " + adapterClass, e);
|
||||||
}
|
}
|
||||||
try {
|
try {
|
||||||
adapter = cons.newInstance();
|
return cons.newInstance();
|
||||||
} catch (IllegalAccessException | InstantiationException e) {
|
} catch (IllegalAccessException | InstantiationException e) {
|
||||||
throw new MojoExecutionException("Error creating test adapter", e);
|
throw new MojoExecutionException("Error creating test adapter", e);
|
||||||
} catch (InvocationTargetException 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("<init>", 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 {
|
private void findTestsInDependencies(ClassLoader classLoader) throws MojoExecutionException {
|
||||||
try {
|
try {
|
||||||
Log log = getLog();
|
Log log = getLog();
|
||||||
|
@ -477,8 +291,8 @@ public class BuildJavascriptTestMojo extends AbstractMojo {
|
||||||
}
|
}
|
||||||
try {
|
try {
|
||||||
Class<?> candidate = Class.forName(className, true, classLoader);
|
Class<?> candidate = Class.forName(className, true, classLoader);
|
||||||
if (adapter.acceptClass(candidate)) {
|
if (tool.getAdapter().acceptClass(candidate)) {
|
||||||
testClasses.add(candidate.getName());
|
tool.getTestClasses().add(candidate.getName());
|
||||||
getLog().info("Test class detected: " + candidate.getName());
|
getLog().info("Test class detected: " + candidate.getName());
|
||||||
}
|
}
|
||||||
} catch (ClassNotFoundException e) {
|
} 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<MethodReference> 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<ClassHolderTransformer> instantiateTransformers(ClassLoader classLoader)
|
private List<ClassHolderTransformer> instantiateTransformers(ClassLoader classLoader)
|
||||||
throws MojoExecutionException {
|
throws MojoExecutionException {
|
||||||
|
@ -543,29 +335,4 @@ public class BuildJavascriptTestMojo extends AbstractMojo {
|
||||||
}
|
}
|
||||||
return transformerInstances;
|
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);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
|
@ -0,0 +1,56 @@
|
||||||
|
package org.teavm.maven;
|
||||||
|
|
||||||
|
import org.apache.maven.plugin.logging.Log;
|
||||||
|
import org.teavm.tooling.TeaVMToolLog;
|
||||||
|
|
||||||
|
/**
|
||||||
|
*
|
||||||
|
* @author Alexey Andreev <konsoletyper@gmail.com>
|
||||||
|
*/
|
||||||
|
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);
|
||||||
|
}
|
||||||
|
}
|