org.python.core.PathPackageManager Maven / Gradle / Ivy
Go to download
Jython is an implementation of the high-level, dynamic, object-oriented
language Python written in 100% Pure Java, and seamlessly integrated with
the Java platform. It thus allows you to run Python on any Java platform.
// Copyright (c) Corporation for National Research Initiatives
// Copyright 2000 Samuele Pedroni
package org.python.core;
import java.io.BufferedInputStream;
import java.io.File;
import java.io.FileInputStream;
import java.io.FilenameFilter;
import java.io.IOException;
/**
* Path package manager. Gathering classes info dynamically from a set of
* directories in path {@link #searchPath}, and statically from a set of jars,
* like {@link CachedJarsPackageManager}.
*/
public abstract class PathPackageManager extends CachedJarsPackageManager {
public PyList searchPath;
public PathPackageManager() {
this.searchPath = new PyList();
}
/**
* Helper for {@link #packageExists(java.lang.String,java.lang.String)}.
* Scans for package pkg.name the directories in path.
*/
protected boolean packageExists(PyList path, String pkg, String name) {
String child = pkg.replace('.', File.separatorChar) + File.separator
+ name;
for (int i = 0; i < path.__len__(); i++) {
String dir = imp.defaultEmptyPathDirectory(path.pyget(i).__str__().toString());
File f = new File(dir, child);
if (f.isDirectory() && imp.caseok(f, name, name.length())) {
/*
* Figure out if we have a directory a mixture of python and
* java or just an empty directory (which means Java) or a
* directory with only Python source (which means Python).
*/
PackageExistsFileFilter m = new PackageExistsFileFilter();
f.listFiles(m);
boolean exists = m.packageExists();
if (exists) {
Py.writeComment("import", "java package as '"
+ f.getAbsolutePath() + "'");
}
return exists;
}
}
return false;
}
class PackageExistsFileFilter implements FilenameFilter {
private boolean java;
private boolean python;
public boolean accept(File dir, String name) {
if(name.endsWith(".py") || name.endsWith("$py.class") || name.endsWith("$_PyInner.class")) {
python = true;
}else if (name.endsWith(".class")) {
java = true;
}
return false;
}
public boolean packageExists() {
if (this.python && !this.java) {
return false;
}
return true;
}
}
/**
* Helper for {@link #doDir(PyJavaPackage,boolean,boolean)}. Scans for
* package jpkg content over the directories in path. Add to ret the founded
* classes/pkgs. Filter out classes using {@link #filterByName},{@link #filterByAccess}.
*/
protected void doDir(PyList path, PyList ret, PyJavaPackage jpkg,
boolean instantiate, boolean exclpkgs) {
String child = jpkg.__name__.replace('.', File.separatorChar);
for (int i = 0; i < path.__len__(); i++) {
String dir = path.pyget(i).__str__().toString();
if (dir.length() == 0) {
dir = null;
}
File childFile = new File(dir, child);
String[] list = childFile.list();
if (list == null) {
continue;
}
doList: for (int j = 0; j < list.length; j++) {
String jname = list[j];
File cand = new File(childFile, jname);
int jlen = jname.length();
boolean pkgCand = false;
if (cand.isDirectory()) {
if (!instantiate && exclpkgs) {
continue;
}
pkgCand = true;
} else {
if (!jname.endsWith(".class")) {
continue;
}
jlen -= 6;
}
jname = jname.substring(0, jlen);
PyString name = new PyString(jname);
if (filterByName(jname, pkgCand)) {
continue;
}
// for opt maybe we should some hash-set for ret
if (jpkg.__dict__.has_key(name) || jpkg.clsSet.has_key(name)
|| ret.__contains__(name)) {
continue;
}
if (!Character.isJavaIdentifierStart(jname.charAt(0))) {
continue;
}
for (int k = 1; k < jlen; k++) {
if (!Character.isJavaIdentifierPart(jname.charAt(k))) {
continue doList;
}
}
if (!pkgCand) {
try {
int acc = checkAccess(new BufferedInputStream(
new FileInputStream(cand)));
if ((acc == -1) || filterByAccess(jname, acc)) {
continue;
}
} catch (IOException e) {
continue;
}
}
if (instantiate) {
if (pkgCand) {
jpkg.addPackage(jname);
} else {
jpkg.addLazyClass(jname);
}
}
ret.append(name);
}
}
}
/**
* Add directory dir (if exists) to {@link #searchPath}.
*/
public void addDirectory(File dir) {
try {
if (dir.getPath().length() == 0) {
this.searchPath.append(Py.EmptyString);
} else {
this.searchPath.append(new PyString(dir.getCanonicalPath()));
}
} catch (IOException e) {
warning("skipping bad directory, '" + dir + "'");
}
}
// ??pending:
// Uses simply split and not a StringTokenizer+trim to adhere to
// sun jvm parsing of classpath.
// E.g. "a;" is parsed by sun jvm as a, ""; the latter is interpreted
// as cwd. jview trims and cwd is per default in classpath.
// The logic here should work for both(...). Need to distinguish?
// This code does not avoid duplicates in searchPath.
// Should cause no problem (?).
/**
* Adds "classpath" entry. Calls {@link #addDirectory} if path refers to a
* dir, {@link #addJarToPackages(java.io.File, boolean)} with param cache
* true if path refers to a jar.
*/
public void addClassPath(String path) {
PyList paths = new PyString(path).split(java.io.File.pathSeparator);
for (int i = 0; i < paths.__len__(); i++) {
String entry = paths.pyget(i).toString();
if (entry.endsWith(".jar") || entry.endsWith(".zip")) {
addJarToPackages(new File(entry), true);
} else {
File dir = new File(entry);
if (entry.length() == 0 || dir.isDirectory()) {
addDirectory(dir);
}
}
}
}
public PyList doDir(PyJavaPackage jpkg, boolean instantiate,
boolean exclpkgs) {
PyList basic = basicDoDir(jpkg, instantiate, exclpkgs);
PyList ret = new PyList();
doDir(this.searchPath, ret, jpkg, instantiate, exclpkgs);
return merge(basic, ret);
}
public boolean packageExists(String pkg, String name) {
return packageExists(this.searchPath, pkg, name);
}
}