//
// Sources/ag/kcmedia/JavaBrowser.java: Class file for WO Component 'JavaBrowser'
// Project DevStudio
//
// Created by ak on Wed Jul 24 2002
//
package ag.kcmedia;
import java.io.File;
import java.io.IOException;
import java.io.PrintWriter;
import java.io.StringWriter;
import java.lang.reflect.Modifier;
import java.util.Enumeration;
import jode.bytecode.ClassInfo;
import jode.bytecode.FieldInfo;
import jode.bytecode.MethodInfo;
import jode.bytecode.TypeSignature;
import jode.decompiler.Decompiler;
import jode.type.Type;
import org.apache.log4j.Logger;
import org.apache.commons.lang3.StringUtils;
import com.webobjects.foundation.NSArray;
import com.webobjects.foundation.NSDictionary;
import com.webobjects.foundation.NSMutableArray;
import com.webobjects.foundation.NSMutableDictionary;
import com.webobjects.foundation.NSSelector;
import er.extensions.localization.ERXLocalizer;
public class Jode extends Object {
static final Logger log = Logger.getLogger(JavaBrowser.class);
public static NSMutableArray documentationPaths = new NSMutableArray();
public static NSMutableDictionary allClasses = new NSMutableDictionary();
public static NSMutableDictionary allPackages = new NSMutableDictionary();
public static String cp;
public static boolean initialized = false;
public static void initialize() {
if(initialized)
return;
initialized = true;
ERXLocalizer l = ERXLocalizer.localizerForLanguage("English");
jode.GlobalOptions.err = new PrintWriter(new StringWriter());
documentationPaths = (NSMutableArray)l.valueForKey("DocumentationPaths");
NSArray arr = (NSArray)l.valueForKey("ClassPaths");
cp = arr.componentsJoinedByString(":");
ClassInfo.setClassPath(cp);
arr = (NSArray)l.valueForKey("PackagesToIndex");
for(Enumeration e = arr.objectEnumerator(); e.hasMoreElements();) {
PackageProxy.indexPackage((String)e.nextElement(), null, true);
}
}
public static PackageProxy packageProxyForName(String packageName) {
Jode.initialize();
return (PackageProxy)allPackages.objectForKey(packageName);
}
public static NSDictionary allPackages() {
Jode.initialize();
return allPackages;
}
public static NSDictionary allClasses() {
Jode.initialize();
return allClasses;
}
public static ClassProxy classProxyForName(String packageName, String className) {
Jode.initialize();
return classProxyForName(packageName + (packageName == "" ? "": ".") + className);
}
public static ClassProxy classProxyForName(String fullClassName) {
Jode.initialize();
return (ClassProxy)allClasses.objectForKey(fullClassName);
}
public static class PackageProxy {
protected PackageProxy packageProxy;
protected String name;
protected ClassInfo classInfo;
protected NSMutableArray subPackages = new NSMutableArray();
protected NSMutableArray classes = new NSMutableArray();
public PackageProxy(String name, PackageProxy packageProxy, ClassInfo classInfo) {
this.packageProxy = packageProxy;
this.name = name;
this.classInfo = classInfo;
if(this.packageProxy != null) {
this.packageProxy.addSubPackage(this);
}
}
public String name() {return name;}
public PackageProxy packageProxy() {return packageProxy;}
public ClassInfo classInfo() {return classInfo;}
public void addClass(ClassProxy classProxy) {
classes.addObject(classProxy);
}
public NSArray classes() { return classes; }
public void addSubPackage(PackageProxy subPackageProxy) {
subPackages.addObject(subPackageProxy);
}
public NSArray subPackages() { return subPackages; }
public String toString() {return name;}
public static void indexClass(String className, String packageName, int modifyTypes) {
if(allClasses.valueForKey(className) != null)
return;
String classNameWithPackage = packageName + (packageName == "" ? "": ".") + className;
ClassProxy classProxy = new ClassProxy(className, (PackageProxy)allPackages.valueForKey(packageName), ClassInfo.forName(classNameWithPackage));
allClasses.takeValueForKey(classProxy,classNameWithPackage);
}
public static void indexPackage(String packageName, PackageProxy parentPackage, boolean indexClasses) {
if(allPackages.valueForKey(packageName) != null)
return;
PackageProxy packageProxy = new PackageProxy(packageName, parentPackage, ClassInfo.forName(packageName));
allPackages.takeValueForKey(packageProxy, packageName);
Enumeration e = ClassInfo.getClassesAndPackages(packageName);
while(e.hasMoreElements()) {
String className = (String)e.nextElement();
String classNameWithPackage = packageName + (packageName == "" ? "": ".") + className;
if(ClassInfo.isPackage(classNameWithPackage)) {
indexPackage(classNameWithPackage, packageProxy, indexClasses);
} else {
if(className.indexOf("$") < 0) {
if(indexClasses) {
indexClass(className, packageName, 0);
}
}
}
}
}
}
public static class ClassProxy {
protected PackageProxy packageProxy;
protected String name;
protected ClassInfo classInfo;
protected String sourceCode;
protected String documentation;
public ClassProxy(String name, PackageProxy packageProxy, ClassInfo classInfo) {
this.packageProxy = packageProxy;
this.name = name;
this.classInfo = classInfo;
this.sourceCode = null;
if(this.packageProxy != null) {
this.packageProxy.addClass(this);
}
}
public String name() {return name;}
public String fullName() {return classInfo().getName();}
public PackageProxy packageProxy() {return packageProxy;}
public ClassInfo classInfo() {return classInfo;}
public NSMutableArray names;
public NSArray names() {
if(names == null) {
names = new NSMutableArray();
ClassInfo ci = classInfo();
FieldInfo fi[] = ci.getFields();
for(int i = 0; i < fi.length; i++) {
FieldInfo f = fi[i];
names.addObject(f.getName());
}
MethodInfo mi[] = ci.getMethods();
for(int i = 0; i < mi.length; i++) {
MethodInfo f = mi[i];
names.addObject(f.getName());
}
names.addObject(name());
}
return names;
}
public NSArray variables() {
ClassInfo ci = classInfo();
FieldInfo fi[] = ci.getFields();
NSMutableArray fields = new NSMutableArray(fi.length);
for(int i = 0; i < fi.length; i++) {
FieldInfo f = fi[i];
StringBuffer sb = new StringBuffer(512);
String typeInfo = f.getType();
String fieldName = f.getName();
Type param = Type.tType(TypeSignature.getReturnType(typeInfo));
sb.append(ERXStringUtilities.lastPropertyKeyInKeyPath(param.toString()));
sb.append(" ");
sb.append(fieldName);
fields.addObject(sb.toString());
}
return fields;
}
public NSArray methods() {
ClassInfo ci = classInfo();
MethodInfo mi[] = ci.getMethods();
NSMutableArray methods = new NSMutableArray(mi.length);
for(int i = 0; i < mi.length; i++) {
MethodInfo m = mi[i];
StringBuffer sb = new StringBuffer(512);
String typeInfo = m.getType();
String params[] = TypeSignature.getParameterTypes(typeInfo);
String methodName = m.getName();
if(methodName.equals("<clinit>")) {
continue;
}
sb.append(Modifier.toString(m.getModifiers()));
sb.append(" ");
if(methodName.equals("<init>")) {
sb.append(ERXStringUtilities.lastPropertyKeyInKeyPath(ci.getName()));
} else {
Type param = Type.tType(TypeSignature.getReturnType(typeInfo));
sb.append(ERXStringUtilities.lastPropertyKeyInKeyPath(param.toString()));
sb.append(" ");
sb.append(methodName);
}
sb.append("(");
for(int j = 0; j < params.length; j++) {
Type param = Type.tType(params[j]);
sb.append(ERXStringUtilities.lastPropertyKeyInKeyPath(param.toString()));
if(j < params.length - 1)
sb.append(", ");
}
sb.append(")");
// log.debug(sb.toString());
methods.addObject(sb.toString());
}
return methods;
}
public String sourceCode() {
if(sourceCode != null)
return sourceCode;
StringWriter writer = new StringWriter();
try {
Decompiler decompiler = new Decompiler();
decompiler.setClassPath(cp);
decompiler.decompile(classInfo().getName(), writer, null);
} catch (IOException ex) {
log.error(ex.toString());
} catch (jode.AssertError ex) {
log.error(ex.toString());
return ex.toString() + " occurred. \n\n"
+ "Please check if you have all necessary jar and class files \n"
+ "added to ClassPaths property in the Localizable.strings file.";
}
sourceCode = writer.toString();
try {
Class JavaCCtoHTML = Class.forName("JavaCCtoHTML");
NSSelector prettyString = new NSSelector("prettyString", new Class [] {String.class});
prettyString.invoke(JavaCCtoHTML, sourceCode);
// sourceCode = JavaCCtoHTML.prettyString(sourceCode);
} catch (Exception ex) {
log.error(ex);
}
sourceCode = StringUtils.replace(sourceCode, "\n\n", "<br>");
return sourceCode;
}
public String documentationPath() {
String classPath = classInfo().getName().replace('.','/');
for(Enumeration e = documentationPaths.objectEnumerator(); e.hasMoreElements();) {
String path = (String)e.nextElement();
String wholePath = path + classPath + ".html";
File f = new File(wholePath);
if(f.exists()) {
return wholePath;
}
}
return null;
}
public String documentation() {
String docPath = documentationPath();
if(docPath != null) {
documentation = ERXStringUtilities.stringWithContentsOfFile(docPath);
} else {
documentation = "No docs available";
}
return documentation;
}
public String toString() {return name;}
}
}