001: package tide.bytecode;
002:
003: import java.lang.reflect.Field;
004: import java.lang.reflect.Constructor;
005: import java.lang.reflect.Member;
006: import tide.editor.MainEditorFrame;
007: import java.lang.reflect.Method;
008: import tide.utils.SyntaxUtils;
009: import java.io.StringReader;
010: import java.io.BufferedReader;
011: import snow.utils.ProcessUtils;
012: import snow.utils.StringUtils;
013: import java.util.*;
014: import java.io.File;
015:
016: /** Uses javap to disasemble the bytecode.
017: * Reads the names (iff compiled with "-g") from LocalVariableTable
018: * Easy: classes contains exactely one type. (inner and outer classes are included as comments)
019: * The string representation is "parsable", i.e. the bytecode is commented. Making it directly browsable in the editor.
020: */
021: public final class DecompiledClass //extends Object implements Serializable, Runnable // just to test !
022: {
023: public final String requestedJavaName; // a.b.c.d
024: public final boolean withbytecode;
025:
026: // p1,p2,...
027: public boolean hasAnyDefaultNamedArguments = false;
028:
029: // may not be present
030: public String compiledFrom = "";
031: public String declarationLine = "";
032:
033: public String packageName = "";
034: // type full name (with $ for internal classes)
035: public String typeName = "";
036: // with "." only
037: public String javaName = "";
038:
039: public String simpleTypeName = ""; // Hello instead Wrapper$Hello if inner class
040: public String wrapperTypeName = ""; // Wrapper (non empty iff this is an inner type).
041:
042: public boolean isClass = false;
043: public boolean isInterface = false;
044: public boolean isAnnotation = false;
045: public boolean isEnumeration = false;
046:
047: public String implements TypesList = ""; // , separated
048: public String extendsTypesList = ""; // , separated
049:
050: public String modifiers = "";
051:
052: // and fields and constructors
053: public final List<TMember> members = new ArrayList<TMember>();
054:
055: public String completeContent = "";
056:
057: private final List<Const> constantPool = new ArrayList<Const>();
058:
059: String actualParsedFieldOrMethodOrConstructor = null;
060:
061: // todo: replace with a fixed enum since we can only be on one tag at a time.
062: boolean inInnerClass = false;
063: boolean inLineNumberTable = false;
064: boolean inLocalVariableTable = false;
065: boolean inLocalVariableTypeTable = false;
066: boolean inCode = false;
067: boolean inException = false;
068:
069: // for the previous field method or constructor
070: List<Param> params = new ArrayList<Param>();
071: StringBuilder code = new StringBuilder();
072: StringBuilder innerClasses = new StringBuilder();
073:
074: /** Parses the javap output.
075: */
076: public DecompiledClass(final String javaName,
077: final File classesBase, final File javaPTool,
078: final boolean withbytecode) throws Exception {
079:
080: this .withbytecode = withbytecode;
081: this .requestedJavaName = javaName;
082:
083: List<String> args = new ArrayList<String>();
084: args.add(javaPTool.getAbsolutePath());
085:
086: args.add("-private");
087: if (withbytecode) {
088: args.add("-c"); // bytecode
089: args.add("-verbose"); // lot of debug info + "-l" at the end (local variable table, line number)...
090: } else {
091: args.add("-l");
092: }
093: args.add(javaName);
094: //ProcessBuilder pb = new ProcessBuilder(args);
095: //pb.directory(classesBase);
096: //Process p = pb.start();
097: String out = ProcessUtils.readWholeProcessStack(args,
098: classesBase, 30000); // 30 sec (?) !
099: completeContent = out;
100:
101: // read the output per line
102: StringReader st = new StringReader(out);
103: BufferedReader br = new BufferedReader(st);
104:
105: // the two first lines are fix:
106: String line = br.readLine();
107: if (line.startsWith("Compiled from")) {
108: this .compiledFrom = StringUtils.removeQuotes(line
109: .substring(14), '"');
110: this .declarationLine = br.readLine();
111: } else if (line.startsWith("ERROR:")) {
112: System.out.println("Command: " + args);
113: throw new Exception(line);
114: } else {
115: this .declarationLine = line;
116: }
117: analyseDeclarationLine();
118:
119: wl: while ((line = br.readLine()) != null) // next line until end
120: {
121: lineScanned(line);
122: }
123:
124: // System.out.println(""+ this.toString());
125: // System.out.println("\n=========================== whole output:");
126: // System.out.println(""+out);
127: }
128:
129: /** extract many infos from the first line
130: */
131: void analyseDeclarationLine() {
132: // ex: public final class tide.bytecode.DecompiledClass extends java.lang.Object implements java.io.Serializable{
133:
134: if (declarationLine.endsWith("{")) {
135: declarationLine = declarationLine.substring(0,
136: declarationLine.length() - 1);
137: }
138: String[] mt = SyntaxUtils
139: .extractModifiersAndType(this .declarationLine);
140: this .modifiers = mt[0];
141: this .typeName = mt[1];
142:
143: // detect as one of the 4 types {class, int, ann, enum}
144: //
145: if (typeName.startsWith("class ")) // also enums
146: {
147: typeName = typeName.substring(6);
148:
149: if (typeName.indexOf("extends java.lang.Enum") >= 0) {
150: isEnumeration = true;
151: typeName = typeName.replace("extends java.lang.Enum",
152: "");
153: } else {
154: isClass = true;
155: }
156:
157: } else if (typeName.startsWith("interface ")) // also annotations
158: {
159: typeName = typeName.substring(10);
160: if (typeName
161: .indexOf("extends java.lang.annotation.Annotation") >= 0) {
162: isAnnotation = true;
163: typeName = typeName.replace(
164: "extends java.lang.annotation.Annotation", "");
165: } else {
166: isInterface = true;
167: }
168: }
169:
170: int impPos = typeName.indexOf("implements ");
171: if (impPos >= 0) {
172: int impEnd = typeName.indexOf(' ', impPos + 11);
173: if (impEnd == -1)
174: impEnd = typeName.length();
175:
176: this .implements TypesList = typeName.substring(impPos + 11,
177: impEnd);
178: String impName = typeName.substring(impPos, impEnd);
179: typeName = typeName.replace(impName, "");
180: }
181:
182: int extPos = typeName.indexOf("extends ");
183: if (extPos >= 0) {
184: int extEnd = typeName.indexOf(' ', extPos + 8);
185: if (extEnd == -1)
186: extEnd = typeName.length();
187:
188: this .extendsTypesList = typeName.substring(extPos + 8,
189: extEnd);
190: String extName = typeName.substring(extPos, extEnd);
191: typeName = typeName.replace(extName, "");
192:
193: // trivial case: forget it:
194: if (extendsTypesList.equals("java.lang.Object")) {
195: extendsTypesList = "";
196: }
197: }
198:
199: // should rest: typeName !
200: typeName = typeName.trim();
201: if (typeName.indexOf(' ') > 0) {
202: System.out.println("Decomp ERROR: " + declarationLine); // enough info to debug !
203: }
204:
205: // full java name
206: this .javaName = typeName.replace('$', '.');
207:
208: // package name (prepend to all type names)
209: int lp = typeName.lastIndexOf('.');
210: if (lp >= 0) {
211: this .packageName = typeName.substring(0, lp);
212: this .typeName = typeName.substring(lp + 1);
213: }
214:
215: // the names
216: int dp = typeName.lastIndexOf('$');
217: if (dp > 0) {
218: // we have an inner type
219: this .wrapperTypeName = typeName.substring(0, dp);
220: this .simpleTypeName = typeName.substring(dp + 1);
221: } else {
222: this .wrapperTypeName = "";
223: this .simpleTypeName = typeName;
224: }
225: }
226:
227: /** only usable after having called analyseDeclarationLine
228: */
229: private String removePackageAndWrapperFromName(String name) {
230: String ret = name;
231:
232: if (this .packageName.length() > 0) {
233: if (ret.startsWith(this .packageName + ".")) {
234: ret = ret.substring(packageName.length() + 1);
235: }
236: }
237:
238: if (this .wrapperTypeName.length() > 0) {
239: if (ret.startsWith(this .wrapperTypeName + "$")) {
240: ret = ret.substring(wrapperTypeName.length() + 1);
241: }
242: }
243:
244: return ret;
245: }
246:
247: /** called for each new lines parsed from the javap output
248: */
249: private void lineScanned(final String line) {
250: String lineTrim = line.trim();
251:
252: // ignore empty lines...
253: if (lineTrim.length() == 0) {
254: // but record which current block may be terminated now
255: if (inLineNumberTable)
256: inLineNumberTable = false;
257: if (inLocalVariableTable)
258: inLocalVariableTable = false;
259: if (inException)
260: inException = false;
261: if (inCode)
262: inCode = false;
263:
264: return;
265: }
266:
267: if (line.startsWith("const #")) {
268: constLineRead(line);
269: return;
270: }
271:
272: // Add previous declaration when next comes
273: //
274:
275: if (!(line.startsWith(" ") || line.startsWith("\t"))) // whitespace !
276: {
277: // line starting at column 0 are the field or method names OR { or }
278: //
279: if (lineTrim.equals("{"))
280: return; // ignore...
281:
282: constructPreviousFieldOrMethodOrConstructor();
283:
284: // for the next one !
285: if (lineTrim.equals("}")) {
286: actualParsedFieldOrMethodOrConstructor = null;
287: } else {
288: actualParsedFieldOrMethodOrConstructor = line;
289: }
290: return;
291: //System.out.println(""+line);
292: }
293:
294: if (lineTrim.equals("LocalVariableTable:")) {
295: inLocalVariableTable = true;
296: return;
297: }
298: if (lineTrim.equals("LocalVariableTypeTable:")) // [Nov2007]: java6 ?
299: {
300: inLocalVariableTable = false;
301: inLocalVariableTypeTable = true;
302: return;
303: }
304: if (lineTrim.equals("Exceptions")) {
305: inLocalVariableTable = false;
306: inException = true;
307: return;
308: }
309:
310: if (lineTrim.equals("LineNumberTable:")) {
311: inLineNumberTable = true;
312: return;
313: }
314:
315: if (inLocalVariableTable) {
316: if (lineTrim.startsWith("Start"))
317: return; // header
318: try {
319: // collect the names!
320: String[] spl = lineTrim.split("\\s+");
321: params.add(new Param(Integer.parseInt(spl[2]), spl[3],
322: spl[4]));
323:
324: } catch (Exception ex) {
325: // [Nov207]:
326: System.out.println("DE::can't read param in "
327: + lineTrim);
328: }
329: return;
330: }
331:
332: if (inLineNumberTable) {
333: // ignore !
334: return;
335: }
336:
337: if (inInnerClass) {
338: if (lineTrim.startsWith("minor")
339: || lineTrim.startsWith("major")) {
340: inInnerClass = false;
341: return;
342: }
343: //System.out.println("Inner class decl: "+line);
344: innerClassDeclRead(lineTrim);
345:
346: return;
347: }
348:
349: // append line in buffer
350: if (actualParsedFieldOrMethodOrConstructor != null) {
351: this .code.append(" " + line + "\n"); // keep also original indents...
352: }
353:
354: if (inCode) {
355: return;
356: }
357: if (inException) {
358: return;
359: }
360:
361: // StackMapTable:
362:
363: if (lineTrim.equals("Code:")) {
364: inCode = true;
365: return;
366: }
367: if (lineTrim.equals("Exception table:")) {
368: inException = true;
369: return;
370: }
371: if (lineTrim.equals("InnerClass:")) {
372: inInnerClass = true;
373: return;
374: }
375:
376: }
377:
378: /** take the collected data (bytecode, lines, LineNumberTable, LocalVariableTable, ...) to construct
379: * the previous element
380: */
381: private void constructPreviousFieldOrMethodOrConstructor() {
382: if (actualParsedFieldOrMethodOrConstructor == null
383: || actualParsedFieldOrMethodOrConstructor.length() == 0)
384: return;
385:
386: //System.out.println("decl: "+actualParsedFieldOrMethodOrConstructor+" "+params.size());
387:
388: TMember ms = new TMember(params,
389: actualParsedFieldOrMethodOrConstructor, code.toString());
390: members.add(ms);
391: params.clear();
392: actualParsedFieldOrMethodOrConstructor = "";
393: code.setLength(0);
394:
395: //System.out.println("SIGNATURE: "+ms.toStringSignature());
396: }
397:
398: /** during parsing
399: */
400: private void constLineRead(String constLine) {
401: constantPool.add(new Const(constLine));
402: }
403:
404: /** during parsing
405: */
406: private void innerClassDeclRead(String line) {
407: innerClasses.append(" " + line + "\n");
408: }
409:
410: /** Finds corresponding parsed item from a class member obtained via reflection.
411: * this is the glue allowing to find the member parameter names !
412: */
413: public TMember getMember(Member m) {
414: for (TMember tm : members) {
415: if (tm.equalsMember(m))
416: return tm;
417: }
418:
419: // not found
420: return null;
421: }
422:
423: /** dummy java code (withoudt body)...
424: * should be "parsable"
425: */
426: @Override
427: public final String toString() {
428: StringBuilder sb = new StringBuilder();
429: if (packageName.length() > 0) {
430: sb.append("package " + packageName + ";\n");
431: }
432:
433: //
434: if (this .wrapperTypeName.length() > 0) {
435: sb.append("\n// WRAPPER CLASS: " + this .wrapperTypeName
436: + "\n");
437: }
438:
439: sb.append("\n");
440: if (modifiers.length() > 0) {
441: sb.append(modifiers + " ");
442: }
443: if (isClass)
444: sb.append("class");
445: else if (isEnumeration)
446: sb.append("enum");
447: else if (isInterface)
448: sb.append("interface");
449: else if (isAnnotation)
450: sb.append("@interface");
451:
452: sb.append(" " + simpleTypeName);
453: if (extendsTypesList.length() > 0) {
454: sb.append("\n\t\t\t extends " + extendsTypesList);
455: }
456: if (implements TypesList.length() > 0) {
457: sb.append("\n\t\t\t implements " + implements TypesList);
458: }
459:
460: sb.append("\n{");
461:
462: sb.append("\n // compiled from: " + compiledFrom);
463: //sb.append("\n // requested: "+requestedJavaName);
464: sb.append("\n // decl: " + declarationLine);
465: //sb.append("\n // mod: "+modifiers);
466: sb.append("\n // type: " + typeName);
467:
468: if (innerClasses.length() > 0) {
469: sb.append("\n /* INNER CLASSES:\n");
470: sb.append(innerClasses);
471: sb.append(" */");
472: }
473:
474: sb.append("\n // Constants: " + constantPool.size());
475:
476: sb.append("\n");
477: for (TMember ms : members) {
478: sb.append("\n " + ms);
479: }
480: //sb.append("/* end */");
481: sb.append("\r\n}");
482:
483: if (completeContent != null && completeContent.length() > 0
484: && MainEditorFrame.debug) {
485: sb.append("\n\n\n\n\n \n\n\n\n\n/* complete content:\n "
486: + completeContent + "\n*/");
487: }
488: return sb.toString();
489: }
490:
491: /** Currently not used...
492: */
493: public class Const {
494: // "const #1 = Method #141.#282; // tide/bytecode/DecompiledClass.makeTypeNameReadable:(Ljava/lang/String;)Ljava/lang/String;"
495: final int nb;
496: final String val;
497:
498: public Const(String line) {
499: int posEq = line.indexOf('=');
500: nb = Integer.parseInt(line.substring(7, posEq).trim());
501: val = line.substring(posEq + 1).trim();
502:
503: // remove // comments ??
504: // todo..
505: }
506: }
507:
508: /** constructor, method, field
509: */
510: public class TMember {
511: boolean isField = false;
512: boolean isConstructor = false;
513: String mname = "";
514: String modifiers = "";
515: String type = ""; // empty for constructory
516: final List<Param> params = new ArrayList<Param>();
517: final String code;
518: public boolean hasDefaultNamedArguments;
519:
520: public List<Param> getParameters() {
521: return params;
522: }
523:
524: /** finds corresponding parsed item from a class member obtained via reflection
525: */
526: public boolean equalsMember(Member m) {
527: if (m instanceof Constructor) {
528: if (!isConstructor)
529: return false;
530: Constructor me = (Constructor) m;
531:
532: String cn = removePackageAndWrapperFromName(m.getName());
533: if (!cn.equals(mname))
534: return false;
535: Class[] pt = me.getParameterTypes();
536: if (pt.length != params.size())
537: return false;
538:
539: for (int i = 0; i < pt.length; i++) {
540: String sn = SyntaxUtils
541: .convertVmNameToFullJavaNames(pt[i]
542: .getName());
543: if (!params.get(i).type.equals(sn)) {
544: //System.out.println("TMemberParam: '"+params.get(i).type+"' != '"+sn+"'");
545: return false;
546: }
547: }
548:
549: return true;
550:
551: } else if (m instanceof Method) {
552: if (this .isField)
553: return false;
554: Method me = (Method) m;
555:
556: if (!m.getName().equals(mname))
557: return false;
558: Class[] pt = me.getParameterTypes();
559: if (pt.length != params.size())
560: return false;
561:
562: //System.out.println(""+Arrays.toString(pt));
563: for (int i = 0; i < pt.length; i++) {
564: String sn = SyntaxUtils
565: .convertVmNameToFullJavaNames(pt[i]
566: .getName());
567: if (!params.get(i).type.equals(sn)) {
568: // System.out.println("TMemberParam: '"+params.get(i).type+"' != '"+sn+"'");
569: return false;
570: }
571: }
572:
573: return true;
574: } else if (m instanceof Field) {
575: if (!isField)
576: return false;
577: // fields are completely defined by their name. (unique)
578: //System.out.println(""+m.getName()+" =?= "+mname);
579: return m.getName().equals(mname);
580: }
581: return false;
582: }
583:
584: // keep params
585: public TMember(List<Param> allParams, String line, String code) {
586: this .code = code;
587: Collections.sort(allParams);
588:
589: if (line.endsWith(";")) {
590: line = line.substring(0, line.length() - 1);
591: }
592:
593: //this.name = name;
594: int poss = line.indexOf('(');
595: if (poss < 0) {
596: // field !
597: isField = true;
598: scanModifiersRetAndName(line);
599: return;
600: }
601: int pose = line.indexOf(')', poss);
602: if (pose < 0)
603: return;
604:
605: scanModifiersRetAndName(line.substring(0, poss).trim());
606:
607: // Keep the correct arguments
608: //
609: String args = line.substring(poss + 1, pose).trim();
610:
611: int np = 0;
612: if (args.length() > 0) {
613: np = StringUtils.count(args, ',') + 1;
614: }
615:
616: String[] ptypes = args.split(",");
617: //System.out.println(""+np+" arguments: "+allParams+", "+Arrays.toString(ptypes));
618:
619: if (allParams.size() > 0) {
620: for (int i = 0; i < allParams.size(); i++) {
621: if (params.size() >= np)
622: break;
623: Param pi = allParams.get(i);
624: if (pi.name.equals("this"))
625: continue;
626: params.add(pi);
627: }
628: } else {
629: for (int i = 0; i < np; i++) {
630: params.add(new Param(i, "p" + (i + 1), ptypes[i]));
631: hasDefaultNamedArguments = true;
632: // outer class member flag
633: hasAnyDefaultNamedArguments = true;
634: }
635: }
636: }
637:
638: private void scanModifiersRetAndName(String mrn) {
639: int lastPosSp = mrn.lastIndexOf(' ');
640: if (lastPosSp > 0) {
641: mname = mrn.substring(lastPosSp + 1);
642: // now: mod and return without name
643: mrn = mrn.substring(0, lastPosSp).trim();
644:
645: String[] mt = SyntaxUtils.extractModifiersAndType(mrn);
646: modifiers = mt[0];
647: type = mt[1];
648: } else {
649: mname = mrn;
650: }
651:
652: if (type.length() == 0) {
653: isConstructor = true;
654: mname = removePackageAndWrapperFromName(mname);
655: }
656: }
657:
658: /** should be compatible with the signature of class members (Constructor, java.lang.reflect.Method, ...)
659: * NO MODIFIERS HERE ! and no param names
660: */
661: public final String toStringSignature() {
662: StringBuilder sb = new StringBuilder();
663: if (isField) {
664: sb.append(type + " ");
665: sb.append(mname);
666: } else if (isConstructor) {
667: // no type.
668: sb.append(mname);
669: } else {
670: sb.append(type + " ");
671: sb.append(mname);
672: }
673: // params
674: if (!isField) {
675: sb.append(toStringArguments(false, false));
676: }
677: return sb.toString();
678: }
679:
680: public final String toStringArguments(boolean withNames,
681: boolean simpleTypesNames) {
682: StringBuilder sb = new StringBuilder();
683: sb.append("(");
684: for (int i = 0; i < params.size(); i++) {
685: Param p = params.get(i);
686: if (simpleTypesNames) {
687: sb.append(SyntaxUtils
688: .makeSingleJavaNameSimple(p.type));
689: } else {
690: sb.append(p.type);
691: }
692: if (withNames) {
693: sb.append(" ");
694: sb.append(p.name);
695: }
696: if (i < params.size() - 1) {
697: sb.append(","); // no space !
698: if (withNames)
699: sb.append(" ");
700: }
701: }
702: sb.append(")");
703: return sb.toString();
704: }
705:
706: @Override
707: public final String toString() {
708: StringBuilder sb = new StringBuilder();
709: if (isField) {
710: if (modifiers.length() > 0)
711: sb.append(modifiers + " ");
712: sb.append(type + " ");
713: sb.append(mname);
714: sb.append(";");
715: } else if (isConstructor) {
716: if (modifiers.length() > 0)
717: sb.append(modifiers + " ");
718: // no type.
719: sb.append(mname);
720: sb.append("(");
721: } else {
722: if (modifiers.length() > 0)
723: sb.append(modifiers + " ");
724: sb.append(type + " ");
725: sb.append(mname);
726: sb.append("(");
727: }
728:
729: // params
730: if (!isField) {
731: for (int i = 0; i < params.size(); i++) {
732: Param p = params.get(i);
733: sb.append(p.type);
734: sb.append(" ");
735: sb.append(p.name);
736: if (i < params.size() - 1)
737: sb.append(", ");
738: }
739: sb.append(")");
740:
741: if (!isConstructor && modifiers.contains("abstract")) {
742: sb.append(";");
743: } else {
744: sb.append(" { }");
745: }
746: }
747:
748: if (code.length() > 0) {
749: sb.append("\n /*\n" + code + " */\n");
750: }
751:
752: /*sb.append(mname);
753: sb.append("\n\ttype= "+type);
754: sb.append("\n\tmod= "+modifiers);
755: sb.append("\n\tparams= "+params+"\n");*/
756: return sb.toString();
757: }
758: }
759:
760: public int test(double a, double bb, double[][][] ccc) {
761: return -1;
762: }
763:
764: /** Converts a VM type name (I, D, Ljava.lang.String;, ...) to standard java type name
765: * (int, double, java.lang.String, ...).
766: * length1 => use vm native type...
767: */
768: private String makeTypeNameReadable(String n) {
769: if (n.length() == 1)
770: return SyntaxUtils.getNameForVMNativeType(n.charAt(0));
771: String type = SyntaxUtils.convertVmNameToFullJavaNames(n)
772: .replace('/', '.');
773: if (type.endsWith(";")) {
774: // remove "L" and ";"
775: type = type.substring(1, type.length() - 1);
776: }
777: // remove java.lang.XX if XX has no furter points !! (TODO)
778:
779: return type;
780: }
781:
782: public class Param implements Comparable<Param> {
783: int slot;
784: public final String name;
785: String type;
786:
787: public Param(int slot, String name, String type) {
788: this .slot = slot;
789: this .name = name;
790:
791: this .type = makeTypeNameReadable(type.trim());
792: }
793:
794: @Override
795: public final String toString() {
796: StringBuilder sb = new StringBuilder();
797: //sb.append(""+slot+":"); // debug
798: sb.append(type);
799: sb.append(" ");
800: sb.append(name);
801: return sb.toString();
802: }
803:
804: public int compareTo(Param p2) {
805: return Integer.valueOf(slot).compareTo(p2.slot);
806: }
807: }
808:
809: public enum TestEnum // decl: public final class tide.bytecode.DecompiledClass$TestEnum extends java.lang.Enum{
810: {
811: AA, BB, CC
812: }
813:
814: /* javaCC refuse the interface below, (just uncommented for completion )...
815: public @interface TestAnnot // decl: public interface tide.bytecode.DecompiledClass$TestAnnot extends java.lang.annotation.Annotation{
816: {
817: String hallo();
818: } */
819:
820: public interface TestInter // decl: public interface tide.bytecode.DecompiledClass$TestInter{
821: {
822: void hello();
823: }
824:
825: static class StatClass // decl: class tide.bytecode.DecompiledClass$StatClass extends java.lang.Object{
826: {
827: static class InnerStatClass // decl: class tide.bytecode.DecompiledClass$StatClass$InnerStatClass extends java.lang.Object{
828: {
829: }
830:
831: public double[] hello(int[] a, String hallo) {
832: return new double[] { 1 };
833: }
834: }
835:
836: /*test
837: public static void main(String[] arguments) throws Exception
838: {
839: File base = new File("C:/classes/tide/");
840: File javaP = new File("C:/Java/jdk1.6.0_05/bin/javap.exe");
841: DecompiledClass dc = new DecompiledClass("tide.bytecode.DecompiledClass", base, javaP,false);
842: //DecompiledClass dc2 = new DecompiledClass("tide.bytecode.DecompiledClass.StatClass", base, javaP);
843: //System.out.println(""+dc);
844:
845: Class c = Class.forName("tide.bytecode.DecompiledClass");
846: System.out.println("Class "+c);
847:
848:
849: for(Class ci : c.getClasses())
850: {
851: System.out.println(""+ci);
852: }
853: //TEST
854: for(Method m : c.getMethods())
855: {
856: if(dc.getMember(m)==null)
857: {
858: System.out.println("### Method not found: " +m);
859: }
860: //System.out.println(""+m);
861: }
862:
863: for(Field m : c.getFields())
864: {
865: if(dc.getMember(m)==null)
866: {
867: System.out.println("Field not found: " +m);
868: }
869: //System.out.println("Field: "+m);
870: }
871:
872: for(Constructor m : c.getConstructors())
873: {
874: if(dc.getMember(m)==null)
875: {
876: System.out.println("Constructor not found: " +m);
877: }
878: //System.out.println("Field: "+m);
879: }
880: }*/
881:
882: /* all classes recurse !
883: *
884: static void test()
885: {
886: //FileUtils.
887:
888: }
889:
890: public void testRet1()
891: {
892: }
893:
894: public void testRet1(int a)
895: {
896: //return 1;
897: }
898:
899: public int testRet1(String a)
900: {
901: return 2;
902: }
903:
904: interface InnerInterface
905: {
906: }
907:
908: /
909: static
910: {
911: int a=2;
912: System.out.println("static initializer "+a);
913: }*/
914:
915: }
|