001: /*
002: * ModuleList.java
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.ObjectOutputStream;
014: import java.io.Serializable;
015: import java.util.ArrayList;
016: import java.util.List;
017: import java.util.Iterator;
018:
019: /*
020: * This class is responsible for managing packages used in a context. In
021: * addition, it provides a cache mechanism for exported symbols.
022: */
023: class ModuleList implements Cloneable, Serializable {
024:
025: transient ArrayList usedPackages = new ArrayList();
026:
027: transient Package basePackage;
028:
029: transient private SymbolTable cache = new SymbolTable();
030:
031: private int modCount = 0;
032:
033: ModuleList(Package basePackage) {
034: this .basePackage = basePackage;
035: }
036:
037: synchronized void add(Package pkg) {
038: usedPackages.remove(pkg);
039: usedPackages.add(pkg);
040: modCount++;
041: cache = new SymbolTable();
042: }
043:
044: synchronized boolean remove(Package pkg) {
045: if (usedPackages.remove(pkg)) {
046: modCount++;
047: cache = new SymbolTable();
048: return true;
049: }
050: return false;
051: }
052:
053: boolean contains(Package pkg) {
054: return usedPackages.contains(pkg);
055: }
056:
057: synchronized void clear() {
058: usedPackages.clear();
059: cache = new SymbolTable();
060: modCount++;
061: }
062:
063: Value resolve(String symbol, Context context) {
064: Value v = cache.lookup0(symbol);
065: if (v != null) {
066: return v;
067: }
068: loop: while (true) {
069: int size = usedPackages.size();
070: int m = modCount;
071: for (int i = 0; i < size; i++) {
072: Package pkg = (Package) usedPackages.get(size - i - 1);
073: v = pkg.lookupExportedSymbol(symbol, context);
074: if (v != null) {
075: synchronized (cache) {
076: cache.set(symbol, v.get());
077: }
078: return v;
079: }
080: if (modCount != m) {
081: continue loop;
082: }
083: }
084: break;
085: }
086: return null;
087: }
088:
089: public Object clone() {
090: try {
091: ModuleList mlist = (ModuleList) super .clone();
092: mlist.usedPackages = (ArrayList) usedPackages.clone();
093: mlist.cache = new SymbolTable();
094: mlist.modCount = 0;
095: return mlist;
096: } catch (CloneNotSupportedException e) {
097: throw new InternalError();
098: }
099: }
100:
101: String[] getPackageNames() {
102: int size = usedPackages.size();
103: String[] names = new String[size];
104: int i = 0;
105: for (Iterator it = usedPackages.iterator(); it.hasNext();) {
106: Package p = (Package) it.next();
107: names[i++] = p.getName();
108: }
109: return names;
110: }
111:
112: public int hashCode() {
113: return usedPackages.hashCode() ^ basePackage.hashCode();
114: }
115:
116: public boolean equals(Object obj) {
117: if (obj instanceof ModuleList) {
118: ModuleList m = (ModuleList) obj;
119: return usedPackages.equals(m.usedPackages)
120: && basePackage.equals(m.basePackage);
121: } else {
122: return false;
123: }
124: }
125:
126: private synchronized void writeObject(ObjectOutputStream s)
127: throws IOException {
128: s.defaultWriteObject();
129: s.writeUTF(basePackage.getName());
130: int size = usedPackages.size();
131: s.writeInt(size);
132: for (int i = 0; i < size; i++) {
133: Package p = (Package) usedPackages.get(i);
134: s.writeUTF(p.getName());
135: }
136: }
137:
138: private static void readPackage(Context ctx, String pkgName,
139: List newPkgs) throws IOException {
140: Package pkg = Package.getPackage(pkgName, ctx);
141: newPkgs.add(pkg);
142:
143: ModuleList m = ctx.moduleList;
144: if (m == null || !m.contains(pkg)) {
145: pkg.initializeModule();
146: if (!pkg.initialized) {
147: ctx.loadModule(pkgName, pkg);
148: List results = ctx.moduleList.usedPackages;
149: for (Iterator it = results.iterator(); it.hasNext();) {
150: Package p = (Package) it.next();
151: if (!newPkgs.contains(p)) {
152: p.initializeModule();
153: if (!p.initialized) {
154: ctx.loadModule(p.getName(), p);
155: p.initialized = true;
156: }
157: newPkgs.add(p);
158: }
159: }
160: pkg.initialized = true;
161: }
162: }
163: }
164:
165: private void readObject(ObjectInputStream s) throws IOException,
166: ClassNotFoundException {
167: s.defaultReadObject();
168: Context ctx = Runtime.getThreadContext();
169: if (ctx == null) {
170: ctx = new Context();
171: }
172: String baseName = s.readUTF();
173: basePackage = Package.getPackage(baseName, ctx);
174: ArrayList newPkgs = new ArrayList();
175: cache = new SymbolTable();
176: int size = s.readInt();
177: for (int i = 0; i < size; i++) {
178: String pkgName = s.readUTF();
179: readPackage(ctx, pkgName, newPkgs);
180: }
181: this.usedPackages = newPkgs;
182: }
183: }
|