package water.deploy;
import java.io.*;
import java.util.*;
import java.util.Map.Entry;
import java.util.jar.*;
import javassist.*;
import water.*;
import water.api.DocGen;
import water.util.Utils;
public class LaunchJar extends Request2 {
static final int API_WEAVER = 1;
static public DocGen.FieldDoc[] DOC_FIELDS;
@API(help = "Jars keys", required = true, filter = Default.class)
public String jars;
@API(help = "Class to instantiate and launch", required = true, filter = Default.class)
public String job_class;
@Override protected Response serve() {
final Job job;
try {
// Move jars from KV store to tmp files
ClassPool pool = new ClassPool(true);
ArrayList<JarEntry> entries = new ArrayList<JarEntry>();
String[] splits = jars.split(",");
for( int i = 0; i < splits.length; i++ ) {
Key key = Key.make(splits[i]);
throw H2O.unimpl();
//ValueArray va = UKV.get(key);
//File file = File.createTempFile("h2o", ".jar");
//Utils.writeFileAndClose(file, va.openStream());
//DKV.remove(key);
//pool.appendClassPath(file.getPath());
//
//JarFile jar = new JarFile(file);
//Enumeration e = jar.entries();
//while( e.hasMoreElements() ) {
// JarEntry entry = (JarEntry) e.nextElement();
// entries.add(entry);
//}
//jar.close();
}
// Append UID to class names so allow multiple invocations
String uid = Key.rand();
ClassMap renames = new ClassMap();
for( JarEntry entry : entries ) {
if( entry.getName().endsWith(".class") ) {
String n = Utils.className(entry.getName());
String u;
int index = n.indexOf("$");
if( index < 0 )
index = n.length();
u = n.substring(0, index) + uid + n.substring(index);
renames.put(n, u);
}
}
ArrayList<CtClass> updated = new ArrayList();
for( Entry<String, String> entry : ((Map<String, String>) renames).entrySet() ) {
CtClass c = pool.get(entry.getKey().replace('/', '.'));
c.replaceClassName(renames);
updated.add(c);
}
// Create jar file and register it on each node
HashSet<String> packages = new HashSet();
ByteArrayOutputStream mem = new ByteArrayOutputStream();
JarOutputStream jar = new JarOutputStream(mem);
DataOutputStream bc = new DataOutputStream(jar);
for( CtClass c : updated ) {
jar.putNextEntry(new JarEntry(c.getName().replace('.', '/') + ".class"));
c.toBytecode(bc);
bc.flush();
String p = c.getPackageName();
if( p == null )
throw new IllegalArgumentException("Package is null for class " + c);
packages.add(p);
}
jar.close();
weavePackages(packages.toArray(new String[0]));
AddJar task = new AddJar();
task._data = mem.toByteArray();
task.invokeOnAllNodes();
// Start job
Class c = Class.forName(job_class + uid);
job = (Job) c.newInstance();
job.fork();
} catch( Exception ex ) {
throw new RuntimeException(ex);
}
return Response.done(this);
}
public static void weavePackages(String... names) {
WeavePackages task = new WeavePackages();
task._names = names;
task.invokeOnAllNodes();
}
static class WeavePackages extends DRemoteTask {
String[] _names;
@Override public void lcompute() {
for( String name : _names )
Boot.weavePackage(name);
tryComplete();
}
@Override public void reduce(DRemoteTask drt) {
}
}
static class AddJar extends DRemoteTask {
byte[] _data;
@Override public void lcompute() {
try {
File file = File.createTempFile("h2o", ".jar");
Utils.writeFileAndClose(file, new ByteArrayInputStream(_data));
Boot._init.addExternalJars(file);
tryComplete();
} catch( Exception ex ) {
throw new RuntimeException(ex);
}
}
@Override public void reduce(DRemoteTask drt) {
}
}
}