/*
* ProActive Parallel Suite(TM):
* The Open Source library for parallel and distributed
* Workflows & Scheduling, Orchestration, Cloud Automation
* and Big Data Analysis on Enterprise Grids & Clouds.
*
* Copyright (c) 2007 - 2017 ActiveEon
* Contact: contact@activeeon.com
*
* This library is free software: you can redistribute it and/or
* modify it under the terms of the GNU Affero General Public License
* as published by the Free Software Foundation: version 3 of
* the License.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Affero General Public License for more details.
*
* You should have received a copy of the GNU Affero General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*
* If needed, contact us to obtain a release under GPL Version 2 or 3
* or a different license than the AGPL.
*/
package org.ow2.proactive_grid_cloud_portal.cli.console;
import java.io.*;
import java.net.*;
import java.util.*;
import java.util.jar.JarEntry;
import java.util.jar.JarFile;
/**
* A Completor implementation that completes java class names. By default,
* it scans the java class path to locate all the classes.
*
* @author <a href="mailto:mwp1@cornell.edu">Marc Prud'hommeaux</a>
*/
public class ClassNameCompletor extends SimpleCompletor {
/**
* Complete candidates using all the classes available in the
* java <em>CLASSPATH</em>.
*/
public ClassNameCompletor() throws IOException {
this(null);
}
public ClassNameCompletor(final SimpleCompletor.SimpleCompletorFilter filter) throws IOException {
super(getClassNames(), filter);
setDelimiter(".");
}
public static String[] getClassNames() throws IOException {
Set urls = new HashSet();
for (ClassLoader loader = ClassNameCompletor.class.getClassLoader(); loader != null; loader = loader.getParent()) {
if (!(loader instanceof URLClassLoader)) {
continue;
}
urls.addAll(Arrays.asList(((URLClassLoader) loader).getURLs()));
}
// Now add the URL that holds java.lang.String. This is because
// some JVMs do not report the core classes jar in the list of
// class loaders.
Class[] systemClasses = new Class[] { String.class, javax.swing.JFrame.class };
for (int i = 0; i < systemClasses.length; i++) {
URL classURL = systemClasses[i].getResource("/" + systemClasses[i].getName().replace('.', '/') + ".class");
if (classURL != null) {
URLConnection uc = (URLConnection) classURL.openConnection();
if (uc instanceof JarURLConnection) {
urls.add(((JarURLConnection) uc).getJarFileURL());
}
}
}
Set classes = new HashSet();
for (Iterator i = urls.iterator(); i.hasNext();) {
URL url = (URL) i.next();
File file = new File(url.getFile());
if (file.isDirectory()) {
Set files = getClassFiles(file.getAbsolutePath(), new HashSet(), file, new int[] { 200 });
classes.addAll(files);
continue;
}
if ((file == null) || !file.isFile()) // TODO: handle directories
{
continue;
}
if (!file.toString().endsWith(".jar"))
continue;
JarFile jf = new JarFile(file);
for (Enumeration e = jf.entries(); e.hasMoreElements();) {
JarEntry entry = (JarEntry) e.nextElement();
if (entry == null) {
continue;
}
String name = entry.getName();
if (!name.endsWith(".class")) // only use class files
{
continue;
}
classes.add(name);
}
}
// now filter classes by changing "/" to "." and trimming the
// trailing ".class"
Set classNames = new TreeSet();
for (Iterator i = classes.iterator(); i.hasNext();) {
String name = (String) i.next();
classNames.add(name.replace('/', '.').substring(0, name.length() - 6));
}
return (String[]) classNames.toArray(new String[classNames.size()]);
}
private static Set getClassFiles(String root, Set holder, File directory, int[] maxDirectories) {
// we have passed the maximum number of directories to scan
if (maxDirectories[0]-- < 0) {
return holder;
}
File[] files = directory.listFiles();
for (int i = 0; (files != null) && (i < files.length); i++) {
String name = files[i].getAbsolutePath();
if (!(name.startsWith(root))) {
continue;
} else if (files[i].isDirectory()) {
getClassFiles(root, holder, files[i], maxDirectories);
} else if (files[i].getName().endsWith(".class")) {
holder.add(files[i].getAbsolutePath().substring(root.length() + 1));
}
}
return holder;
}
}