1 20 21 package net.innig.macker.structure; 22 23 import net.innig.macker.util.ClassNameTranslator; 24 import net.innig.macker.structure.ClassParseException; 25 26 import java.io.File ; 27 import java.io.InputStream ; 28 import java.io.IOException ; 29 import java.util.*; 30 31 import net.innig.collect.*; 32 33 36 public class ClassManager 37 { 38 public ClassManager() 39 { 40 allClasses = new TreeSet(); 42 primaryClasses = new TreeSet(); 43 classNameToInfo = new TreeMap(); 44 references = new TreeMultiMap(); 45 classLoader = Thread.currentThread().getContextClassLoader(); 46 47 for(Iterator i = PrimitiveTypeInfo.ALL.iterator(); i.hasNext(); ) 48 replaceClass((ClassInfo) i.next()); 49 } 50 51 public ClassLoader getClassLoader() 52 { return classLoader; } 53 54 public void setClassLoader(ClassLoader classLoader) 55 { this.classLoader = classLoader; } 56 57 public ClassInfo readClass(File classFile) 58 throws ClassParseException, IOException 59 { 60 ClassInfo classInfo = new ParsedClassInfo(this, classFile); 61 addClass(classInfo); 62 return classInfo; 63 } 64 65 public ClassInfo readClass(InputStream classFile) 66 throws ClassParseException, IOException 67 { 68 ClassInfo classInfo = new ParsedClassInfo(this, classFile); 69 addClass(classInfo); 70 return classInfo; 71 } 72 73 private void addClass(ClassInfo classInfo) 74 { 75 ClassInfo existing = findClassInfo(classInfo.getFullName()); 76 if(existing != null && !(existing instanceof HollowClassInfo)) 77 throw new IllegalStateException ( 78 "ClassManager already contains a class named " + classInfo); 79 replaceClass(classInfo); 80 } 81 82 private void replaceClass(ClassInfo classInfo) 83 { 84 allClasses.add(classInfo); 85 classNameToInfo.put(classInfo.getFullName(), classInfo); 86 } 87 88 public void makePrimary(ClassInfo classInfo) 89 { 90 if(!classInfo.isComplete()) 91 throw new IncompleteClassInfoException( 92 classInfo + " cannot be a primary class, because the" 93 + " class file isn't on Macker's classpath"); 94 if(classInfo instanceof PrimitiveTypeInfo) 95 throw new IllegalArgumentException ( 96 classInfo + " cannot be a primary class, because it is a primitive type"); 97 checkOwner(classInfo); 98 classInfo = findClassInfo(classInfo.getFullName()); primaryClasses.add(classInfo); 100 references.putAll(classInfo, classInfo.getReferences().keySet()); 101 allClasses.addAll(classInfo.getReferences().keySet()); 102 } 103 104 public Set getAllClasses() 105 { return Collections.unmodifiableSet(allClasses); } 106 107 public Set getPrimaryClasses() 108 { return Collections.unmodifiableSet(primaryClasses); } 109 110 public MultiMap getReferences() 111 { return InnigCollections.unmodifiableMultiMap(references); } 112 113 public ClassInfo getClassInfo(String className) 114 { 115 ClassInfo classInfo = findClassInfo(className); 116 if(classInfo != null) 117 return classInfo; 118 else 119 { 120 classInfo = new HollowClassInfo(this, className); 121 replaceClass(classInfo); 122 return classInfo; 123 } 124 } 125 126 ClassInfo loadClassInfo(String className) 127 { 128 ClassInfo classInfo = findClassInfo(className); 129 if(classInfo == null || classInfo instanceof HollowClassInfo) 130 { 131 classInfo = null; String resourceName = ClassNameTranslator.classToResourceName(className); 133 InputStream classStream = classLoader.getResourceAsStream(resourceName); 134 135 if(classStream == null) 136 { 137 showIncompleteWarning(); 138 System.out.println("WARNING: Unable to find class " + className + " in the classpath"); 139 } 140 else 141 try { 142 classInfo = new ParsedClassInfo(this, classStream); 143 } 144 catch(Exception e) 145 { 146 if(e instanceof RuntimeException ) 147 throw (RuntimeException ) e; 148 showIncompleteWarning(); 149 System.out.println("WARNING: Unable to load class " + className + ": " + e); 150 } 151 finally 152 { 153 try { classStream.close(); } 154 catch(IOException ioe) { } } 156 157 if(classInfo == null) 158 classInfo = new IncompleteClassInfo(this, className); 159 160 replaceClass(classInfo); 161 } 162 163 return classInfo; 164 } 165 166 private ClassInfo findClassInfo(String className) 167 { return (ClassInfo) classNameToInfo.get(className); } 168 169 private void checkOwner(ClassInfo classInfo) 170 throws IllegalStateException 171 { 172 if(classInfo.getClassManager() != this) 173 throw new IllegalStateException ( 174 "classInfo argument (" + classInfo + ") is not managed by this ClassManager"); 175 } 176 177 private void showIncompleteWarning() 178 { 179 if(!incompleteClassWarning) 180 { 181 incompleteClassWarning = true; 182 System.out.println( 183 "WARNING: Macker is unable to load some of the external classes" 184 + " used by the primary classes (see warnings below). Rules which" 185 + " depend on attributes of these missing classes other than their" 186 + " names will fail."); 187 } 188 } 189 190 private boolean incompleteClassWarning; 191 private ClassLoader classLoader; 192 private Set allClasses, primaryClasses; 193 private Map classNameToInfo; 194 private MultiMap references; 195 } 196 197 198 199 | Popular Tags |