• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (c) 2002-2007, Marc Prud'hommeaux. All rights reserved.
3  *
4  * This software is distributable under the BSD license. See the terms of the
5  * BSD license in the documentation provided with this software.
6  */
7 package jline;
8 
9 import java.io.*;
10 import java.net.*;
11 import java.util.*;
12 import java.util.jar.JarEntry;
13 import java.util.jar.JarFile;
14 
15 /**
16  *  A Completor implementation that completes java class names. By default,
17  *  it scans the java class path to locate all the classes.
18  *
19  *  @author  <a href="mailto:mwp1@cornell.edu">Marc Prud'hommeaux</a>
20  */
21 public class ClassNameCompletor extends SimpleCompletor {
22 
23     /**
24      *  Complete candidates using all the classes available in the
25      *  java <em>CLASSPATH</em>.
26      */
ClassNameCompletor()27     public ClassNameCompletor() throws IOException {
28         this(null);
29     }
30 
ClassNameCompletor(final SimpleCompletorFilter filter)31     public ClassNameCompletor(final SimpleCompletorFilter filter)
32         throws IOException {
33         super(getClassNames(), filter);
34         setDelimiter(".");
35     }
36 
getClassNames()37     public static String[] getClassNames() throws IOException {
38         Set urls = new HashSet();
39 
40         for (ClassLoader loader = ClassNameCompletor.class
41             .getClassLoader(); loader != null;
42                  loader = loader.getParent()) {
43             if (!(loader instanceof URLClassLoader)) {
44                 continue;
45             }
46 
47             urls.addAll(Arrays.asList(((URLClassLoader) loader).getURLs()));
48         }
49 
50         // Now add the URL that holds java.lang.String. This is because
51         // some JVMs do not report the core classes jar in the list of
52         // class loaders.
53         Class[] systemClasses = new Class[] {
54             String.class, javax.swing.JFrame.class
55             };
56 
57         for (int i = 0; i < systemClasses.length; i++) {
58             URL classURL = systemClasses[i].getResource("/"
59                 + systemClasses[i].getName() .replace('.', '/') + ".class");
60 
61             if (classURL != null) {
62                 URLConnection uc = (URLConnection) classURL.openConnection();
63 
64                 if (uc instanceof JarURLConnection) {
65                     urls.add(((JarURLConnection) uc).getJarFileURL());
66                 }
67             }
68         }
69 
70         Set classes = new HashSet();
71 
72         for (Iterator i = urls.iterator(); i.hasNext();) {
73             URL url = (URL) i.next();
74             File file = new File(url.getFile());
75 
76             if (file.isDirectory()) {
77                 Set files = getClassFiles(file.getAbsolutePath(),
78                     new HashSet(), file, new int[] { 200 });
79                 classes.addAll(files);
80 
81                 continue;
82             }
83 
84             if ((file == null) || !file.isFile()) // TODO: handle directories
85              {
86                 continue;
87             }
88             if (!file.toString().endsWith (".jar"))
89                 continue;
90 
91             JarFile jf = new JarFile(file);
92 
93             for (Enumeration e = jf.entries(); e.hasMoreElements();) {
94                 JarEntry entry = (JarEntry) e.nextElement();
95 
96                 if (entry == null) {
97                     continue;
98                 }
99 
100                 String name = entry.getName();
101 
102                 if (!name.endsWith(".class")) // only use class files
103                  {
104                     continue;
105                 }
106 
107                 classes.add(name);
108             }
109         }
110 
111         // now filter classes by changing "/" to "." and trimming the
112         // trailing ".class"
113         Set classNames = new TreeSet();
114 
115         for (Iterator i = classes.iterator(); i.hasNext();) {
116             String name = (String) i.next();
117             classNames.add(name.replace('/', '.').
118                 substring(0, name.length() - 6));
119         }
120 
121         return (String[]) classNames.toArray(new String[classNames.size()]);
122     }
123 
getClassFiles(String root, Set holder, File directory, int[] maxDirectories)124     private static Set getClassFiles(String root, Set holder, File directory,
125         int[] maxDirectories) {
126         // we have passed the maximum number of directories to scan
127         if (maxDirectories[0]-- < 0) {
128             return holder;
129         }
130 
131         File[] files = directory.listFiles();
132 
133         for (int i = 0; (files != null) && (i < files.length); i++) {
134             String name = files[i].getAbsolutePath();
135 
136             if (!(name.startsWith(root))) {
137                 continue;
138             } else if (files[i].isDirectory()) {
139                 getClassFiles(root, holder, files[i], maxDirectories);
140             } else if (files[i].getName().endsWith(".class")) {
141                 holder.add(files[i].getAbsolutePath().
142                     substring(root.length() + 1));
143             }
144         }
145 
146         return holder;
147     }
148 }
149