1 package org.codehaus.classworlds;
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49 import java.io.ByteArrayOutputStream;
50 import java.io.DataInputStream;
51 import java.io.IOException;
52 import java.net.MalformedURLException;
53 import java.net.URL;
54 import java.net.URLClassLoader;
55 import java.util.Enumeration;
56
57 /*** Classloader for <code>ClassRealm</code>s.
58 *
59 * @author <a href="mailto:bob@eng.werken.com">bob mcwhirter</a>
60 *
61 * @version $Id: RealmClassLoader.java,v 1.3 2004/07/06 17:37:36 dandiep Exp $
62 */
63 class RealmClassLoader
64 extends URLClassLoader
65 {
66
67
68
69
70 /*** The realm. */
71 protected DefaultClassRealm realm;
72
73
74
75
76
77 /*** Construct.
78 *
79 * @param realm The realm for which this loads.
80 */
81 RealmClassLoader(DefaultClassRealm realm)
82 {
83 this( realm, null );
84 }
85
86 /*** Construct.
87 *
88 * @param realm The realm for which this loads.
89 *
90 * @param classLoader The parent ClassLoader.
91 */
92 RealmClassLoader(DefaultClassRealm realm, ClassLoader classLoader)
93 {
94 super( new URL[0], classLoader );
95 this.realm = realm;
96 }
97
98
99
100
101
102 /*** Retrieve the realm.
103 *
104 * @return The realm.
105 */
106 DefaultClassRealm getRealm()
107 {
108 return this.realm;
109 }
110
111 /*** Add a constituent to this realm for locating classes.
112 * If the url definition ends in .class its a BytesURLStreamHandler
113 * so use defineClass insead. addURL is still called for byte[]
114 * even though it has no affect and we use defineClass instead,
115 * this is for consistentency and to allow access to the class
116 * with getURLs()
117 *
118 * @param constituent URL to contituent jar or directory.
119 */
120 void addConstituent(URL constituent)
121 {
122 String urlStr = constituent.toExternalForm();
123 if (!urlStr.endsWith(".class"))
124 {
125 if ( urlStr.startsWith( "jar:" )
126 &&
127 urlStr.endsWith( "!/" ) )
128 {
129 urlStr = urlStr.substring( 4,
130 urlStr.length() - 2 );
131
132 try
133 {
134 constituent = new URL( urlStr );
135 }
136 catch (MalformedURLException e)
137 {
138 e.printStackTrace();
139 }
140 }
141
142 addURL( constituent );
143 }
144 else
145 {
146 try
147 {
148 byte[] b = getBytesToEndOfStream( new DataInputStream( constituent.openStream() ) );
149 int start = urlStr.lastIndexOf("byteclass") + 10;
150 int end = urlStr.lastIndexOf(".class");
151
152 String className = urlStr.substring(start, end);
153
154 super.defineClass(className, b, 0, b.length);
155
156 addURL(constituent);
157 }
158 catch (IOException e)
159 {
160 e.printStackTrace();
161 }
162 }
163 }
164
165
166 /***
167 * Helper method for addConstituent that reads in a DataInputStream and returns it as a byte[]
168 * It attempts to use in.available - the size of the file - else defaults to 2048
169 */
170 public byte[] getBytesToEndOfStream(DataInputStream in) throws IOException
171 {
172 final int chunkSize = (in.available() > 0) ? in.available() : 2048;
173 byte[] buf = new byte[chunkSize];
174 ByteArrayOutputStream byteStream = new ByteArrayOutputStream(chunkSize);
175 int count;
176
177 while ((count=in.read(buf)) != -1)
178 {
179 byteStream.write(buf, 0, count);
180 }
181 return byteStream.toByteArray();
182 }
183
184 /*** Load a class directly from this classloader without
185 * defering through any other <code>ClassRealm</code>.
186 *
187 * @param name The name of the class to load.
188 *
189 * @return The loaded class.
190 *
191 * @throws ClassNotFoundException If the class could not be found.
192 */
193 Class loadClassDirect(String name) throws ClassNotFoundException
194 {
195 return super.loadClass( name, true );
196 }
197
198
199
200
201
202 /*** Load a class.
203 *
204 * @param name The name of the class to load.
205 * @param resolve If <code>true</code> then resolve the class.
206 *
207 * @return The loaded class.
208 *
209 * @throws ClassNotFoundException If the class cannot be found.
210 */
211 protected Class loadClass(String name,
212 boolean resolve) throws ClassNotFoundException
213 {
214 return getRealm().loadClass( name );
215 }
216
217 /*** Retrieve the <code>URL</code>s used by this <code>ClassLoader</code>.
218 *
219 * @return The urls.
220 */
221 public URL[] getURLs()
222 {
223 return super.getURLs();
224 }
225
226 /*** Find a resource within this ClassLoader only (don't delegate to the parent).
227 *
228 * @return The resource.
229 */
230 public URL findResource( String name )
231 {
232 return super.findResource( name );
233 }
234
235 public URL getResource(String name)
236 {
237 return getRealm().getResource( name );
238 }
239
240 /*** Get a resource from this ClassLoader, and don't search the realm.
241 * Otherwise we'd recurse indefinitely.
242 *
243 * @return The resource.
244 */
245 public URL getResourceDirect(String name)
246 {
247 return super.getResource( name );
248 }
249
250 public Enumeration findResources(String name) throws IOException
251 {
252 return getRealm().findResources( name );
253 }
254
255 /*** Find resources from this ClassLoader, and don't search the realm.
256 * Otherwise we'd recurse indefinitely.
257 *
258 * @return The resource.
259 */
260 public Enumeration findResourcesDirect(String name)
261 throws IOException
262 {
263 return super.findResources( name );
264 }
265 }