blob: 6039e87afb2f0b6907b18c401784bf7fc50c5505 [file] [log] [blame]
/*
* Licensed to the Apache Software Foundation (ASF) under one or more contributor license
* agreements. See the NOTICE file distributed with this work for additional information regarding
* copyright ownership. The ASF licenses this file to You 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.apache.geode.test.compiler;
import static java.util.stream.Collectors.toList;
import java.io.File;
import java.io.IOException;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
import java.util.stream.Stream;
import javax.tools.ToolProvider;
import com.google.common.base.Charsets;
import com.google.common.io.Files;
import org.apache.commons.io.FileUtils;
public class JavaCompiler {
private File tempDir;
private String classpath;
public JavaCompiler() {
this.tempDir = Files.createTempDir();
tempDir.deleteOnExit();
this.classpath = System.getProperty("java.class.path");
}
public void addToClasspath(File jarFile) {
classpath += File.pathSeparator + jarFile.getAbsolutePath();
}
public List<CompiledSourceCode> compile(File... sourceFiles) throws IOException {
String[] sourceFileContents =
Arrays.stream(sourceFiles).map(this::readFileToString).toArray(String[]::new);
return compile(sourceFileContents);
}
public List<CompiledSourceCode> compile(String... sourceFileContents) throws IOException {
UncompiledSourceCode[] uncompiledSourceCodes = Arrays.stream(sourceFileContents)
.map(UncompiledSourceCode::fromSourceCode).toArray(UncompiledSourceCode[]::new);
return compile(uncompiledSourceCodes);
}
public List<CompiledSourceCode> compile(UncompiledSourceCode... uncompiledSources)
throws IOException {
File temporarySourcesDirectory = createSubdirectory(tempDir, "sources");
File temporaryClassesDirectory = createSubdirectory(tempDir, "classes");
List<String> options =
Stream.of("-d", temporaryClassesDirectory.getAbsolutePath(), "-classpath", classpath)
.collect(toList());
try {
for (UncompiledSourceCode sourceCode : uncompiledSources) {
File sourceFile = new File(temporarySourcesDirectory, sourceCode.simpleClassName + ".java");
FileUtils.writeStringToFile(sourceFile, sourceCode.sourceCode, Charsets.UTF_8);
options.add(sourceFile.getAbsolutePath());
}
int exitCode = ToolProvider.getSystemJavaCompiler().run(System.in, System.out, System.err,
options.toArray(new String[] {}));
if (exitCode != 0) {
throw new RuntimeException(
"Unable to compile the given source code. See System.err for details.");
}
List<CompiledSourceCode> compiledSourceCodes = new ArrayList<>();
addCompiledClasses(compiledSourceCodes, "", temporaryClassesDirectory);
return compiledSourceCodes;
} finally {
FileUtils.deleteDirectory(temporaryClassesDirectory);
}
}
private static void addCompiledClasses(List<CompiledSourceCode> ret, String pkgName, File dir)
throws IOException {
for (File file : dir.listFiles()) {
String filename = file.getName();
if (file.isDirectory()) {
String qname = pkgName + filename + ".";
addCompiledClasses(ret, qname, file);
} else if (filename.endsWith(".class")) {
String qname = pkgName + filename.substring(0, filename.length() - 6);
ret.add(new CompiledSourceCode(qname, FileUtils.readFileToByteArray(file)));
} else {
System.err.println("Unexpected file : " + file.getAbsolutePath());
}
}
}
private File createSubdirectory(File parent, String directoryName) {
File subdirectory = parent.toPath().resolve(directoryName).toFile();
if (!subdirectory.exists()) {
subdirectory.mkdirs();
}
if (!subdirectory.exists() || !subdirectory.isDirectory()) {
throw new IllegalArgumentException("Invalid directory" + subdirectory.getAbsolutePath());
}
return subdirectory;
}
private String readFileToString(File file) {
try {
return FileUtils.readFileToString(file, Charsets.UTF_8);
} catch (IOException e) {
throw new RuntimeException(e);
}
}
}