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