| 1 | /* Copyright (C) 1999, 2000 Free Software Foundation
|
|---|
| 2 |
|
|---|
| 3 | This file is part of libgcj.
|
|---|
| 4 |
|
|---|
| 5 | This software is copyrighted work licensed under the terms of the
|
|---|
| 6 | Libgcj License. Please consult the file "LIBGCJ_LICENSE" for
|
|---|
| 7 | details. */
|
|---|
| 8 |
|
|---|
| 9 | package java.net;
|
|---|
| 10 |
|
|---|
| 11 | import java.io.*;
|
|---|
| 12 | import java.util.jar.*;
|
|---|
| 13 | import java.util.Enumeration;
|
|---|
| 14 | import java.util.Vector;
|
|---|
| 15 |
|
|---|
| 16 | public class URLClassLoader extends ClassLoader
|
|---|
| 17 | {
|
|---|
| 18 | // The URLStreamHandlerFactory
|
|---|
| 19 | URLStreamHandlerFactory factory = null;
|
|---|
| 20 |
|
|---|
| 21 | // `path' contains simply the URL's we're using for the searching.
|
|---|
| 22 | private Vector path;
|
|---|
| 23 |
|
|---|
| 24 | // If path[n] is a zip/jar, then this holds a JarURLConnection for
|
|---|
| 25 | // that thing, otherwise, path[n] is null.
|
|---|
| 26 | private Vector info;
|
|---|
| 27 |
|
|---|
| 28 | private URLStreamHandler getHandler0 (String protocol)
|
|---|
| 29 | {
|
|---|
| 30 | if (factory != null)
|
|---|
| 31 | return factory.createURLStreamHandler(protocol);
|
|---|
| 32 | else
|
|---|
| 33 | return null;
|
|---|
| 34 | }
|
|---|
| 35 |
|
|---|
| 36 | public URLClassLoader (URL[] urls)
|
|---|
| 37 | {
|
|---|
| 38 | this (urls, null, null);
|
|---|
| 39 | }
|
|---|
| 40 |
|
|---|
| 41 | public URLClassLoader (URL[] urls, ClassLoader parent)
|
|---|
| 42 | {
|
|---|
| 43 | this (urls, parent, null);
|
|---|
| 44 | }
|
|---|
| 45 |
|
|---|
| 46 | // A File URL may actually be a Jar URL. Convert if possible.
|
|---|
| 47 | private URL jarFileize (URL url)
|
|---|
| 48 | {
|
|---|
| 49 | if (! url.getProtocol ().equals ("jar"))
|
|---|
| 50 | {
|
|---|
| 51 | String f = url.getFile ();
|
|---|
| 52 |
|
|---|
| 53 | // If it ends with '/' we'll take it for a directory,
|
|---|
| 54 | // otherwise it's a jar file. This is how JDK 1.2 defines
|
|---|
| 55 | // it, so we will not try to be smart here.
|
|---|
| 56 | if (f.charAt (f.length ()-1) != '/')
|
|---|
| 57 | {
|
|---|
| 58 | try
|
|---|
| 59 | {
|
|---|
| 60 | url = new URL ("jar", "", -1, (url.toExternalForm ())+"!/",
|
|---|
| 61 | getHandler0 ("jar"));
|
|---|
| 62 | }
|
|---|
| 63 | catch (MalformedURLException x)
|
|---|
| 64 | {
|
|---|
| 65 | /* ignore */
|
|---|
| 66 | }
|
|---|
| 67 | }
|
|---|
| 68 | }
|
|---|
| 69 | return url;
|
|---|
| 70 | }
|
|---|
| 71 |
|
|---|
| 72 | protected void addURL (URL url)
|
|---|
| 73 | {
|
|---|
| 74 | JarURLConnection conn = null;
|
|---|
| 75 |
|
|---|
| 76 | // Convert a Jar File URL into Jar URL if possible.
|
|---|
| 77 | url = jarFileize (url);
|
|---|
| 78 |
|
|---|
| 79 | path.addElement (url);
|
|---|
| 80 |
|
|---|
| 81 | if (url.getProtocol ().equals ("jar"))
|
|---|
| 82 | {
|
|---|
| 83 | try
|
|---|
| 84 | {
|
|---|
| 85 | conn = (JarURLConnection) url.openConnection ();
|
|---|
| 86 | }
|
|---|
| 87 | catch (java.io.IOException x)
|
|---|
| 88 | {
|
|---|
| 89 | /* ignore */
|
|---|
| 90 | }
|
|---|
| 91 | }
|
|---|
| 92 |
|
|---|
| 93 | info.addElement (conn);
|
|---|
| 94 | }
|
|---|
| 95 |
|
|---|
| 96 | public URLClassLoader (URL[] urls, ClassLoader parent,
|
|---|
| 97 | URLStreamHandlerFactory fac)
|
|---|
| 98 | {
|
|---|
| 99 | super (parent);
|
|---|
| 100 |
|
|---|
| 101 | factory = fac;
|
|---|
| 102 |
|
|---|
| 103 | if (urls == null || urls.length == 0)
|
|---|
| 104 | {
|
|---|
| 105 | path = new Vector (1);
|
|---|
| 106 | info = new Vector (1);
|
|---|
| 107 | return;
|
|---|
| 108 | }
|
|---|
| 109 |
|
|---|
| 110 | path = new Vector (urls.length);
|
|---|
| 111 | info = new Vector (urls.length);
|
|---|
| 112 |
|
|---|
| 113 | for (int i = 0; i < urls.length; i++)
|
|---|
| 114 | {
|
|---|
| 115 | // Convert a Jar File URL into a Jar URL is possible.
|
|---|
| 116 | URL u = jarFileize(urls[i]);
|
|---|
| 117 |
|
|---|
| 118 | path.addElement (u);
|
|---|
| 119 |
|
|---|
| 120 | if (u.getProtocol ().equals ("jar"))
|
|---|
| 121 | {
|
|---|
| 122 | JarURLConnection conn = null;
|
|---|
| 123 | try
|
|---|
| 124 | {
|
|---|
| 125 | conn = (JarURLConnection) u.openConnection ();
|
|---|
| 126 | }
|
|---|
| 127 | catch (java.io.IOException x)
|
|---|
| 128 | {
|
|---|
| 129 | /* ignore */
|
|---|
| 130 | }
|
|---|
| 131 | info.addElement (conn);
|
|---|
| 132 | }
|
|---|
| 133 | else
|
|---|
| 134 | {
|
|---|
| 135 | info.addElement (null);
|
|---|
| 136 | }
|
|---|
| 137 | }
|
|---|
| 138 | }
|
|---|
| 139 |
|
|---|
| 140 | public URL[] getURLs ()
|
|---|
| 141 | {
|
|---|
| 142 | URL[] urls = new URL[path.size()];
|
|---|
| 143 | path.copyInto (urls);
|
|---|
| 144 | return urls;
|
|---|
| 145 | }
|
|---|
| 146 |
|
|---|
| 147 | public Enumeration findResources (String name)
|
|---|
| 148 | {
|
|---|
| 149 | Vector results = new Vector ();
|
|---|
| 150 |
|
|---|
| 151 | for (int i = 0; i < path.size(); i++)
|
|---|
| 152 | {
|
|---|
| 153 | URL u = (URL)path.elementAt (i);
|
|---|
| 154 |
|
|---|
| 155 | try {
|
|---|
| 156 | JarURLConnection conn = (JarURLConnection) info.elementAt (i);
|
|---|
| 157 |
|
|---|
| 158 | if (conn != null)
|
|---|
| 159 | {
|
|---|
| 160 | if (conn.getJarFile().getJarEntry (name) != null)
|
|---|
| 161 | results.addElement (new URL(u, name, getHandler0 (u.getProtocol())));
|
|---|
| 162 | }
|
|---|
| 163 | else
|
|---|
| 164 | {
|
|---|
| 165 | URL p = new URL (u, name, getHandler0 (u.getProtocol()));
|
|---|
| 166 |
|
|---|
| 167 | InputStream is = p.openStream();
|
|---|
| 168 | if (is != null)
|
|---|
| 169 | {
|
|---|
| 170 | is.close();
|
|---|
| 171 | results.addElement (p);
|
|---|
| 172 | }
|
|---|
| 173 | }
|
|---|
| 174 |
|
|---|
| 175 | // if we get an exception ... try the next path element
|
|---|
| 176 | } catch (IOException x) {
|
|---|
| 177 | continue;
|
|---|
| 178 | }
|
|---|
| 179 | }
|
|---|
| 180 |
|
|---|
| 181 | return results.elements ();
|
|---|
| 182 | }
|
|---|
| 183 |
|
|---|
| 184 | public URL findResource (String name)
|
|---|
| 185 | {
|
|---|
| 186 | for (int i = 0; i < path.size(); i++)
|
|---|
| 187 | {
|
|---|
| 188 | URL u = (URL)path.elementAt (i);
|
|---|
| 189 |
|
|---|
| 190 | try {
|
|---|
| 191 | JarURLConnection conn = (JarURLConnection) info.elementAt (i);
|
|---|
| 192 |
|
|---|
| 193 | if (conn != null)
|
|---|
| 194 | {
|
|---|
| 195 | if (conn.getJarFile().getJarEntry (name) != null)
|
|---|
| 196 | return new URL(u, name, getHandler0 (u.getProtocol()));
|
|---|
| 197 | }
|
|---|
| 198 | else
|
|---|
| 199 | {
|
|---|
| 200 | URL p = new URL (u, name, getHandler0 (u.getProtocol()));
|
|---|
| 201 |
|
|---|
| 202 | InputStream is = p.openStream();
|
|---|
| 203 | if (is != null)
|
|---|
| 204 | {
|
|---|
| 205 | is.close();
|
|---|
| 206 | return p;
|
|---|
| 207 | }
|
|---|
| 208 | }
|
|---|
| 209 |
|
|---|
| 210 | // if we get an exception ... try the next path element
|
|---|
| 211 | } catch (IOException x) {
|
|---|
| 212 | continue;
|
|---|
| 213 | }
|
|---|
| 214 | }
|
|---|
| 215 |
|
|---|
| 216 | return null;
|
|---|
| 217 | }
|
|---|
| 218 |
|
|---|
| 219 | // and finally, we can implement our class loader functionality.
|
|---|
| 220 | protected Class findClass (String name)
|
|---|
| 221 | throws ClassNotFoundException
|
|---|
| 222 | {
|
|---|
| 223 | if (name == null)
|
|---|
| 224 | throw new ClassNotFoundException ("null");
|
|---|
| 225 |
|
|---|
| 226 | try
|
|---|
| 227 | {
|
|---|
| 228 | URL u = getResource (name.replace ('.', '/') + ".class");
|
|---|
| 229 |
|
|---|
| 230 | if (u == null)
|
|---|
| 231 | throw new ClassNotFoundException (name);
|
|---|
| 232 |
|
|---|
| 233 | URLConnection connection = u.openConnection ();
|
|---|
| 234 | InputStream is = connection.getInputStream ();
|
|---|
| 235 |
|
|---|
| 236 | int len = connection.getContentLength ();
|
|---|
| 237 | byte[] data = new byte[len];
|
|---|
| 238 |
|
|---|
| 239 | int left = len;
|
|---|
| 240 | int off = 0;
|
|---|
| 241 | while (left > 0)
|
|---|
| 242 | {
|
|---|
| 243 | int c = is.read (data, off, len-off);
|
|---|
| 244 | if (c == -1 || c == 0)
|
|---|
| 245 | throw new InternalError ("premature end of file");
|
|---|
| 246 | left -= c;
|
|---|
| 247 | off += c;
|
|---|
| 248 | }
|
|---|
| 249 |
|
|---|
| 250 | return defineClass (name, data, 0, len);
|
|---|
| 251 | }
|
|---|
| 252 | catch (java.io.IOException x)
|
|---|
| 253 | {
|
|---|
| 254 | throw new ClassNotFoundException(name);
|
|---|
| 255 | }
|
|---|
| 256 | }
|
|---|
| 257 | }
|
|---|
| 258 |
|
|---|