1 10 11 package com.triactive.jdo.util; 12 13 import java.util.Arrays ; 14 import java.util.Collections ; 15 import java.util.HashMap ; 16 import java.util.HashSet ; 17 import java.util.Iterator ; 18 import java.util.Set ; 19 import java.util.StringTokenizer ; 20 import java.util.WeakHashMap ; 21 import javax.jdo.JDOUserException; 22 import org.apache.log4j.Category; 23 24 25 public class Imports 26 { 27 private static final Category LOG = Category.getInstance(Imports.class); 28 29 30 private static final String [] primitives = 31 { "boolean", "byte", "char", "double", "float", "int", "long", "short" }; 32 33 34 private static final Class [] primitiveClasses = 35 { boolean.class, byte.class, char.class, double.class, float.class, int.class, long.class, short.class }; 36 37 38 private static final char[] primitiveTypeChars = 39 { 'Z', 'B', 'C', 'D', 'F', 'I', 'J', 'S' }; 40 41 private static final WeakHashMap nonExistentClassNamesByLoader = new WeakHashMap (); 42 43 private HashMap importedClassesByName = new HashMap (); 44 private HashSet importedPackageNames = new HashSet (); 45 46 47 public Imports() 48 { 49 importedPackageNames.add("java.lang"); 50 } 51 52 53 public void importPackage(Class c) 54 { 55 while (c.isArray()) 56 c = c.getComponentType(); 57 58 String className = c.getName(); 59 int lastDot = className.lastIndexOf('.'); 60 61 if (lastDot > 0) 62 importedPackageNames.add(className.substring(0, lastDot)); 63 } 64 65 66 public void parseImports(String imports) 67 { 68 StringTokenizer t1 = new StringTokenizer (imports, ";"); 69 70 while (t1.hasMoreTokens()) 71 { 72 String importDecl = t1.nextToken().trim(); 73 74 if (importDecl.length() == 0 && !t1.hasMoreTokens()) 75 break; 76 77 StringTokenizer t2 = new StringTokenizer (importDecl, " "); 78 79 if (t2.countTokens() != 2 || !t2.nextToken().equals("import")) 80 throw new JDOUserException("Invalid import declaration: " + importDecl); 81 82 String importName = t2.nextToken(); 83 int lastDot = importName.lastIndexOf("."); 84 String lastPart = importName.substring(lastDot + 1); 85 86 if (lastPart.equals("*")) 87 { 88 if (lastDot < 1) 89 throw new JDOUserException("Invalid package import: " + importName); 90 91 importedPackageNames.add(importName.substring(0, lastDot)); 92 } 93 else 94 { 95 if (importedClassesByName.get(lastPart) != null) 96 throw new JDOUserException("Duplicate class import: " + importName); 97 98 try 99 { 100 importedClassesByName.put(lastPart, classForName(importName)); 101 } 102 catch (ClassNotFoundException e) 103 { 104 throw new JDOUserException("Class named in imports not found: " + importName); 105 } 106 } 107 } 108 } 109 110 111 129 130 private Class classForName(String className) throws ClassNotFoundException 131 { 132 ClassLoader loader = getClass().getClassLoader(); 133 Set names; 134 135 synchronized (nonExistentClassNamesByLoader) 136 { 137 names = (Set )nonExistentClassNamesByLoader.get(loader); 138 139 if (names == null) 140 { 141 names = Collections.synchronizedSet(new HashSet ()); 142 nonExistentClassNamesByLoader.put(loader, names); 143 } 144 else 145 { 146 if (names.contains(className)) 147 throw new ClassNotFoundException (className + " (cached from previous lookup attempt)"); 148 } 149 } 150 151 try 152 { 153 return Class.forName(className, true, loader); 154 } 155 catch (ClassNotFoundException e) 156 { 157 LOG.debug("Caching the fact that " + className + " was not found by " + loader); 158 names.add(className); 159 throw e; 160 } 161 } 162 163 164 public Class resolveClassDeclaration(String classDecl) throws ClassNotFoundException 165 { 166 String className; 167 String dims = null; 168 int bktIdx = classDecl.indexOf("[]"); 169 170 if (bktIdx > 0) 171 { 172 className = classDecl.substring(0, bktIdx); 173 StringBuffer dimBuf = new StringBuffer (); 174 175 do 176 { 177 dimBuf.append('['); 178 bktIdx += 2; 179 } while (classDecl.startsWith("[]", bktIdx)); 180 181 if (bktIdx < classDecl.length()) 182 throw new ClassNotFoundException (classDecl); 183 184 dims = dimBuf.toString(); 185 } 186 else 187 className = classDecl; 188 189 Class c; 190 int p = Arrays.binarySearch(primitives, className); 191 192 if (p >= 0) 193 { 194 if (dims == null) 195 c = primitiveClasses[p]; 196 else 197 c = classForName(dims + primitiveTypeChars[p]); 198 } 199 else 200 { 201 c = (Class )importedClassesByName.get(className); 202 203 if (c == null) 204 { 205 try 206 { 207 c = classForName(className); 208 } 209 catch (ClassNotFoundException e) 210 { 211 Iterator packageNames = importedPackageNames.iterator(); 212 213 while (packageNames.hasNext()) 214 { 215 String packageName = (String )packageNames.next(); 216 217 try 218 { 219 Class c1 = classForName(packageName + '.' + className); 220 221 if (c != null) 222 throw new JDOUserException("Ambiguous class declaration, could be " + c.getName() + " or " + c1.getName()); 223 224 c = c1; 225 } 226 catch (ClassNotFoundException e1) 227 { 228 } 229 } 230 231 if (c == null) 232 throw e; 233 234 LOG.warn("Class " + c.getName() + " was not explicitly imported; this may have a noticeable impact on performance", new JDOUserException()); 235 } 236 } 237 238 if (dims != null) 239 c = classForName(dims + 'L' + c.getName() + ';'); 240 } 241 242 return c; 243 } 244 } 245 | Popular Tags |