All Downloads are FREE. Search and download functionalities are using the official Maven repository.

src.org.python.core.JavaImportHelper 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.

There is a newer version: 2.7.4
Show newest version
package org.python.core;

import java.util.ArrayList;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import java.util.TreeMap;

/**
 * Helper class handling the VM specific java package detection.
 */
public class JavaImportHelper {

    private static final String DOT = ".";

    /**
     * Try to add the java package.
     * 

* This is handy in cases where the package scan cannot run, or when the initial classpath does * not contain all .jar files (such as in J2EE containers). *

* There is some self-healing in the sense that a correct, explicit import of a java class will * succeed even if sys.modules already contains a Py.None entry for the corresponding java * package. * * @param packageName The dotted name of the java package * @param fromlist A tuple with the from names to import. Can be null or empty. * * @return true if a java package was doubtlessly identified and added, * false otherwise. */ protected static boolean tryAddPackage(final String packageName, PyObject fromlist) { // make sure we do not turn off the added flag, once it is set boolean packageAdded = false; if (packageName != null) { // check explicit imports first (performance optimization) // handle 'from java.net import URL' like explicit imports List stringFromlist = getFromListAsStrings(fromlist); for (String fromName : stringFromlist) { if (isJavaClass(packageName, fromName)) { packageAdded = addPackage(packageName, packageAdded); } } // handle 'import java.net.URL' style explicit imports int dotPos = packageName.lastIndexOf(DOT); if (dotPos > 0) { String lastDottedName = packageName.substring(dotPos + 1); String packageCand = packageName.substring(0, dotPos); if (isJavaClass(packageCand, lastDottedName)) { packageAdded = addPackage(packageCand, packageAdded); } } // if all else fails, check already loaded packages if (!packageAdded) { // build the actual map with the packages known to the VM Map packages = buildLoadedPackages(); // add known packages String parentPackageName = packageName; if (isLoadedPackage(packageName, packages)) { packageAdded = addPackage(packageName, packageAdded); } dotPos = 0; do { dotPos = parentPackageName.lastIndexOf(DOT); if (dotPos > 0) { parentPackageName = parentPackageName.substring(0, dotPos); if (isLoadedPackage(parentPackageName, packages)) { packageAdded = addPackage(parentPackageName, packageAdded); } } } while (dotPos > 0); // handle package imports like 'from java import math' for (String fromName : stringFromlist) { String fromPackageName = packageName + DOT + fromName; if (isLoadedPackage(fromPackageName, packages)) { packageAdded = addPackage(fromPackageName, packageAdded); } } } } return packageAdded; } /** * Check if a java package is already known to the VM. *

* May return false even if the given package name is a valid java package ! * * @param packageName * * @return true if the package with the given name is already loaded by the VM, * false otherwise. */ protected static boolean isLoadedPackage(String packageName) { return isLoadedPackage(packageName, buildLoadedPackages()); } /** * Convert the fromlist into a java.lang.String based list. *

* Do some sanity checks: filter out '*' and empty tuples, as well as non tuples. * * @param fromlist * @return a list containing java.lang.String entries */ private static final List getFromListAsStrings(PyObject fromlist) { List stringFromlist = new ArrayList(); if (fromlist != null && fromlist != Py.EmptyTuple && fromlist instanceof PyTuple) { Iterator iterator = ((PyTuple) fromlist).iterator(); while (iterator.hasNext()) { Object obj = iterator.next(); if (obj instanceof PyString) { obj = ((PyString) obj).getString(); } if (obj instanceof String) { String fromName = (String) obj; if (!"*".equals(fromName)) { stringFromlist.add(fromName); } } } } return stringFromlist; } /** * Faster way to check if a java package is already known to the VM. *

* May return false even if the given package name is a valid java package ! * * @param packageName * @param packages A Map containing all packages actually known to the VM. Such a Map can be * obtained using {@link JavaImportHelper.buildLoadedPackagesTree()} * * @return true if the package with the given name is already loaded by the VM, * false otherwise. */ private static boolean isLoadedPackage(String javaPackageName, Map packages) { boolean isLoaded = false; if (javaPackageName != null) { isLoaded = packages.containsKey(javaPackageName); } return isLoaded; } /** * Build a Map of the currently known packages to the VM. *

* All parent packages appear as single entries like python modules, e.g. java, * java.lang, java.lang.reflect, */ private static Map buildLoadedPackages() { TreeMap packageMap = new TreeMap(); Package[] packages = Package.getPackages(); for (int i = 0; i < packages.length; i++) { String packageName = packages[i].getName(); packageMap.put(packageName, ""); int dotPos = 0; do { dotPos = packageName.lastIndexOf(DOT); if (dotPos > 0) { packageName = packageName.substring(0, dotPos); packageMap.put(packageName, ""); } } while (dotPos > 0); } return packageMap; } /** * Try to load packageName.className and return {@code true} if successful. * * @return true if the java class can be found by the current Py classloader setup */ private static boolean isJavaClass(String packageName, String className) { return className != null && className.length() > 0 && Py.findClass(packageName + "." + className) != null; } /** * Add a java package to sys.modules, if not already done. * * @return true if something was really added, false otherwise */ private static boolean addPackage(String packageName, boolean packageAdded) { PyObject modules = Py.getSystemState().modules; String internedPackageName = packageName.intern(); PyObject module = modules.__finditem__(internedPackageName); // a previously failed import could have created a Py.None entry in sys.modules if (module == null || module == Py.None) { int dotPos = 0; do { PyJavaPackage p = PySystemState.add_package(packageName); if(dotPos == 0) { modules.__setitem__(internedPackageName, p); } else { module = modules.__finditem__(internedPackageName); if (module == null || module == Py.None) { modules.__setitem__(internedPackageName, p); } } dotPos = packageName.lastIndexOf(DOT); if (dotPos > 0) { packageName = packageName.substring(0, dotPos); internedPackageName = packageName.intern(); } } while(dotPos > 0); // make sure not to turn off the packageAdded flag packageAdded = true; } return packageAdded; } }





© 2015 - 2024 Weber Informatics LLC | Privacy Policy