|
|
@ -1,670 +0,0 @@ |
|
|
/** |
|
|
|
|
|
* Reflection.java |
|
|
|
|
|
* |
|
|
|
|
|
* A utility class for javacomplete mainly for reading class or package information. |
|
|
|
|
|
* Version: 0.77 |
|
|
|
|
|
* Maintainer: cheng fang <fangread@yahoo.com.cn> |
|
|
|
|
|
* Last Change: 2007-09-16 |
|
|
|
|
|
* Copyright: Copyright (C) 2007 cheng fang. All rights reserved. |
|
|
|
|
|
* License: Vim License (see vim's :help license) |
|
|
|
|
|
* |
|
|
|
|
|
*/ |
|
|
|
|
|
|
|
|
|
|
|
import java.lang.reflect.*; |
|
|
|
|
|
import java.io.*; |
|
|
|
|
|
import java.util.*; |
|
|
|
|
|
import java.util.zip.*; |
|
|
|
|
|
|
|
|
|
|
|
class Reflection { |
|
|
|
|
|
static final String VERSION = "0.77"; |
|
|
|
|
|
|
|
|
|
|
|
static final int OPTION_FIELD = 1; |
|
|
|
|
|
static final int OPTION_METHOD = 2; |
|
|
|
|
|
static final int OPTION_STATIC_FIELD = 4; |
|
|
|
|
|
static final int OPTION_STATIC_METHOD = 8; |
|
|
|
|
|
static final int OPTION_CONSTRUCTOR = 16; |
|
|
|
|
|
static final int OPTION_STATIC = 12; // compound static
|
|
|
|
|
|
static final int OPTION_INSTANCE = 15; // compound instance
|
|
|
|
|
|
static final int OPTION_ALL = 31; // compound all
|
|
|
|
|
|
static final int OPTION_SUPER = 32; |
|
|
|
|
|
static final int OPTION_SAME_PACKAGE = 64; |
|
|
|
|
|
|
|
|
|
|
|
static final int STRATEGY_ALPHABETIC = 128; |
|
|
|
|
|
static final int STRATEGY_HIERARCHY = 256; |
|
|
|
|
|
static final int STRATEGY_DEFAULT = 512; |
|
|
|
|
|
|
|
|
|
|
|
static final int RETURN_ALL_PACKAGE_INFO = 0x1000; |
|
|
|
|
|
|
|
|
|
|
|
static final String KEY_NAME = "'n':"; // "'name':";
|
|
|
|
|
|
static final String KEY_TYPE = "'t':"; // "'type':";
|
|
|
|
|
|
static final String KEY_MODIFIER = "'m':"; // "'modifier':";
|
|
|
|
|
|
static final String KEY_PARAMETERTYPES = "'p':"; // "'parameterTypes':";
|
|
|
|
|
|
static final String KEY_RETURNTYPE = "'r':"; // "'returnType':";
|
|
|
|
|
|
static final String KEY_DESCRIPTION = "'d':"; // "'description':";
|
|
|
|
|
|
static final String KEY_DECLARING_CLASS = "'c':"; // "'declaringclass':";
|
|
|
|
|
|
|
|
|
|
|
|
static final String NEWLINE = ""; // "\r\n"
|
|
|
|
|
|
|
|
|
|
|
|
static boolean debug_mode = false; |
|
|
|
|
|
|
|
|
|
|
|
static Hashtable htClasspath = new Hashtable(); |
|
|
|
|
|
|
|
|
|
|
|
public static boolean existed(String fqn) { |
|
|
|
|
|
boolean result = false; |
|
|
|
|
|
try { |
|
|
|
|
|
Class.forName(fqn); |
|
|
|
|
|
result = true; |
|
|
|
|
|
} |
|
|
|
|
|
catch (Exception ex) { |
|
|
|
|
|
} |
|
|
|
|
|
return result; |
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
public static String existedAndRead(String fqns) { |
|
|
|
|
|
Hashtable mapPackages = new Hashtable(); // qualified name --> StringBuffer
|
|
|
|
|
|
Hashtable mapClasses = new Hashtable(); // qualified name --> StringBuffer
|
|
|
|
|
|
|
|
|
|
|
|
for (StringTokenizer st = new StringTokenizer(fqns, ","); st.hasMoreTokens(); ) { |
|
|
|
|
|
String fqn = st.nextToken(); |
|
|
|
|
|
try { |
|
|
|
|
|
Class clazz = Class.forName(fqn); |
|
|
|
|
|
putClassInfo(mapClasses, clazz); |
|
|
|
|
|
} |
|
|
|
|
|
catch (Exception ex) { |
|
|
|
|
|
String binaryName = fqn; |
|
|
|
|
|
boolean found = false; |
|
|
|
|
|
while (true) { |
|
|
|
|
|
try { |
|
|
|
|
|
int lastDotPos = binaryName.lastIndexOf('.'); |
|
|
|
|
|
if (lastDotPos == -1) |
|
|
|
|
|
break; |
|
|
|
|
|
binaryName = binaryName.substring(0, lastDotPos) + '$' + binaryName.substring(lastDotPos+1, binaryName.length()); |
|
|
|
|
|
Class clazz = Class.forName(binaryName); |
|
|
|
|
|
putClassInfo(mapClasses, clazz); |
|
|
|
|
|
found = true; |
|
|
|
|
|
break; |
|
|
|
|
|
} |
|
|
|
|
|
catch (Exception e) { |
|
|
|
|
|
} |
|
|
|
|
|
} |
|
|
|
|
|
if (!found) |
|
|
|
|
|
putPackageInfo(mapPackages, fqn); |
|
|
|
|
|
} |
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
if (mapPackages.size() > 0 || mapClasses.size() > 0) { |
|
|
|
|
|
StringBuffer sb = new StringBuffer(4096); |
|
|
|
|
|
sb.append("{"); |
|
|
|
|
|
for (Enumeration e = mapPackages.keys(); e.hasMoreElements(); ) { |
|
|
|
|
|
String s = (String)e.nextElement(); |
|
|
|
|
|
sb.append("'").append( s.replace('$', '.') ).append("':").append(mapPackages.get(s)).append(","); |
|
|
|
|
|
} |
|
|
|
|
|
for (Enumeration e = mapClasses.keys(); e.hasMoreElements(); ) { |
|
|
|
|
|
String s = (String)e.nextElement(); |
|
|
|
|
|
sb.append("'").append( s.replace('$', '.') ).append("':").append(mapClasses.get(s)).append(","); |
|
|
|
|
|
} |
|
|
|
|
|
sb.append("}"); |
|
|
|
|
|
return sb.toString(); |
|
|
|
|
|
} |
|
|
|
|
|
else |
|
|
|
|
|
return ""; |
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
private static String getPackageList(String fqn) { |
|
|
|
|
|
Hashtable mapPackages = new Hashtable(); |
|
|
|
|
|
putPackageInfo(mapPackages, fqn); |
|
|
|
|
|
return mapPackages.size() > 0 ? mapPackages.get(fqn).toString() : ""; |
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
private static Hashtable collectClassPath() { |
|
|
|
|
|
if (!htClasspath.isEmpty()) |
|
|
|
|
|
return htClasspath; |
|
|
|
|
|
|
|
|
|
|
|
// runtime classes
|
|
|
|
|
|
if ("Kaffe".equals(System.getProperty("java.vm.name"))) { |
|
|
|
|
|
addClasspathesFromDir(System.getProperty("java.home") + File.separator + "share" + File.separator + "kaffe" + File.separator); |
|
|
|
|
|
} |
|
|
|
|
|
else if ("GNU libgcj".equals(System.getProperty("java.vm.name"))) { |
|
|
|
|
|
if (new File(System.getProperty("sun.boot.class.path")).exists()) |
|
|
|
|
|
htClasspath.put(System.getProperty("sun.boot.class.path"), ""); |
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
if (System.getProperty("java.vendor").toLowerCase(Locale.US).indexOf("microsoft") >= 0) { |
|
|
|
|
|
// `*.ZIP` files in `Packages` directory
|
|
|
|
|
|
addClasspathesFromDir(System.getProperty("java.home") + File.separator + "Packages" + File.separator); |
|
|
|
|
|
} |
|
|
|
|
|
else { |
|
|
|
|
|
// the following code works for several kinds of JDK
|
|
|
|
|
|
// - JDK1.1: classes.zip
|
|
|
|
|
|
// - JDK1.2+: rt.jar
|
|
|
|
|
|
// - JDK1.4+ of Sun and Apple: rt.jar + jce.jar + jsse.jar
|
|
|
|
|
|
// - JDK1.4 of IBM split rt.jar into core.jar, graphics.jar, server.jar
|
|
|
|
|
|
// combined jce.jar and jsse.jar into security.jar
|
|
|
|
|
|
// - JDK for MacOS X split rt.jar into classes.jar, ui.jar in Classes directory
|
|
|
|
|
|
addClasspathesFromDir(System.getProperty("java.home") + File.separator + "lib" + File.separator); |
|
|
|
|
|
addClasspathesFromDir(System.getProperty("java.home") + File.separator + "jre" + File.separator + "lib" + File.separator); |
|
|
|
|
|
addClasspathesFromDir(System.getProperty("java.home") + File.separator + ".." + File.separator + "Classes" + File.separator); |
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
// ext
|
|
|
|
|
|
String extdirs = System.getProperty("java.ext.dirs"); |
|
|
|
|
|
for (StringTokenizer st = new StringTokenizer(extdirs, File.pathSeparator); st.hasMoreTokens(); ) { |
|
|
|
|
|
addClasspathesFromDir(st.nextToken() + File.separator); |
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
// user classpath
|
|
|
|
|
|
String classPath = System.getProperty("java.class.path"); |
|
|
|
|
|
StringTokenizer st = new StringTokenizer(classPath, File.pathSeparator); |
|
|
|
|
|
while (st.hasMoreTokens()) { |
|
|
|
|
|
String path = st.nextToken(); |
|
|
|
|
|
File f = new File(path); |
|
|
|
|
|
if (!f.exists()) |
|
|
|
|
|
continue; |
|
|
|
|
|
|
|
|
|
|
|
if (path.endsWith(".jar") || path.endsWith(".zip")) |
|
|
|
|
|
htClasspath.put(f.toString(), ""); |
|
|
|
|
|
else { |
|
|
|
|
|
if (f.isDirectory()) |
|
|
|
|
|
htClasspath.put(f.toString(), ""); |
|
|
|
|
|
} |
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
return htClasspath; |
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
private static void addClasspathesFromDir(String dirpath) { |
|
|
|
|
|
File dir = new File(dirpath); |
|
|
|
|
|
if (dir.isDirectory()) { |
|
|
|
|
|
String[] items = dir.list(); // use list() instead of listFiles() since the latter are introduced in 1.2
|
|
|
|
|
|
for (int i = 0; i < items.length; i++) { |
|
|
|
|
|
File f = new File(dirpath + items[i]); |
|
|
|
|
|
if (!f.exists()) |
|
|
|
|
|
continue; |
|
|
|
|
|
|
|
|
|
|
|
if (items[i].endsWith(".jar") || items[i].endsWith(".zip") || items[i].endsWith(".ZIP")) { |
|
|
|
|
|
htClasspath.put(f.toString(), ""); |
|
|
|
|
|
} |
|
|
|
|
|
else if (items.equals("classes")) { |
|
|
|
|
|
if (f.isDirectory()) |
|
|
|
|
|
htClasspath.put(f.toString(), ""); |
|
|
|
|
|
} |
|
|
|
|
|
} |
|
|
|
|
|
} |
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
/** |
|
|
|
|
|
* If name is empty, put all loadable package info into map once. |
|
|
|
|
|
*/ |
|
|
|
|
|
private static void putPackageInfo(Hashtable map, String name) { |
|
|
|
|
|
String prefix = name.replace('.', '/') + "/"; |
|
|
|
|
|
Hashtable subpackages = new Hashtable(); |
|
|
|
|
|
Hashtable classes = new Hashtable(); |
|
|
|
|
|
for (Enumeration e = collectClassPath().keys(); e.hasMoreElements(); ) { |
|
|
|
|
|
String path = (String)e.nextElement(); |
|
|
|
|
|
if (path.endsWith(".jar") || path.endsWith(".zip")) |
|
|
|
|
|
appendListFromJar(subpackages, classes, path, prefix); |
|
|
|
|
|
else |
|
|
|
|
|
appendListFromFolder(subpackages, classes, path, prefix); |
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
if (subpackages.size() > 0 || classes.size() > 0) { |
|
|
|
|
|
StringBuffer sb = new StringBuffer(1024); |
|
|
|
|
|
sb.append("{'tag':'PACKAGE','subpackages':["); |
|
|
|
|
|
for (Enumeration e = subpackages.keys(); e.hasMoreElements(); ) { |
|
|
|
|
|
sb.append("'").append(e.nextElement()).append("',"); |
|
|
|
|
|
} |
|
|
|
|
|
sb.append("],'classes':["); |
|
|
|
|
|
for (Enumeration e = classes.keys(); e.hasMoreElements(); ) { |
|
|
|
|
|
sb.append("'").append(e.nextElement()).append("',"); |
|
|
|
|
|
} |
|
|
|
|
|
sb.append("]}"); |
|
|
|
|
|
map.put(name, sb.toString()); |
|
|
|
|
|
} |
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
public static void appendListFromJar(Hashtable subpackages, Hashtable classes, String path, String prefix) { |
|
|
|
|
|
try { |
|
|
|
|
|
for (Enumeration entries = new ZipFile(path).entries(); entries.hasMoreElements(); ) { |
|
|
|
|
|
String entry = entries.nextElement().toString(); |
|
|
|
|
|
int len = entry.length(); |
|
|
|
|
|
if (entry.endsWith(".class") && entry.indexOf('$') == -1 |
|
|
|
|
|
&& entry.startsWith(prefix)) { |
|
|
|
|
|
int splitPos = entry.indexOf('/', prefix.length()); |
|
|
|
|
|
String shortname = entry.substring(prefix.length(), splitPos == -1 ? entry.length()-6 : splitPos); |
|
|
|
|
|
if (splitPos == -1) { |
|
|
|
|
|
if (!classes.containsKey(shortname)) |
|
|
|
|
|
classes.put(shortname, ""); //classes.put(shortname, "{'tag':'CLASSDEF','name':'"+shortname+"'}");
|
|
|
|
|
|
} |
|
|
|
|
|
else { |
|
|
|
|
|
if (!subpackages.containsKey(shortname)) |
|
|
|
|
|
subpackages.put(shortname, ""); //subpackages.put(shortname, "{'tag':'PACKAGE','name':'" +shortname+"'}");
|
|
|
|
|
|
} |
|
|
|
|
|
} |
|
|
|
|
|
} |
|
|
|
|
|
} |
|
|
|
|
|
catch (Throwable e) { |
|
|
|
|
|
//e.printStackTrace();
|
|
|
|
|
|
} |
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
public static void appendListFromFolder(Hashtable subpackages, Hashtable classes, String path, String prefix) { |
|
|
|
|
|
try { |
|
|
|
|
|
String fullPath = path + "/" + prefix; |
|
|
|
|
|
File file = new File(fullPath); |
|
|
|
|
|
if (file.isDirectory()) { |
|
|
|
|
|
String[] descents = file.list(); |
|
|
|
|
|
for (int i = 0; i < descents.length; i++) { |
|
|
|
|
|
if (descents[i].indexOf('$') == -1) { |
|
|
|
|
|
if (descents[i].endsWith(".class")) { |
|
|
|
|
|
String shortname = descents[i].substring(0, descents[i].length()-6); |
|
|
|
|
|
if (!classes.containsKey(shortname)) |
|
|
|
|
|
classes.put(shortname, ""); |
|
|
|
|
|
} |
|
|
|
|
|
else if ((new File(fullPath + "/" + descents[i])).isDirectory()) { |
|
|
|
|
|
if (!subpackages.containsKey(descents[i])) |
|
|
|
|
|
subpackages.put(descents[i], ""); |
|
|
|
|
|
} |
|
|
|
|
|
} |
|
|
|
|
|
} |
|
|
|
|
|
} |
|
|
|
|
|
} |
|
|
|
|
|
catch (Throwable e) { |
|
|
|
|
|
} |
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
private static int INDEX_PACKAGE = 0; |
|
|
|
|
|
private static int INDEX_CLASS = 1; |
|
|
|
|
|
|
|
|
|
|
|
// generate information of all packages in jar files.
|
|
|
|
|
|
public static String getPackageList() { |
|
|
|
|
|
Hashtable map = new Hashtable(); |
|
|
|
|
|
|
|
|
|
|
|
for (Enumeration e = collectClassPath().keys(); e.hasMoreElements(); ) { |
|
|
|
|
|
String path = (String)e.nextElement(); |
|
|
|
|
|
if (path.endsWith(".jar") || path.endsWith(".zip")) |
|
|
|
|
|
appendListFromJar(path, map); |
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
StringBuffer sb = new StringBuffer(4096); |
|
|
|
|
|
sb.append("{"); |
|
|
|
|
|
//sb.append("'*':'").append( map.remove("") ).append("',"); // default package
|
|
|
|
|
|
for (Enumeration e = map.keys(); e.hasMoreElements(); ) { |
|
|
|
|
|
String s = (String)e.nextElement(); |
|
|
|
|
|
StringBuffer[] sbs = (StringBuffer[])map.get(s); |
|
|
|
|
|
sb.append("'").append( s.replace('/', '.') ).append("':") |
|
|
|
|
|
.append("{'tag':'PACKAGE'"); |
|
|
|
|
|
if (sbs[INDEX_PACKAGE].length() > 0) |
|
|
|
|
|
sb.append(",'subpackages':[").append(sbs[INDEX_PACKAGE]).append("]"); |
|
|
|
|
|
if (sbs[INDEX_CLASS].length() > 0) |
|
|
|
|
|
sb.append(",'classes':[").append(sbs[INDEX_CLASS]).append("]"); |
|
|
|
|
|
sb.append("},"); |
|
|
|
|
|
} |
|
|
|
|
|
sb.append("}"); |
|
|
|
|
|
return sb.toString(); |
|
|
|
|
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
public static void appendListFromJar(String path, Hashtable map) { |
|
|
|
|
|
try { |
|
|
|
|
|
for (Enumeration entries = new ZipFile(path).entries(); entries.hasMoreElements(); ) { |
|
|
|
|
|
String entry = entries.nextElement().toString(); |
|
|
|
|
|
int len = entry.length(); |
|
|
|
|
|
if (entry.endsWith(".class") && entry.indexOf('$') == -1) { |
|
|
|
|
|
int slashpos = entry.lastIndexOf('/'); |
|
|
|
|
|
String parent = entry.substring(0, slashpos); |
|
|
|
|
|
String child = entry.substring(slashpos+1, len-6); |
|
|
|
|
|
putItem(map, parent, child, INDEX_CLASS); |
|
|
|
|
|
|
|
|
|
|
|
slashpos = parent.lastIndexOf('/'); |
|
|
|
|
|
if (slashpos != -1) { |
|
|
|
|
|
AddToParent(map, parent.substring(0, slashpos), parent.substring(slashpos+1)); |
|
|
|
|
|
} |
|
|
|
|
|
} |
|
|
|
|
|
} |
|
|
|
|
|
} |
|
|
|
|
|
catch (Throwable e) { |
|
|
|
|
|
//e.printStackTrace();
|
|
|
|
|
|
} |
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
public static void putItem(Hashtable map, String parent, String child, int index) { |
|
|
|
|
|
StringBuffer[] sbs = (StringBuffer[])map.get(parent); |
|
|
|
|
|
if (sbs == null) { |
|
|
|
|
|
sbs = new StringBuffer[] { new StringBuffer(256), // packages
|
|
|
|
|
|
new StringBuffer(256) // classes
|
|
|
|
|
|
}; |
|
|
|
|
|
} |
|
|
|
|
|
if (sbs[index].toString().indexOf("'" + child + "',") == -1) |
|
|
|
|
|
sbs[index].append("'").append(child).append("',"); |
|
|
|
|
|
map.put(parent, sbs); |
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
public static void AddToParent(Hashtable map, String parent, String child) { |
|
|
|
|
|
putItem(map, parent, child, INDEX_PACKAGE); |
|
|
|
|
|
|
|
|
|
|
|
int slashpos = parent.lastIndexOf('/'); |
|
|
|
|
|
if (slashpos != -1) { |
|
|
|
|
|
AddToParent(map, parent.substring(0, slashpos), parent.substring(slashpos+1)); |
|
|
|
|
|
} |
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
public static String getClassInfo(String className) { |
|
|
|
|
|
Hashtable mapClasses = new Hashtable(); |
|
|
|
|
|
try { |
|
|
|
|
|
Class clazz = Class.forName(className); |
|
|
|
|
|
putClassInfo(mapClasses, clazz); |
|
|
|
|
|
} |
|
|
|
|
|
catch (Exception ex) { |
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
if (mapClasses.size() == 1) { |
|
|
|
|
|
return mapClasses.get(className).toString(); // return {...}
|
|
|
|
|
|
} |
|
|
|
|
|
else if (mapClasses.size() > 1) { |
|
|
|
|
|
StringBuffer sb = new StringBuffer(4096); |
|
|
|
|
|
sb.append("["); |
|
|
|
|
|
for (Enumeration e = mapClasses.keys(); e.hasMoreElements(); ) { |
|
|
|
|
|
String s = (String)e.nextElement(); |
|
|
|
|
|
sb.append(mapClasses.get(s)).append(","); |
|
|
|
|
|
} |
|
|
|
|
|
sb.append("]"); |
|
|
|
|
|
return sb.toString(); // return [...]
|
|
|
|
|
|
} |
|
|
|
|
|
else |
|
|
|
|
|
return ""; |
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
private static void putClassInfo(Hashtable map, Class clazz) { |
|
|
|
|
|
if (map.containsKey(clazz.getName())) |
|
|
|
|
|
return ; |
|
|
|
|
|
|
|
|
|
|
|
try { |
|
|
|
|
|
StringBuffer sb = new StringBuffer(1024); |
|
|
|
|
|
sb.append("{") |
|
|
|
|
|
.append("'tag':'CLASSDEF',").append(NEWLINE) |
|
|
|
|
|
.append("'flags':'").append(Integer.toString(clazz.getModifiers(), 2)).append("',").append(NEWLINE) |
|
|
|
|
|
.append("'name':'").append(clazz.getName().replace('$', '.')).append("',").append(NEWLINE) |
|
|
|
|
|
//.append("'package':'").append(clazz.getPackage().getName()).append("',").append(NEWLINE) // no getPackage() in JDK1.1
|
|
|
|
|
|
.append("'classpath':'1',").append(NEWLINE) |
|
|
|
|
|
.append("'fqn':'").append(clazz.getName().replace('$', '.')).append("',").append(NEWLINE); |
|
|
|
|
|
|
|
|
|
|
|
Class[] interfaces = clazz.getInterfaces(); |
|
|
|
|
|
if (clazz.isInterface()) { |
|
|
|
|
|
sb.append("'extends':["); |
|
|
|
|
|
} else { |
|
|
|
|
|
Class superclass = clazz.getSuperclass(); |
|
|
|
|
|
if (superclass != null && !"java.lang.Object".equals(superclass.getName())) { |
|
|
|
|
|
sb.append("'extends':['").append(superclass.getName().replace('$', '.')).append("'],").append(NEWLINE); |
|
|
|
|
|
putClassInfo(map, superclass); // !!
|
|
|
|
|
|
} |
|
|
|
|
|
sb.append("'implements':["); |
|
|
|
|
|
} |
|
|
|
|
|
for (int i = 0, n = interfaces.length; i < n; i++) { |
|
|
|
|
|
sb.append("'").append(interfaces[i].getName().replace('$', '.')).append("',"); |
|
|
|
|
|
putClassInfo(map, interfaces[i]); // !!
|
|
|
|
|
|
} |
|
|
|
|
|
sb.append("],").append(NEWLINE);; |
|
|
|
|
|
|
|
|
|
|
|
Constructor[] ctors = clazz.getConstructors(); |
|
|
|
|
|
sb.append("'ctors':["); |
|
|
|
|
|
for (int i = 0, n = ctors.length; i < n; i++) { |
|
|
|
|
|
Constructor ctor = ctors[i]; |
|
|
|
|
|
sb.append("{"); |
|
|
|
|
|
appendModifier(sb, ctor.getModifiers()); |
|
|
|
|
|
appendParameterTypes(sb, ctor.getParameterTypes()); |
|
|
|
|
|
sb.append(KEY_DESCRIPTION).append("'").append(ctors[i].toString()).append("'"); |
|
|
|
|
|
sb.append("},").append(NEWLINE); |
|
|
|
|
|
} |
|
|
|
|
|
sb.append("], ").append(NEWLINE); |
|
|
|
|
|
|
|
|
|
|
|
Field[] fields = clazz.getFields(); |
|
|
|
|
|
//java.util.Arrays.sort(fields, comparator);
|
|
|
|
|
|
sb.append("'fields':["); |
|
|
|
|
|
for (int i = 0, n = fields.length; i < n; i++) { |
|
|
|
|
|
Field f = fields[i]; |
|
|
|
|
|
int modifier = f.getModifiers(); |
|
|
|
|
|
sb.append("{"); |
|
|
|
|
|
sb.append(KEY_NAME).append("'").append(f.getName()).append("',"); |
|
|
|
|
|
if (!f.getDeclaringClass().getName().equals(clazz.getName())) |
|
|
|
|
|
sb.append(KEY_DECLARING_CLASS).append("'").append(f.getDeclaringClass().getName()).append("',"); |
|
|
|
|
|
appendModifier(sb, modifier); |
|
|
|
|
|
sb.append(KEY_TYPE).append("'").append(f.getType().getName()).append("'"); |
|
|
|
|
|
sb.append("},").append(NEWLINE); |
|
|
|
|
|
} |
|
|
|
|
|
sb.append("], ").append(NEWLINE); |
|
|
|
|
|
|
|
|
|
|
|
Method[] methods = clazz.getMethods(); |
|
|
|
|
|
//java.util.Arrays.sort(methods, comparator);
|
|
|
|
|
|
sb.append("'methods':["); |
|
|
|
|
|
for (int i = 0, n = methods.length; i < n; i++) { |
|
|
|
|
|
Method m = methods[i]; |
|
|
|
|
|
int modifier = m.getModifiers(); |
|
|
|
|
|
sb.append("{"); |
|
|
|
|
|
sb.append(KEY_NAME).append("'").append(m.getName()).append("',"); |
|
|
|
|
|
if (!m.getDeclaringClass().getName().equals(clazz.getName())) |
|
|
|
|
|
sb.append(KEY_DECLARING_CLASS).append("'").append(m.getDeclaringClass().getName()).append("',"); |
|
|
|
|
|
appendModifier(sb, modifier); |
|
|
|
|
|
sb.append(KEY_RETURNTYPE).append("'").append(m.getReturnType().getName()).append("',"); |
|
|
|
|
|
appendParameterTypes(sb, m.getParameterTypes()); |
|
|
|
|
|
sb.append(KEY_DESCRIPTION).append("'").append(m.toString()).append("'"); |
|
|
|
|
|
sb.append("},").append(NEWLINE); |
|
|
|
|
|
} |
|
|
|
|
|
sb.append("], ").append(NEWLINE); |
|
|
|
|
|
|
|
|
|
|
|
Class[] classes = clazz.getClasses(); |
|
|
|
|
|
sb.append("'classes': ["); |
|
|
|
|
|
for (int i = 0, n = classes.length; i < n; i++) { |
|
|
|
|
|
Class c = classes[i]; |
|
|
|
|
|
sb.append("'").append(c.getName().replace('$', '.')).append("',"); |
|
|
|
|
|
putClassInfo(map, c); // !!
|
|
|
|
|
|
} |
|
|
|
|
|
sb.append("], ").append(NEWLINE); |
|
|
|
|
|
|
|
|
|
|
|
appendDeclaredMembers(map, clazz, sb); |
|
|
|
|
|
|
|
|
|
|
|
sb.append("}"); |
|
|
|
|
|
map.put(clazz.getName(), sb); |
|
|
|
|
|
} |
|
|
|
|
|
catch (Exception ex) { |
|
|
|
|
|
//ex.printStackTrace();
|
|
|
|
|
|
} |
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
private static void appendDeclaredMembers(Hashtable map, Class clazz, StringBuffer sb) { |
|
|
|
|
|
Constructor[] ctors = clazz.getDeclaredConstructors(); |
|
|
|
|
|
sb.append("'declared_ctors':["); |
|
|
|
|
|
for (int i = 0, n = ctors.length; i < n; i++) { |
|
|
|
|
|
Constructor ctor = ctors[i]; |
|
|
|
|
|
if (!Modifier.isPublic(ctor.getModifiers())) { |
|
|
|
|
|
sb.append("{"); |
|
|
|
|
|
appendModifier(sb, ctor.getModifiers()); |
|
|
|
|
|
appendParameterTypes(sb, ctor.getParameterTypes()); |
|
|
|
|
|
sb.append(KEY_DESCRIPTION).append("'").append(ctors[i].toString()).append("'"); |
|
|
|
|
|
sb.append("},").append(NEWLINE); |
|
|
|
|
|
} |
|
|
|
|
|
} |
|
|
|
|
|
sb.append("], ").append(NEWLINE); |
|
|
|
|
|
|
|
|
|
|
|
Field[] fields = clazz.getDeclaredFields(); |
|
|
|
|
|
sb.append("'declared_fields':["); |
|
|
|
|
|
for (int i = 0, n = fields.length; i < n; i++) { |
|
|
|
|
|
Field f = fields[i]; |
|
|
|
|
|
int modifier = f.getModifiers(); |
|
|
|
|
|
if (!Modifier.isPublic(modifier)) { |
|
|
|
|
|
sb.append("{"); |
|
|
|
|
|
sb.append(KEY_NAME).append("'").append(f.getName()).append("',"); |
|
|
|
|
|
if (!f.getDeclaringClass().getName().equals(clazz.getName())) |
|
|
|
|
|
sb.append(KEY_DECLARING_CLASS).append("'").append(f.getDeclaringClass().getName()).append("',"); |
|
|
|
|
|
appendModifier(sb, modifier); |
|
|
|
|
|
sb.append(KEY_TYPE).append("'").append(f.getType().getName()).append("'"); |
|
|
|
|
|
sb.append("},").append(NEWLINE); |
|
|
|
|
|
} |
|
|
|
|
|
} |
|
|
|
|
|
sb.append("], ").append(NEWLINE); |
|
|
|
|
|
|
|
|
|
|
|
Method[] methods = clazz.getDeclaredMethods(); |
|
|
|
|
|
sb.append("'declared_methods':["); |
|
|
|
|
|
for (int i = 0, n = methods.length; i < n; i++) { |
|
|
|
|
|
Method m = methods[i]; |
|
|
|
|
|
int modifier = m.getModifiers(); |
|
|
|
|
|
if (!Modifier.isPublic(modifier)) { |
|
|
|
|
|
sb.append("{"); |
|
|
|
|
|
sb.append(KEY_NAME).append("'").append(m.getName()).append("',"); |
|
|
|
|
|
if (!m.getDeclaringClass().getName().equals(clazz.getName())) |
|
|
|
|
|
sb.append(KEY_DECLARING_CLASS).append("'").append(m.getDeclaringClass().getName()).append("',"); |
|
|
|
|
|
appendModifier(sb, modifier); |
|
|
|
|
|
sb.append(KEY_RETURNTYPE).append("'").append(m.getReturnType().getName()).append("',"); |
|
|
|
|
|
appendParameterTypes(sb, m.getParameterTypes()); |
|
|
|
|
|
sb.append(KEY_DESCRIPTION).append("'").append(m.toString()).append("'"); |
|
|
|
|
|
sb.append("},").append(NEWLINE); |
|
|
|
|
|
} |
|
|
|
|
|
} |
|
|
|
|
|
sb.append("], ").append(NEWLINE); |
|
|
|
|
|
|
|
|
|
|
|
Class[] classes = clazz.getDeclaredClasses(); |
|
|
|
|
|
sb.append("'declared_classes': ["); |
|
|
|
|
|
for (int i = 0, n = classes.length; i < n; i++) { |
|
|
|
|
|
Class c = classes[i]; |
|
|
|
|
|
if (!Modifier.isPublic(c.getModifiers())) { |
|
|
|
|
|
sb.append("'").append(c.getName().replace('$', '.')).append("',"); |
|
|
|
|
|
putClassInfo(map, c); // !!
|
|
|
|
|
|
} |
|
|
|
|
|
} |
|
|
|
|
|
sb.append("], ").append(NEWLINE); |
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
private static void appendModifier(StringBuffer sb, int modifier) { |
|
|
|
|
|
sb.append(KEY_MODIFIER).append("'").append(Integer.toString(modifier, 2)).append("', "); |
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
private static void appendParameterTypes(StringBuffer sb, Class[] paramTypes) { |
|
|
|
|
|
if (paramTypes.length == 0) return ; |
|
|
|
|
|
|
|
|
|
|
|
sb.append(KEY_PARAMETERTYPES).append("["); |
|
|
|
|
|
for (int j = 0; j < paramTypes.length; j++) { |
|
|
|
|
|
sb.append("'").append(paramTypes[j].getName()).append("',"); |
|
|
|
|
|
} |
|
|
|
|
|
sb.append("],"); |
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
private static boolean isBlank(String str) { |
|
|
|
|
|
int len; |
|
|
|
|
|
if (str == null || (len = str.length()) == 0) |
|
|
|
|
|
return true; |
|
|
|
|
|
for (int i = 0; i < len; i++) |
|
|
|
|
|
if ((Character.isWhitespace(str.charAt(i)) == false)) |
|
|
|
|
|
return false; |
|
|
|
|
|
return true; |
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
// test methods
|
|
|
|
|
|
|
|
|
|
|
|
static void debug(String s) { |
|
|
|
|
|
if (debug_mode) |
|
|
|
|
|
System.out.println(s); |
|
|
|
|
|
} |
|
|
|
|
|
static void output(String s) { |
|
|
|
|
|
if (!debug_mode) |
|
|
|
|
|
System.out.print(s); |
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
private static void usage() { |
|
|
|
|
|
System.out.println("Reflection for javacomplete (" + VERSION + ")"); |
|
|
|
|
|
System.out.println(" java [-classpath] Reflection [-c] [-d] [-e] [-h] [-v] [-p] [-s] name[,comma_separated_name_list]"); |
|
|
|
|
|
System.out.println("Options:"); |
|
|
|
|
|
System.out.println(" -a list all members in alphabetic order"); |
|
|
|
|
|
System.out.println(" -c list constructors"); |
|
|
|
|
|
System.out.println(" -C return class info"); |
|
|
|
|
|
System.out.println(" -d default strategy, i.e. instance fields, instance methods, static fields, static methods"); |
|
|
|
|
|
System.out.println(" -e check class existed"); |
|
|
|
|
|
System.out.println(" -E check class existed and read class information"); |
|
|
|
|
|
System.out.println(" -D debug mode"); |
|
|
|
|
|
System.out.println(" -p list package content"); |
|
|
|
|
|
System.out.println(" -P print all package info in the Vim dictionary format"); |
|
|
|
|
|
System.out.println(" -s list static fields and methods"); |
|
|
|
|
|
System.out.println(" -h help"); |
|
|
|
|
|
System.out.println(" -v version"); |
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
public static void main(String[] args) { |
|
|
|
|
|
String className = null; |
|
|
|
|
|
int option = 0x0; |
|
|
|
|
|
boolean wholeClassInfo = false; |
|
|
|
|
|
boolean onlyStatic = false; |
|
|
|
|
|
boolean onlyConstructor = false; |
|
|
|
|
|
boolean listPackageContent = false; |
|
|
|
|
|
boolean checkExisted = false; |
|
|
|
|
|
boolean checkExistedAndRead = false; |
|
|
|
|
|
boolean allPackageInfo = false; |
|
|
|
|
|
|
|
|
|
|
|
for (int i = 0, n = args.length; i < n && !isBlank(args[i]); i++) { |
|
|
|
|
|
//debug(args[i]);
|
|
|
|
|
|
if (args[i].charAt(0) == '-') { |
|
|
|
|
|
if (args[i].length() > 1) { |
|
|
|
|
|
switch (args[i].charAt(1)) { |
|
|
|
|
|
case 'a': |
|
|
|
|
|
break; |
|
|
|
|
|
case 'c': // request constructors
|
|
|
|
|
|
option = option | OPTION_CONSTRUCTOR; |
|
|
|
|
|
onlyConstructor = true; |
|
|
|
|
|
break; |
|
|
|
|
|
case 'C': // class info
|
|
|
|
|
|
wholeClassInfo = true; |
|
|
|
|
|
break; |
|
|
|
|
|
case 'd': // default strategy
|
|
|
|
|
|
option = option | STRATEGY_DEFAULT; |
|
|
|
|
|
break; |
|
|
|
|
|
case 'D': // debug mode
|
|
|
|
|
|
debug_mode = true; |
|
|
|
|
|
break; |
|
|
|
|
|
case 'e': // class existed
|
|
|
|
|
|
checkExisted = true; |
|
|
|
|
|
break; |
|
|
|
|
|
case 'E': // check existed and read class information
|
|
|
|
|
|
checkExistedAndRead = true; |
|
|
|
|
|
break; |
|
|
|
|
|
case 'h': // help
|
|
|
|
|
|
usage(); |
|
|
|
|
|
return ; |
|
|
|
|
|
case 'v': // version
|
|
|
|
|
|
System.out.println("Reflection for javacomplete (" + VERSION + ")"); |
|
|
|
|
|
break; |
|
|
|
|
|
case 'p': |
|
|
|
|
|
listPackageContent = true; |
|
|
|
|
|
break; |
|
|
|
|
|
case 'P': |
|
|
|
|
|
option = RETURN_ALL_PACKAGE_INFO; |
|
|
|
|
|
break; |
|
|
|
|
|
case 's': // request static members
|
|
|
|
|
|
option = option | OPTION_STATIC_METHOD | OPTION_STATIC_FIELD; |
|
|
|
|
|
onlyStatic = true; |
|
|
|
|
|
break; |
|
|
|
|
|
default: |
|
|
|
|
|
} |
|
|
|
|
|
} |
|
|
|
|
|
} |
|
|
|
|
|
else { |
|
|
|
|
|
className = args[i]; |
|
|
|
|
|
} |
|
|
|
|
|
} |
|
|
|
|
|
if (className == null && (option & RETURN_ALL_PACKAGE_INFO) != RETURN_ALL_PACKAGE_INFO) { |
|
|
|
|
|
return; |
|
|
|
|
|
} |
|
|
|
|
|
if (option == 0x0) |
|
|
|
|
|
option = OPTION_INSTANCE; |
|
|
|
|
|
|
|
|
|
|
|
if (wholeClassInfo) |
|
|
|
|
|
output( getClassInfo(className) ); |
|
|
|
|
|
else if ((option & RETURN_ALL_PACKAGE_INFO) == RETURN_ALL_PACKAGE_INFO) |
|
|
|
|
|
output( getPackageList() ); |
|
|
|
|
|
else if (checkExistedAndRead) |
|
|
|
|
|
output( existedAndRead(className) ); |
|
|
|
|
|
else if (checkExisted) |
|
|
|
|
|
output( String.valueOf(existed(className)) ); |
|
|
|
|
|
else if (listPackageContent) |
|
|
|
|
|
output( getPackageList(className) ); |
|
|
|
|
|
} |
|
|
|
|
|
} |
|
|
|