/*
* MicroJIAC - A Lightweight Agent Framework
* This file is part of MicroJIAC Java6-Platform.
*
* Copyright (c) 2007-2012 DAI-Labor, Technische Universität Berlin
*
* This library includes software developed at DAI-Labor, Technische
* Universität Berlin (http://www.dai-labor.de)
*
* This library is free software: you can redistribute it and/or modify it
* under the terms of the GNU Lesser General Public License as published
* by the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This library is distributed in the hope that it will be useful, but
* WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with this library. If not, see <http://www.gnu.org/licenses/>.
*/
/*
* $Id$
*/
package de.jiac.micro.performance;
import java.net.URL;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;
import javax.tools.Diagnostic;
import javax.tools.DiagnosticListener;
import javax.tools.JavaCompiler;
import javax.tools.JavaFileObject;
import javax.tools.StandardJavaFileManager;
import javax.tools.ToolProvider;
import javax.tools.Diagnostic.Kind;
import javax.tools.JavaCompiler.CompilationTask;
import org.slf4j.LoggerFactory;
import de.jiac.micro.cl.ClassPath;
import de.jiac.micro.cl.ContainerClassLoader;
import de.jiac.micro.config.generator.AbstractConfiguration;
import de.jiac.micro.config.generator.ConfigurationGenerator;
import de.jiac.micro.config.generator.NodeConfiguration;
import de.jiac.micro.core.IScope;
import de.jiac.micro.internal.ByteArrayJavaFileCache;
import de.jiac.micro.internal.compile.ByteArrayJavaFileObject;
import de.jiac.micro.internal.compile.ByteFileManager;
import de.jiac.micro.internal.compile.CharSequenceJavaFileObject;
/**
* @author Marcel Patzlaff
* @version $Revision:$
*/
public class TestLauncherWithCompilation {
private static class ConfigurationDiagnosticListener implements DiagnosticListener<JavaFileObject> {
protected int errors= 0;
protected ConfigurationDiagnosticListener() {}
public void report(Diagnostic<? extends JavaFileObject> diagnostic) {
if(diagnostic.getKind() == Kind.ERROR) {
errors++;
System.err.println(diagnostic.getMessage(null));
}
}
}
static void execute(String[] args) {
if(args.length != 1) {
System.out.println("usage: " + TestLauncherWithCompilation.class.getName() + " namespace");
System.exit(0);
return;
}
String namespace= args[0];
AbstractConfiguration[] configs;
try {
configs= ConfigurationGenerator.execute(namespace, TestLauncherWithCompilation.class.getClassLoader(), LoggerFactory.getLogger(TestLauncherWithCompilation.class));
} catch (Exception e) {
e.printStackTrace();
System.err.println("namespace does not contain a valid application definition: " + e.getMessage());
System.exit(1);
return;
}
Map<String, ByteArrayJavaFileObject> classes;
final List<NodeConfiguration> nodes= new ArrayList<NodeConfiguration>();
try {
JavaCompiler compiler= ToolProvider.getSystemJavaCompiler();
ArrayList<JavaFileObject> sources= new ArrayList<JavaFileObject>();
for(AbstractConfiguration config : configs) {
sources.add(new CharSequenceJavaFileObject(config.className, config.source));
if(config instanceof NodeConfiguration) {
nodes.add((NodeConfiguration) config);
}
}
StandardJavaFileManager stdFileManager= compiler.getStandardFileManager(null, null, null);
ByteFileManager<StandardJavaFileManager> byteFileManager= new ByteFileManager<StandardJavaFileManager>(stdFileManager);
ConfigurationDiagnosticListener listener= new ConfigurationDiagnosticListener();
CompilationTask task= compiler.getTask(null, byteFileManager, listener, null, null, sources);
task.call();
byteFileManager.close();
classes= byteFileManager.getStore();
if(listener.errors > 0) {
System.err.println("could not compile node configurations");
System.exit(1);
return;
}
} catch (Exception e) {
e.printStackTrace(System.err);
System.err.println("could not compile node configurations");
System.exit(1);
return;
}
if(nodes.size() != 1) {
System.err.println("exactly one node has to be configured");
System.exit(1);
} else {
// start the node in the current vm
launchInCurrentVM(nodes.get(0).className, classes);
}
}
private static void launchInCurrentVM(final String nodeConfigClassName, final Map<String, ByteArrayJavaFileObject> classes) {
ByteArrayJavaFileCache cache= new ByteArrayJavaFileCache(classes.values());
ClassPath cp= new ClassPath();
for(URL url : cache.getURLs()) {
cp.addURL(url);
}
// FIXME: this class loader sucks... create it more specific!!!
final ContainerClassLoader nodeLoader= new ContainerClassLoader(cp, TestLauncherWithCompilation.class.getClassLoader());
try {
instantiateAndLaunch(nodeLoader, nodeConfigClassName);
} catch (Exception e) {
e.printStackTrace(System.err);
System.err.println("could not launch node in current vm");
System.exit(1);
return;
}
}
protected static void instantiateAndLaunch(final ContainerClassLoader loader, final String className) throws Exception {
Class nodeScopeClass= loader.loadClass(IScope.NODE_SCOPE_CLASS);
final IScope nodeScope= (IScope) nodeScopeClass.newInstance();
System.out.println("initialising node scope");
final Object startLock= new Object();
final IScope.IScopeStateChangeListener l= new IScope.IScopeStateChangeListener() {
public void onPause(IScope scope) {
}
public void onSetup(IScope scope) {
}
public void onStart(IScope scope) {
synchronized (startLock) {
startLock.notify();
}
}
public void onTerminate(IScope scope) {
}
};
nodeScope.setup(loader, className, l);
synchronized (startLock) {
nodeScope.signal(IScope.SIG_START);
startLock.wait();
}
Runtime.getRuntime().addShutdownHook(
new Thread() {
public void run() {
nodeScope.signal(IScope.SIG_TERMINATE);
}
}
);
}
}