11package io .osv ;
22
3- import io .osv .jul .IsolatingLogManager ;
4- import net .sf .cglib .proxy .Dispatcher ;
5- import net .sf .cglib .proxy .Enhancer ;
6-
73import java .io .File ;
84import java .io .FileNotFoundException ;
95import java .io .FilePermission ;
10- import java .lang .reflect .Field ;
116import java .lang .reflect .InvocationTargetException ;
127import java .lang .reflect .Method ;
138import java .net .MalformedURLException ;
2015import java .util .Properties ;
2116import java .util .jar .JarFile ;
2217import java .util .jar .Manifest ;
23- import java .util .logging .LogManager ;
2418import java .util .zip .ZipException ;
2519
2620/*
21+ * Copyright (C) 2016 Waldemar Kozaczuk
2722 * Copyright (C) 2014 Cloudius Systems, Ltd.
2823 *
2924 * This work is open source software, licensed under the terms of the
3025 * BSD license as described in the LICENSE file in the top-level directory.
3126 */
32- public class ContextIsolator {
33- private static final ContextIsolator instance = new ContextIsolator ();
34-
35- static {
36- verifyLogManagerIsInstalled ();
37- }
38-
39- private final Context masterContext ;
40- private final Properties commonSystemProperties ;
41-
42- private static void verifyLogManagerIsInstalled () {
43- LogManager manager = LogManager .getLogManager ();
44- if (!(manager instanceof IsolatingLogManager )) {
45- throw new AssertionError ("For isolation to work logging manager must be "
46- + IsolatingLogManager .class .getName () + " but is: " + manager .getClass ().getName ());
47- }
48- }
49-
50- private final InheritableThreadLocal <Context > currentContext = new InheritableThreadLocal <Context >() {
51- @ Override
52- protected Context initialValue () {
53- return masterContext ;
54- }
55- };
56-
57- private final ClassLoader parentClassLoaderForIsolates ;
58-
59- public static ContextIsolator getInstance () {
60- return instance ;
61- }
62-
63- public ContextIsolator () {
64- ClassLoader originalSystemClassLoader = getOsvClassLoader ().getParent ();
65- commonSystemProperties = copyOf (System .getProperties ());
66- masterContext = new Context (originalSystemClassLoader , copyOf (commonSystemProperties ));
67-
68- parentClassLoaderForIsolates = originalSystemClassLoader ;
69-
70- installSystemPropertiesProxy ();
71- }
72-
73- private Properties copyOf (Properties properties ) {
74- Properties result = new Properties ();
75- result .putAll (properties );
76- return result ;
77- }
78-
79- private static void installSystemPropertiesProxy () {
80- Enhancer enhancer = new Enhancer ();
81- enhancer .setSuperclass (Properties .class );
82- enhancer .setCallback (new Dispatcher () {
83- @ Override
84- public Object loadObject () throws Exception {
85- return instance .getContext ().getProperties ();
86- }
87- });
88- Properties contextAwareProperties = (Properties ) enhancer .create ();
89-
90- try {
91- Field props = System .class .getDeclaredField ("props" );
92- props .setAccessible (true );
93- props .set (System .class , contextAwareProperties );
94- } catch (NoSuchFieldException | IllegalAccessException e ) {
95- throw new AssertionError ("Unable to override System.props" , e );
96- }
97- }
98-
99- public Context getContext () {
100- return currentContext .get ();
101- }
102-
103- private Context run (ClassLoader classLoader , final String classpath , final String mainClass ,
104- final String [] args , final Properties properties ) {
105- Properties contextProperties = new Properties ();
106- contextProperties .putAll (commonSystemProperties );
107- contextProperties .putAll (properties );
108-
109- final Context context = new Context (classLoader , contextProperties );
27+ public abstract class Jvm <T > {
28+ public abstract void runSync (String ... args ) throws Throwable ;
11029
111- Thread thread = new Thread () {
112- @ Override
113- public void run () {
114- currentContext .set (context );
115- context .setProperty ("java.class.path" , classpath );
116-
117- try {
118- runMain (loadClass (mainClass ), args );
119- } catch (InterruptedException e ) {
120- Thread .currentThread ().interrupt ();
121- } catch (MainClassNotFoundException e ) {
122- context .setException (e );
123- } catch (Throwable e ) {
124- getUncaughtExceptionHandler ().uncaughtException (this , e );
125- }
126- }
127- };
128-
129- context .setMainThread (thread );
130- thread .setUncaughtExceptionHandler (new Thread .UncaughtExceptionHandler () {
131- @ Override
132- public void uncaughtException (Thread t , Throwable e ) {
133- context .setException (e );
134- }
135- });
136- thread .setContextClassLoader (classLoader );
137- thread .start ();
138- return context ;
139- }
140-
141- public void runSync (String ... args ) throws Throwable {
142- Context context = run (args );
143-
144- while (true ) {
145- try {
146- context .join ();
147- return ;
148- } catch (InterruptedException e ) {
149- context .interrupt ();
150- }
151- }
152- }
153-
154- public Context run (String ... args ) throws Throwable {
30+ public T run (String ... args ) throws Throwable {
15531 Properties properties = new Properties ();
15632
15733 ArrayList <String > classpath = new ArrayList <>();
@@ -189,7 +65,7 @@ public Context run(String... args) throws Throwable {
18965 throw new IllegalArgumentException ("No jar or class specified to run." );
19066 }
19167
192- private Context runJar (String jarName , String [] args , ArrayList <String > classpath , Properties properties ) throws Throwable {
68+ private T runJar (String jarName , String [] args , ArrayList <String > classpath , Properties properties ) throws Throwable {
19369 File jarFile = new File (jarName );
19470 try {
19571 JarFile jar = new JarFile (jarFile );
@@ -208,26 +84,31 @@ private Context runJar(String jarName, String[] args, ArrayList<String> classpat
20884 }
20985 }
21086
211- private Context runClass (String mainClass , String [] args , Iterable <String > classpath , Properties properties ) throws MalformedURLException {
212- ClassLoader appClassLoader = getClassLoader (classpath , parentClassLoaderForIsolates );
87+ private T runClass (String mainClass , String [] args , Iterable <String > classpath , Properties properties ) throws MalformedURLException {
88+ ClassLoader appClassLoader = createAppClassLoader (classpath , getParentClassLoader () );
21389 return run (appClassLoader , joinClassPath (classpath ), mainClass , args , properties );
21490 }
21591
216- private static ClassLoader getClassLoader (Iterable <String > classpath , ClassLoader parent ) throws MalformedURLException {
92+ protected abstract T run (ClassLoader classLoader , final String classpath , final String mainClass ,
93+ final String [] args , final Properties properties );
94+
95+ protected abstract ClassLoader getParentClassLoader ();
96+
97+ private ClassLoader createAppClassLoader (Iterable <String > classpath , ClassLoader parent ) throws MalformedURLException {
21798 List <URL > urls = toUrls (classpath );
21899 URL [] urlArray = urls .toArray (new URL [urls .size ()]);
219100 return new AppClassLoader (urlArray , parent );
220101 }
221102
222- private static List <URL > toUrls (Iterable <String > classpath ) throws MalformedURLException {
103+ private List <URL > toUrls (Iterable <String > classpath ) throws MalformedURLException {
223104 ArrayList <URL > urls = new ArrayList <>();
224105 for (String path : classpath ) {
225106 urls .add (toUrl (path ));
226107 }
227108 return urls ;
228109 }
229110
230- private static void runMain (Class <?> klass , String [] args ) throws Throwable {
111+ protected void runMain (Class <?> klass , String [] args ) throws Throwable {
231112 Method main = klass .getMethod ("main" , String [].class );
232113 try {
233114 main .invoke (null , new Object []{args });
@@ -236,18 +117,15 @@ private static void runMain(Class<?> klass, String[] args) throws Throwable {
236117 }
237118 }
238119
239- private static OsvSystemClassLoader getOsvClassLoader () {
240- ClassLoader systemClassLoader = ClassLoader .getSystemClassLoader ();
241- if (!(systemClassLoader instanceof OsvSystemClassLoader )) {
242- throw new AssertionError ("System class loader should be an instance of "
243- + OsvSystemClassLoader .class .getName () + " but is "
244- + systemClassLoader .getClass ().getName ());
120+ protected Class <?> loadClass (String name ) throws MainClassNotFoundException {
121+ try {
122+ return Thread .currentThread ().getContextClassLoader ().loadClass (name );
123+ } catch (ClassNotFoundException ex ) {
124+ throw new MainClassNotFoundException (name );
245125 }
246-
247- return (OsvSystemClassLoader ) systemClassLoader ;
248126 }
249127
250- private static String joinClassPath (Iterable <String > classpath ) {
128+ private String joinClassPath (Iterable <String > classpath ) {
251129 StringBuilder sb = new StringBuilder ();
252130 boolean first = true ;
253131 for (String path : classpath ) {
@@ -260,29 +138,21 @@ private static String joinClassPath(Iterable<String> classpath) {
260138 return sb .toString ();
261139 }
262140
263- private static URL toUrl (String path ) throws MalformedURLException {
141+ private URL toUrl (String path ) throws MalformedURLException {
264142 return new URL ("file:///" + path + (isDirectory (path ) ? "/" : "" ));
265143 }
266144
267- private static boolean isDirectory (String path ) {
145+ private boolean isDirectory (String path ) {
268146 return new File (path ).isDirectory ();
269147 }
270148
271- private static Class <?> loadClass (String name ) throws MainClassNotFoundException {
272- try {
273- return Thread .currentThread ().getContextClassLoader ().loadClass (name );
274- } catch (ClassNotFoundException ex ) {
275- throw new MainClassNotFoundException (name );
276- }
277- }
278-
279149 // Expand classpath, as given in the "-classpath" option, to a list of
280150 // jars or directories. As in the traditional "java" command-line
281151 // launcher, components of the class path are separated by ":", and
282152 // we also support the traditional (but awkward) Java wildcard syntax,
283153 // where "dir/*" adds to the classpath all jar files in the given
284154 // directory.
285- private static Iterable <String > expandClassPath (String classpath ) {
155+ private Iterable <String > expandClassPath (String classpath ) {
286156 ArrayList <String > ret = new ArrayList <>();
287157 for (String component : classpath .split (":" )) {
288158 if (component .endsWith ("/*" )) {
@@ -307,10 +177,6 @@ private static Iterable<String> expandClassPath(String classpath) {
307177 return ret ;
308178 }
309179
310- public Object receive () throws InterruptedException {
311- return getContext ().takeMessage ();
312- }
313-
314180 private static class AppClassLoader extends URLClassLoader {
315181 public AppClassLoader (URL [] urlArray , ClassLoader parent ) {
316182 super (urlArray , parent );
@@ -324,5 +190,4 @@ protected PermissionCollection getPermissions(CodeSource codesource) {
324190 return permissions ;
325191 }
326192 }
327-
328193}
0 commit comments