/* Copyright (c) Jython Developers */
package org.python.core;
import java.io.File;
import java.io.IOException;
import java.io.InputStream;
import java.util.Map;
import java.util.logging.Level;
import org.python.core.util.FileUtil;
import org.python.core.util.StringUtil;
import org.python.core.util.importer;
import org.python.expose.ExposedMethod;
import org.python.expose.ExposedNew;
import org.python.expose.ExposedType;
import org.python.util.Generic;
@Untraversable
@ExposedType(name="ClasspathPyImporter")
public class ClasspathPyImporter extends importer {
public static final String PYCLASSPATH_PREFIX = "__pyclasspath__/";
public static final PyType TYPE = PyType.fromClass(ClasspathPyImporter.class);
public ClasspathPyImporter(PyType subType) {
super(subType);
}
public ClasspathPyImporter() {
super();
}
@ExposedNew
@ExposedMethod
final void ClasspathPyImporter___init__(PyObject[] args, String[] kwds) {
ArgParser ap = new ArgParser("__init__", args, kwds, new String[] {"path"});
String path = ap.getString(0);
if (path == null || !path.startsWith(PYCLASSPATH_PREFIX)) {
throw Py.ImportError("path isn't for classpath importer");
}
if (!path.endsWith("/")) {
path += "/";
}
this.path = path;
}
/**
* Return the contents of the jarred file at the specified path
* as bytes.
*
* @param path a String path name within the archive
* @return a String of data in binary mode (no CRLF)
*/
@Override
public String get_data(String path) {
return ClasspathPyImporter_get_data(path);
}
@ExposedMethod
final String ClasspathPyImporter_get_data(String path) {
// Strip any leading occurrence of the hook string
int len = PYCLASSPATH_PREFIX.length();
if (len < path.length() && path.startsWith(PYCLASSPATH_PREFIX)) {
path = path.substring(len);
}
// Bundle wraps the stream together with a close operation
try (Bundle bundle = makeBundle(path, makeEntry(path))) {
byte[] data = FileUtil.readBytes(bundle.inputStream);
return StringUtil.fromBytes(data);
} catch (IOException ioe) {
throw Py.IOError(ioe);
}
}
/**
* Return the source code for the module as a string (using
* newline characters for line endings)
*
* @param fullname the fully qualified name of the module
* @return a String of the module's source code or null
*/
public String get_source(String fullname) {
return ClasspathPyImporter_get_source(fullname);
}
@ExposedMethod
final String ClasspathPyImporter_get_source(String fullname) {
ModuleInfo moduleInfo = getModuleInfo(fullname);
if (moduleInfo == ModuleInfo.ERROR) {
return null;
} else if (moduleInfo == ModuleInfo.NOT_FOUND) {
throw Py.ImportError(String.format("can't find module '%s'", fullname));
} else {
// Turn the module name into a source file name
String path = makeFilename(fullname);
if (moduleInfo == ModuleInfo.PACKAGE) {
path += File.separator + "__init__.py";
} else {
path += ".py";
}
// Bundle wraps the stream together with a close operation
try (Bundle bundle = makeBundle(path, makeEntry(path))) {
InputStream is = bundle.inputStream;
if (is != null) {
byte[] data = FileUtil.readBytes(is);
return StringUtil.fromBytes(data);
} else {
// we have the module, but no source
return null;
}
} catch (IOException ioe) {
throw Py.IOError(ioe);
}
}
}
/**
* Find the module for the fully qualified name.
*
* @param fullname the fully qualified name of the module
* @param path if not installed on the meta-path None or a module path
* @return a loader instance if this importer can load the module, None
* otherwise
*/
@ExposedMethod(defaults = "null")
final PyObject ClasspathPyImporter_find_module(String fullname, String path) {
return importer_find_module(fullname, path);
}
/**
* Determine whether a module is a package.
*
* @param fullname the fully qualified name of the module
* @return whether the module is a package
*/
@ExposedMethod
final boolean ClasspathPyImporter_is_package(String fullname) {
return importer_is_package(fullname);
}
/**
* Return the code object associated with the module.
*
* @param fullname the fully qualified name of the module
* @return the module's PyCode object or None
*/
@ExposedMethod
final PyObject ClasspathPyImporter_get_code(String fullname) {
ModuleCodeData moduleCodeData = getModuleCode(fullname);
if (moduleCodeData != null) {
return moduleCodeData.code;
}
return Py.None;
}
/**
* Load a module for the fully qualified name.
*
* @param fullname the fully qualified name of the module
* @return a loaded PyModule
*/
@ExposedMethod
final PyObject ClasspathPyImporter_load_module(String fullname) {
return importer_load_module(fullname);
}
@Override
protected long getSourceMtime(String path) {
// Can't determine this easily
return -1;
}
@Override
protected Bundle makeBundle(String fullFilename, String entry) {
InputStream is = entries.remove(entry);
return new Bundle(is) {
@Override
public void close() {
try {
inputStream.close();
} catch (IOException e) {
throw Py.JavaError(e);
}
}
};
}
@Override
protected String makeEntry(String filename) {
// In some contexts, the resource string arrives as from os.path.join(*parts)
if (!getSeparator().equals(File.separator)) {
filename = filename.replace(File.separator, getSeparator());
}
if (entries.containsKey(filename)) {
return filename;
}
InputStream is;
if (Py.getSystemState().getClassLoader() != null) {
is = tryClassLoader(filename, Py.getSystemState().getClassLoader(), "sys");
} else {
is = tryClassLoader(filename, imp.getParentClassLoader(), "parent");
}
if (is != null) {
entries.put(filename, is);
return filename;
}
return null;
}
private InputStream tryClassLoader(String fullFilename, ClassLoader loader, String place) {
if (loader != null) {
logger.log(Level.FINE, "# trying {0} in {1} class loader",
new Object[] {fullFilename, place});
return loader.getResourceAsStream(fullFilename);
}
return null;
}
@Override
protected String makeFilename(String fullname) {
return path.replace(PYCLASSPATH_PREFIX, "") + fullname.replace('.', '/');
}
@Override
protected String makeFilePath(String fullname) {
return path + fullname.replace('.', '/');
}
@Override
protected String makePackagePath(String fullname) {
return path;
}
@Override
protected String getSeparator() {
return "/";
}
private Map entries = Generic.map();
private String path;
}
Ads help maintain this website.