001package io.ebean.enhance.common; 002 003import io.ebean.enhance.asm.ClassReader; 004 005import java.util.HashMap; 006import java.util.Map; 007 008/** 009 * Reads class information as an alternative to using a ClassLoader. 010 * <p> 011 * Used because if annotation classes are not in the classpath they are silently 012 * dropped from the class information. We are especially interested to know if 013 * super classes are entities during enhancement. 014 * </p> 015 */ 016public class ClassMetaReader { 017 018 private final Map<String, ClassMeta> cache = new HashMap<>(); 019 020 private final EnhanceContext enhanceContext; 021 022 public ClassMetaReader(EnhanceContext enhanceContext) { 023 this.enhanceContext = enhanceContext; 024 } 025 026 public ClassMeta get(boolean readMethodAnnotations, String name, ClassLoader classLoader) throws ClassNotFoundException { 027 return getWithCache(readMethodAnnotations, name, classLoader); 028 } 029 030 private ClassMeta getWithCache(boolean readMethodAnnotations, String name, ClassLoader classLoader) throws ClassNotFoundException { 031 032 synchronized (cache) { 033 ClassMeta meta = cache.get(name); 034 if (meta == null) { 035 meta = readFromResource(readMethodAnnotations, name, classLoader); 036 if (meta != null) { 037 if (meta.isCheckSuperClassForEntity()) { 038 ClassMeta superMeta = getWithCache(readMethodAnnotations, meta.getSuperClassName(), classLoader); 039 if (superMeta != null && superMeta.isEntity()) { 040 meta.setSuperMeta(superMeta); 041 } 042 } 043 cache.put(name, meta); 044 } 045 } 046 return meta; 047 } 048 } 049 050 private ClassMeta readFromResource(boolean readMethodAnnotations, String className, ClassLoader classLoader) 051 throws ClassNotFoundException { 052 053 byte[] classBytes = enhanceContext.getClassBytes(className, classLoader); 054 if (classBytes == null){ 055 if (enhanceContext.isLog(2)) { 056 enhanceContext.log(null, "Could not read meta data for class ["+className+"]."); 057 } 058 return null; 059 } else { 060 if (enhanceContext.isLog(5)) { 061 enhanceContext.log(className, "read ClassMeta"); 062 } 063 } 064 ClassReader cr = new ClassReader(classBytes); 065 ClassMetaReaderVisitor ca = new ClassMetaReaderVisitor(readMethodAnnotations, enhanceContext); 066 cr.accept(ca, ClassReader.SKIP_FRAMES + ClassReader.SKIP_DEBUG); 067 068 return ca.getClassMeta(); 069 } 070 071}