1 9 package org.jboss.remoting.loading; 10 11 import java.io.File ; 12 import java.io.FileOutputStream ; 13 import java.io.IOException ; 14 import java.io.OutputStream ; 15 import java.lang.ref.Reference ; 16 import java.lang.ref.ReferenceQueue ; 17 import java.lang.ref.WeakReference ; 18 import java.util.Collections ; 19 import java.util.HashMap ; 20 import java.util.Map ; 21 import org.jboss.logging.Logger; 22 import org.jboss.remoting.Client; 23 24 32 public class ClassByteClassLoader extends ClassLoader 33 { 34 private static final Logger log = Logger.getLogger(ClassByteClassLoader.class); 35 private final Map loadedClasses = Collections.synchronizedMap(new java.util.HashMap ()); 36 private final Map loadedResources = Collections.synchronizedMap(new java.util.HashMap ()); 37 private final ReferenceQueue queue = new ReferenceQueue (); 38 39 private Client loaderClient = null; 40 41 public ClassByteClassLoader() 42 { 43 super(); 44 } 45 46 public ClassByteClassLoader(ClassLoader parent) 47 { 48 super(parent); 49 } 50 51 public void setClientInvoker(Client loaderClient) 52 { 53 this.loaderClient = loaderClient; 54 } 55 56 59 public void destroy() 60 { 61 if(loaderClient != null && loaderClient.isConnected()) 62 { 63 loaderClient.disconnect(); 64 } 65 } 66 67 72 private final class MyRef extends WeakReference 73 { 74 private final String key; 75 76 MyRef(String key, Object obj) 77 { 78 super(obj); 79 this.key = key; 80 } 81 } 82 83 87 private void clean(MyRef myref) 88 { 89 loadedClasses.remove(myref.key); 90 File f = (File ) loadedResources.remove(myref.key); 91 if(f != null) 92 { 93 f.delete(); 94 } 95 myref.clear(); 96 myref = null; 97 } 98 99 103 private void performMaintenance() 104 { 105 int count = 0; 106 Reference ref = null; 107 while((ref = queue.poll()) != null) 108 { 109 count++; 110 MyRef myref = (MyRef) ref; 111 clean(myref); 112 } 113 114 if(count > 0 && log.isTraceEnabled()) 115 { 116 log.trace("ClassByteClassLoader reclaimed " + count + " objects"); 117 } 118 } 119 120 121 public String toString() 122 { 123 return "ClassByteClassLoader [" + loadedClasses + "]"; 124 } 125 126 protected void finalize() throws Throwable 127 { 128 performMaintenance(); 130 131 java.util.Iterator iter = loadedResources.values().iterator(); 132 while(iter.hasNext()) 133 { 134 ((java.io.File ) iter.next()).delete(); 135 } 136 loadedResources.clear(); 137 loadedClasses.clear(); 138 super.finalize(); 139 } 140 141 public Class loadClass(String className, ClassBytes bytes[]) 142 throws ClassNotFoundException , java.io.IOException 143 { 144 performMaintenance(); 146 147 if(log.isTraceEnabled()) 148 { 149 log.trace("loadClass: " + className + ", bytes: " + bytes); 150 } 151 if(bytes != null) 152 { 153 for(int c = 0; c < bytes.length; c++) 154 { 155 addClass(bytes[c]); 156 } 157 } 158 Class cl = lookupCachedClass(className); 159 if(cl != null) 160 { 161 return cl; 162 } 163 cl = findLoadedClass(className); 164 if(cl != null) 165 { 166 return cl; 167 } 168 cl = ClassLoader.getSystemClassLoader().loadClass(className); 169 if(cl != null) 170 { 171 return cl; 172 } 173 cl = super.loadClass(className, true); 174 if(cl != null) 175 { 176 return cl; 177 } 178 cl = loadFromNetwork(className); 179 if(cl != null) 180 { 181 return cl; 182 } 183 throw new ClassNotFoundException ("Could not load class " + className); 184 } 185 186 private void addClassResource(String name, byte buf[]) 187 throws IOException 188 { 189 performMaintenance(); 191 192 OutputStream out = null; 193 File file = null; 194 try 195 { 196 file = File.createTempFile("cbc", ".class"); 197 file.deleteOnExit(); 198 if(log.isTraceEnabled()) 199 { 200 log.trace("adding resource at: " + name + " to file: " + file); 201 } 202 out = new FileOutputStream (file); 203 out.write(buf); 204 out.flush(); 205 } 206 catch(java.io.IOException ex) 207 { 208 file = null; 209 throw ex; 210 } 211 finally 212 { 213 if(out != null) 214 { 215 try 216 { 217 out.close(); 218 } 219 catch(Exception ig) 220 { 221 } 222 out = null; 223 } 224 if(file != null) 225 { 226 loadedResources.put(name, file); 227 } 228 } 229 } 230 231 public java.io.InputStream getResourceAsStream(String name) 232 { 233 performMaintenance(); 235 236 String denormalized = name.replace('/', '.').substring(0, name.length() - 6); 237 java.io.File file = (java.io.File ) loadedResources.get(denormalized); 238 if(log.isTraceEnabled()) 239 { 240 log.trace("getResourceAsStream =>" + denormalized + " = " + file); 241 } 242 if(file != null && file.exists()) 243 { 244 try 245 { 246 return new java.io.BufferedInputStream (new java.io.FileInputStream (file)); 247 } 248 catch(Exception ex) 249 { 250 251 } 252 } 253 return super.getResourceAsStream(name); 254 } 255 256 public Class addClass(ClassBytes classBytes) 257 throws java.io.IOException 258 { 259 performMaintenance(); 261 262 Class cl = null; 263 String name = classBytes.getClassName(); 264 if(loadedClasses.containsKey(name) == false) 265 { 266 byte buf[] = classBytes.getClassBytes(); 267 boolean array = ClassUtil.isArrayClass(name); 268 String cn = (array) ? ClassUtil.getArrayClassPart(name) : name; 269 if(log.isTraceEnabled()) 270 { 271 log.trace(" add class: " + name + ", array?" + array + ", using as: " + cn); 272 } 273 cl = defineClass(cn, buf, 0, buf.length); 274 resolveClass(cl); 275 addClassResource(cn, buf); 276 loadedClasses.put(cn, new MyRef(cn, cl)); 277 } 278 return cl; 279 } 280 281 284 private Class lookupCachedClass(String cn) 285 { 286 Class cl = null; 287 MyRef ref = (MyRef) loadedClasses.get(cn); 288 if(ref != null) 289 { 290 cl = (Class ) ref.get(); 292 if(cl == null) 293 { 294 clean(ref); 296 } 297 } 298 return cl; 299 } 300 301 313 protected Class findClass(String name) throws ClassNotFoundException 314 { 315 performMaintenance(); 317 318 boolean array = ClassUtil.isArrayClass(name); 319 String cn = (array) ? ClassUtil.getArrayClassPart(name) : name; 320 if(log.isTraceEnabled()) 321 { 322 log.trace("++ loadClass: " + name + ", array?" + array + ", normalized: [" + cn + "]"); 323 } 324 Class cl = lookupCachedClass(cn); 325 if(cl == null) 327 { 328 cl = findLoadedClass(cn); 330 } 331 if(cl != null) 332 { 333 if(array) 334 { 335 Object obj = java.lang.reflect.Array.newInstance(cl, 1); 338 return obj.getClass(); 339 } 340 return cl; 341 } 342 343 cl = loadFromNetwork(cn); 344 if(cl != null) 345 { 346 if(log.isTraceEnabled()) 347 { 348 log.trace("Loaded " + cn + " can class is " + cl); 349 } 350 return cl; 351 } 352 353 354 if(log.isTraceEnabled()) 355 { 356 log.trace("++ findClass: " + name + " not found, throwing ClassNotFoundException"); 357 } 358 throw new ClassNotFoundException (name); 359 } 360 361 private Class loadFromNetwork(String className) 362 { 363 Class loadedClass = null; 364 365 if(loaderClient != null) 366 { 367 String marshallerMethodName = "load_class"; 368 Map metadata = new HashMap (); 369 metadata.put("classname", className); 370 371 try 372 { 373 Object obj = loaderClient.invoke(marshallerMethodName, metadata); 374 375 if(obj != null) 376 { 377 if(obj instanceof ClassBytes) 378 { 379 ClassBytes classBytes = (ClassBytes) obj; 380 String name = classBytes.getClassName(); 381 382 loadedClass = addClass(classBytes); 383 } 384 else 385 { 386 log.error("Can not load remote class bytes. Returned object (" + obj + ") is not ClassBytes."); 387 } 388 } 389 else 390 { 391 log.error("Can not load remote class bytes."); 392 } 393 } 394 catch(Throwable throwable) 395 { 396 log.error("Error loading remote class.", throwable); 397 } 398 } 399 else 400 { 401 log.trace("Remoting Client for ClassByteClassLoader is null. Can not load class remotely."); 402 } 403 404 return loadedClass; 405 } 406 } 407 | Popular Tags |