42 |
import java.net.MalformedURLException; |
import java.net.MalformedURLException; |
43 |
import java.net.URL; |
import java.net.URL; |
44 |
import java.util.StringTokenizer; |
import java.util.StringTokenizer; |
45 |
|
import java.util.Vector; |
46 |
import java.util.zip.ZipFile; |
import java.util.zip.ZipFile; |
47 |
import java.util.zip.ZipEntry; |
import java.util.zip.ZipEntry; |
48 |
|
import gnu.java.io.PlatformHelper; |
49 |
|
import gnu.java.net.protocol.jar.JarURLConnection.JarFileCache; |
50 |
|
|
51 |
/** |
/** |
52 |
* The default system class loader. VMs may wish to replace this with a |
* The default system class loader. VMs may wish to replace this with a |
68 |
/** Flag to avoid infinite loops. */ |
/** Flag to avoid infinite loops. */ |
69 |
private static boolean is_trying; |
private static boolean is_trying; |
70 |
|
|
71 |
|
/** value of classpath property */ |
72 |
|
private static String classpath = null; |
73 |
|
|
74 |
|
/** A vector contains information for each path in classpath, |
75 |
|
* the item of the vector can be: |
76 |
|
* null: if corresponding path isn't valid; |
77 |
|
* ZipFile object: if corresponding path is a zip/jar file; |
78 |
|
* String object: if corresponding path is a directory. |
79 |
|
*/ |
80 |
|
private static Vector pathinfos = new Vector(); |
81 |
|
|
82 |
/** |
/** |
83 |
* Creates a class loader. Note that the parent may be null, when this is |
* Creates a class loader. Note that the parent may be null, when this is |
84 |
* created as the system class loader by ClassLoader.getSystemClassLoader. |
* created as the system class loader by ClassLoader.getSystemClassLoader. |
111 |
{ |
{ |
112 |
if (name.charAt(0) == '/') |
if (name.charAt(0) == '/') |
113 |
name = name.substring(1); |
name = name.substring(1); |
114 |
|
|
115 |
String cp = System.getProperty("java.class.path", "."); |
String cp = System.getProperty("java.class.path", "."); |
116 |
StringTokenizer st = new StringTokenizer(cp, File.pathSeparator); |
|
117 |
while (st.hasMoreTokens()) |
Vector bak_pathinfos = null; // the backup of pathinfos |
118 |
|
|
119 |
|
/* if is_trying is true, it's called recursively and in |
120 |
|
* a transient status, so we backup pathinfos into a temp |
121 |
|
* variable, and when all are done, restore pathinfos to |
122 |
|
* backup state. That means, this call won't persistent |
123 |
|
* its state, it's just a fall through to get out of |
124 |
|
* transient state. And when next time it's called again |
125 |
|
* and is_trying is false, pathinfos will be re-calculated. |
126 |
|
*/ |
127 |
|
if (is_trying) |
128 |
{ |
{ |
129 |
String path = st.nextToken(); |
bak_pathinfos = pathinfos; |
130 |
if (path.toLowerCase().endsWith(".zip") || |
pathinfos = new Vector(); |
131 |
path.toLowerCase().endsWith(".jar")) |
} |
132 |
{ |
|
133 |
if (is_trying) // Avoid infinite loop. |
// if classpath property has been changed |
134 |
continue; |
if (!cp.equals(classpath)) |
135 |
File f = new File(path); |
{ |
136 |
if (! f.exists()) |
pathinfos.clear(); |
137 |
continue; |
StringTokenizer st = new StringTokenizer(cp, File.pathSeparator); |
138 |
path = f.getAbsolutePath(); |
while (st.hasMoreTokens()) |
139 |
ZipFile zf; |
{ |
140 |
try |
String path = st.nextToken(); |
141 |
{ |
// check if path exists, if not, cache failure |
142 |
synchronized (NO_SUCH_ARCHIVE) |
File f = new File(path); |
143 |
{ |
if(!f.exists()) |
144 |
is_trying = true; |
{ |
145 |
zf = gnu.java.net.protocol.jar.JarURLConnection |
pathinfos.add(null); |
146 |
.JarFileCache.get(new URL("file://" + path)); |
continue; |
147 |
is_trying = false; |
} |
148 |
} |
|
149 |
if (zf == null) |
String lc_path = path.toLowerCase(); |
150 |
continue; |
path = f.getAbsolutePath(); |
151 |
} |
|
152 |
catch (Exception e) |
if (lc_path.endsWith(".zip") || |
153 |
{ |
lc_path.endsWith(".jar")) //whether it's zip/jar file |
154 |
continue; |
{ |
155 |
} |
if (is_trying) // Avoid infinite loop. |
156 |
|
continue; |
157 |
|
|
158 |
|
path = f.getAbsolutePath(); |
159 |
|
ZipFile zf; |
160 |
|
try |
161 |
|
{ |
162 |
|
// Construct URL object for the parth |
163 |
|
StringBuffer sb = |
164 |
|
new StringBuffer(PlatformHelper.INITIAL_MAX_PATH); |
165 |
|
sb.append("file://"); |
166 |
|
sb.append(path); |
167 |
|
URL url = new URL(sb.toString()); |
168 |
|
// class-level critical section |
169 |
|
synchronized (NO_SUCH_ARCHIVE) |
170 |
|
{ |
171 |
|
is_trying = true; |
172 |
|
zf = JarFileCache.get(url); |
173 |
|
is_trying = false; |
174 |
|
} |
175 |
|
} |
176 |
|
catch (Exception e) |
177 |
|
{ |
178 |
|
zf = null; |
179 |
|
} |
180 |
|
pathinfos.add(zf); |
181 |
|
} |
182 |
|
else //not zip/jar file |
183 |
|
{ |
184 |
|
if ( !PlatformHelper.endWithSeparator(path) ) |
185 |
|
pathinfos.add(path + File.separator); |
186 |
|
else |
187 |
|
pathinfos.add(path); |
188 |
|
} |
189 |
|
} // while more paths |
190 |
|
} // if classpath property has been changed |
191 |
|
|
192 |
|
URL result = null; |
193 |
|
for (int i = 0; i < pathinfos.size(); i++) |
194 |
|
{ |
195 |
|
Object o = pathinfos.elementAt(i); |
196 |
|
if (o == null ) |
197 |
|
continue; //it's not a valid path |
198 |
|
|
199 |
|
if (o instanceof ZipFile) |
200 |
|
{ //it's a zip/jar file |
201 |
|
ZipFile zf = (ZipFile)o; |
202 |
ZipEntry ze = zf.getEntry(name); |
ZipEntry ze = zf.getEntry(name); |
203 |
|
|
204 |
|
// if the resource doesn't reside in this zip/jar file |
205 |
if (ze == null) |
if (ze == null) |
206 |
continue; |
continue; |
207 |
|
|
208 |
try |
try |
209 |
{ |
{ |
210 |
if (path.charAt(0) == '/') |
StringBuffer sb = |
211 |
return new URL("jar:file:/" + path + "!/" + name); |
new StringBuffer(PlatformHelper.INITIAL_MAX_PATH); |
212 |
else |
sb.append("jar:file://"); |
213 |
return new URL("jar:file://" + path + "!/" + name); |
sb.append(zf.getName()); |
214 |
|
sb.append("!/"); |
215 |
|
sb.append(name); |
216 |
|
result = new URL(sb.toString()); |
217 |
} |
} |
218 |
catch (MalformedURLException e) |
catch (MalformedURLException e) |
219 |
{ |
{ |
220 |
continue; |
result = null; |
221 |
} |
} |
222 |
|
break; |
223 |
} |
} |
224 |
File f; |
// otherwise o is string |
225 |
if (path.endsWith(File.separator)) |
String path = (String)o; |
226 |
f = new File(path + name); |
File f = new File(path + name); |
|
else |
|
|
f = new File(path + File.separator + name); |
|
|
|
|
227 |
if (f.exists()) |
if (f.exists()) |
228 |
try |
{ |
229 |
{ |
try |
230 |
return new URL("file://" + f.getAbsolutePath()); |
{ |
231 |
} |
result = new URL("file://" + f.getAbsolutePath()); |
232 |
catch (MalformedURLException e) |
} |
233 |
{ |
catch (MalformedURLException e) |
234 |
continue; |
{ |
235 |
} |
result = null; |
236 |
|
} |
237 |
|
break; |
238 |
|
} |
239 |
|
} //for each paths |
240 |
|
|
241 |
|
// Restore pathinfos |
242 |
|
if (is_trying) |
243 |
|
{ |
244 |
|
pathinfos = bak_pathinfos; |
245 |
} |
} |
246 |
return null; |
else |
247 |
} |
{ |
248 |
|
/* update classpath, hopefully next time classpath is |
249 |
|
* not changed, so pathinfos will not be re-calcualted. |
250 |
|
*/ |
251 |
|
classpath = cp; |
252 |
|
} |
253 |
|
|
254 |
|
return result; |
255 |
|
|
256 |
|
} //End of systemGetResource |
257 |
|
|
258 |
} |
} |