001: // Copyright (c) Corporation for National Research Initiatives
002: // Copyright 2000 Samuele Pedroni
003:
004: package org.python.core;
005:
006: import java.io.EOFException;
007:
008: /**
009: * Abstract package manager.
010: */
011: public abstract class PackageManager extends Object {
012:
013: public PyJavaPackage topLevelPackage;
014:
015: public PackageManager() {
016: this .topLevelPackage = new PyJavaPackage("", this );
017: }
018:
019: abstract public Class findClass(String pkg, String name,
020: String reason);
021:
022: public Class findClass(String pkg, String name) {
023: return findClass(pkg, name, "java class");
024: }
025:
026: public void notifyPackageImport(String pkg, String name) {
027: }
028:
029: /**
030: * Dynamically check if pkg.name exists as java pkg in the controlled
031: * hierarchy. Should be overriden.
032: *
033: * @param pkg parent pkg name
034: * @param name candidate name
035: * @return true if pkg exists
036: */
037: public abstract boolean packageExists(String pkg, String name);
038:
039: /**
040: * Reports the specified package content names. Should be overriden. Used by
041: * {@link PyJavaPackage#__dir__} and {@link PyJavaPackage#fillDir}.
042: *
043: * @return resulting list of names (PyList of PyString)
044: * @param jpkg queried package
045: * @param instantiate if true then instatiate reported names in package dict
046: * @param exclpkgs exclude packages (just when instantiate is false)
047: */
048: public abstract PyList doDir(PyJavaPackage jpkg,
049: boolean instantiate, boolean exclpkgs);
050:
051: /**
052: * Append a directory to the list of directories searched for java packages
053: * and java classes.
054: *
055: * @param dir A directory.
056: */
057: public abstract void addDirectory(java.io.File dir);
058:
059: /**
060: * Append a directory to the list of directories searched for java packages
061: * and java classes.
062: *
063: * @param dir A directory name.
064: */
065: public abstract void addJarDir(String dir, boolean cache);
066:
067: /**
068: * Append a jar file to the list of locations searched for java packages and
069: * java classes.
070: *
071: * @param jarfile A directory name.
072: */
073: public abstract void addJar(String jarfile, boolean cache);
074:
075: /**
076: * Basic helper implementation of {@link #doDir}. It merges information
077: * from jpkg {@link PyJavaPackage#clsSet} and {@link PyJavaPackage#__dict__}.
078: */
079: protected PyList basicDoDir(PyJavaPackage jpkg,
080: boolean instantiate, boolean exclpkgs) {
081: PyStringMap dict = jpkg.__dict__;
082: PyStringMap cls = jpkg.clsSet;
083:
084: if (!instantiate) {
085: PyList ret = cls.keys();
086:
087: PyList dictKeys = dict.keys();
088:
089: for (int i = 0; i < dictKeys.__len__(); i++) {
090: PyObject name = dictKeys.pyget(i);
091: if (!cls.has_key(name)) {
092: if (exclpkgs
093: && dict.get(name) instanceof PyJavaPackage)
094: continue;
095: ret.append(name);
096: }
097: }
098:
099: return ret;
100: }
101:
102: PyList clsNames = cls.keys();
103:
104: for (int i = 0; i < clsNames.__len__(); i++) {
105: PyObject name = clsNames.pyget(i);
106: if (!dict.has_key(name))
107: jpkg.addLazyClass(name.toString());
108: }
109:
110: return dict.keys();
111: }
112:
113: /**
114: * Helper merging list2 into list1. Returns list1.
115: */
116: protected PyList merge(PyList list1, PyList list2) {
117: for (int i = 0; i < list2.__len__(); i++) {
118: PyObject name = list2.pyget(i);
119: list1.append(name);
120: }
121:
122: return list1;
123: }
124:
125: public PyObject lookupName(String name) {
126: PyObject top = this .topLevelPackage;
127: do {
128: int dot = name.indexOf('.');
129: String firstName = name;
130: String lastName = null;
131: if (dot != -1) {
132: firstName = name.substring(0, dot);
133: lastName = name.substring(dot + 1, name.length());
134: }
135: firstName = firstName.intern();
136: top = top.__findattr__(firstName);
137: if (top == null)
138: return null;
139: // ??pending: test for jpkg/jclass?
140: name = lastName;
141: } while (name != null);
142: return top;
143: }
144:
145: /**
146: * Creates package/updates statically known classes info. Uses
147: * {@link PyJavaPackage#addPackage(java.lang.String, java.lang.String) },
148: * {@link PyJavaPackage#addPlaceholders}.
149: *
150: * @param name package name
151: * @param classes comma-separated string
152: * @param jarfile involved jarfile; can be null
153: * @return created/updated package
154: */
155: public PyJavaPackage makeJavaPackage(String name, String classes,
156: String jarfile) {
157: PyJavaPackage p = this .topLevelPackage;
158: if (name.length() != 0)
159: p = p.addPackage(name, jarfile);
160:
161: if (classes != null)
162: p.addPlaceholders(classes);
163:
164: return p;
165: }
166:
167: /**
168: * Check that a given stream is a valid Java .class file. And return its
169: * access permissions as an int.
170: */
171: static protected int checkAccess(java.io.InputStream cstream)
172: throws java.io.IOException {
173: java.io.DataInputStream istream = new java.io.DataInputStream(
174: cstream);
175:
176: try {
177: int magic = istream.readInt();
178: if (magic != 0xcafebabe) {
179: return -1;
180: }
181: } catch (EOFException eof) {
182: //Empty or 1 byte file.
183: return -1;
184: }
185: //int minor =
186: istream.readShort();
187: //int major =
188: istream.readShort();
189:
190: // Check versions???
191: // System.out.println("magic: "+magic+", "+major+", "+minor);
192: int nconstants = istream.readShort();
193: for (int i = 1; i < nconstants; i++) {
194: int cid = istream.readByte();
195: // System.out.println(""+i+" : "+cid);
196: switch (cid) {
197: case 7:
198: istream.skipBytes(2);
199: break;
200: case 9:
201: case 10:
202: case 11:
203: istream.skipBytes(4);
204: break;
205: case 8:
206: istream.skipBytes(2);
207: break;
208: case 3:
209: case 4:
210: istream.skipBytes(4);
211: break;
212: case 5:
213: case 6:
214: istream.skipBytes(8);
215: i++;
216: break;
217: case 12:
218: istream.skipBytes(4);
219: break;
220: case 1:
221: // System.out.println("utf: "+istream.readUTF()+";");
222: int slength = istream.readUnsignedShort();
223: istream.skipBytes(slength);
224: break;
225: default:
226: // System.err.println("unexpected cid: "+cid+", "+i+", "+
227: // nconstants);
228: // for (int j=0; j<10; j++)
229: // System.err.print(", "+istream.readByte());
230: // System.err.println();
231: return -1;
232: }
233: }
234: return istream.readShort();
235: }
236:
237: }
|