diff --git a/pom.xml b/pom.xml index ea900f9c3..54733ecef 100644 --- a/pom.xml +++ b/pom.xml @@ -137,6 +137,11 @@ maven-core 3.0 + + org.apache.maven + maven-artifact + 3.0 + javax.websocket javax.websocket-api diff --git a/teavm-core/src/main/java/org/teavm/debugging/information/DebugInformation.java b/teavm-core/src/main/java/org/teavm/debugging/information/DebugInformation.java index b2e344ced..11c5e9723 100644 --- a/teavm-core/src/main/java/org/teavm/debugging/information/DebugInformation.java +++ b/teavm-core/src/main/java/org/teavm/debugging/information/DebugInformation.java @@ -377,8 +377,8 @@ public class DebugInformation { writer.write(this); } - public void writeAsSourceMaps(Writer output, String sourceFile) throws IOException { - new SourceMapsWriter(output).write(sourceFile, this); + public void writeAsSourceMaps(Writer output, String sourceRoot, String sourceFile) throws IOException { + new SourceMapsWriter(output).write(sourceFile, sourceRoot, this); } public static DebugInformation read(InputStream input) throws IOException { diff --git a/teavm-core/src/main/java/org/teavm/debugging/information/SourceMapsWriter.java b/teavm-core/src/main/java/org/teavm/debugging/information/SourceMapsWriter.java index a14a8d8c6..e30dca559 100644 --- a/teavm-core/src/main/java/org/teavm/debugging/information/SourceMapsWriter.java +++ b/teavm-core/src/main/java/org/teavm/debugging/information/SourceMapsWriter.java @@ -35,12 +35,14 @@ class SourceMapsWriter { this.output = output; } - public void write(String generatedFile, DebugInformation debugInfo) throws IOException { + public void write(String generatedFile, String sourceRoot, DebugInformation debugInfo) throws IOException { output.write("{\"version\":3"); output.write(",\"file\":\""); writeEscapedString(generatedFile); output.write("\""); - output.write(",\"sourceRoot\":\"\""); + output.write(",\"sourceRoot\":\""); + writeEscapedString(sourceRoot); + output.write("\""); output.write(",\"sources\":["); for (int i = 0; i < debugInfo.fileNames.length; ++i) { if (i > 0) { @@ -59,7 +61,7 @@ class SourceMapsWriter { lastSourceFile = 0; lastSourceLine = 0; for (SourceLocationIterator iter = debugInfo.iterateOverSourceLocations(); !iter.isEndReached(); iter.next()) { - writeSegment(iter.getLocation(), iter.getFileNameId(), iter.getLine()); + writeSegment(iter.getLocation(), iter.getFileNameId(), iter.getLine() - 1); } output.write("\"}"); } diff --git a/teavm-core/src/main/java/org/teavm/tooling/DirectorySourceFileProvider.java b/teavm-core/src/main/java/org/teavm/tooling/DirectorySourceFileProvider.java new file mode 100644 index 000000000..51cdd74f2 --- /dev/null +++ b/teavm-core/src/main/java/org/teavm/tooling/DirectorySourceFileProvider.java @@ -0,0 +1,48 @@ +/* + * 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.File; +import java.io.FileInputStream; +import java.io.IOException; +import java.io.InputStream; + +/** + * + * @author Alexey Andreev + */ +public class DirectorySourceFileProvider implements SourceFileProvider { + private File baseDirectory; + + public DirectorySourceFileProvider(File baseDirectory) { + this.baseDirectory = baseDirectory; + } + + @Override + public void open() throws IOException { + } + + @Override + public void close() throws IOException { + } + + @Override + @SuppressWarnings("resource") + public InputStream openSourceFile(String fullPath) throws IOException { + File file = new File(baseDirectory, fullPath); + return file.exists() ? new FileInputStream(file) : null; + } +} diff --git a/teavm-core/src/main/java/org/teavm/tooling/JarSourceFileProvider.java b/teavm-core/src/main/java/org/teavm/tooling/JarSourceFileProvider.java new file mode 100644 index 000000000..4610d40a5 --- /dev/null +++ b/teavm-core/src/main/java/org/teavm/tooling/JarSourceFileProvider.java @@ -0,0 +1,59 @@ +/* + * 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.File; +import java.io.IOException; +import java.io.InputStream; +import java.util.zip.ZipEntry; +import java.util.zip.ZipFile; + +/** + * + * @author Alexey Andreev + */ +public class JarSourceFileProvider implements SourceFileProvider { + private File file; + private ZipFile zipFile; + + public JarSourceFileProvider(File file) { + this.file = file; + } + + @Override + public void open() throws IOException { + zipFile = new ZipFile(file); + } + + @Override + public void close() throws IOException { + if (this.zipFile == null) { + return; + } + ZipFile zipFile = this.zipFile; + this.zipFile = null; + zipFile.close(); + } + + @Override + public InputStream openSourceFile(String fullPath) throws IOException { + if (zipFile == null) { + return null; + } + ZipEntry entry = zipFile.getEntry(fullPath); + return entry != null ? zipFile.getInputStream(entry) : null; + } +} diff --git a/teavm-core/src/main/java/org/teavm/tooling/ProgramSourceAggregator.java b/teavm-core/src/main/java/org/teavm/tooling/ProgramSourceAggregator.java new file mode 100644 index 000000000..de340d0cc --- /dev/null +++ b/teavm-core/src/main/java/org/teavm/tooling/ProgramSourceAggregator.java @@ -0,0 +1,91 @@ +/* + * 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.util.List; +import java.util.Set; +import org.teavm.model.*; +import org.teavm.model.instructions.*; + +/** + * + * @author Alexey Andreev + */ +class ProgramSourceAggregator implements InstructionReader { + private Set sourceFiles; + + public ProgramSourceAggregator(Set sourceFiles) { + this.sourceFiles = sourceFiles; + } + + public void addLocationsOfProgram(ProgramReader program) { + for (int i = 0; i < program.basicBlockCount(); ++i) { + BasicBlockReader block = program.basicBlockAt(i); + block.readAllInstructions(this); + } + } + + @Override + public void location(InstructionLocation location) { + if (location != null && location.getFileName() != null && !location.getFileName().isEmpty()) { + sourceFiles.add(location.getFileName()); + } + } + + @Override public void nop() { } + @Override public void classConstant(VariableReader receiver, ValueType cst) { } + @Override public void nullConstant(VariableReader receiver) { } + @Override public void integerConstant(VariableReader receiver, int cst) { } + @Override public void longConstant(VariableReader receiver, long cst) { } + @Override public void floatConstant(VariableReader receiver, float cst) { } + @Override public void doubleConstant(VariableReader receiver, double cst) { } + @Override public void stringConstant(VariableReader receiver, String cst) { } + @Override public void binary(BinaryOperation op, VariableReader receiver, VariableReader first, + VariableReader second, NumericOperandType type) { } + @Override public void negate(VariableReader receiver, VariableReader operand, NumericOperandType type) { } + @Override public void assign(VariableReader receiver, VariableReader assignee) { } + @Override public void cast(VariableReader receiver, VariableReader value, ValueType targetType) { } + @Override public void cast(VariableReader receiver, VariableReader value, NumericOperandType sourceType, + NumericOperandType targetType) { } + @Override public void cast(VariableReader receiver, VariableReader value, IntegerSubtype type, + CastIntegerDirection targetType) { } + @Override public void jumpIf(BranchingCondition cond, VariableReader operand, BasicBlockReader consequent, + BasicBlockReader alternative) { } + @Override public void jumpIf(BinaryBranchingCondition cond, VariableReader first, VariableReader second, + BasicBlockReader consequent, BasicBlockReader alternative) { } + @Override public void jump(BasicBlockReader target) { } + @Override public void choose(VariableReader condition, List table, + BasicBlockReader defaultTarget) { } + @Override public void exit(VariableReader valueToReturn) { } + @Override public void raise(VariableReader exception) { } + @Override public void createArray(VariableReader receiver, ValueType itemType, VariableReader size) { } + @Override public void createArray(VariableReader receiver, ValueType itemType, + List dimensions) { } + @Override public void create(VariableReader receiver, String type) { } + @Override public void getField(VariableReader receiver, VariableReader instance, FieldReference field, + ValueType fieldType) { } + @Override public void putField(VariableReader instance, FieldReference field, VariableReader value) { } + @Override public void arrayLength(VariableReader receiver, VariableReader array) { } + @Override public void cloneArray(VariableReader receiver, VariableReader array) { } + @Override public void unwrapArray(VariableReader receiver, VariableReader array, ArrayElementType elementType) { } + @Override public void getElement(VariableReader receiver, VariableReader array, VariableReader index) { } + @Override public void putElement(VariableReader array, VariableReader index, VariableReader value) { } + @Override public void invoke(VariableReader receiver, VariableReader instance, MethodReference method, + List arguments, InvocationType type) { } + @Override public void isInstance(VariableReader receiver, VariableReader value, ValueType type) { } + @Override public void initClass(String className) { } + @Override public void nullCheck(VariableReader receiver, VariableReader value) { } +} diff --git a/teavm-core/src/main/java/org/teavm/tooling/SourceFileProvider.java b/teavm-core/src/main/java/org/teavm/tooling/SourceFileProvider.java new file mode 100644 index 000000000..c5567b036 --- /dev/null +++ b/teavm-core/src/main/java/org/teavm/tooling/SourceFileProvider.java @@ -0,0 +1,31 @@ +/* + * 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.IOException; +import java.io.InputStream; + +/** + * + * @author Alexey Andreev + */ +public interface SourceFileProvider { + void open() throws IOException; + + void close() throws IOException; + + InputStream openSourceFile(String fullPath) throws IOException; +} diff --git a/teavm-core/src/main/java/org/teavm/tooling/SourceFilesCopier.java b/teavm-core/src/main/java/org/teavm/tooling/SourceFilesCopier.java new file mode 100644 index 000000000..f400c20bf --- /dev/null +++ b/teavm-core/src/main/java/org/teavm/tooling/SourceFilesCopier.java @@ -0,0 +1,99 @@ +/* + * 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.HashSet; +import java.util.List; +import java.util.Set; +import org.apache.commons.io.IOUtils; +import org.teavm.model.ClassReader; +import org.teavm.model.ListableClassReaderSource; +import org.teavm.model.MethodReader; + +/** + * + * @author Alexey Andreev + */ +public class SourceFilesCopier { + private TeaVMToolLog log = new EmptyTeaVMToolLog(); + private List sourceFileProviders; + private Set sourceFiles = new HashSet<>(); + + public SourceFilesCopier(List sourceFileProviders) { + this.sourceFileProviders = sourceFileProviders; + } + + public void setLog(TeaVMToolLog log) { + this.log = log; + } + + public void addClasses(ListableClassReaderSource classReader) { + ProgramSourceAggregator sourceAggregator = new ProgramSourceAggregator(sourceFiles); + for (String className : classReader.getClassNames()) { + ClassReader cls = classReader.get(className); + for (MethodReader method : cls.getMethods()) { + if (method.getProgram() == null) { + continue; + } + sourceAggregator.addLocationsOfProgram(method.getProgram()); + } + } + } + + public void copy(File targetDirectory) { + for (SourceFileProvider provider : sourceFileProviders) { + try { + provider.open(); + } catch (IOException e) { + log.warning("Error opening source file provider", e); + } + } + targetDirectory.mkdirs(); + for (String fileName : sourceFiles) { + try (InputStream input = findSourceFile(fileName)) { + if (input != null) { + File outputFile = new File(targetDirectory, fileName); + outputFile.getParentFile().mkdirs(); + try (OutputStream output = new FileOutputStream(outputFile)) { + IOUtils.copy(input, output); + } + } else { + log.info("Missing source file: " + fileName); + } + } catch (IOException e) { + log.warning("Could not copy source file " + fileName, e); + } + } + for (SourceFileProvider provider : sourceFileProviders) { + try { + provider.close(); + } catch (IOException e) { + log.warning("Error closing source file provider", e); + } + } + } + + private InputStream findSourceFile(String fileName) throws IOException { + for (SourceFileProvider provider : sourceFileProviders) { + InputStream input = provider.openSourceFile(fileName); + if (input != null) { + return input; + } + } + return null; + } +} diff --git a/teavm-core/src/main/java/org/teavm/tooling/TeaVMTestTool.java b/teavm-core/src/main/java/org/teavm/tooling/TeaVMTestTool.java index 3780bb586..1d8f225e0 100644 --- a/teavm-core/src/main/java/org/teavm/tooling/TeaVMTestTool.java +++ b/teavm-core/src/main/java/org/teavm/tooling/TeaVMTestTool.java @@ -55,9 +55,12 @@ public class TeaVMTestTool { private TeaVMToolLog log = new EmptyTeaVMToolLog(); private boolean debugInformationGenerated; private boolean sourceMapsGenerated; + private boolean sourceFilesCopied; private boolean incremental; + private List sourceFileProviders = new ArrayList<>(); private RegularMethodNodeCache astCache; private ProgramCache programCache; + private SourceFilesCopier sourceFilesCopier; public File getOutputDir() { return outputDir; @@ -147,6 +150,18 @@ public class TeaVMTestTool { this.sourceMapsGenerated = sourceMapsGenerated; } + public boolean isSourceFilesCopied() { + return sourceFilesCopied; + } + + public void setSourceFilesCopied(boolean sourceFilesCopied) { + this.sourceFilesCopied = sourceFilesCopied; + } + + public void addSourceFileProvider(SourceFileProvider sourceFileProvider) { + sourceFileProviders.add(sourceFileProvider); + } + public void generate() throws TeaVMToolException { Runnable finalizer = null; try { @@ -233,6 +248,8 @@ public class TeaVMTestTool { } int methodsGenerated = 0; log.info("Generating test files"); + sourceFilesCopier = new SourceFilesCopier(sourceFileProviders); + sourceFilesCopier.setLog(log); FiniteExecutor executor = new SimpleFiniteExecutor(); if (numThreads != 1) { int threads = numThreads != 0 ? numThreads : Runtime.getRuntime().availableProcessors(); @@ -260,6 +277,9 @@ public class TeaVMTestTool { ++methodsGenerated; } executor.complete(); + if (sourceFilesCopied) { + sourceFilesCopier.copy(new File(new File(outputDir, "tests"), "src")); + } log.info("Test files successfully generated for " + methodsGenerated + " method(s)."); } catch (IOException e) { throw new TeaVMToolException("IO error occured generating JavaScript files", e); @@ -374,9 +394,12 @@ public class TeaVMTestTool { String sourceMapsFileName = targetName + ".map"; try (Writer sourceMapsOut = new OutputStreamWriter(new FileOutputStream( new File(outputDir, sourceMapsFileName)), "UTF-8")) { - debugInfo.writeAsSourceMaps(sourceMapsOut, targetName); + debugInfo.writeAsSourceMaps(sourceMapsOut, "src", targetName); } } + if (sourceFilesCopied && vm.getWrittenClasses() != null) { + sourceFilesCopier.addClasses(vm.getWrittenClasses()); + } } private void escapeStringLiteral(String text, Writer writer) throws IOException { diff --git a/teavm-core/src/main/java/org/teavm/tooling/TeaVMTool.java b/teavm-core/src/main/java/org/teavm/tooling/TeaVMTool.java index 3b4e3fd8d..634e82edc 100644 --- a/teavm-core/src/main/java/org/teavm/tooling/TeaVMTool.java +++ b/teavm-core/src/main/java/org/teavm/tooling/TeaVMTool.java @@ -46,6 +46,7 @@ public class TeaVMTool { private boolean bytecodeLogging; private boolean debugInformationGenerated; private boolean sourceMapsFileGenerated; + private boolean sourceFilesCopied; private boolean incremental; private File cacheDirectory = new File("./teavm-cache"); private List transformers = new ArrayList<>(); @@ -61,6 +62,7 @@ public class TeaVMTool { private boolean cancelled; private TeaVMProgressListener progressListener; private TeaVM vm; + private List sourceFileProviders = new ArrayList<>(); public File getTargetDirectory() { return targetDirectory; @@ -150,6 +152,14 @@ public class TeaVMTool { this.sourceMapsFileGenerated = sourceMapsFileGenerated; } + public boolean isSourceFilesCopied() { + return sourceFilesCopied; + } + + public void setSourceFilesCopied(boolean sourceFilesCopied) { + this.sourceFilesCopied = sourceFilesCopied; + } + public Properties getProperties() { return properties; } @@ -194,6 +204,10 @@ public class TeaVMTool { return vm != null ? vm.getClasses() : Collections.emptyList(); } + public void addSourceFileProvider(SourceFileProvider sourceFileProvider) { + sourceFileProviders.add(sourceFileProvider); + } + public void generate() throws TeaVMToolException { try { cancelled = false; @@ -295,10 +309,14 @@ public class TeaVMTool { writer.append("\n//# sourceMappingURL=").append(sourceMapsFileName); try (Writer sourceMapsOut = new OutputStreamWriter(new FileOutputStream( new File(targetDirectory, sourceMapsFileName)), "UTF-8")) { - debugInfo.writeAsSourceMaps(sourceMapsOut, targetFileName); + debugInfo.writeAsSourceMaps(sourceMapsOut, "src", targetFileName); } log.info("Source maps successfully written"); } + if (sourceFilesCopied) { + copySourceFiles(); + log.info("Source files successfully written"); + } if (incremental) { programCache.flush(); astCache.flush(); @@ -335,6 +353,16 @@ public class TeaVMTool { vm.checkForMissingItems(); } + private void copySourceFiles() { + if (vm.getWrittenClasses() == null) { + return; + } + SourceFilesCopier copier = new SourceFilesCopier(sourceFileProviders); + copier.addClasses(vm.getWrittenClasses()); + copier.setLog(log); + copier.copy(new File(targetDirectory, "src")); + } + private AbstractRendererListener runtimeInjector = new AbstractRendererListener() { @Override public void begin(RenderingContext context, BuildTarget buildTarget) throws IOException { diff --git a/teavm-core/src/main/java/org/teavm/vm/TeaVM.java b/teavm-core/src/main/java/org/teavm/vm/TeaVM.java index 5d17956dc..74dbfc46f 100644 --- a/teavm-core/src/main/java/org/teavm/vm/TeaVM.java +++ b/teavm-core/src/main/java/org/teavm/vm/TeaVM.java @@ -85,6 +85,7 @@ public class TeaVM implements TeaVMHost, ServiceRepository { private boolean incremental; private TeaVMProgressListener progressListener; private boolean cancelled; + private ListableClassHolderSource writtenClasses; TeaVM(ClassReaderSource classSource, ClassLoader classLoader) { this.classSource = classSource; @@ -312,6 +313,14 @@ public class TeaVM implements TeaVMHost, ServiceRepository { return dependencyChecker.getAchievableClasses(); } + public DependencyInfo getDependencyInfo() { + return dependencyChecker; + } + + public ListableClassReaderSource getWrittenClasses() { + return writtenClasses; + } + /** *

After building checks whether the build has failed due to some missing items (classes, methods and fields). * If it has failed, throws exception, containing report on all missing items. @@ -378,6 +387,7 @@ public class TeaVM implements TeaVMHost, ServiceRepository { return; } ListableClassHolderSource classSet = link(dependencyChecker); + writtenClasses = classSet; if (wasCancelled()) { return; } diff --git a/teavm-maven/teavm-maven-plugin/pom.xml b/teavm-maven/teavm-maven-plugin/pom.xml index 109a66204..f689cc002 100644 --- a/teavm-maven/teavm-maven-plugin/pom.xml +++ b/teavm-maven/teavm-maven-plugin/pom.xml @@ -43,6 +43,11 @@ maven-core provided + + org.apache.maven + maven-artifact + provided + org.teavm teavm-core diff --git a/teavm-maven/teavm-maven-plugin/src/main/java/org/teavm/maven/BuildJavascriptMojo.java b/teavm-maven/teavm-maven-plugin/src/main/java/org/teavm/maven/BuildJavascriptMojo.java index 5bb42851a..1eed97cac 100644 --- a/teavm-maven/teavm-maven-plugin/src/main/java/org/teavm/maven/BuildJavascriptMojo.java +++ b/teavm-maven/teavm-maven-plugin/src/main/java/org/teavm/maven/BuildJavascriptMojo.java @@ -23,6 +23,7 @@ import java.net.URL; import java.net.URLClassLoader; import java.util.*; import org.apache.maven.artifact.Artifact; +import org.apache.maven.artifact.repository.MavenArtifactRepository; import org.apache.maven.plugin.AbstractMojo; import org.apache.maven.plugin.MojoExecutionException; import org.apache.maven.plugin.logging.Log; @@ -31,6 +32,7 @@ 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.apache.maven.repository.RepositorySystem; import org.teavm.model.ClassHolderTransformer; import org.teavm.tooling.*; @@ -47,6 +49,18 @@ public class BuildJavascriptMojo extends AbstractMojo { @Component private MavenProject project; + @Component + private RepositorySystem repositorySystem; + + @Parameter(required = true, readonly = true, defaultValue = "${localRepository}") + private MavenArtifactRepository localRepository; + + @Parameter(required = true, readonly = true, defaultValue = "${project.remoteArtifactRepositories}") + private List remoteRepositories; + + @Parameter(readonly = true, defaultValue = "${plugin.artifacts}") + private List pluginArtifacts; + @Parameter(defaultValue = "${project.build.directory}/javascript") private File targetDirectory; @@ -80,6 +94,9 @@ public class BuildJavascriptMojo extends AbstractMojo { @Parameter private boolean sourceMapsGenerated; + @Parameter + private boolean sourceFilesCopied; + @Parameter private boolean incremental; @@ -165,6 +182,14 @@ public class BuildJavascriptMojo extends AbstractMojo { this.sourceMapsGenerated = sourceMapsGenerated; } + public boolean isSourceFilesCopied() { + return sourceFilesCopied; + } + + public void setSourceFilesCopied(boolean sourceFilesCopied) { + this.sourceFilesCopied = sourceFilesCopied; + } + public boolean isIncremental() { return incremental; } @@ -196,6 +221,17 @@ public class BuildJavascriptMojo extends AbstractMojo { tool.setTargetDirectory(targetDirectory); tool.setTargetFileName(targetFileName); tool.getTransformers().addAll(instantiateTransformers(classLoader)); + if (sourceFilesCopied) { + MavenSourceFileProviderLookup lookup = new MavenSourceFileProviderLookup(); + lookup.setMavenProject(project); + lookup.setRepositorySystem(repositorySystem); + lookup.setLocalRepository(localRepository); + lookup.setRemoteRepositories(remoteRepositories); + lookup.setPluginDependencies(pluginArtifacts); + for (SourceFileProvider provider : lookup.resolve()) { + tool.addSourceFileProvider(provider); + } + } if (classAliases != null) { tool.getClassAliases().addAll(Arrays.asList(classAliases)); } @@ -209,6 +245,7 @@ public class BuildJavascriptMojo extends AbstractMojo { tool.setIncremental(incremental); tool.setDebugInformationGenerated(debugInformationGenerated); tool.setSourceMapsFileGenerated(sourceMapsGenerated); + tool.setSourceFilesCopied(sourceFilesCopied); tool.generate(); tool.checkForMissingItems(); } catch (RuntimeException e) { diff --git a/teavm-maven/teavm-maven-plugin/src/main/java/org/teavm/maven/BuildJavascriptTestMojo.java b/teavm-maven/teavm-maven-plugin/src/main/java/org/teavm/maven/BuildJavascriptTestMojo.java index 342a1e4f0..2c6f338dd 100644 --- a/teavm-maven/teavm-maven-plugin/src/main/java/org/teavm/maven/BuildJavascriptTestMojo.java +++ b/teavm-maven/teavm-maven-plugin/src/main/java/org/teavm/maven/BuildJavascriptTestMojo.java @@ -27,6 +27,7 @@ import java.util.jar.JarEntry; import java.util.jar.JarFile; import org.apache.commons.io.FilenameUtils; import org.apache.maven.artifact.Artifact; +import org.apache.maven.artifact.repository.MavenArtifactRepository; import org.apache.maven.plugin.AbstractMojo; import org.apache.maven.plugin.MojoExecutionException; import org.apache.maven.plugin.MojoFailureException; @@ -36,9 +37,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.apache.maven.repository.RepositorySystem; import org.teavm.model.ClassHolderTransformer; import org.teavm.testing.JUnitTestAdapter; import org.teavm.testing.TestAdapter; +import org.teavm.tooling.SourceFileProvider; import org.teavm.tooling.TeaVMTestTool; import org.teavm.tooling.TeaVMToolException; @@ -56,6 +59,18 @@ public class BuildJavascriptTestMojo extends AbstractMojo { @Component private MavenProject project; + @Component + private RepositorySystem repositorySystem; + + @Parameter(required = true, readonly = true, defaultValue = "${localRepository}") + private MavenArtifactRepository localRepository; + + @Parameter(required = true, readonly = true, defaultValue = "${project.remoteArtifactRepositories}") + private List remoteRepositories; + + @Parameter(readonly = true, defaultValue = "${plugin.artifacts}") + private List pluginArtifacts; + @Parameter(defaultValue = "${project.build.directory}/javascript-test") private File outputDir; @@ -98,6 +113,9 @@ public class BuildJavascriptTestMojo extends AbstractMojo { @Parameter private boolean sourceMapsGenerated; + @Parameter + private boolean sourceFilesCopied; + private TeaVMTestTool tool = new TeaVMTestTool(); public void setProject(MavenProject project) { @@ -164,6 +182,14 @@ public class BuildJavascriptTestMojo extends AbstractMojo { this.sourceMapsGenerated = sourceMapsGenerated; } + public boolean isSourceFilesCopied() { + return sourceFilesCopied; + } + + public void setSourceFilesCopied(boolean sourceFilesCopied) { + this.sourceFilesCopied = sourceFilesCopied; + } + @Override public void execute() throws MojoExecutionException, MojoFailureException { if (System.getProperty("maven.test.skip", "false").equals("true") || @@ -188,6 +214,18 @@ public class BuildJavascriptTestMojo extends AbstractMojo { tool.setIncremental(incremental); tool.setDebugInformationGenerated(debugInformationGenerated); tool.setSourceMapsGenerated(sourceMapsGenerated); + tool.setSourceFilesCopied(sourceFilesCopied); + if (sourceFilesCopied) { + MavenSourceFileProviderLookup lookup = new MavenSourceFileProviderLookup(); + lookup.setMavenProject(project); + lookup.setRepositorySystem(repositorySystem); + lookup.setLocalRepository(localRepository); + lookup.setRemoteRepositories(remoteRepositories); + lookup.setPluginDependencies(pluginArtifacts); + for (SourceFileProvider provider : lookup.resolve()) { + tool.addSourceFileProvider(provider); + } + } if (properties != null) { tool.getProperties().putAll(properties); } diff --git a/teavm-maven/teavm-maven-plugin/src/main/java/org/teavm/maven/MavenSourceFileProviderLookup.java b/teavm-maven/teavm-maven-plugin/src/main/java/org/teavm/maven/MavenSourceFileProviderLookup.java new file mode 100644 index 000000000..42887a97b --- /dev/null +++ b/teavm-maven/teavm-maven-plugin/src/main/java/org/teavm/maven/MavenSourceFileProviderLookup.java @@ -0,0 +1,97 @@ +/* + * Copyright 2013 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.maven; + +import java.io.File; +import java.util.ArrayList; +import java.util.HashSet; +import java.util.List; +import java.util.Set; +import org.apache.maven.artifact.Artifact; +import org.apache.maven.artifact.repository.ArtifactRepository; +import org.apache.maven.artifact.resolver.ArtifactResolutionRequest; +import org.apache.maven.artifact.resolver.ArtifactResolutionResult; +import org.apache.maven.project.MavenProject; +import org.apache.maven.repository.RepositorySystem; +import org.teavm.tooling.DirectorySourceFileProvider; +import org.teavm.tooling.JarSourceFileProvider; +import org.teavm.tooling.SourceFileProvider; + +/** + * + * @author Alexey Andreev + */ +public class MavenSourceFileProviderLookup { + private MavenProject mavenProject; + private RepositorySystem repositorySystem; + private ArtifactRepository localRepository; + private List remoteRepositories; + private List pluginDependencies; + + public void setMavenProject(MavenProject mavenProject) { + this.mavenProject = mavenProject; + } + + public void setRepositorySystem(RepositorySystem repositorySystem) { + this.repositorySystem = repositorySystem; + } + + public void setLocalRepository(ArtifactRepository localRepository) { + this.localRepository = localRepository; + } + + public void setRemoteRepositories(List remoteRepositories) { + this.remoteRepositories = remoteRepositories; + } + + public void setPluginDependencies(List pluginDependencies) { + this.pluginDependencies = pluginDependencies; + } + + public List resolve() { + List initialArtifacts = new ArrayList<>(); + initialArtifacts.addAll(mavenProject.getArtifacts()); + if (pluginDependencies != null) { + initialArtifacts.addAll(pluginDependencies); + } + Set artifacts = new HashSet<>(); + for (Artifact artifact : initialArtifacts) { + if (artifact.getClassifier() != null && artifact.getClassifier().equals("sources")) { + artifacts.add(artifact); + } else { + artifacts.add(repositorySystem.createArtifactWithClassifier(artifact.getGroupId(), + artifact.getArtifactId(), artifact.getVersion(), artifact.getType(), "sources")); + } + } + List providers = new ArrayList<>(); + for (Artifact artifact : artifacts) { + ArtifactResolutionRequest request = new ArtifactResolutionRequest() + .setLocalRepository(localRepository) + .setRemoteRepositories(new ArrayList<>(remoteRepositories)) + .setArtifact(artifact); + ArtifactResolutionResult result = repositorySystem.resolve(request); + for (Artifact resolvedArtifact : result.getArtifacts()) { + if (resolvedArtifact.getFile() != null) { + providers.add(new JarSourceFileProvider(resolvedArtifact.getFile())); + } + } + } + for (String sourceRoot : mavenProject.getCompileSourceRoots()) { + providers.add(new DirectorySourceFileProvider(new File(sourceRoot))); + } + return providers; + } +} diff --git a/teavm-samples/pom.xml b/teavm-samples/pom.xml index 83f3598ae..e75fe9742 100644 --- a/teavm-samples/pom.xml +++ b/teavm-samples/pom.xml @@ -69,6 +69,7 @@ true true true + true ${project.build.directory}/javascript/hello