Skip to content

Commit

Permalink
Merge branch 'dev'
Browse files Browse the repository at this point in the history
  • Loading branch information
ngocdaothanh committed Apr 11, 2014
2 parents bfea1f9 + 53602b3 commit 42163d8
Show file tree
Hide file tree
Showing 4 changed files with 66 additions and 35 deletions.
16 changes: 8 additions & 8 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -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.

Expand Down
57 changes: 42 additions & 15 deletions dev/README.rst
Original file line number Diff line number Diff line change
@@ -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
-------------

Expand All @@ -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-<version>/
scalive
scalive.cmd
scalive-<version>.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-<version>.zip scalive-<version>
18 changes: 11 additions & 7 deletions src/main/java/scalive/Classpath.java
Original file line number Diff line number Diff line change
Expand Up @@ -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();
Expand Down Expand Up @@ -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. */
Expand All @@ -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);
}
Expand All @@ -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) {
Expand Down
10 changes: 5 additions & 5 deletions src/main/java/scalive/Server.java
Original file line number Diff line number Diff line change
Expand Up @@ -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);
Expand All @@ -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");
}
}

0 comments on commit 42163d8

Please sign in to comment.