1 25 26 package org.objectweb.easybeans.loader; 27 28 import java.io.File ; 29 import java.io.FileOutputStream ; 30 import java.io.IOException ; 31 import java.lang.reflect.InvocationTargetException ; 32 import java.lang.reflect.Method ; 33 import java.net.URL ; 34 import java.net.URLClassLoader ; 35 import java.util.HashMap ; 36 import java.util.Map ; 37 38 import org.objectweb.easybeans.log.JLog; 39 import org.objectweb.easybeans.log.JLogFactory; 40 41 47 public class EasyBeansClassLoader extends URLClassLoader implements Cloneable { 48 49 52 private static JLog logger = JLogFactory.getLog(EasyBeansClassLoader.class); 53 54 59 private boolean recomputeToString = true; 60 61 64 private String toStringValue = null; 65 66 69 private Class javaLangClassLoaderClass = null; 70 71 74 private Method defineClassMethod = null; 75 76 80 private Map <String , byte[]> mapDefined = new HashMap <String , byte[]>(); 81 82 87 public EasyBeansClassLoader(final URL [] urls, final ClassLoader parent) { 88 super(urls, parent); 89 } 90 91 95 public EasyBeansClassLoader(final URL [] urls) { 96 super(urls); 97 } 98 99 107 @Override 108 protected Class <?> findClass(final String name) throws ClassNotFoundException { 109 Class clazz = searchingDefinedClass(name); 110 if (clazz != null) { 111 return clazz; 112 } 113 return super.findClass(name); 115 } 116 117 123 private Class <?> defineInternalClass(final String className, final byte[] bytecode) { 124 FileOutputStream fos = null; 127 try { 128 String fName = System.getProperty("java.io.tmpdir") + File.separator + className + ".class"; 129 fos = new FileOutputStream (fName); 130 fos.write(bytecode); 131 } catch (IOException ioe) { 132 throw new RuntimeException (ioe); 133 } 134 136 ClassLoader loader = this; 138 if (javaLangClassLoaderClass == null) { 139 try { 140 javaLangClassLoaderClass = Class.forName("java.lang.ClassLoader"); 141 } catch (ClassNotFoundException e) { 142 logger.error("Cannot use the ClassLoader class", e); 143 return null; 144 } 145 } 146 if (defineClassMethod == null) { 147 try { 148 defineClassMethod = javaLangClassLoaderClass.getDeclaredMethod("defineClass", new Class [] { 149 String .class, byte[].class, int.class, int.class}); 150 } catch (SecurityException e) { 151 logger.error("Method defineClass not available in the classloader class", e); 152 return null; 153 } catch (NoSuchMethodException e) { 154 logger.error("Method defineClass not available in the classloader class", e); 155 return null; 156 } 157 } 158 defineClassMethod.setAccessible(true); 160 try { 161 Object [] args = new Object [] {className, bytecode, new Integer (0), new Integer (bytecode.length)}; 162 try { 163 return (Class ) defineClassMethod.invoke(loader, args); 164 } catch (IllegalArgumentException e) { 165 logger.error("Cannot invoke the defineClass method on the classloader", e); 166 } catch (IllegalAccessException e) { 167 logger.error("Cannot invoke the defineClass method on the classloader", e); 168 } catch (InvocationTargetException e) { 169 logger.error("Cannot invoke the defineClass method on the classloader", e); 170 } 171 } finally { 172 defineClassMethod.setAccessible(false); 173 } 174 return null; 175 } 176 177 183 public void addClassDefinition(final String className, final byte[] bytecode) { 184 if (mapDefined.get(className) != null) { 186 logger.warn("There is already a bytecode defined for the class named '" + className 187 + "'. Not replacing. This could be due to a duplicated class in the given package."); 188 } 189 mapDefined.put(className, bytecode); 190 } 191 192 198 @Override 199 public Class <?> loadClass(final String name) throws ClassNotFoundException { 200 searchingDefinedClass(name); 201 return super.loadClass(name, false); 202 } 203 204 209 private Class searchingDefinedClass(final String className) { 210 if (mapDefined != null) { 212 byte[] defined = mapDefined.get(className); 213 if (defined != null) { 214 Class clazz = defineInternalClass(className, defined); 215 if (clazz != null) { 216 mapDefined.remove(className); 218 return clazz; 219 } 220 221 } 222 } 223 return null; 224 } 225 226 227 231 @Override 232 public String toString() { 233 if (recomputeToString) { 235 computeToString(); 236 } 237 return toStringValue; 238 } 239 240 243 private void computeToString() { 244 StringBuffer sb = new StringBuffer (); 245 sb.append(this.getClass().getName()); 246 sb.append("["); 247 sb.append("urls="); 248 URL [] urls = getURLs(); 249 for (int u = 0; u < urls.length; u++) { 250 sb.append(urls[u]); 251 if (u != urls.length - 1) { 252 sb.append(";"); 253 } 254 } 255 sb.append("]"); 256 toStringValue = sb.toString(); 257 258 recomputeToString = false; 260 } 261 262 267 @Override 268 public Object clone() { 269 return new EasyBeansClassLoader(getURLs(), this.getParent()); 270 } 271 } 272 | Popular Tags |