This is an automated email from the git hooks/post-receive script. tmancill pushed a commit to branch master in repository shimdandy.
commit 148989372c829047ec4269fc0250b3e37fa34aa0 Author: Tom Marble <[email protected]> Date: Fri Aug 11 09:10:13 2017 -0500 upstream at 1.2.0 --- .gitignore | 4 + README.md | 82 +++ api/pom.xml | 14 + .../projectodd/shimdandy/ClojureRuntimeShim.java | 195 +++++++ impl/pom.xml | 34 ++ .../shimdandy/impl/ClojureRuntimeShimImpl.java | 609 +++++++++++++++++++++ .../shimdandy/impl/ClojureRuntimeShimImplTest.java | 41 ++ pom.xml | 75 +++ 8 files changed, 1054 insertions(+) diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..8b29c57 --- /dev/null +++ b/.gitignore @@ -0,0 +1,4 @@ +target +*.iml +*.idea +*~ \ No newline at end of file diff --git a/README.md b/README.md new file mode 100644 index 0000000..b77b0b4 --- /dev/null +++ b/README.md @@ -0,0 +1,82 @@ +# ShimDandy + +A Clojure runtime shim, allowing for multiple Clojure runtimes in the +same JVM. + +Clojure has a static runtime (implemented as static methods off of +clojure.lang.RT), so to run multiple runtimes in the same JVM, they +have to be loaded in isolated ClassLoader trees. ShimDandy provides a +mechanism for isolating the runtimes within a non-Clojure application, +and for calling in to the runtimes from the app. + +## Usage + +The project provides two artifacts: `shimdandy-api.jar` and +`shimdandy-impl.jar`. `shimdandy-api` can be on the boot classpath of +your app, but `shimdandy-impl` should not be on the boot classpath or +exposed to any ClassLoader initially. Nor should any Clojure jars - +having a Clojure jar on the classpath will cause the RT from that jar +(and only that RT) to be loaded, preventing isolation. + +You then create a ClassLoader that has access to `shimdandy-impl.jar`, +`clojure.jar`, and any dependencies you want in the runtime +(`URLClassLoader` works well for this). That ClassLoader is then +passed to `ClojureRuntimeShim.newRuntime`, which returns a +`ClojureRuntimeShim` instance. This instance provides `require` and +`invoke` methods that can be used to call in to the runtime. + +Example: + + URL[] urls = {new URL("file:/path/to/shimdandy-impl.jar"), + new URL("file:/path/to/clojure.jar"), + new URL("file:/path/to/app/src/")}; + ClassLoader cl = new URLClassLoader(urls, parentClassLoader); + ClojureRuntimeShim runtime = ClojureRuntimeShim.newRuntime(cl, "my-app-name"); + + runtime.require("my-app.core"); + Object retval = runtime.invoke("my-app.core/some-fn", arg1, arg2); + +When you are done with a shim, you should close it: + + runtime.close(); + +The latest version is `1.2.0`: + + <dependency> + <groupId>org.projectodd.shimdandy</groupId> + <artifactId>shimdandy-api</artifactId> + <version>1.2.0</version> + </dependency> + +## Preventing memory leaks + +If any code in the shim used an agent or a future, the agent thread +pool will have been started, and those threads will continue to run +after you are done with the shim. This will consume a few resources, +but the bigger concern is the contextClassLoader for those threads +will hold a reference to the shim's classloader, which will prevent +any classes loaded in the shim from being unloaded. Those classes will +eventually cause an OutOfMemoryException from exhausted permgen space +if you create lots of shims. It's best practice to `close()` the shim +when you are done with it (see above). This will shutdown the agent +pool for you. + +This same caveat applies to any other threads started from within the +shim - you need to make sure they are stopped. One particular culprit +is the `clojure.core.async.impl.timers/timeout-daemon` thread. If you +use `core.async`, you need to interrupt that thread on shim shutdown +to interrupt its loop and allow it to exit. + +If you are using a `URLClassLoader`, you should also `close()` it when +you are done with the shim, as some implementations may leak file +descriptors. + +In addition, be sure to use Clojure 1.6.0 or newer to prevent +[other memory leaks](http://dev.clojure.org/jira/browse/CLJ-1125). + +I realize the example here is pretty sparse - please file an issue if +you have any questions. + +Copyright (C) 2013-2015 Tobias Crawley. + +Licensed under the Eclipse Public License v1.0 diff --git a/api/pom.xml b/api/pom.xml new file mode 100644 index 0000000..4b5f4e7 --- /dev/null +++ b/api/pom.xml @@ -0,0 +1,14 @@ +<?xml version="1.0"?> +<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd"> + <modelVersion>4.0.0</modelVersion> + <parent> + <groupId>org.projectodd.shimdandy</groupId> + <artifactId>shimdandy-parent</artifactId> + <version>1.2.0</version> + </parent> + <groupId>org.projectodd.shimdandy</groupId> + <artifactId>shimdandy-api</artifactId> + <version>1.2.0</version> + <name>shimdandy-api</name> + <description>shimdandy API</description> +</project> diff --git a/api/src/main/java/org/projectodd/shimdandy/ClojureRuntimeShim.java b/api/src/main/java/org/projectodd/shimdandy/ClojureRuntimeShim.java new file mode 100644 index 0000000..2cd6794 --- /dev/null +++ b/api/src/main/java/org/projectodd/shimdandy/ClojureRuntimeShim.java @@ -0,0 +1,195 @@ +package org.projectodd.shimdandy; + +/** + * Provides a shim for accessing the Clojure runtime without loading Clojure classes in the + * current classLoader. + * + * @author [email protected] + */ +public abstract class ClojureRuntimeShim { + /** + * Creates a new runtime shim. The given classLoader must be able to find shimdandy classes and + * ClojureRuntimeShimImpl. + */ + public static ClojureRuntimeShim newRuntime(ClassLoader classLoader, String name) { + ClojureRuntimeShim runtime; + try { + runtime = (ClojureRuntimeShim)classLoader + .loadClass("org.projectodd.shimdandy.impl.ClojureRuntimeShimImpl") + .newInstance(); + } catch (Exception e) { + throw new RuntimeException("Failed to load ClojureRuntimeShimImpl", e); + } + + runtime.setClassLoader( classLoader ); + runtime.setName( name ); + runtime.init(); + + return runtime; + } + + public static ClojureRuntimeShim newRuntime(ClassLoader classLoader) { + return newRuntime(classLoader, null); + } + + public void close() { + invoke("clojure.core/shutdown-agents"); + } + + public abstract void require(String... namespaces); + + public abstract Object invoke(String namespacedFunction); + + public abstract Object invoke(Object fn); + + public abstract Object invoke(String namespacedFunction, Object arg1); + + public abstract Object invoke(Object fn, Object arg1); + + public abstract Object invoke(String namespacedFunction, Object arg1, Object arg2); + + public abstract Object invoke(Object fn, Object arg1, Object arg2); + + public abstract Object invoke(String namespacedFunction, Object arg1, Object arg2, Object arg3); + + public abstract Object invoke(Object fn, Object arg1, Object arg2, Object arg3); + + public abstract Object invoke(String namespacedFunction, Object arg1, Object arg2, Object arg3, Object arg4); + + public abstract Object invoke(Object fn, Object arg1, Object arg2, Object arg3, Object arg4); + + public abstract Object invoke(String namespacedFunction, Object arg1, Object arg2, Object arg3, Object arg4, Object arg5); + + public abstract Object invoke(Object fn, Object arg1, Object arg2, Object arg3, Object arg4, Object arg5); + + public abstract Object invoke(String namespacedFunction, Object arg1, Object arg2, Object arg3, Object arg4, Object arg5, Object arg6); + + public abstract Object invoke(Object fn, Object arg1, Object arg2, Object arg3, Object arg4, Object arg5, Object arg6); + + public abstract Object invoke(String namespacedFunction, Object arg1, Object arg2, Object arg3, Object arg4, Object arg5, Object arg6, Object arg7); + + public abstract Object invoke(Object fn, Object arg1, Object arg2, Object arg3, Object arg4, Object arg5, Object arg6, Object arg7); + + public abstract Object invoke(String namespacedFunction, Object arg1, Object arg2, Object arg3, Object arg4, Object arg5, Object arg6, Object arg7, + Object arg8); + + public abstract Object invoke(Object fn, Object arg1, Object arg2, Object arg3, Object arg4, Object arg5, Object arg6, Object arg7, + Object arg8); + + public abstract Object invoke(String namespacedFunction, Object arg1, Object arg2, Object arg3, Object arg4, Object arg5, Object arg6, Object arg7, + Object arg8, Object arg9); + + public abstract Object invoke(Object fn, Object arg1, Object arg2, Object arg3, Object arg4, Object arg5, Object arg6, Object arg7, + Object arg8, Object arg9); + + public abstract Object invoke(String namespacedFunction, Object arg1, Object arg2, Object arg3, Object arg4, Object arg5, Object arg6, Object arg7, + Object arg8, Object arg9, Object arg10); + + public abstract Object invoke(Object fn, Object arg1, Object arg2, Object arg3, Object arg4, Object arg5, Object arg6, Object arg7, + Object arg8, Object arg9, Object arg10); + + public abstract Object invoke(String namespacedFunction, Object arg1, Object arg2, Object arg3, Object arg4, Object arg5, Object arg6, Object arg7, + Object arg8, Object arg9, Object arg10, Object arg11); + + public abstract Object invoke(Object fn, Object arg1, Object arg2, Object arg3, Object arg4, Object arg5, Object arg6, Object arg7, + Object arg8, Object arg9, Object arg10, Object arg11); + + public abstract Object invoke(String namespacedFunction, Object arg1, Object arg2, Object arg3, Object arg4, Object arg5, Object arg6, Object arg7, + Object arg8, Object arg9, Object arg10, Object arg11, Object arg12); + + public abstract Object invoke(Object fn, Object arg1, Object arg2, Object arg3, Object arg4, Object arg5, Object arg6, Object arg7, + Object arg8, Object arg9, Object arg10, Object arg11, Object arg12); + + public abstract Object invoke(String namespacedFunction, Object arg1, Object arg2, Object arg3, Object arg4, Object arg5, Object arg6, Object arg7, + Object arg8, Object arg9, Object arg10, Object arg11, Object arg12, Object arg13); + + public abstract Object invoke(Object fn, Object arg1, Object arg2, Object arg3, Object arg4, Object arg5, Object arg6, Object arg7, + Object arg8, Object arg9, Object arg10, Object arg11, Object arg12, Object arg13); + + public abstract Object invoke(String namespacedFunction, Object arg1, Object arg2, Object arg3, Object arg4, Object arg5, Object arg6, Object arg7, + Object arg8, Object arg9, Object arg10, Object arg11, Object arg12, Object arg13, Object arg14); + + public abstract Object invoke(Object fn, Object arg1, Object arg2, Object arg3, Object arg4, Object arg5, Object arg6, Object arg7, + Object arg8, Object arg9, Object arg10, Object arg11, Object arg12, Object arg13, Object arg14); + + public abstract Object invoke(String namespacedFunction, Object arg1, Object arg2, Object arg3, Object arg4, Object arg5, Object arg6, Object arg7, + Object arg8, Object arg9, Object arg10, Object arg11, Object arg12, Object arg13, Object arg14, + Object arg15); + + public abstract Object invoke(Object fn, Object arg1, Object arg2, Object arg3, Object arg4, Object arg5, Object arg6, Object arg7, + Object arg8, Object arg9, Object arg10, Object arg11, Object arg12, Object arg13, Object arg14, + Object arg15); + + public abstract Object invoke(String namespacedFunction, Object arg1, Object arg2, Object arg3, Object arg4, Object arg5, Object arg6, Object arg7, + Object arg8, Object arg9, Object arg10, Object arg11, Object arg12, Object arg13, Object arg14, + Object arg15, Object arg16); + + public abstract Object invoke(Object fn, Object arg1, Object arg2, Object arg3, Object arg4, Object arg5, Object arg6, Object arg7, + Object arg8, Object arg9, Object arg10, Object arg11, Object arg12, Object arg13, Object arg14, + Object arg15, Object arg16); + + public abstract Object invoke(String namespacedFunction, Object arg1, Object arg2, Object arg3, Object arg4, Object arg5, Object arg6, Object arg7, + Object arg8, Object arg9, Object arg10, Object arg11, Object arg12, Object arg13, Object arg14, + Object arg15, Object arg16, Object arg17); + + public abstract Object invoke(Object fn, Object arg1, Object arg2, Object arg3, Object arg4, Object arg5, Object arg6, Object arg7, + Object arg8, Object arg9, Object arg10, Object arg11, Object arg12, Object arg13, Object arg14, + Object arg15, Object arg16, Object arg17); + + public abstract Object invoke(String namespacedFunction, Object arg1, Object arg2, Object arg3, Object arg4, Object arg5, Object arg6, Object arg7, + Object arg8, Object arg9, Object arg10, Object arg11, Object arg12, Object arg13, Object arg14, + Object arg15, Object arg16, Object arg17, Object arg18); + + public abstract Object invoke(Object fn, Object arg1, Object arg2, Object arg3, Object arg4, Object arg5, Object arg6, Object arg7, + Object arg8, Object arg9, Object arg10, Object arg11, Object arg12, Object arg13, Object arg14, + Object arg15, Object arg16, Object arg17, Object arg18); + + public abstract Object invoke(String namespacedFunction, Object arg1, Object arg2, Object arg3, Object arg4, Object arg5, Object arg6, Object arg7, + Object arg8, Object arg9, Object arg10, Object arg11, Object arg12, Object arg13, Object arg14, + Object arg15, Object arg16, Object arg17, Object arg18, Object arg19); + + public abstract Object invoke(Object fn, Object arg1, Object arg2, Object arg3, Object arg4, Object arg5, Object arg6, Object arg7, + Object arg8, Object arg9, Object arg10, Object arg11, Object arg12, Object arg13, Object arg14, + Object arg15, Object arg16, Object arg17, Object arg18, Object arg19); + + public abstract Object invoke(String namespacedFunction, Object arg1, Object arg2, Object arg3, Object arg4, Object arg5, Object arg6, Object arg7, + Object arg8, Object arg9, Object arg10, Object arg11, Object arg12, Object arg13, Object arg14, + Object arg15, Object arg16, Object arg17, Object arg18, Object arg19, Object arg20); + + public abstract Object invoke(Object fn, Object arg1, Object arg2, Object arg3, Object arg4, Object arg5, Object arg6, Object arg7, + Object arg8, Object arg9, Object arg10, Object arg11, Object arg12, Object arg13, Object arg14, + Object arg15, Object arg16, Object arg17, Object arg18, Object arg19, Object arg20); + + public abstract Object invoke(String namespacedFunction, Object arg1, Object arg2, Object arg3, Object arg4, Object arg5, Object arg6, Object arg7, + Object arg8, Object arg9, Object arg10, Object arg11, Object arg12, Object arg13, Object arg14, + Object arg15, Object arg16, Object arg17, Object arg18, Object arg19, Object arg20, + Object... args); + + public abstract Object invoke(Object fn, Object arg1, Object arg2, Object arg3, Object arg4, Object arg5, Object arg6, Object arg7, + Object arg8, Object arg9, Object arg10, Object arg11, Object arg12, Object arg13, Object arg14, + Object arg15, Object arg16, Object arg17, Object arg18, Object arg19, Object arg20, + Object... args); + + + + public void setName(String name) { + this.name = name; + } + + public String getName() { + return this.name; + } + + public void setClassLoader(ClassLoader classLoader) { + this.classLoader = classLoader; + } + + public ClassLoader getClassLoader() { + return this.classLoader; + } + + public abstract void init(); + + protected ClassLoader classLoader; + protected String name; +} diff --git a/impl/pom.xml b/impl/pom.xml new file mode 100644 index 0000000..7caa60b --- /dev/null +++ b/impl/pom.xml @@ -0,0 +1,34 @@ +<?xml version="1.0"?> +<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd"> + <modelVersion>4.0.0</modelVersion> + <parent> + <groupId>org.projectodd.shimdandy</groupId> + <artifactId>shimdandy-parent</artifactId> + <version>1.2.0</version> + </parent> + <groupId>org.projectodd.shimdandy</groupId> + <artifactId>shimdandy-impl</artifactId> + <version>1.2.0</version> + <name>shimdandy-impl</name> + <description>shimdandy Implementation</description> + + <dependencies> + <dependency> + <groupId>org.projectodd.shimdandy</groupId> + <artifactId>shimdandy-api</artifactId> + <version>${project.version}</version> + <scope>provided</scope> + </dependency> + <dependency> + <groupId>org.clojure</groupId> + <artifactId>clojure</artifactId> + <scope>provided</scope> + </dependency> + <dependency> + <groupId>junit</groupId> + <artifactId>junit</artifactId> + <version>4.11</version> + <scope>test</scope> + </dependency> + </dependencies> +</project> diff --git a/impl/src/main/java/org/projectodd/shimdandy/impl/ClojureRuntimeShimImpl.java b/impl/src/main/java/org/projectodd/shimdandy/impl/ClojureRuntimeShimImpl.java new file mode 100644 index 0000000..e3d1a39 --- /dev/null +++ b/impl/src/main/java/org/projectodd/shimdandy/impl/ClojureRuntimeShimImpl.java @@ -0,0 +1,609 @@ +package org.projectodd.shimdandy.impl; + +import clojure.lang.IFn; +import clojure.lang.RT; +import clojure.lang.Symbol; +import clojure.lang.Var; +import org.projectodd.shimdandy.ClojureRuntimeShim; + +import java.lang.reflect.Field; +import java.util.concurrent.atomic.AtomicLong; + +/** + */ +public class ClojureRuntimeShimImpl extends ClojureRuntimeShim { + public void init() { + ClassLoader origLoader = preInvoke(); + Exception ex = null; + try { + Field dvalField = Var.class.getDeclaredField("dvals"); + dvalField.setAccessible(true); + this.dvals = (ThreadLocal)dvalField.get(null); + + this.require = RT.var("clojure.core", "require"); + this.resolve = RT.var("clojure.core", "resolve"); + clojure.lang.Compiler.LOADER.bindRoot(this.classLoader); + } catch (IllegalAccessException e) { + ex = e; + } catch (NoSuchFieldException e) { + ex = e; + } finally { + postInvoke(origLoader); + } + + if (ex != null) { + throw new RuntimeException("Failed to access Var.dvals", ex); + } + } + + protected ClassLoader preInvoke() { + final ClassLoader originalClassloader = Thread.currentThread().getContextClassLoader(); + Thread.currentThread().setContextClassLoader(this.classLoader); + this.callDepth.get().getAndIncrement(); + + return originalClassloader; + } + + protected void postInvoke(ClassLoader loader) { + if (this.callDepth.get().decrementAndGet() == 0) { + this.dvals.remove(); + this.callDepth.remove(); + } + Thread.currentThread().setContextClassLoader(loader); + } + + protected Var var(String namespacedFunction) { + ClassLoader origLoader = preInvoke(); + try { + Var var = (Var)this.resolve.invoke(Symbol.create(namespacedFunction)); + if (var == null) { + String[] parts = namespacedFunction.split("/"); + this.require.invoke(Symbol.create(parts[0])); + var = RT.var(parts[0], parts[1]); + } + + return var; + } catch (Exception e) { + throw new RuntimeException( "Failed to load Var " + namespacedFunction, e ); + } finally { + postInvoke( origLoader ); + } + } + + @Override + public void require(String... namespaces) { + ClassLoader origLoader = preInvoke(); + try { + for (String ns : namespaces) { + this.require.invoke(Symbol.create(ns)); + } + } finally { + postInvoke(origLoader); + } + } + + @Override + public Object invoke(String namespacedFunction) { + return invoke( var( namespacedFunction ) ); + } + + @Override + public Object invoke(Object fn) { + ClassLoader origLoader = preInvoke(); + try { + return ((IFn)fn).invoke(); + } finally { + postInvoke( origLoader ); + } + } + + @Override + public Object invoke(String namespacedFunction, Object arg1) { + return invoke( var( namespacedFunction ), arg1 ); + } + + @Override + public Object invoke(Object fn, Object arg1) { + ClassLoader origLoader = preInvoke(); + try { + return ((IFn)fn).invoke(arg1); + } finally { + postInvoke( origLoader ); + } + } + + @Override + public Object invoke(String namespacedFunction, Object arg1, Object arg2) { + return invoke( var( namespacedFunction ), arg1, arg2); + } + + @Override + public Object invoke(Object fn, Object arg1, Object arg2) { + ClassLoader origLoader = preInvoke(); + try { + return ((IFn)fn).invoke(arg1, arg2); + } finally { + postInvoke( origLoader ); + } + } + + @Override + public Object invoke(String namespacedFunction, Object arg1, Object arg2, + Object arg3) { + return invoke( var( namespacedFunction ), arg1, arg2, arg3); + } + + @Override + public Object invoke(Object fn, Object arg1, Object arg2, + Object arg3) { + ClassLoader origLoader = preInvoke(); + try { + return ((IFn)fn).invoke(arg1, arg2, arg3); + } finally { + postInvoke( origLoader ); + } + } + + @Override + public Object invoke(String namespacedFunction, Object arg1, Object arg2, + Object arg3, Object arg4) { + return invoke(var( namespacedFunction ), arg1, arg2, + arg3, arg4); + } + + @Override + public Object invoke(Object fn, Object arg1, Object arg2, + Object arg3, Object arg4) { + ClassLoader origLoader = preInvoke(); + try { + return ((IFn)fn).invoke(arg1, arg2, + arg3, arg4); + } finally { + postInvoke( origLoader ); + } + } + + @Override + public Object invoke(String namespacedFunction, Object arg1, Object arg2, + Object arg3, Object arg4, Object arg5) { + return invoke(var( namespacedFunction ), arg1, arg2, + arg3, arg4, arg5); + } + + @Override + public Object invoke(Object fn, Object arg1, Object arg2, + Object arg3, Object arg4, Object arg5) { + ClassLoader origLoader = preInvoke(); + try { + return ((IFn)fn).invoke(arg1, arg2, + arg3, arg4, arg5); + } finally { + postInvoke( origLoader ); + } + } + + @Override + public Object invoke(String namespacedFunction, Object arg1, Object arg2, + Object arg3, Object arg4, Object arg5, Object arg6) { + return invoke(var( namespacedFunction ), arg1, arg2, + arg3, arg4, arg5, arg6); + } + + @Override + public Object invoke(Object fn, Object arg1, Object arg2, + Object arg3, Object arg4, Object arg5, Object arg6) { + ClassLoader origLoader = preInvoke(); + try { + return ((IFn)fn).invoke(arg1, arg2, + arg3, arg4, arg5, arg6); + } finally { + postInvoke( origLoader ); + } + } + + @Override + public Object invoke(String namespacedFunction, Object arg1, Object arg2, + Object arg3, Object arg4, Object arg5, Object arg6, Object arg7) { + return invoke(var( namespacedFunction ), arg1, arg2, + arg3, arg4, arg5, arg6, arg7); + } + + @Override + public Object invoke(Object fn, Object arg1, Object arg2, + Object arg3, Object arg4, Object arg5, Object arg6, Object arg7) { + ClassLoader origLoader = preInvoke(); + try { + return ((IFn)fn).invoke(arg1, arg2, + arg3, arg4, arg5, arg6, arg7); + } finally { + postInvoke( origLoader ); + } + } + + @Override + public Object invoke(String namespacedFunction, Object arg1, Object arg2, + Object arg3, Object arg4, Object arg5, Object arg6, Object arg7, + Object arg8) { + return invoke(var( namespacedFunction ), arg1, arg2, + arg3, arg4, arg5, arg6, arg7, + arg8); + } + + @Override + public Object invoke(Object fn, Object arg1, Object arg2, + Object arg3, Object arg4, Object arg5, Object arg6, Object arg7, + Object arg8) { + ClassLoader origLoader = preInvoke(); + try { + return ((IFn)fn).invoke(arg1, arg2, + arg3, arg4, arg5, arg6, arg7, + arg8); + } finally { + postInvoke( origLoader ); + } + } + + @Override + public Object invoke(String namespacedFunction, Object arg1, Object arg2, + Object arg3, Object arg4, Object arg5, Object arg6, Object arg7, + Object arg8, Object arg9) { + return invoke(var( namespacedFunction ), arg1, arg2, + arg3, arg4, arg5, arg6, arg7, + arg8, arg9); + } + + @Override + public Object invoke(Object fn, Object arg1, Object arg2, + Object arg3, Object arg4, Object arg5, Object arg6, Object arg7, + Object arg8, Object arg9) { + ClassLoader origLoader = preInvoke(); + try { + return ((IFn)fn).invoke(arg1, arg2, + arg3, arg4, arg5, arg6, arg7, + arg8, arg9); + } finally { + postInvoke( origLoader ); + } + } + + @Override + public Object invoke(String namespacedFunction, Object arg1, Object arg2, + Object arg3, Object arg4, Object arg5, Object arg6, Object arg7, + Object arg8, Object arg9, Object arg10) { + return invoke(var( namespacedFunction ), arg1, arg2, + arg3, arg4, arg5, arg6, arg7, + arg8, arg9, arg10); + } + + @Override + public Object invoke(Object fn, Object arg1, Object arg2, + Object arg3, Object arg4, Object arg5, Object arg6, Object arg7, + Object arg8, Object arg9, Object arg10) { + ClassLoader origLoader = preInvoke(); + try { + return ((IFn)fn).invoke(arg1, arg2, + arg3, arg4, arg5, arg6, arg7, + arg8, arg9, arg10); + } finally { + postInvoke( origLoader ); + } + } + + @Override + public Object invoke(String namespacedFunction, Object arg1, Object arg2, + Object arg3, Object arg4, Object arg5, Object arg6, Object arg7, + Object arg8, Object arg9, Object arg10, Object arg11) { + return invoke(var( namespacedFunction ), arg1, arg2, + arg3, arg4, arg5, arg6, arg7, + arg8, arg9, arg10, arg11); + } + + @Override + public Object invoke(Object fn, Object arg1, Object arg2, + Object arg3, Object arg4, Object arg5, Object arg6, Object arg7, + Object arg8, Object arg9, Object arg10, Object arg11) { + ClassLoader origLoader = preInvoke(); + try { + return ((IFn)fn).invoke(arg1, arg2, + arg3, arg4, arg5, arg6, arg7, + arg8, arg9, arg10, arg11); + } finally { + postInvoke( origLoader ); + } + } + + @Override + public Object invoke(String namespacedFunction, Object arg1, Object arg2, + Object arg3, Object arg4, Object arg5, Object arg6, Object arg7, + Object arg8, Object arg9, Object arg10, Object arg11, Object arg12) { + return invoke(var( namespacedFunction ), arg1, arg2, + arg3, arg4, arg5, arg6, arg7, + arg8, arg9, arg10, arg11, arg12); + } + + @Override + public Object invoke(Object fn, Object arg1, Object arg2, + Object arg3, Object arg4, Object arg5, Object arg6, Object arg7, + Object arg8, Object arg9, Object arg10, Object arg11, Object arg12) { + ClassLoader origLoader = preInvoke(); + try { + return ((IFn)fn).invoke(arg1, arg2, + arg3, arg4, arg5, arg6, arg7, + arg8, arg9, arg10, arg11, arg12); + } finally { + postInvoke( origLoader ); + } + } + + @Override + public Object invoke(String namespacedFunction, Object arg1, Object arg2, + Object arg3, Object arg4, Object arg5, Object arg6, Object arg7, + Object arg8, Object arg9, Object arg10, Object arg11, Object arg12, + Object arg13) { + return invoke(var( namespacedFunction ), arg1, arg2, + arg3, arg4, arg5, arg6, arg7, + arg8, arg9, arg10, arg11, arg12, + arg13); + } + + @Override + public Object invoke(Object fn, Object arg1, Object arg2, + Object arg3, Object arg4, Object arg5, Object arg6, Object arg7, + Object arg8, Object arg9, Object arg10, Object arg11, Object arg12, + Object arg13) { + ClassLoader origLoader = preInvoke(); + try { + return ((IFn)fn).invoke(arg1, arg2, + arg3, arg4, arg5, arg6, arg7, + arg8, arg9, arg10, arg11, arg12, + arg13); + } finally { + postInvoke( origLoader ); + } + } + + @Override + public Object invoke(String namespacedFunction, Object arg1, Object arg2, + Object arg3, Object arg4, Object arg5, Object arg6, Object arg7, + Object arg8, Object arg9, Object arg10, Object arg11, Object arg12, + Object arg13, Object arg14) { + return invoke(var( namespacedFunction ), arg1, arg2, + arg3, arg4, arg5, arg6, arg7, + arg8, arg9, arg10, arg11, arg12, + arg13, arg14); + } + + @Override + public Object invoke(Object fn, Object arg1, Object arg2, + Object arg3, Object arg4, Object arg5, Object arg6, Object arg7, + Object arg8, Object arg9, Object arg10, Object arg11, Object arg12, + Object arg13, Object arg14) { + ClassLoader origLoader = preInvoke(); + try { + return ((IFn)fn).invoke(arg1, arg2, + arg3, arg4, arg5, arg6, arg7, + arg8, arg9, arg10, arg11, arg12, + arg13, arg14); + } finally { + postInvoke( origLoader ); + } + } + + @Override + public Object invoke(String namespacedFunction, Object arg1, Object arg2, + Object arg3, Object arg4, Object arg5, Object arg6, Object arg7, + Object arg8, Object arg9, Object arg10, Object arg11, Object arg12, + Object arg13, Object arg14, Object arg15) { + return invoke(var( namespacedFunction ), arg1, arg2, + arg3, arg4, arg5, arg6, arg7, + arg8, arg9, arg10, arg11, arg12, + arg13, arg14, arg15); + } + + @Override + public Object invoke(Object fn, Object arg1, Object arg2, + Object arg3, Object arg4, Object arg5, Object arg6, Object arg7, + Object arg8, Object arg9, Object arg10, Object arg11, Object arg12, + Object arg13, Object arg14, Object arg15) { + ClassLoader origLoader = preInvoke(); + try { + return ((IFn)fn).invoke(arg1, arg2, + arg3, arg4, arg5, arg6, arg7, + arg8, arg9, arg10, arg11, arg12, + arg13, arg14, arg15); + } finally { + postInvoke( origLoader ); + } + } + + @Override + public Object invoke(String namespacedFunction, Object arg1, Object arg2, + Object arg3, Object arg4, Object arg5, Object arg6, Object arg7, + Object arg8, Object arg9, Object arg10, Object arg11, Object arg12, + Object arg13, Object arg14, Object arg15, Object arg16) { + return invoke(var( namespacedFunction ), arg1, arg2, + arg3, arg4, arg5, arg6, arg7, + arg8, arg9, arg10, arg11, arg12, + arg13, arg14, arg15, arg16); + } + + @Override + public Object invoke(Object fn, Object arg1, Object arg2, + Object arg3, Object arg4, Object arg5, Object arg6, Object arg7, + Object arg8, Object arg9, Object arg10, Object arg11, Object arg12, + Object arg13, Object arg14, Object arg15, Object arg16) { + ClassLoader origLoader = preInvoke(); + try { + return ((IFn)fn).invoke(arg1, arg2, + arg3, arg4, arg5, arg6, arg7, + arg8, arg9, arg10, arg11, arg12, + arg13, arg14, arg15, arg16); + } finally { + postInvoke( origLoader ); + } + } + + @Override + public Object invoke(String namespacedFunction, Object arg1, Object arg2, + Object arg3, Object arg4, Object arg5, Object arg6, Object arg7, + Object arg8, Object arg9, Object arg10, Object arg11, Object arg12, + Object arg13, Object arg14, Object arg15, Object arg16, Object arg17) { + return invoke(var( namespacedFunction ), arg1, arg2, + arg3, arg4, arg5, arg6, arg7, + arg8, arg9, arg10, arg11, arg12, + arg13, arg14, arg15, arg16, arg17); + } + + @Override + public Object invoke(Object fn, Object arg1, Object arg2, + Object arg3, Object arg4, Object arg5, Object arg6, Object arg7, + Object arg8, Object arg9, Object arg10, Object arg11, Object arg12, + Object arg13, Object arg14, Object arg15, Object arg16, Object arg17) { + ClassLoader origLoader = preInvoke(); + try { + return ((IFn)fn).invoke(arg1, arg2, + arg3, arg4, arg5, arg6, arg7, + arg8, arg9, arg10, arg11, arg12, + arg13, arg14, arg15, arg16, arg17); + } finally { + postInvoke( origLoader ); + } + } + + @Override + public Object invoke(String namespacedFunction, Object arg1, Object arg2, + Object arg3, Object arg4, Object arg5, Object arg6, Object arg7, + Object arg8, Object arg9, Object arg10, Object arg11, Object arg12, + Object arg13, Object arg14, Object arg15, Object arg16, + Object arg17, Object arg18) { + return invoke(var( namespacedFunction ), arg1, arg2, + arg3, arg4, arg5, arg6, arg7, + arg8, arg9, arg10, arg11, arg12, + arg13, arg14, arg15, arg16, + arg17, arg18); + } + + @Override + public Object invoke(Object fn, Object arg1, Object arg2, + Object arg3, Object arg4, Object arg5, Object arg6, Object arg7, + Object arg8, Object arg9, Object arg10, Object arg11, Object arg12, + Object arg13, Object arg14, Object arg15, Object arg16, + Object arg17, Object arg18) { + ClassLoader origLoader = preInvoke(); + try { + return ((IFn)fn).invoke(arg1, arg2, + arg3, arg4, arg5, arg6, arg7, + arg8, arg9, arg10, arg11, arg12, + arg13, arg14, arg15, arg16, + arg17, arg18); + } finally { + postInvoke( origLoader ); + } + } + + @Override + public Object invoke(String namespacedFunction, Object arg1, Object arg2, + Object arg3, Object arg4, Object arg5, Object arg6, Object arg7, + Object arg8, Object arg9, Object arg10, Object arg11, Object arg12, + Object arg13, Object arg14, Object arg15, Object arg16, + Object arg17, Object arg18, Object arg19) { + return invoke(var( namespacedFunction ), arg1, arg2, + arg3, arg4, arg5, arg6, arg7, + arg8, arg9, arg10, arg11, arg12, + arg13, arg14, arg15, arg16, + arg17, arg18, arg19); + } + + @Override + public Object invoke(Object fn, Object arg1, Object arg2, + Object arg3, Object arg4, Object arg5, Object arg6, Object arg7, + Object arg8, Object arg9, Object arg10, Object arg11, Object arg12, + Object arg13, Object arg14, Object arg15, Object arg16, + Object arg17, Object arg18, Object arg19) { + ClassLoader origLoader = preInvoke(); + try { + return ((IFn)fn).invoke(arg1, arg2, + arg3, arg4, arg5, arg6, arg7, + arg8, arg9, arg10, arg11, arg12, + arg13, arg14, arg15, arg16, + arg17, arg18, arg19); + } finally { + postInvoke( origLoader ); + } + } + + @Override + public Object invoke(String namespacedFunction, Object arg1, Object arg2, + Object arg3, Object arg4, Object arg5, Object arg6, Object arg7, + Object arg8, Object arg9, Object arg10, Object arg11, Object arg12, + Object arg13, Object arg14, Object arg15, Object arg16, + Object arg17, Object arg18, Object arg19, Object arg20) { + return invoke(var( namespacedFunction ), arg1, arg2, + arg3, arg4, arg5, arg6, arg7, + arg8, arg9, arg10, arg11, arg12, + arg13, arg14, arg15, arg16, + arg17, arg18, arg19, arg20); + } + + @Override + public Object invoke(Object fn, Object arg1, Object arg2, + Object arg3, Object arg4, Object arg5, Object arg6, Object arg7, + Object arg8, Object arg9, Object arg10, Object arg11, Object arg12, + Object arg13, Object arg14, Object arg15, Object arg16, + Object arg17, Object arg18, Object arg19, Object arg20) { + ClassLoader origLoader = preInvoke(); + try { + return ((IFn)fn).invoke(arg1, arg2, + arg3, arg4, arg5, arg6, arg7, + arg8, arg9, arg10, arg11, arg12, + arg13, arg14, arg15, arg16, + arg17, arg18, arg19, arg20); + } finally { + postInvoke( origLoader ); + } + } + + @Override + public Object invoke(String namespacedFunction, Object arg1, Object arg2, + Object arg3, Object arg4, Object arg5, Object arg6, Object arg7, + Object arg8, Object arg9, Object arg10, Object arg11, Object arg12, + Object arg13, Object arg14, Object arg15, Object arg16, + Object arg17, Object arg18, Object arg19, Object arg20, + Object... args) { + return invoke(var( namespacedFunction ), arg1, arg2, + arg3, arg4, arg5, arg6, arg7, + arg8, arg9, arg10, arg11, arg12, + arg13, arg14, arg15, arg16, + arg17, arg18, arg19, arg20, + args); + } + + @Override + public Object invoke(Object fn, Object arg1, Object arg2, + Object arg3, Object arg4, Object arg5, Object arg6, Object arg7, + Object arg8, Object arg9, Object arg10, Object arg11, Object arg12, + Object arg13, Object arg14, Object arg15, Object arg16, + Object arg17, Object arg18, Object arg19, Object arg20, + Object... args) { + ClassLoader origLoader = preInvoke(); + try { + return ((IFn)fn).invoke(arg1, arg2, + arg3, arg4, arg5, arg6, arg7, + arg8, arg9, arg10, arg11, arg12, + arg13, arg14, arg15, arg16, + arg17, arg18, arg19, arg20, + args); + } finally { + postInvoke( origLoader ); + } + } + + private Var require; + private Var resolve; + private ThreadLocal dvals; + private final ThreadLocal<AtomicLong> callDepth = new ThreadLocal<AtomicLong>() { + protected AtomicLong initialValue() { + return new AtomicLong(0); + } + }; +} diff --git a/impl/src/test/java/org/projectodd/shimdandy/impl/ClojureRuntimeShimImplTest.java b/impl/src/test/java/org/projectodd/shimdandy/impl/ClojureRuntimeShimImplTest.java new file mode 100644 index 0000000..813a420 --- /dev/null +++ b/impl/src/test/java/org/projectodd/shimdandy/impl/ClojureRuntimeShimImplTest.java @@ -0,0 +1,41 @@ +package org.projectodd.shimdandy.impl; + +import clojure.lang.Symbol; +import clojure.lang.Var; +import org.junit.Before; +import org.junit.Test; + +import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertNotNull; + +public class ClojureRuntimeShimImplTest { + @Before + public void setup() { + shim = new ClojureRuntimeShimImpl(); + shim.setClassLoader(Symbol.class.getClassLoader()); + shim.init(); + } + + @Test + public void testVarWhenVarExistsInRTOnly() { + Object ns = shim.invoke("clojure.core/create-ns", Symbol.create("foo")); + Var intern = shim.var("clojure.core/intern"); + intern.invoke(ns, Symbol.create("bar"), "baz"); + Var bar = shim.var("foo/bar"); + assertNotNull(bar); + assertEquals("baz", bar.deref()); + } + + @Test + public void testVarWhenNSExists() { + Var trim = shim.var("clojure.string/trim"); + assertNotNull(trim); + } + + @Test + public void testInvoke() { + assertEquals("ham", shim.invoke("clojure.core/identity", "ham")); + } + + private ClojureRuntimeShimImpl shim; +} diff --git a/pom.xml b/pom.xml new file mode 100644 index 0000000..4f48685 --- /dev/null +++ b/pom.xml @@ -0,0 +1,75 @@ +<?xml version="1.0" encoding="UTF-8"?> +<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd"> + <modelVersion>4.0.0</modelVersion> + + <groupId>org.projectodd.shimdandy</groupId> + <artifactId>shimdandy-parent</artifactId> + <version>1.2.0</version> + <packaging>pom</packaging> + <description>Shimdandy parent POM</description> + + <name>shimdandy-parent</name> + <url>https://github.com/projectodd/shimdandy</url> + + <licenses> + <license> + <name>Eclipse Public License - v 1.0</name> + <url>http://www.eclipse.org/legal/epl-v10.html</url> + <distribution>repo</distribution> + </license> + </licenses> + + <parent> + <groupId>org.sonatype.oss</groupId> + <artifactId>oss-parent</artifactId> + <version>7</version> + </parent> + + <scm> + <connection>scm:git:[email protected]:projectodd/shimdandy.git</connection> + <developerConnection>scm:git:[email protected]:projectodd/shimdandy.git</developerConnection> + <url>https://github.com/projectodd/shimdandy/</url> + </scm> + + <developers> + <developer> + <id>tcrawey</id> + <name>Toby Crawley</name> + <email>[email protected]</email> + </developer> + </developers> + + <properties> + <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding> + <version.clojure>1.7.0-alpha4</version.clojure> + </properties> + + <dependencyManagement> + <dependencies> + <dependency> + <groupId>org.clojure</groupId> + <artifactId>clojure</artifactId> + <version>${version.clojure}</version> + </dependency> + </dependencies> + </dependencyManagement> + + <modules> + <module>api</module> + <module>impl</module> + </modules> + +<distributionManagement> + <repository> + <id>sonatype-nexus-staging</id> + <name>Nexus Staging Repo</name> + <url>https://oss.sonatype.org/service/local/staging/deploy/maven2/</url> + </repository> + <snapshotRepository> + <id>sonatype-nexus-snapshots</id> + <name>Nexus Snapshot Repo</name> + <url>https://oss.sonatype.org/content/repositories/snapshots/</url> + </snapshotRepository> +</distributionManagement> + +</project> -- Alioth's /usr/local/bin/git-commit-notice on /srv/git.debian.org/git/pkg-java/shimdandy.git _______________________________________________ pkg-java-commits mailing list [email protected] http://lists.alioth.debian.org/cgi-bin/mailman/listinfo/pkg-java-commits

