11package org .python .core ;
22
3+ import java .util .ArrayList ;
34import java .util .Iterator ;
5+ import java .util .List ;
46import java .util .Map ;
57import java .util .TreeMap ;
68
911 */
1012public class JavaImportHelper {
1113
14+ private static final String DOT = "." ;
15+
1216 /**
1317 * Try to add the java package.
1418 * <p>
@@ -24,56 +28,62 @@ public class JavaImportHelper {
2428 * @return <code>true</code> if a java package was doubtlessly identified and added, <code>false</code>
2529 * otherwise.
2630 */
27- protected static boolean tryAddPackage (String packageName , PyObject fromlist ) {
31+ protected static boolean tryAddPackage (final String packageName , PyObject fromlist ) {
2832 // make sure we do not turn off the added flag, once it is set
2933 boolean packageAdded = false ;
3034
3135 if (packageName != null ) {
32- // build the actual map with the packages known to the VM
33- Map packages = buildLoadedPackages ();
36+ // check explicit imports first (performance optimization)
37+
38+ // handle 'from java.net import URL' like explicit imports
39+ List stringFromlist = getFromListAsStrings (fromlist );
40+ Iterator fromlistIterator = stringFromlist .iterator ();
41+ while (fromlistIterator .hasNext ()) {
42+ String fromName = (String ) fromlistIterator .next ();
43+ if (isJavaClass (packageName , fromName )) {
44+ packageAdded = addPackage (packageName , packageAdded );
3445
35- // handle package name
36- if (isLoadedPackage (packageName , packages )) {
37- packageAdded = addPackage (packageName , packageAdded );
46+ }
3847 }
39- String parentPackageName = packageName ;
40- int dotPos = 0 ;
41- String lastDottedName = null ;
42- do {
43- dotPos = parentPackageName .lastIndexOf ("." );
44- if (dotPos > 0 ) {
45- parentPackageName = parentPackageName .substring (0 , dotPos );
46- if (isLoadedPackage (parentPackageName , packages )) {
47- packageAdded = addPackage (parentPackageName , packageAdded );
48- }
49- // handle 'import java.net.URL' style explicit imports
50- if (lastDottedName == null ) {
51- lastDottedName = packageName .substring (dotPos + 1 );
52- if (isJavaClass (parentPackageName , lastDottedName )) {
48+
49+ // handle 'import java.net.URL' style explicit imports
50+ int dotPos = packageName .lastIndexOf (DOT );
51+ if (dotPos > 0 ) {
52+ String lastDottedName = packageName .substring (dotPos + 1 );
53+ String packageCand = packageName .substring (0 , dotPos );
54+ if (isJavaClass (packageCand , lastDottedName )) {
55+ packageAdded = addPackage (packageCand , packageAdded );
56+ }
57+ }
58+
59+ // if all else fails, check already loaded packages
60+ if (!packageAdded ) {
61+ // build the actual map with the packages known to the VM
62+ Map packages = buildLoadedPackages ();
63+
64+ // add known packages
65+ String parentPackageName = packageName ;
66+ if (isLoadedPackage (packageName , packages )) {
67+ packageAdded = addPackage (packageName , packageAdded );
68+ }
69+ dotPos = 0 ;
70+ do {
71+ dotPos = parentPackageName .lastIndexOf (DOT );
72+ if (dotPos > 0 ) {
73+ parentPackageName = parentPackageName .substring (0 , dotPos );
74+ if (isLoadedPackage (parentPackageName , packages )) {
5375 packageAdded = addPackage (parentPackageName , packageAdded );
5476 }
5577 }
56- }
57- } while (dotPos > 0 );
78+ } while (dotPos > 0 );
5879
59- // handle fromlist
60- if (fromlist != null && fromlist != Py .EmptyTuple && fromlist instanceof PyTuple ) {
61- Iterator iterator = ((PyTuple ) fromlist ).iterator ();
62- while (iterator .hasNext ()) {
63- Object obj = iterator .next ();
64- if (obj instanceof String ) {
65- String fromName = (String ) obj ;
66- if (!"*" .equals (fromName )) {
67- if (isJavaClass (packageName , fromName )) {
68- packageAdded = addPackage (packageName , packageAdded );
69- } else {
70- // handle cases like: from java import math
71- String fromPackageName = packageName + "." + fromName ;
72- if (isLoadedPackage (fromPackageName , packages )) {
73- packageAdded = addPackage (fromPackageName , packageAdded );
74- }
75- }
76- }
80+ // handle package imports like 'from java import math'
81+ fromlistIterator = stringFromlist .iterator ();
82+ while (fromlistIterator .hasNext ()) {
83+ String fromName = (String ) fromlistIterator .next ();
84+ String fromPackageName = packageName + DOT + fromName ;
85+ if (isLoadedPackage (fromPackageName , packages )) {
86+ packageAdded = addPackage (fromPackageName , packageAdded );
7787 }
7888 }
7989 }
@@ -95,6 +105,32 @@ protected static boolean isLoadedPackage(String packageName) {
95105 return isLoadedPackage (packageName , buildLoadedPackages ());
96106 }
97107
108+ /**
109+ * Convert the fromlist into a java.lang.String based list.
110+ * <p>
111+ * Do some sanity checks: filter out '*' and empty tuples, as well as non tuples.
112+ *
113+ * @param fromlist
114+ * @return a list containing java.lang.String entries
115+ */
116+ private static final List getFromListAsStrings (PyObject fromlist ) {
117+ List stringFromlist = new ArrayList ();
118+
119+ if (fromlist != null && fromlist != Py .EmptyTuple && fromlist instanceof PyTuple ) {
120+ Iterator iterator = ((PyTuple ) fromlist ).iterator ();
121+ while (iterator .hasNext ()) {
122+ Object obj = iterator .next ();
123+ if (obj instanceof String ) {
124+ String fromName = (String ) obj ;
125+ if (!"*" .equals (fromName )) {
126+ stringFromlist .add (fromName );
127+ }
128+ }
129+ }
130+ }
131+ return stringFromlist ;
132+ }
133+
98134 /**
99135 * Faster way to check if a java package is already known to the VM.
100136 * <p>
@@ -129,7 +165,7 @@ private static Map buildLoadedPackages() {
129165 packageMap .put (packageName , "" );
130166 int dotPos = 0 ;
131167 do {
132- dotPos = packageName .lastIndexOf ("." );
168+ dotPos = packageName .lastIndexOf (DOT );
133169 if (dotPos > 0 ) {
134170 packageName = packageName .substring (0 , dotPos );
135171 packageMap .put (packageName , "" );
@@ -176,7 +212,7 @@ private static boolean addPackage(String packageName, boolean packageAdded) {
176212 PyJavaPackage p = PySystemState .add_package (packageName );
177213 Py .getSystemState ().modules .__setitem__ (internedPackageName , p );
178214 added = true ;
179- dotPos = packageName .lastIndexOf ("." );
215+ dotPos = packageName .lastIndexOf (DOT );
180216 if (dotPos > 0 ) {
181217 packageName = packageName .substring (0 , dotPos );
182218 }
0 commit comments