@@ -289,52 +289,164 @@ private static boolean isPackage(String packageName)
289289 return false ;
290290 }
291291
292- private static void completePackage (String packageName )
293- throws IOException
292+ private static Map <String , Set <String >> importMap = new HashMap <String , Set <String >>();
293+ private static final String CLASS_NAME_RE = "(?:$|.)?(\\ w+).class" ;
294+ private static final String DIGITS_CLASS_NAME_RE = "\\ d+" ;
295+
296+ private static Pattern classnamePattern , digitsClassnamePattern ;
297+ static
294298 {
295- ArrayList <String > paths = new ArrayList <String >();
299+ classnamePattern = Pattern .compile (CLASS_NAME_RE );
300+ digitsClassnamePattern = Pattern .compile (DIGITS_CLASS_NAME_RE );
301+ }
302+
303+ private static void addToImportMap (String classFileName )
304+ {
305+ Matcher classnameMatcher = classnamePattern .matcher (classFileName );
306+ if (classnameMatcher .find ())
307+ {
308+ String classname = classnameMatcher .group (1 );
309+ Matcher digitsClassnameMatcher = digitsClassnamePattern .matcher (classname );
310+ if (!digitsClassnameMatcher .find ())
311+ {
312+ if (!importMap .containsKey (classname )) {
313+ importMap .put (classname , new HashSet <String >());
314+ }
315+ String fullClassname = classFileName .replace ("/" , "." ).replace (".class" , "" );
316+ if (fullClassname .startsWith ("." ))
317+ {
318+ fullClassname = fullClassname .substring (1 );
319+ }
320+ importMap .get (classname ).add (fullClassname );
321+ }
322+ }
323+ }
324+
325+ protected static String [] getClasspathEntries ()
326+ {
327+ Set <String > paths = new HashSet <String >();
296328 paths .add ("java/lang/String.class" );
297329 for (String s : System .getProperty ("java.class.path" ).split (System .getProperty ("path.separator" )))
298330 {
299- if (!paths .contains (s ))
300- paths .add (s );
331+ paths .add (s );
301332 }
333+ return paths .toArray (new String [0 ]);
334+ }
302335
303- packageName = packageName .replace ("." , "/" );
304-
305- ClassLoader classLoader = Thread .currentThread ().getContextClassLoader ();
306- for (String s : paths )
336+ protected static URL getUrlFromClasspathEntry (ClassLoader classLoader , String classpathEntry , String packagePath )
337+ {
338+ URL url = null ;
339+ if (classpathEntry .endsWith (".class" ))
340+ url = classLoader .getResource (classpathEntry );
341+ else
307342 {
308- URL url = null ;
309- if (s .endsWith (".class" ))
310- url = classLoader .getResource (s );
343+ String path = "file://" + new File (classpathEntry ).getAbsolutePath ();
344+ if (path .endsWith (".jar" ))
345+ {
346+ path = "jar:" + path + "!/" + packagePath ;
347+ }
311348 else
312349 {
313- String path = "file://" + new File (s ).getAbsolutePath ();
314- if (path .endsWith (".jar" ))
350+ path += "/" + packagePath ;
351+ }
352+ try
353+ {
354+ System .err .println ("path: " + path );
355+ url = new URL (path );
356+ }
357+ catch (Exception e )
358+ {}
359+ }
360+ return url ;
361+ }
362+
363+ protected static void importClass (String classname )
364+ throws IOException
365+ {
366+ boolean importMapPopulated = importMap .size () > 0 ;
367+
368+ if (!importMapPopulated ) {
369+ String [] paths = getClasspathEntries ();
370+
371+ ClassLoader classLoader = Thread .currentThread ().getContextClassLoader ();
372+ for (String s : paths )
373+ {
374+ URL url = getUrlFromClasspathEntry (classLoader , s , "" );
375+ if (url == null )
376+ continue ;
377+ System .err .println ("s: " + s );
378+ System .err .println ("url: " + url );
379+
380+ String filename = URLDecoder .decode (url .getFile (), "UTF-8" );
381+ if (url .getProtocol ().equals ("jar" ))
315382 {
316- path = "jar:" + path + "!/" + packageName ;
383+ filename = filename .substring (5 , filename .indexOf ("!" ));
384+
385+ JarFile jf = new JarFile (filename );
386+ Enumeration <JarEntry > entries = jf .entries ();
387+ while (entries .hasMoreElements ())
388+ {
389+ addToImportMap (entries .nextElement ().getName ());
390+ }
317391 }
318392 else
319393 {
320- path += "/" + packageName ;
321- }
322- try
323- {
324- System . err . println ( "path: " + path );
325- url = new URL ( path );
394+ File folder = new File ( filename ) ;
395+ File [] classFiles = getClassFilesNotInJar ( folder ). toArray ( new File [ 0 ]);
396+ for ( File classFile : classFiles )
397+ {
398+ addToImportMap ( classFile . getAbsolutePath (). substring ( folder . getAbsolutePath (). length ()) );
399+ }
326400 }
327- catch (Exception e )
328- {}
329401 }
402+ }
403+
404+ Set <String > possibleImports = importMap .get (classname );
405+ if (possibleImports != null )
406+ {
407+ for (String impClass : possibleImports )
408+ {
409+ System .out .println (impClass + "\t class" + sep + impClass );
410+ }
411+ }
412+ }
413+
414+ protected static Set <File > getClassFilesNotInJar (File current )
415+ {
416+ Set <File > classFiles = new HashSet <File >();
417+ if (current .isFile () && current .getName ().endsWith (".class" ))
418+ {
419+ classFiles .add (current );
420+ }
421+ else if (current .isDirectory ())
422+ {
423+ for (File file : current .listFiles ())
424+ {
425+ classFiles .addAll (getClassFilesNotInJar (file ));
426+ }
427+ }
428+ return classFiles ;
429+ }
430+
431+ protected static void completePackage (String packageName )
432+ throws IOException
433+ {
434+ String [] paths = getClasspathEntries ();
435+
436+ String packagePath = packageName .replace ("." , "/" );
437+
438+ ClassLoader classLoader = Thread .currentThread ().getContextClassLoader ();
439+ for (String s : paths )
440+ {
441+ URL url = getUrlFromClasspathEntry (classLoader , s , packagePath );
330442 if (url == null )
331443 continue ;
332444 System .err .println ("s: " + s );
333- System .err .println ("packagename: " + packageName );
445+ System .err .println ("packagename: " + packagePath );
334446 System .err .println ("url: " + url );
335447
336448 String filename = URLDecoder .decode (url .getFile (), "UTF-8" );
337- ArrayList <String > packages = new ArrayList <String >();
449+ Set <String > packages = new HashSet <String >();
338450 if (url .getProtocol ().equals ("jar" ))
339451 {
340452 filename = filename .substring (5 , filename .indexOf ("!" ));
@@ -344,16 +456,15 @@ private static void completePackage(String packageName)
344456 while (entries .hasMoreElements ())
345457 {
346458 String name = entries .nextElement ().getName ();
347- if (name .startsWith (packageName ))
459+ if (name .startsWith (packagePath ))
348460 {
349- name = name .substring (packageName .length ()+1 );
461+ name = name .substring (packagePath .length ()+1 );
350462 int idx = name .indexOf ('/' );
351463 if (idx != -1 )
352464 {
353465 name = name .substring (0 , idx );
354- if (! packages .contains (name ))
466+ if (packages .add (name ))
355467 {
356- packages .add (name );
357468 System .out .println (name + "\t package" + sep + name );
358469 }
359470 continue ;
@@ -417,6 +528,11 @@ public static void main(String... unusedargs)
417528 System .err .println ("quitting upon request" );
418529 return ;
419530 }
531+ else if (args [0 ].equals ("-importclass" ))
532+ {
533+ importClass (args [1 ]);
534+ continue ;
535+ }
420536 else if (args [0 ].equals ("-findclass" ))
421537 {
422538 String line = null ;
0 commit comments