1
1
package org .perl6 .nqp .runtime ;
2
2
3
3
import java .io .ByteArrayInputStream ;
4
+ import java .io .ByteArrayOutputStream ;
4
5
import java .io .File ;
5
6
import java .io .IOException ;
6
7
import java .io .InputStream ;
10
11
import java .util .HashMap ;
11
12
import java .util .jar .JarEntry ;
12
13
import java .util .jar .JarInputStream ;
14
+ import java .net .URL ;
13
15
14
16
public class LibraryLoader {
15
17
static HashMap <String ,Class <?>> sharedClassHash = new HashMap <String ,Class <?>>();
16
18
17
19
public void load (ThreadContext tc , String origFilename ) {
20
+ String filename ;
21
+ if ( origFilename .indexOf ("!" ) != -1 ) {
22
+ filename = origFilename .substring (origFilename .lastIndexOf ("!" ) + 1 );
23
+ }
24
+ else {
25
+ filename = origFilename ;
26
+ }
18
27
// Don't load the same thing multiple times.
19
28
if (tc .gc .loaded .contains (origFilename ))
20
29
return ;
21
30
22
31
try {
23
32
// Read in class data.
24
- String filename = origFilename ;
25
33
File file = new File (filename );
26
34
if (!file .exists () && filename .equals ("ModuleLoader.class" )) {
27
35
/* We special case the initial ModuleLoader loading. */
28
36
String [] cps = System .getProperty ("java.class.path" ).split ("[:;]" );
29
37
for (int i = 0 ; i < cps .length ; i ++) {
38
+ if (System .getenv ("NQP_BUILD_DEBUG" ) != null )
39
+ System .out .println ("checking classpath: " + cps [i ]);
30
40
file = new File (cps [i ] + "/" + filename );
31
41
if (file .exists ()) {
32
42
filename = cps [i ] + "/" + filename ;
@@ -40,7 +50,36 @@ public void load(ThreadContext tc, String origFilename) {
40
50
}
41
51
}
42
52
43
- Class <?> c = loadFile (filename , tc .gc .sharingHint );
53
+ // TODO: untangle the logic somewhat...
54
+ // "the filename wasn't changed" is a bad metric for "we didn't find the right file"...
55
+ Class <?> c = null ;
56
+ if ( filename .equals ("ModuleLoader.class" ) ) {
57
+ if (System .getenv ("NQP_BUILD_DEBUG" ) != null )
58
+ System .out .println ("first branch" );
59
+ c = loadFile (LibraryLoader .class .getResource ("/lib/ModuleLoader.jar" ), tc .gc .sharingHint );
60
+ }
61
+ else if ( origFilename .indexOf ("!" ) != -1 || origFilename .indexOf (":" ) != -1 ) {
62
+ if (System .getenv ("NQP_BUILD_DEBUG" ) != null )
63
+ System .out .println ("second branch with " + origFilename );
64
+ c = loadFile (new URL (origFilename ), tc .gc .sharingHint );
65
+ }
66
+ else if ( !(new File (filename )).exists () ) {
67
+ if (System .getenv ("NQP_BUILD_DEBUG" ) != null )
68
+ System .out .println ("third branch, with " + origFilename );
69
+ URL res = LibraryLoader .class .getResource ("/lib/" + filename );
70
+ if ( res != null ) {
71
+ c = loadFile (res , tc .gc .sharingHint );
72
+ }
73
+ else {
74
+ res = LibraryLoader .class .getResource ("/lib/" + filename + ".jar" );
75
+ c = loadFile (res , tc .gc .sharingHint );
76
+ }
77
+ }
78
+ else {
79
+ if (System .getenv ("NQP_BUILD_DEBUG" ) != null )
80
+ System .out .println ("fourth branch, with " + origFilename );
81
+ c = loadFile (filename , tc .gc .sharingHint );
82
+ }
44
83
45
84
// Load the class.
46
85
CompilationUnit cu = (CompilationUnit )c .newInstance ();
@@ -60,31 +99,65 @@ public void load(ThreadContext tc, String origFilename) {
60
99
}
61
100
62
101
public static Class <?> loadFile (String cf , boolean shared ) throws Exception {
102
+ return loadFile (new URL ("file:" + cf ), shared );
103
+ }
104
+
105
+ public static Class <?> loadFile (URL cf , boolean shared ) throws Exception {
63
106
if (shared ) {
107
+ if (System .getenv ("NQP_BUILD_DEBUG" ) != null )
108
+ System .out .println ("cf is shared, " + cf );
64
109
synchronized (sharedClassHash ) {
65
- if (sharedClassHash .containsKey (cf ))
66
- return sharedClassHash .get (cf );
110
+ if (sharedClassHash .containsKey (cf . getPath () ))
111
+ return sharedClassHash .get (cf . getPath () );
67
112
68
113
Class <?> n = loadFile (cf , false );
69
- sharedClassHash .put (cf , n );
114
+ sharedClassHash .put (cf . getPath () , n );
70
115
return n ;
71
116
}
72
117
}
73
118
74
- byte [] b = Files .readAllBytes ( FileSystems .getDefault ().getPath (cf ) );
75
- long sig = b .length < 4 ? 0 :
76
- (b [3 ] & 0xFF ) | ((b [2 ] & 0xFF ) << 8 ) | ((b [1 ] & 0xFF ) << 16 ) | ((b [0 ] & 0xFFL ) << 24 );
119
+ byte [] bs = null ;
120
+
121
+ if (System .getenv ("NQP_BUILD_DEBUG" ) != null )
122
+ System .out .println ("cf is " + cf );
123
+ if (cf .getProtocol ().equals ("jar" )) {
124
+ // XXX: this is a bit gnarly, currently.
125
+ // basically, before we only ever loaded files from disk, but self-executable jars
126
+ // have our libs as jar inside of a jar, and getResource gets us an URL
127
+ // so instead of properly untangling this i'm taking a shortcut (for now)
128
+ // and assume that URLs always point to jars, so we read the resource instead
129
+ // of reading the file
130
+ String res = cf .getPath ();
131
+ res = res .substring (res .lastIndexOf ("!" ) + 1 );
132
+ InputStream is = LibraryLoader .class .getResourceAsStream (res );
133
+ if (is == null ) {
134
+ throw new RuntimeException ("Couldn't find resource " + res );
135
+ }
136
+ ByteArrayOutputStream baos = new ByteArrayOutputStream ();
137
+ int b = is .read ();
138
+ while ( b != -1 ) {
139
+ baos .write (b );
140
+ b = is .read ();
141
+ }
142
+ bs = baos .toByteArray ();
143
+ }
144
+ else {
145
+ bs = Files .readAllBytes ( FileSystems .getDefault ().getPath (cf .getPath ()) );
146
+ }
147
+
148
+ long sig = bs .length < 4 ? 0 :
149
+ (bs [3 ] & 0xFF ) | ((bs [2 ] & 0xFF ) << 8 ) | ((bs [1 ] & 0xFF ) << 16 ) | ((bs [0 ] & 0xFFL ) << 24 );
77
150
78
151
if (sig == 0xCAFEBABEL ) {
79
152
// This is a class file
80
153
81
- return loadNew (b , null );
154
+ return loadNew (bs , null );
82
155
} else if (sig == 0x504B0304 ) {
83
156
// This is a (non-empty, non-self-extracting) zip file
84
157
// These are quite constrained for now
85
158
86
159
JarEntry je ;
87
- JarInputStream jis = new JarInputStream (new ByteArrayInputStream (b ));
160
+ JarInputStream jis = new JarInputStream (new ByteArrayInputStream (bs ));
88
161
byte [] kl = null ;
89
162
byte [] ser = null ;
90
163
@@ -106,14 +179,15 @@ public static Class<?> loadFile(String cf, boolean shared) throws Exception {
106
179
}
107
180
108
181
public static Class <?> loadNew (byte [] bytes , byte [] serial ) {
109
- return new IgnoreNameClassLoader (bytes , serial ).loadClass ();
182
+ return new IgnoreNameClassLoader (bytes , serial , LibraryLoader . class . getClassLoader () ).loadClass ();
110
183
}
111
184
112
185
private static class IgnoreNameClassLoader extends ClassLoader {
113
186
private byte [] bytes ;
114
187
private byte [] serial ;
115
188
116
- public IgnoreNameClassLoader (byte [] bytes , byte [] serial ) {
189
+ public IgnoreNameClassLoader (byte [] bytes , byte [] serial , ClassLoader parent ) {
190
+ super (parent );
117
191
this .bytes = bytes ;
118
192
this .serial = serial ;
119
193
}
0 commit comments