KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > com > triactive > jdo > util > Imports


1 /*
2  * Copyright 2002 (C) TJDO.
3  * All rights reserved.
4  *
5  * This software is distributed under the terms of the TJDO License version 1.0.
6  * See the terms of the TJDO License in the documentation provided with this software.
7  *
8  * $Id: Imports.java,v 1.3 2004/03/22 04:58:13 jackknifebarber Exp $
9  */

10
11 package com.triactive.jdo.util;
12
13 import java.util.Arrays JavaDoc;
14 import java.util.Collections JavaDoc;
15 import java.util.HashMap JavaDoc;
16 import java.util.HashSet JavaDoc;
17 import java.util.Iterator JavaDoc;
18 import java.util.Set JavaDoc;
19 import java.util.StringTokenizer JavaDoc;
20 import java.util.WeakHashMap JavaDoc;
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     /** Sorted array of primitive type names. */
30     private static final String JavaDoc[] primitives =
31         { "boolean", "byte", "char", "double", "float", "int", "long", "short" };
32
33     /** Array of classes for primitive types, parallel with primitives[]. */
34     private static final Class JavaDoc[] primitiveClasses =
35         { boolean.class, byte.class, char.class, double.class, float.class, int.class, long.class, short.class };
36
37     /** Array of type characters for primitive types, parallel with primitives[]. */
38     private static final char[] primitiveTypeChars =
39         { 'Z', 'B', 'C', 'D', 'F', 'I', 'J', 'S' };
40
41     private static final WeakHashMap JavaDoc nonExistentClassNamesByLoader = new WeakHashMap JavaDoc();
42
43     private HashMap JavaDoc importedClassesByName = new HashMap JavaDoc();
44     private HashSet JavaDoc importedPackageNames = new HashSet JavaDoc();
45
46
47     public Imports()
48     {
49         importedPackageNames.add("java.lang");
50     }
51
52
53     public void importPackage(Class JavaDoc c)
54     {
55         while (c.isArray())
56             c = c.getComponentType();
57
58         String JavaDoc 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 JavaDoc imports)
67     {
68         StringTokenizer JavaDoc t1 = new StringTokenizer JavaDoc(imports, ";");
69
70         while (t1.hasMoreTokens())
71         {
72             String JavaDoc importDecl = t1.nextToken().trim();
73
74             if (importDecl.length() == 0 && !t1.hasMoreTokens())
75                 break;
76
77             StringTokenizer JavaDoc t2 = new StringTokenizer JavaDoc(importDecl, " ");
78
79             if (t2.countTokens() != 2 || !t2.nextToken().equals("import"))
80                 throw new JDOUserException("Invalid import declaration: " + importDecl);
81
82             String JavaDoc importName = t2.nextToken();
83             int lastDot = importName.lastIndexOf(".");
84             String JavaDoc 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 JavaDoc e)
103                 {
104                     throw new JDOUserException("Class named in imports not found: " + importName);
105                 }
106             }
107         }
108     }
109
110
111     /**
112      * Returns the <tt>Class</tt> object associated with the class or interface
113      * with the given string name.
114      *
115      * <p>This method is functionally equivalent to <tt>Class.forName(name)</tt>
116      * but maintains a cache of class names that are <em>not</em> found. In
117      * many cases, especially in an app server environment, searching for
118      * non-existent classes can be a very slow process. It's important because
119      * some things in TJDO, notably the macro mechanism used in e.g. view
120      * definitions, tend to repeatedly search for class names that don't exist.
121      *
122      * @param className fully qualified name of the desired class.
123      *
124      * @exception ClassNotFoundException
125      * if the class cannot be located.
126      *
127      * @see Class#forName(String)
128      */

129
130     private Class JavaDoc classForName(String JavaDoc className) throws ClassNotFoundException JavaDoc
131     {
132         ClassLoader JavaDoc loader = getClass().getClassLoader();
133         Set JavaDoc names;
134
135         synchronized (nonExistentClassNamesByLoader)
136         {
137             names = (Set JavaDoc)nonExistentClassNamesByLoader.get(loader);
138
139             if (names == null)
140             {
141                 names = Collections.synchronizedSet(new HashSet JavaDoc());
142                 nonExistentClassNamesByLoader.put(loader, names);
143             }
144             else
145             {
146                 if (names.contains(className))
147                     throw new ClassNotFoundException JavaDoc(className + " (cached from previous lookup attempt)");
148             }
149         }
150
151         try
152         {
153             return Class.forName(className, true, loader);
154         }
155         catch (ClassNotFoundException JavaDoc 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 JavaDoc resolveClassDeclaration(String JavaDoc classDecl) throws ClassNotFoundException JavaDoc
165     {
166         String JavaDoc className;
167         String JavaDoc dims = null;
168         int bktIdx = classDecl.indexOf("[]");
169
170         if (bktIdx > 0)
171         {
172             className = classDecl.substring(0, bktIdx);
173             StringBuffer JavaDoc dimBuf = new StringBuffer JavaDoc();
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 JavaDoc(classDecl);
183
184             dims = dimBuf.toString();
185         }
186         else
187             className = classDecl;
188
189         Class JavaDoc 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 JavaDoc)importedClassesByName.get(className);
202
203             if (c == null)
204             {
205                 try
206                 {
207                     c = classForName(className);
208                 }
209                 catch (ClassNotFoundException JavaDoc e)
210                 {
211                     Iterator JavaDoc packageNames = importedPackageNames.iterator();
212
213                     while (packageNames.hasNext())
214                     {
215                         String JavaDoc packageName = (String JavaDoc)packageNames.next();
216
217                         try
218                         {
219                             Class JavaDoc 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 JavaDoc 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