diff --git a/README.md b/README.md index d45f2c1..856fb17 100644 --- a/README.md +++ b/README.md @@ -6,28 +6,28 @@ JVM processes without any prior setup at the target process. ## Download Download and extract -[scalive-1.0.zip](https://github.com/ngocdaothanh/scalive/releases/download/v1.0/scalive-1.0.zip), +[scalive-1.1.zip](https://github.com/ngocdaothanh/scalive/releases/download/v1.1/scalive-1.1.zip), you will see: ``` -scalive-1.0/ +scalive-1.1/ scalive scalive.cmd - scalive-1.0.jar - - scala-library-2.10.2.jar - scala-compiler-2.10.2.jar - scala-reflect-2.10.2.jar + scalive-1.1.jar scala-library-2.10.3.jar scala-compiler-2.10.3.jar scala-reflect-2.10.3.jar + + scala-library-2.10.4.jar + scala-compiler-2.10.4.jar + scala-reflect-2.10.4.jar ``` scala-library, scala-compiler, and scala-reflect of the appropriate version will be loaded to your running JVM process, if they have not been loaded. -For convenience, Scala 2.10.2 and 2.10.3 JARs are preincluded. If your process +For convenience, Scala 2.10.3 and 2.10.4 JARs are preincluded. If your process is using a different Scala version, you need to manually download the corresponding JARs and save them as above. diff --git a/dev/README.rst b/dev/README.rst index be5161b..d153c4d 100644 --- a/dev/README.rst +++ b/dev/README.rst @@ -1,3 +1,20 @@ +Control flow +------------ + +:: + + AgentLoader ----- attaches Agent ---------------> Target process + passes: * Agent loads Server + * TCP port * Server listens on the + * jarpaths specified TCP port + +:: + + AgentLoader ----- Client connects to the port --> Target process + * Server loads Repl + ----- Keyboard input --> + <---- Repl output --- + zip directory ------------- @@ -8,35 +25,45 @@ This is the directory that will be zipped when Scalive is released. zip/ scalive scalive.cmd - scalive_2.10-1.0-SNAPSHOT.jar -> ../../target/scala-2.10/scalive_2.10-1.0-SNAPSHOT.jar - - scala-library-2.10.2.jar - scala-compiler-2.10.2.jar - scala-reflect-2.10.2.jar + scalive_2.10-1.1-SNAPSHOT.jar -> ../../target/scala-2.10/scalive_2.10-1.1-SNAPSHOT.jar scala-library-2.10.3.jar scala-compiler-2.10.3.jar scala-reflect-2.10.3.jar + scala-library-2.10.4.jar + scala-compiler-2.10.4.jar + scala-reflect-2.10.4.jar + While developing: * Run ``sbt package`` to create/update scalive.jar * Add missing JARs as above * Run ``scalive`` to test -Control flow ------------- +Release +------- + +Based on the ``zip`` directory above, prepare a directory to be zipped and +released (remember to remove uneccessary files, like .gitignore): :: - AgentLoader ----- attaches Agent ---------------> Target process - passes: * Agent loads Server - * TCP port * Server listens on the - * jarpaths specified TCP port + scalive-/ + scalive + scalive.cmd + scalive-.jar <-- Doesn't depend on Scala, thus doesn't follow Scala JAR naming + + scala-library-2.10.3.jar + scala-compiler-2.10.3.jar + scala-reflect-2.10.3.jar + + scala-library-2.10.4.jar + scala-compiler-2.10.4.jar + scala-reflect-2.10.4.jar + +Then zip it: :: - AgentLoader ----- Client connects to the port --> Target process - * Server loads Repl - ----- Keyboard input --> - <---- Repl output --- + zip -r scalive-.zip scalive- diff --git a/src/main/java/scalive/Classpath.java b/src/main/java/scalive/Classpath.java index 95b2349..0eab2e0 100644 --- a/src/main/java/scalive/Classpath.java +++ b/src/main/java/scalive/Classpath.java @@ -4,6 +4,7 @@ import java.lang.reflect.Method; import java.net.URL; import java.net.URLClassLoader; +import java.util.Arrays; public class Classpath { private static Method addURL = getAddURL(); @@ -44,8 +45,9 @@ public static String findJar(String[] jarpaths, String jarbase) throws Exception } public static void addPath(URLClassLoader cl, String path) throws Exception { - URL url = new File(path).toURI().toURL(); - addURL.invoke(cl, url); + URL url = new File(path).toURI().toURL(); + URL[] urls = cl.getURLs(); + if (!Arrays.asList(urls).contains(url)) addURL.invoke(cl, url); } /** Combination of findJar and addPath. */ @@ -55,22 +57,22 @@ public static void findAndAddJar(URLClassLoader cl, String[] jarpaths, String ja } /** - * Similar to findAndAddJar, but only add the JAR to classpath if the - * representativeClass has not been loaded. + * Similar to findAndAddJar without representativeClass, but only find and + * add the JAR to classpath if the representativeClass has not been loaded. */ - public static void addJarToURLClassLoader( + public static void findAndAddJar( URLClassLoader cl, String[] jarpaths, String jarbase, String representativeClass ) throws Exception { try { Class.forName(representativeClass, true, cl); } catch (ClassNotFoundException e) { System.out.println("[Scalive] Load " + jarbase); - Classpath.findAndAddJar(cl, jarpaths, jarbase); + findAndAddJar(cl, jarpaths, jarbase); } } // http://stackoverflow.com/questions/4121567/embedded-scala-repl-inherits-parent-classpath - public static String getURLClasspath(URLClassLoader cl) { + public static String getClasspath(URLClassLoader cl) { URL[] urls = cl.getURLs(); return join(urls, File.pathSeparator); } @@ -81,6 +83,8 @@ public static String getScalaVersion(ClassLoader cl) throws Exception { return (String) m.invoke(k); } + //-------------------------------------------------------------------------- + private static String join(Object[] xs, String separator) { StringBuffer buf = new StringBuffer(); for (Object x: xs) { diff --git a/src/main/java/scalive/Server.java b/src/main/java/scalive/Server.java index 49e99eb..58e2286 100644 --- a/src/main/java/scalive/Server.java +++ b/src/main/java/scalive/Server.java @@ -27,7 +27,7 @@ public static void serve(Socket client, String[] jarpaths) throws Exception { URLClassLoader cl = (URLClassLoader) ClassLoader.getSystemClassLoader(); addJarsToURLClassLoader(cl, jarpaths); - String classpath = Classpath.getURLClasspath(cl); + String classpath = Classpath.getClasspath(cl); Class repl = Class.forName("scalive.Repl"); Method method = repl.getMethod("run", ClassLoader.class, String.class, InputStream.class, OutputStream.class); method.invoke(null, cl, classpath, in, out); @@ -42,14 +42,14 @@ public static void serve(Socket client, String[] jarpaths) throws Exception { private static void addJarsToURLClassLoader(URLClassLoader cl, String[] jarpaths) throws Exception { // Try scala-library first - Classpath.addJarToURLClassLoader(cl, jarpaths, "scala-library-" + DEFAULT_SCALA_VERSION, "scala.AnyVal"); + Classpath.findAndAddJar(cl, jarpaths, "scala-library-" + DEFAULT_SCALA_VERSION, "scala.AnyVal"); // So that we can get the actual Scala version being used String version = Classpath.getScalaVersion(cl); - Classpath.addJarToURLClassLoader(cl, jarpaths, "scala-reflect-" + version, "scala.reflect.runtime.JavaUniverse"); - Classpath.addJarToURLClassLoader(cl, jarpaths, "scala-compiler-" + version, "scala.tools.nsc.interpreter.ILoop"); + Classpath.findAndAddJar(cl, jarpaths, "scala-reflect-" + version, "scala.reflect.runtime.JavaUniverse"); + Classpath.findAndAddJar(cl, jarpaths, "scala-compiler-" + version, "scala.tools.nsc.interpreter.ILoop"); - Classpath.addJarToURLClassLoader(cl, jarpaths, "scalive", "scalive.Repl"); + Classpath.findAndAddJar(cl, jarpaths, "scalive", "scalive.Repl"); } }