package com.avaje.ebean.enhance.agent; import java.util.HashMap; import java.util.Map; import com.avaje.ebean.enhance.asm.ClassReader; /** * Reads class information as an alternative to using a ClassLoader. * <p> * Used because if annotation classes are not in the classpath they are silently * dropped from the class information. We are especially interested to know if * super classes are entities during enhancement. * </p> */ public class ClassMetaReader { private Map<String, ClassMeta> cache = new HashMap<String, ClassMeta>(); private final EnhanceContext enhanceContext; public ClassMetaReader(EnhanceContext enhanceContext) { this.enhanceContext = enhanceContext; } public ClassMeta get(boolean readMethodAnnotations, String name, ClassLoader classLoader) throws ClassNotFoundException { return getWithCache(readMethodAnnotations, name, classLoader); } private ClassMeta getWithCache(boolean readMethodAnnotations, String name, ClassLoader classLoader) throws ClassNotFoundException { synchronized (cache) { ClassMeta meta = cache.get(name); if (meta == null) { meta = readFromResource(readMethodAnnotations, name, classLoader); if (meta != null) { if (meta.isCheckSuperClassForEntity()) { ClassMeta superMeta = getWithCache(readMethodAnnotations, meta.getSuperClassName(), classLoader); if (superMeta != null && superMeta.isEntity()) { meta.setSuperMeta(superMeta); } } cache.put(name, meta); } } return meta; } } private ClassMeta readFromResource(boolean readMethodAnnotations, String className, ClassLoader classLoader) throws ClassNotFoundException { byte[] classBytes = enhanceContext.getClassBytes(className, classLoader); if (classBytes == null){ enhanceContext.log(1, "Class ["+className+"] not found."); return null; } else { if (enhanceContext.isLog(3)) { enhanceContext.log(className, "read ClassMeta"); } } ClassReader cr = new ClassReader(classBytes); ClassMetaReaderVisitor ca = new ClassMetaReaderVisitor(readMethodAnnotations, enhanceContext); cr.accept(ca, 0); return ca.getClassMeta(); } }