1
1
package io .osv ;
2
2
3
- import io .osv .jul .IsolatingLogManager ;
4
- import net .sf .cglib .proxy .Dispatcher ;
5
- import net .sf .cglib .proxy .Enhancer ;
6
-
7
3
import java .io .File ;
8
4
import java .io .FileNotFoundException ;
9
5
import java .io .FilePermission ;
10
- import java .lang .reflect .Field ;
11
6
import java .lang .reflect .InvocationTargetException ;
12
7
import java .lang .reflect .Method ;
13
8
import java .net .MalformedURLException ;
20
15
import java .util .Properties ;
21
16
import java .util .jar .JarFile ;
22
17
import java .util .jar .Manifest ;
23
- import java .util .logging .LogManager ;
24
18
import java .util .zip .ZipException ;
25
19
26
20
/*
21
+ * Copyright (C) 2016 Waldemar Kozaczuk
27
22
* Copyright (C) 2014 Cloudius Systems, Ltd.
28
23
*
29
24
* This work is open source software, licensed under the terms of the
30
25
* BSD license as described in the LICENSE file in the top-level directory.
31
26
*/
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 ;
110
29
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 {
155
31
Properties properties = new Properties ();
156
32
157
33
ArrayList <String > classpath = new ArrayList <>();
@@ -189,7 +65,7 @@ public Context run(String... args) throws Throwable {
189
65
throw new IllegalArgumentException ("No jar or class specified to run." );
190
66
}
191
67
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 {
193
69
File jarFile = new File (jarName );
194
70
try {
195
71
JarFile jar = new JarFile (jarFile );
@@ -208,26 +84,31 @@ private Context runJar(String jarName, String[] args, ArrayList<String> classpat
208
84
}
209
85
}
210
86
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 () );
213
89
return run (appClassLoader , joinClassPath (classpath ), mainClass , args , properties );
214
90
}
215
91
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 {
217
98
List <URL > urls = toUrls (classpath );
218
99
URL [] urlArray = urls .toArray (new URL [urls .size ()]);
219
100
return new AppClassLoader (urlArray , parent );
220
101
}
221
102
222
- private static List <URL > toUrls (Iterable <String > classpath ) throws MalformedURLException {
103
+ private List <URL > toUrls (Iterable <String > classpath ) throws MalformedURLException {
223
104
ArrayList <URL > urls = new ArrayList <>();
224
105
for (String path : classpath ) {
225
106
urls .add (toUrl (path ));
226
107
}
227
108
return urls ;
228
109
}
229
110
230
- private static void runMain (Class <?> klass , String [] args ) throws Throwable {
111
+ protected void runMain (Class <?> klass , String [] args ) throws Throwable {
231
112
Method main = klass .getMethod ("main" , String [].class );
232
113
try {
233
114
main .invoke (null , new Object []{args });
@@ -236,18 +117,15 @@ private static void runMain(Class<?> klass, String[] args) throws Throwable {
236
117
}
237
118
}
238
119
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 );
245
125
}
246
-
247
- return (OsvSystemClassLoader ) systemClassLoader ;
248
126
}
249
127
250
- private static String joinClassPath (Iterable <String > classpath ) {
128
+ private String joinClassPath (Iterable <String > classpath ) {
251
129
StringBuilder sb = new StringBuilder ();
252
130
boolean first = true ;
253
131
for (String path : classpath ) {
@@ -260,29 +138,21 @@ private static String joinClassPath(Iterable<String> classpath) {
260
138
return sb .toString ();
261
139
}
262
140
263
- private static URL toUrl (String path ) throws MalformedURLException {
141
+ private URL toUrl (String path ) throws MalformedURLException {
264
142
return new URL ("file:///" + path + (isDirectory (path ) ? "/" : "" ));
265
143
}
266
144
267
- private static boolean isDirectory (String path ) {
145
+ private boolean isDirectory (String path ) {
268
146
return new File (path ).isDirectory ();
269
147
}
270
148
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
-
279
149
// Expand classpath, as given in the "-classpath" option, to a list of
280
150
// jars or directories. As in the traditional "java" command-line
281
151
// launcher, components of the class path are separated by ":", and
282
152
// we also support the traditional (but awkward) Java wildcard syntax,
283
153
// where "dir/*" adds to the classpath all jar files in the given
284
154
// directory.
285
- private static Iterable <String > expandClassPath (String classpath ) {
155
+ private Iterable <String > expandClassPath (String classpath ) {
286
156
ArrayList <String > ret = new ArrayList <>();
287
157
for (String component : classpath .split (":" )) {
288
158
if (component .endsWith ("/*" )) {
@@ -307,10 +177,6 @@ private static Iterable<String> expandClassPath(String classpath) {
307
177
return ret ;
308
178
}
309
179
310
- public Object receive () throws InterruptedException {
311
- return getContext ().takeMessage ();
312
- }
313
-
314
180
private static class AppClassLoader extends URLClassLoader {
315
181
public AppClassLoader (URL [] urlArray , ClassLoader parent ) {
316
182
super (urlArray , parent );
@@ -324,5 +190,4 @@ protected PermissionCollection getPermissions(CodeSource codesource) {
324
190
return permissions ;
325
191
}
326
192
}
327
-
328
193
}
0 commit comments