1 16 package net.sf.cglib.core; 17 18 import java.io.*; 19 import java.util.*; 20 import java.lang.ref.*; 21 import org.objectweb.asm.ClassReader; 22 import org.objectweb.asm.ClassVisitor; 23 import org.objectweb.asm.ClassWriter; 24 import org.objectweb.asm.Type; 25 26 32 abstract public class AbstractClassGenerator 33 implements ClassGenerator 34 { 35 private static final Object NAME_KEY = new Object (); 36 private static final ThreadLocal CURRENT = new ThreadLocal (); 37 38 private GeneratorStrategy strategy = DefaultGeneratorStrategy.INSTANCE; 39 private NamingPolicy namingPolicy = DefaultNamingPolicy.INSTANCE; 40 private Source source; 41 private ClassLoader classLoader; 42 private String namePrefix; 43 private Object key; 44 private boolean useCache = true; 45 private String className; 46 private boolean attemptLoad; 47 48 protected static class Source { 49 String name; 50 Map cache = new WeakHashMap(); 51 public Source(String name) { 52 this.name = name; 53 } 54 } 55 56 protected AbstractClassGenerator(Source source) { 57 this.source = source; 58 } 59 60 protected void setNamePrefix(String namePrefix) { 61 this.namePrefix = namePrefix; 62 } 63 64 final protected String getClassName() { 65 if (className == null) 66 className = getClassName(getClassLoader()); 67 return className; 68 } 69 70 private String getClassName(final ClassLoader loader) { 71 final Set nameCache = getClassNameCache(loader); 72 return namingPolicy.getClassName(namePrefix, source.name, key, new Predicate() { 73 public boolean evaluate(Object arg) { 74 return nameCache.contains(arg); 75 } 76 }); 77 } 78 79 private Set getClassNameCache(ClassLoader loader) { 80 return (Set)((Map)source.cache.get(loader)).get(NAME_KEY); 81 } 82 83 92 public void setClassLoader(ClassLoader classLoader) { 93 this.classLoader = classLoader; 94 } 95 96 101 public void setNamingPolicy(NamingPolicy namingPolicy) { 102 if (namingPolicy == null) 103 namingPolicy = DefaultNamingPolicy.INSTANCE; 104 this.namingPolicy = namingPolicy; 105 } 106 107 110 public NamingPolicy getNamingPolicy() { 111 return namingPolicy; 112 } 113 114 118 public void setUseCache(boolean useCache) { 119 this.useCache = useCache; 120 } 121 122 125 public boolean getUseCache() { 126 return useCache; 127 } 128 129 134 public void setAttemptLoad(boolean attemptLoad) { 135 this.attemptLoad = attemptLoad; 136 } 137 138 public boolean getAttemptLoad() { 139 return attemptLoad; 140 } 141 142 146 public void setStrategy(GeneratorStrategy strategy) { 147 if (strategy == null) 148 strategy = DefaultGeneratorStrategy.INSTANCE; 149 this.strategy = strategy; 150 } 151 152 155 public GeneratorStrategy getStrategy() { 156 return strategy; 157 } 158 159 163 public static AbstractClassGenerator getCurrent() { 164 return (AbstractClassGenerator)CURRENT.get(); 165 } 166 167 public ClassLoader getClassLoader() { 168 ClassLoader t = classLoader; 169 if (t == null) { 170 t = getDefaultClassLoader(); 171 } 172 if (t == null) { 173 t = getClass().getClassLoader(); 174 } 175 if (t == null) { 176 t = Thread.currentThread().getContextClassLoader(); 177 } 178 if (t == null) { 179 throw new IllegalStateException ("Cannot determine classloader"); 180 } 181 return t; 182 } 183 184 abstract protected ClassLoader getDefaultClassLoader(); 185 186 protected Object create(Object key) { 187 try { 188 Class gen = null; 189 190 synchronized (source) { 191 ClassLoader loader = getClassLoader(); 192 Map cache2 = null; 193 cache2 = (Map)source.cache.get(loader); 194 if (cache2 == null) { 195 cache2 = new HashMap(); 196 cache2.put(NAME_KEY, new HashSet()); 197 source.cache.put(loader, cache2); 198 } else if (useCache) { 199 Reference ref = (Reference)cache2.get(key); 200 gen = (Class ) (( ref == null ) ? null : ref.get()); 201 } 202 if (gen == null) { 203 Object save = CURRENT.get(); 204 CURRENT.set(this); 205 try { 206 this.key = key; 207 208 if (attemptLoad) { 209 try { 210 gen = loader.loadClass(getClassName()); 211 } catch (ClassNotFoundException e) { 212 } 214 } 215 if (gen == null) { 216 byte[] b = strategy.generate(this); 217 String className = ClassNameReader.getClassName(new ClassReader(b)); 218 getClassNameCache(loader).add(className); 219 gen = ReflectUtils.defineClass(className, b, loader); 220 } 221 222 if (useCache) { 223 cache2.put(key, new WeakReference(gen)); 224 } 225 return firstInstance(gen); 226 } finally { 227 CURRENT.set(save); 228 } 229 } 230 } 231 return firstInstance(gen); 232 } catch (RuntimeException e) { 233 throw e; 234 } catch (Error e) { 235 throw e; 236 } catch (Exception e) { 237 throw new CodeGenerationException(e); 238 } 239 } 240 241 abstract protected Object firstInstance(Class type) throws Exception ; 242 abstract protected Object nextInstance(Object instance) throws Exception ; 243 } 244 | Popular Tags |