Skip to content

Commit

Permalink
Merge branch 'master' of https://github.com/jannehietamaki/vert.x
Browse files Browse the repository at this point in the history
  • Loading branch information
purplefox committed May 17, 2012
2 parents 24c6228 + 379369f commit 7fd3b8f
Show file tree
Hide file tree
Showing 3 changed files with 166 additions and 6 deletions.
Original file line number Diff line number Diff line change
@@ -0,0 +1,83 @@
/*
* Copyright 2011-2012 the original author or authors.
*
* 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.vertx.java.deploy.impl.java;

import java.io.File;
import java.util.Collections;

import javax.tools.Diagnostic;
import javax.tools.DiagnosticCollector;
import javax.tools.JavaCompiler;
import javax.tools.JavaFileObject;
import javax.tools.JavaFileObject.Kind;
import javax.tools.StandardJavaFileManager;
import javax.tools.StandardLocation;
import javax.tools.ToolProvider;

/**
*
* Classloader for dynamic .java source file compilation and loading.
*
* @author Janne Hietamäki
*/
public class CompilingClassLoader extends ClassLoader {
private final File sourceFile;
private final MemoryFileManager fileManager;

public CompilingClassLoader(ClassLoader loader, String sourceName) {
super(loader);
this.sourceFile = new File(sourceName).getAbsoluteFile();
if(!this.sourceFile.canRead()) {
throw new RuntimeException("File not found: " + sourceName);
}
try {
DiagnosticCollector<JavaFileObject> diagnostics = new DiagnosticCollector<JavaFileObject>();
JavaCompiler javaCompiler = ToolProvider.getSystemJavaCompiler();
StandardJavaFileManager standardFileManager = javaCompiler.getStandardFileManager(null, null, null);

standardFileManager.setLocation(StandardLocation.SOURCE_PATH, Collections.singleton(sourceFile.getParentFile()));

fileManager = new MemoryFileManager(standardFileManager);
JavaFileObject javaFile = standardFileManager.getJavaFileForInput(StandardLocation.SOURCE_PATH, resolveMainClassName(), Kind.SOURCE);
JavaCompiler.CompilationTask task = javaCompiler.getTask(null, fileManager, diagnostics, null, null, Collections.singleton(javaFile));
boolean valid = task.call();

for (Diagnostic<?> d : diagnostics.getDiagnostics()) {
System.out.println(d);
}
if (!valid) {
throw new RuntimeException("Compilation failed!");
}
} catch (Exception e) {
throw new RuntimeException(e);
}
}

public String resolveMainClassName() {
String fileName = sourceFile.getName();
return fileName.substring(0, fileName.length() - Kind.SOURCE.extension.length());
}

@Override
protected Class<?> findClass(String name) throws ClassNotFoundException {
byte[] bytecode = fileManager.getCompiledClass(name);
if (bytecode == null) {
throw new ClassNotFoundException(name);
}
return defineClass(name, bytecode, 0, bytecode.length);
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -43,8 +43,7 @@ public String getLanguage() {

@Override
public boolean isFactoryFor(String main) {
if (main.endsWith(".java")) {
// TODO requires dynamic compiler
if (isJavaSource(main)) {
return true;
}
if (main.endsWith(".class")) {
Expand All @@ -55,10 +54,20 @@ public boolean isFactoryFor(String main) {
}
return false;
}

private boolean isJavaSource(String main) {
return main.endsWith(".java");
}

public Verticle createVerticle(String main, ClassLoader cl) throws Exception {

Class<?> clazz = cl.loadClass(main);
public Verticle createVerticle(String main, ClassLoader loader) throws Exception {
ClassLoader cl = loader;
String className = main;
if(isJavaSource(main)) {
CompilingClassLoader compilingLoader = new CompilingClassLoader(loader, main);
className = compilingLoader.resolveMainClassName();
cl = compilingLoader;
}
Class<?> clazz = cl.loadClass(className);

Verticle verticle = (Verticle) clazz.newInstance();

Expand All @@ -74,7 +83,7 @@ public Verticle createVerticle(String main, ClassLoader cl) throws Exception {
return verticle;

}

public void reportException(Throwable t) {
mgr.getLogger().error("Exception in Java verticle script", t);
}
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,68 @@
/*
* Copyright 2011-2012 the original author or authors.
*
* 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.vertx.java.deploy.impl.java;

import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.io.OutputStream;
import java.net.URI;
import java.net.URISyntaxException;
import java.util.HashMap;
import java.util.Map;

import javax.tools.FileObject;
import javax.tools.ForwardingJavaFileManager;
import javax.tools.JavaFileManager;
import javax.tools.JavaFileObject;
import javax.tools.SimpleJavaFileObject;

/**
* Java in-memory file manager used by {@link CompilingClassLoader} to handle
* compiled classes
*
* @author Janne Hietam&auml;ki
*/
public class MemoryFileManager extends ForwardingJavaFileManager<JavaFileManager> {
private final Map<String, ByteArrayOutputStream> compiledClasses = new HashMap<String, ByteArrayOutputStream>();

public MemoryFileManager(JavaFileManager fileManager) {
super(fileManager);
}

@Override
public JavaFileObject getJavaFileForOutput(Location location, final String className, JavaFileObject.Kind kind, FileObject sibling) throws IOException {
try {
return new SimpleJavaFileObject(new URI(""), kind) {
public OutputStream openOutputStream() throws IOException {
ByteArrayOutputStream outputStream = new ByteArrayOutputStream();
compiledClasses.put(className, outputStream);
return outputStream;
}
};
} catch (URISyntaxException e) {
throw new RuntimeException(e);
}
}

public byte[] getCompiledClass(String name) {
ByteArrayOutputStream bytes = compiledClasses.get(name);
if (bytes == null) {
return null;
}
return bytes.toByteArray();
}
}

0 comments on commit 7fd3b8f

Please sign in to comment.