001: // Copyright (c) Corporation for National Research Initiatives
002: // Copyright 2000 Samuele Pedroni
003:
004: package org.python.core;
005:
006: import java.io.BufferedInputStream;
007: import java.io.File;
008: import java.io.FileInputStream;
009: import java.io.FilenameFilter;
010: import java.io.IOException;
011:
012: /**
013: * Path package manager. Gathering classes info dynamically from a set of
014: * directories in path {@link #searchPath}, and statically from a set of jars,
015: * like {@link CachedJarsPackageManager}.
016: */
017: public abstract class PathPackageManager extends
018: CachedJarsPackageManager {
019:
020: public PyList searchPath;
021:
022: public PathPackageManager() {
023: this .searchPath = new PyList();
024: }
025:
026: /**
027: * Helper for {@link #packageExists(java.lang.String,java.lang.String)}.
028: * Scans for package pkg.name the directories in path.
029: */
030: protected boolean packageExists(PyList path, String pkg, String name) {
031: String child = pkg.replace('.', File.separatorChar)
032: + File.separator + name;
033:
034: for (int i = 0; i < path.__len__(); i++) {
035: String dir = imp.defaultEmptyPathDirectory(path.pyget(i)
036: .__str__().toString());
037:
038: File f = new File(dir, child);
039: if (f.isDirectory() && imp.caseok(f, name, name.length())) {
040: /*
041: * Figure out if we have a directory a mixture of python and
042: * java or just an empty directory (which means Java) or a
043: * directory with only Python source (which means Python).
044: */
045: PackageExistsFileFilter m = new PackageExistsFileFilter();
046: f.listFiles(m);
047: boolean exists = m.packageExists();
048: if (exists) {
049: Py.writeComment("import", "java package as '"
050: + f.getAbsolutePath() + "'");
051: }
052: return exists;
053: }
054: }
055: return false;
056: }
057:
058: class PackageExistsFileFilter implements FilenameFilter {
059: private boolean java;
060:
061: private boolean python;
062:
063: public boolean accept(File dir, String name) {
064: if (name.endsWith(".py") || name.endsWith("$py.class")
065: || name.endsWith("$_PyInner.class")) {
066: python = true;
067: } else if (name.endsWith(".class")) {
068: java = true;
069: }
070: return false;
071: }
072:
073: public boolean packageExists() {
074: if (this .python && !this .java) {
075: return false;
076: }
077: return true;
078: }
079: }
080:
081: /**
082: * Helper for {@link #doDir(PyJavaPackage,boolean,boolean)}. Scans for
083: * package jpkg content over the directories in path. Add to ret the founded
084: * classes/pkgs. Filter out classes using {@link #filterByName},{@link #filterByAccess}.
085: */
086: protected void doDir(PyList path, PyList ret, PyJavaPackage jpkg,
087: boolean instantiate, boolean exclpkgs) {
088: String child = jpkg.__name__.replace('.', File.separatorChar);
089:
090: for (int i = 0; i < path.__len__(); i++) {
091: String dir = path.pyget(i).__str__().toString();
092: if (dir.length() == 0) {
093: dir = null;
094: }
095:
096: File childFile = new File(dir, child);
097:
098: String[] list = childFile.list();
099: if (list == null) {
100: continue;
101: }
102:
103: doList: for (int j = 0; j < list.length; j++) {
104: String jname = list[j];
105:
106: File cand = new File(childFile, jname);
107:
108: int jlen = jname.length();
109:
110: boolean pkgCand = false;
111:
112: if (cand.isDirectory()) {
113: if (!instantiate && exclpkgs) {
114: continue;
115: }
116: pkgCand = true;
117: } else {
118: if (!jname.endsWith(".class")) {
119: continue;
120: }
121: jlen -= 6;
122: }
123:
124: jname = jname.substring(0, jlen);
125: PyString name = new PyString(jname);
126:
127: if (filterByName(jname, pkgCand)) {
128: continue;
129: }
130:
131: // for opt maybe we should some hash-set for ret
132: if (jpkg.__dict__.has_key(name)
133: || jpkg.clsSet.has_key(name)
134: || ret.__contains__(name)) {
135: continue;
136: }
137:
138: if (!Character.isJavaIdentifierStart(jname.charAt(0))) {
139: continue;
140: }
141:
142: for (int k = 1; k < jlen; k++) {
143: if (!Character
144: .isJavaIdentifierPart(jname.charAt(k))) {
145: continue doList;
146: }
147: }
148:
149: if (!pkgCand) {
150: try {
151: int acc = checkAccess(new BufferedInputStream(
152: new FileInputStream(cand)));
153: if ((acc == -1) || filterByAccess(jname, acc)) {
154: continue;
155: }
156: } catch (IOException e) {
157: continue;
158: }
159: }
160:
161: if (instantiate) {
162: if (pkgCand) {
163: jpkg.addPackage(jname);
164: } else {
165: jpkg.addLazyClass(jname);
166: }
167: }
168:
169: ret.append(name);
170:
171: }
172: }
173:
174: }
175:
176: /**
177: * Add directory dir (if exists) to {@link #searchPath}.
178: */
179: public void addDirectory(File dir) {
180: try {
181: if (dir.getPath().length() == 0) {
182: this .searchPath.append(Py.EmptyString);
183: } else {
184: this .searchPath.append(new PyString(dir
185: .getCanonicalPath()));
186: }
187: } catch (IOException e) {
188: warning("skipping bad directory, '" + dir + "'");
189: }
190: }
191:
192: // ??pending:
193: // Uses simply split and not a StringTokenizer+trim to adhere to
194: // sun jvm parsing of classpath.
195: // E.g. "a;" is parsed by sun jvm as a, ""; the latter is interpreted
196: // as cwd. jview trims and cwd is per default in classpath.
197: // The logic here should work for both(...). Need to distinguish?
198: // This code does not avoid duplicates in searchPath.
199: // Should cause no problem (?).
200:
201: /**
202: * Adds "classpath" entry. Calls {@link #addDirectory} if path refers to a
203: * dir, {@link #addJarToPackages(java.io.File, boolean)} with param cache
204: * true if path refers to a jar.
205: */
206: public void addClassPath(String path) {
207: PyList paths = new PyString(path)
208: .split(java.io.File.pathSeparator);
209:
210: for (int i = 0; i < paths.__len__(); i++) {
211: String entry = paths.pyget(i).toString();
212: if (entry.endsWith(".jar") || entry.endsWith(".zip")) {
213: addJarToPackages(new File(entry), true);
214: } else {
215: File dir = new File(entry);
216: if (entry.length() == 0 || dir.isDirectory()) {
217: addDirectory(dir);
218: }
219: }
220: }
221: }
222:
223: public PyList doDir(PyJavaPackage jpkg, boolean instantiate,
224: boolean exclpkgs) {
225: PyList basic = basicDoDir(jpkg, instantiate, exclpkgs);
226: PyList ret = new PyList();
227:
228: doDir(this .searchPath, ret, jpkg, instantiate, exclpkgs);
229:
230: return merge(basic, ret);
231: }
232:
233: public boolean packageExists(String pkg, String name) {
234: return packageExists(this.searchPath, pkg, name);
235: }
236:
237: }
|