001: /*
002: * @(#)ImportEnv.java 1.3 05/05/25
003: *
004: * Copyright (c) 1997-2005 Sun Microsystems, Inc. All Rights Reserved.
005: *
006: * See the file "LICENSE.txt" for information on usage and redistribution of
007: * this file, and for a DISCLAIMER OF ALL WARRANTIES.
008: */
009: package pnuts.lang;
010:
011: import java.io.IOException;
012: import java.io.ObjectInputStream;
013: import java.io.Serializable;
014: import java.util.List;
015: import java.util.ArrayList;
016: import java.util.Iterator;
017: import java.util.HashMap;
018: import java.util.HashSet;
019: import java.util.Vector;
020: import java.lang.reflect.Modifier;
021: import java.lang.reflect.Field;
022: import java.lang.reflect.Method;
023:
024: import org.pnuts.util.Cache;
025: import org.pnuts.util.MemoryCache;
026: import org.pnuts.lang.CallableMethod;
027:
028: class ImportEnv implements Serializable, Cloneable {
029:
030: private final static boolean DEBUG = false;
031:
032: static final long serialVersionUID = -755390125835215465L;
033:
034: /**
035: * @serial
036: */
037: private HashMap/*<String,Import>*/imports = new HashMap();
038:
039: /**
040: * @serial
041: */
042: private HashMap/*<String,List<String>>*/importedClasses = new HashMap();
043:
044: /**
045: * @serial
046: */
047: private HashMap statics = new HashMap();
048:
049: /**
050: * @serial
051: */
052: private ArrayList/*<Import>*/pkgOrder = new ArrayList();
053:
054: /**
055: * @serial
056: */
057: private ArrayList/*<String>*/classOrder = new ArrayList();
058:
059: /**
060: * @serial
061: */
062: private ArrayList/*<String>*/staticsOrder = new ArrayList();
063:
064: transient private Cache cache = createCache();
065:
066: transient private Cache failCache = createCache();
067:
068: private static Cache createCache() {
069: return new MemoryCache();
070: }
071:
072: private Import getImport(String name) {
073: Import imp = (Import) imports.get(name);
074: if (imp != null) {
075: return imp;
076: } else {
077: return new Import(name);
078: }
079: }
080:
081: synchronized void addClass(String className) {
082: int idx = className.lastIndexOf('.');
083: String name = className.substring(idx + 1);
084: List vec = (List) importedClasses.get(name);
085: if (vec == null) {
086: importedClasses.put(name, vec = new ArrayList());
087: }
088: classOrder.remove(className);
089: classOrder.add(className);
090:
091: vec.remove(className);
092: vec.add(className);
093: cache = createCache();
094: failCache = createCache();
095: }
096:
097: synchronized void addPackage(String pkgname) {
098: Import imp = (Import) imports.get(pkgname);
099: if (imp != null) {
100: pkgOrder.remove(imp);
101: } else {
102: imp = getImport(pkgname);
103: }
104: pkgOrder.add(imp);
105: imports.put(pkgname, imp);
106: cache = createCache();
107: failCache = createCache();
108: }
109:
110: void addStaticMembers(String name, boolean wildcard, Context context) {
111: String arg = wildcard ? name + ".*" : name;
112: staticsOrder.remove(arg);
113: staticsOrder.add(arg);
114:
115: try {
116: if (wildcard) {
117: Class cls = Pnuts.loadClass(name, context);
118: Field[] fields = cls.getFields();
119: for (int i = 0; i < fields.length; i++) {
120: Field f = fields[i];
121: if (Modifier.isStatic(f.getModifiers())) {
122: statics.put(f.getName(), f.get(null));
123: }
124: }
125: HashSet names = new HashSet();
126: Method[] methods = cls.getMethods();
127: for (int i = 0; i < methods.length; i++) {
128: Method m = methods[i];
129: if (Modifier.isStatic(m.getModifiers())) {
130: names.add(m.getName());
131: }
132: }
133: for (Iterator it = names.iterator(); it.hasNext();) {
134: String memberName = (String) it.next();
135: statics.put(memberName, new CallableMethod(cls,
136: memberName));
137: }
138: } else {
139: int idx = name.lastIndexOf('.');
140: if (idx > 0) {
141: String className = name.substring(0, idx);
142: final String memberName = name.substring(idx + 1);
143: final Class cls = Pnuts.loadClass(className,
144: context);
145: try {
146: Field f = cls.getField(memberName);
147: if (Modifier.isStatic(f.getModifiers())) {
148: statics.put(memberName, f.get(null));
149: return;
150: }
151: } catch (NoSuchFieldException e) {
152: }
153: statics.put(memberName, new CallableMethod(cls,
154: memberName));
155: }
156: }
157: cache = createCache();
158: failCache = createCache();
159:
160: } catch (ClassNotFoundException e1) {
161: throw new PnutsException(e1, context);
162: } catch (IllegalAccessException e2) {
163: throw new PnutsException(e2, context);
164: }
165: }
166:
167: synchronized Object get(String sym, Context context) {
168: Object v = cache.get(sym);
169: if (v != null) {
170: return v;
171: }
172: List vec = (List) importedClasses.get(sym);
173: if (vec != null) {
174: int size = vec.size();
175: for (int i = size - 1; i >= 0; i--) {
176: try {
177: return Pnuts
178: .loadClass((String) vec.get(i), context);
179: } catch (ClassNotFoundException cnf) {
180: }
181: }
182: }
183: int symlen = sym.length();
184: StringBuffer buf = new StringBuffer(sym);
185: boolean lowercase = !Character.isUpperCase(sym.charAt(0));
186:
187: int size = pkgOrder.size();
188: for (int i = size - 1; i >= 0; i--) {
189: Import imp = (Import) pkgOrder.get(i);
190: buf.setLength(symlen);
191: String name = imp.getName();
192: if (lowercase && name.startsWith("java.")) {
193: continue;
194: }
195: buf.append(name);
196: String key = buf.toString();
197: if (failCache.get(key) != null) {
198: continue;
199: }
200: Class value = imp.get(sym, context);
201: if (value != null) {
202: cache.put(sym, value);
203: return value;
204: } else {
205: failCache.put(key, key);
206: }
207: }
208: Object value = statics.get(sym);
209: if (value != null) {
210: cache.put(sym, value);
211: return value;
212: }
213: return null;
214: }
215:
216: String[] list() {
217: String ret[] = new String[pkgOrder.size() + classOrder.size()
218: + staticsOrder.size()];
219: int i = ret.length - 1;
220: for (Iterator it = staticsOrder.iterator(); it.hasNext();) {
221: ret[i--] = "static " + (String) it.next();
222: }
223: for (Iterator it = pkgOrder.iterator(); it.hasNext();) {
224: String name = ((Import) it.next()).getName();
225: if ("".equals(name)) {
226: ret[i--] = "*";
227: } else {
228: ret[i--] = name + ".*";
229: }
230: }
231: for (Iterator it = classOrder.iterator(); it.hasNext();) {
232: ret[i--] = (String) it.next();
233: }
234: return ret;
235: }
236:
237: void reset() {
238: cache = createCache();
239: failCache = createCache();
240: for (Iterator it = pkgOrder.iterator(); it.hasNext();) {
241: ((Import) it.next()).reset();
242: }
243: }
244:
245: public Object clone() {
246: try {
247: ImportEnv c = (ImportEnv) super .clone();
248: c.imports = (HashMap) imports.clone();
249: c.importedClasses = (HashMap) importedClasses.clone();
250: c.pkgOrder = (ArrayList) pkgOrder.clone();
251: c.classOrder = (ArrayList) classOrder.clone();
252: c.statics = (HashMap) statics.clone();
253: c.staticsOrder = (ArrayList) staticsOrder.clone();
254: c.cache = createCache();
255: c.failCache = createCache();
256: return c;
257: } catch (Throwable t) {
258: throw new InternalError();
259: }
260: }
261:
262: private void readObject(ObjectInputStream s) throws IOException,
263: ClassNotFoundException {
264: s.defaultReadObject();
265: cache = createCache();
266: failCache = createCache();
267: }
268: }
|