git-svn-id: https://svn.code.sf.net/p/jode/code/branches/stable@1049 379699f6-c40d-0410-875b-85095c16579estable
parent
999834f14d
commit
e3d7a55d64
@ -0,0 +1,9 @@ |
|||||||
|
Makefile |
||||||
|
Makefile.in |
||||||
|
configure |
||||||
|
config.log |
||||||
|
config.cache |
||||||
|
config.status |
||||||
|
stamp-h |
||||||
|
libtool |
||||||
|
aclocal.m4 |
@ -0,0 +1 @@ |
|||||||
|
Jochen Hoenicke <Jochen.Hoenicke@Informatik.Uni-Oldenburg.DE> |
@ -0,0 +1,33 @@ |
|||||||
|
Before installing, make sure you have a java compiler (e.g javac or |
||||||
|
jikes) and the java 1.1 runtime class library installed. If you want |
||||||
|
to run this program you need at least a 1.1 compatible java virtual |
||||||
|
machine. There are some bugs in javac included in the SUN JDK 1.1, it |
||||||
|
won't work. |
||||||
|
|
||||||
|
This package was designed to use the GNU standard for configuration |
||||||
|
and makefiles. To build and install do the following: |
||||||
|
|
||||||
|
0). Make sure that you have all libraries that are needed in you |
||||||
|
classpath. You need gnu.getopt, and if you have JDK 1.1 you also need |
||||||
|
the collection classes and swing for 1.1. |
||||||
|
|
||||||
|
1). Run "aclocal && autoconf && automake --add-missing". |
||||||
|
|
||||||
|
2). Run the "configure" script to configure the package. There are |
||||||
|
various options you might want to pass to configure to control how the |
||||||
|
package is built. "configure --help" will give a complete list. |
||||||
|
|
||||||
|
If you have jikes, you should specify it with --with-jikes. You can |
||||||
|
give a path to the directory where it resides, otherwise it is |
||||||
|
searched in the path. |
||||||
|
|
||||||
|
3). Type "make" to build the package. If you don't have jikes, you |
||||||
|
should make clean first, since the dependency problem is not yet |
||||||
|
resolved. |
||||||
|
|
||||||
|
4). Type "make install" to install everything. This doesn't work yet. |
||||||
|
|
||||||
|
The created jar file is stored in the share directory. |
||||||
|
|
||||||
|
Jochen |
||||||
|
|
@ -0,0 +1,5 @@ |
|||||||
|
## Input file for automake to generate the Makefile.in used by configure
|
||||||
|
|
||||||
|
SUBDIRS = jode doc test
|
||||||
|
|
||||||
|
EXTRA_DIST = TODO
|
@ -0,0 +1,10 @@ |
|||||||
|
1.0.90 is a prerelease.. |
||||||
|
* First version using configure. Jode can now be almost automatically |
||||||
|
build, see INSTALL for instructions. |
||||||
|
* The decompiler can handler inner and anoymous classes. |
||||||
|
* You now need the gnu getopt package. |
||||||
|
* You need JDK 1.2 or alternatively the swing and collection packages |
||||||
|
for 1.1 |
||||||
|
|
||||||
|
|
||||||
|
|
@ -0,0 +1,106 @@ |
|||||||
|
takes class-files as input and produces something similar to the |
||||||
|
original java-File. Of course this can't be perfect: There is no way |
||||||
|
to produce the comments or the names of local variables (except when |
||||||
|
compiled with <code>-g</code>) and there are often more ways to write |
||||||
|
the same thing. But it does its job quite well.</P> |
||||||
|
|
||||||
|
<h2>Quick Test</h2> |
||||||
|
I have now an applet interface to the decompiler. |
||||||
|
<a href="jode-applet.html">Check it out</a>. |
||||||
|
|
||||||
|
<h2>How to get it</h2> |
||||||
|
<P>You can donwload the files in zip form. |
||||||
|
The <a href="jode_src.zip">sources</a> contain only the |
||||||
|
<code>java</code> files, the <a href="jode_cls.zip">classes</a> |
||||||
|
contain only the <code>class</code> files. </p> |
||||||
|
|
||||||
|
<p>I also have a <a href="jode.tar.gz">tar.gz file</a> containing only |
||||||
|
the <code>RCS</code> directories. This is the form I maintain the |
||||||
|
project, but you probably need unix and a few tools to use them.</p> |
||||||
|
|
||||||
|
<p>There are also some <a href="snapshot/">snapshots</a> that have new |
||||||
|
features like inner and anonymous classes. </p> |
||||||
|
|
||||||
|
<p><a href=".">Click here</a> to browse the files online. |
||||||
|
</p> |
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
<h2>How to use it</h2> |
||||||
|
|
||||||
|
<p>I have some simple step by step pages. There are three |
||||||
|
possibilities: |
||||||
|
<ul> |
||||||
|
<li> <a href="jode-useapplet.html"> Using the applet version</a>. |
||||||
|
This can make problem due to java's security policy, but is the |
||||||
|
simplest way and works on most platforms. |
||||||
|
</li> |
||||||
|
<li> If you use Windows, you should look on <a |
||||||
|
href="jode-win.html">this page</a>.</li> |
||||||
|
<li> Unix users should look on <a href="jode-unix.html">this page</a>. |
||||||
|
</ul> |
||||||
|
|
||||||
|
<h2>Known bugs</h2> |
||||||
|
|
||||||
|
<p>There may be situations, where the code doesn't understand complex |
||||||
|
expressions. In this many ugly temporary variables are used, but the |
||||||
|
code should still be compileable. This does especially happen when |
||||||
|
you compile with `-O' flag and javac has inlined some methods. </p> |
||||||
|
|
||||||
|
<p>Sometimes this program may exit with an <code>Exception</code> or |
||||||
|
produce incorrect code. Most time the code can't be compiled, so that |
||||||
|
it can be easily spotted. If you have one of these problems (except |
||||||
|
those that occur on some of the <code>jode.test</code> files, I would |
||||||
|
be very interested in a bug report (including the <code>class</code> |
||||||
|
file, if possible).</p> |
||||||
|
|
||||||
|
<p>Sometimes it generates some <code>GOTO</code> expression and |
||||||
|
labels. This can't be compiled, but shouldn't happen any more with |
||||||
|
javac or jikes.</p> |
||||||
|
|
||||||
|
<p>It doesn't handle inner and anonymous classes, yet. You can |
||||||
|
decompile them separately, though (use `<code>+$</code>' switch under |
||||||
|
jikes), but there is a bug in javac, so that a final variable is twice |
||||||
|
initialized. If you encounter this problem just remove the doubled |
||||||
|
line by hand. </p> |
||||||
|
|
||||||
|
<p><b>New!</b> The latest <a href="snapshot">snapshot</a> can handle |
||||||
|
inner and anonymous classes.</p> |
||||||
|
|
||||||
|
|
||||||
|
<h2>Why did I wrote it?</h2> |
||||||
|
|
||||||
|
<p>Someday I found <code>guavad</code>, a disassembler for java byte |
||||||
|
code (it does similar things like <code>javap -c</code>). I used |
||||||
|
it on a class file, and found that it was possible to reconstruct the |
||||||
|
original java code. First I did it by hand on some small routines, |
||||||
|
but I soon realized that it was a rather stupid task, and that I could |
||||||
|
write a <a href="../perl/dasm_to_java.perl"><code>perl</code> script</a> |
||||||
|
that does the same. At the end of the next day I had a working |
||||||
|
decompiler.</p> |
||||||
|
|
||||||
|
<p>Now while it was working, it was not easy to use. You had to |
||||||
|
decompile the code first with a disassembler, cut the method, you |
||||||
|
wanted to decompile and then run the perl script on it. So I decided |
||||||
|
to get some information of the class files and do this all |
||||||
|
automatically. I decided to write it in <code>java</code> now, |
||||||
|
because it suited best.</p> |
||||||
|
|
||||||
|
<p>Just for the records: the java code is now more than 50 times |
||||||
|
bigger than the original perl script and is still growing.</p> |
||||||
|
|
||||||
|
<h2>License</h2> |
||||||
|
|
||||||
|
<p>This code is under GNU GPL. That basically means, that you can copy |
||||||
|
or modify this code, as long as you put all your modification under |
||||||
|
the GPL again. <A HREF="http://www.gnu.org/copyleft/gpl.html"> Look |
||||||
|
here for the complete license</a>.</p> |
||||||
|
|
||||||
|
<hr> |
||||||
|
|
||||||
|
<p><A HREF="mailto:Jochen.Hoenicke@Informatik.Uni-Oldenburg.DE"> |
||||||
|
http://www.informatik.uni-oldenburg.de/~delwi/jode/jode.html</A>, last |
||||||
|
updated on <em>17-Jun-1999</em>.</p> |
||||||
|
|
||||||
|
</body> |
||||||
|
</html> |
@ -0,0 +1,43 @@ |
|||||||
|
dnl |
||||||
|
dnl Add macros |
||||||
|
dnl JODE_CHECK_JAVA |
||||||
|
dnl |
||||||
|
|
||||||
|
dnl JODE_CHECK_JAVA(path) |
||||||
|
AC_DEFUN(JODE_CHECK_JAVA, |
||||||
|
[ |
||||||
|
AC_PATH_PROG(JAVAC, javac, "", $PATH:$1/bin) |
||||||
|
AC_PATH_PROG(JAR, jar, "", $PATH:$1/bin) |
||||||
|
for path in $1/lib $1/jre/lib $1/shared; do |
||||||
|
for classlib in classes.zip rt.jar; do |
||||||
|
AC_CHECK_FILES($path/$classlib, |
||||||
|
[ CLASSLIB=$path/$classlib |
||||||
|
break 3 |
||||||
|
], [ true ]) |
||||||
|
done |
||||||
|
done |
||||||
|
AC_SUBST(CLASSPATH) |
||||||
|
AC_SUBST(CLASSLIB) |
||||||
|
]) |
||||||
|
|
||||||
|
AC_DEFUN(JODE_CHECK_CLASS, |
||||||
|
[ |
||||||
|
if (IFS=":" |
||||||
|
clazz=`echo $1 | sed -e 's/\./\//g' -e 's/\(.*\)/\1.class/'` |
||||||
|
jode_found=0 |
||||||
|
for path in $2; do |
||||||
|
if test -d $path; then |
||||||
|
if test -e $path/$clazz; then |
||||||
|
exit 0 |
||||||
|
fi |
||||||
|
elif $UNZIP -v -C $path $clazz &>/dev/null ; then |
||||||
|
exit 0 |
||||||
|
fi |
||||||
|
done; |
||||||
|
exit 1) |
||||||
|
then |
||||||
|
$3 |
||||||
|
else |
||||||
|
$4 |
||||||
|
fi |
||||||
|
]) |
@ -0,0 +1,128 @@ |
|||||||
|
dnl Process this file with autoconf to produce a configure script. |
||||||
|
AC_INIT() |
||||||
|
|
||||||
|
AM_INIT_AUTOMAKE(jode, 1.0.90) |
||||||
|
|
||||||
|
dnl Checks for programs. |
||||||
|
dnl AC_PROG_CXX |
||||||
|
dnl AC_PROG_AWK |
||||||
|
dnl AC_PROG_CC |
||||||
|
dnl AC_PROG_CPP |
||||||
|
dnl AC_PROG_INSTALL |
||||||
|
dnl AC_PROG_LN_S |
||||||
|
AC_PROG_MAKE_SET |
||||||
|
dnl AC_PROG_RANLIB |
||||||
|
dnl AC_PATH_PROG(ZIP, zip) |
||||||
|
AC_PATH_PROG(UNZIP, unzip) |
||||||
|
|
||||||
|
dnl Checks for libraries. |
||||||
|
|
||||||
|
dnl Checks for header files. |
||||||
|
|
||||||
|
dnl Checks for typedefs, structures, and compiler characteristics. |
||||||
|
|
||||||
|
dnl Checks for library functions. |
||||||
|
|
||||||
|
dnl hack to quote Makefile lines |
||||||
|
QUOTE="" |
||||||
|
AC_SUBST(QUOTE) |
||||||
|
|
||||||
|
AC_SUBST(SHELL) |
||||||
|
|
||||||
|
AC_ARG_WITH(java, |
||||||
|
[ --with-java specify path to a java-like program ], |
||||||
|
[ |
||||||
|
if test ${withval} != "" || test ${withval} != "yes" || test ${withval} != "no"; then |
||||||
|
# set javac to user input value |
||||||
|
JODE_CHECK_JAVA(${withval}) |
||||||
|
else |
||||||
|
JODE_CHECK_JAVA(/usr/lib/java) |
||||||
|
fi |
||||||
|
], |
||||||
|
[ |
||||||
|
JODE_CHECK_JAVA(/usr/lib/java) |
||||||
|
]) |
||||||
|
|
||||||
|
dnl jikes can also handle dependancies. |
||||||
|
AC_ARG_WITH(jikes, |
||||||
|
[ --with-jikes specify location of jikes ], |
||||||
|
[ |
||||||
|
USER_SPECIFIED_JIKES=true |
||||||
|
if test "${withval}" = "yes" || test "${withval}" = ""; then |
||||||
|
AC_PATH_PROG(JIKES, jikes, "", $PATH) |
||||||
|
else |
||||||
|
echo "searching jikes in ${withval}:$PATH" |
||||||
|
AC_PATH_PROG(JIKES, jikes, "", ${withval}:$PATH) |
||||||
|
fi |
||||||
|
if test -n "$JIKES"; then |
||||||
|
JAVAC=$JIKES |
||||||
|
fi |
||||||
|
], |
||||||
|
[ |
||||||
|
USER_SPECIFIED_JIKES= |
||||||
|
AC_PATH_PROG(JIKES, jikes, "", $PATH) |
||||||
|
]) |
||||||
|
AM_CONDITIONAL(HAVE_JIKES, test x"$JIKES" != x) |
||||||
|
|
||||||
|
AC_ARG_WITH(javac, |
||||||
|
[ --with-javac specify location of javac ], |
||||||
|
[ |
||||||
|
if test x$USER_SPECIFIED_JIKES == xtrue; then |
||||||
|
AC_MSG_ERROR(You must only give one option --with-javac or --with-jikes) |
||||||
|
fi |
||||||
|
if test ${withval} != "" || test ${withval} != "yes" || test ${withval} != "no"; then |
||||||
|
AC_CHECK_FILES(${withval}, |
||||||
|
[ JAVAC=${withval} ], |
||||||
|
[ AC_MSG_ERROR(${withval} does not exists) ]) |
||||||
|
fi |
||||||
|
], [ true ]) |
||||||
|
|
||||||
|
JODE_CHECK_CLASS(java.lang.Object, $CLASSLIB, |
||||||
|
[ true ], |
||||||
|
[ AC_MSG_ERROR(Please specify location of java class library for jikes) ]) |
||||||
|
|
||||||
|
AC_MSG_CHECKING(for collection classes) |
||||||
|
JODE_CHECK_CLASS(java.util.Set, $CLASSPATH:$CLASSLIB, |
||||||
|
[ COLLECTIONS="java.util" ], |
||||||
|
[ JODE_CHECK_CLASS(com.sun.java.util.collections.Set, $CLASSPATH:$CLASSLIB, |
||||||
|
[ COLLECTIONS="com.sun.java.util.collections" ], |
||||||
|
[ AC_MSG_RESULT(no) |
||||||
|
AC_MSG_ERROR(You need the Java 1.2 collection classes in your classpath) |
||||||
|
]) |
||||||
|
] ) |
||||||
|
AC_MSG_RESULT($COLLECTIONS) |
||||||
|
AC_SUBST(COLLECTIONS) |
||||||
|
|
||||||
|
AC_MSG_CHECKING(for gnu.getopt) |
||||||
|
JODE_CHECK_CLASS(gnu.getopt.Getopt, $CLASSPATH:$CLASSLIB, |
||||||
|
[ AC_MSG_RESULT(yes) ], |
||||||
|
[ AC_MSG_RESULT(no) |
||||||
|
AC_MSG_ERROR(You need gnu getopt for java.) ]) |
||||||
|
|
||||||
|
AC_MSG_CHECKING(for swing) |
||||||
|
JODE_CHECK_CLASS(javax.swing.JFrame, $CLASSPATH:$CLASSLIB, |
||||||
|
[ JAVAX_SWING="javax.swing" ], |
||||||
|
[ JODE_CHECK_CLASS(com.sun.swing.JFrame, $CLASSPATH:$CLASSLIB, |
||||||
|
[ JAVAX_SWING="com.sun.java.swing" ], |
||||||
|
[ JAVAX_SWING="no" ]) ] ) |
||||||
|
AC_MSG_RESULT($JAVAX_SWING) |
||||||
|
AC_SUBST(JAVAX_SWING) |
||||||
|
if test x"$JAVAX_SWING" != x; then |
||||||
|
SWING_CLASSES="jode/swingui/Main.class" |
||||||
|
else |
||||||
|
AC_MSG_WARN(Swing is not in classpath ... skipping swingui) |
||||||
|
SWING_CLASSES="" |
||||||
|
fi |
||||||
|
AC_SUBST(SWING_CLASSES) |
||||||
|
|
||||||
|
AC_SUBST(CLASSPATH) |
||||||
|
AC_SUBST(JAVAC) |
||||||
|
|
||||||
|
AC_OUTPUT(Makefile |
||||||
|
jode/Makefile |
||||||
|
doc/Makefile |
||||||
|
test/Makefile |
||||||
|
jode/GlobalOptions.java |
||||||
|
jode/swingui/Main.java |
||||||
|
jode/swingui/PackagesTreeModel.java) |
||||||
|
|
@ -0,0 +1,2 @@ |
|||||||
|
Makefile |
||||||
|
Makefile.in |
@ -0,0 +1,5 @@ |
|||||||
|
## Input file for automake to generate the Makefile.in used by configure
|
||||||
|
|
||||||
|
EXTRA_DIST = \
|
||||||
|
jode.html jode-applet.html jode-obfuscator.html jode-unix.html \
|
||||||
|
jode-useapplet.html jode-win.html
|
@ -0,0 +1,39 @@ |
|||||||
|
<html> |
||||||
|
<head> |
||||||
|
<title>Jode Test Applet</title> |
||||||
|
</head> |
||||||
|
|
||||||
|
|
||||||
|
<body> |
||||||
|
<a href="jode.html">Up</a> |
||||||
|
|
||||||
|
<h1>Test Applet</h1> |
||||||
|
|
||||||
|
<applet code="jode/JodeApplet.class" archive="jode-applet.jar" width=640 height=400> |
||||||
|
<param name=classpath |
||||||
|
value="http://www.informatik.uni-oldenburg.de/~delwi/jode/jode_cls.zip"> |
||||||
|
<param name=class value="jode.JodeApplet"> |
||||||
|
</applet><br><br> |
||||||
|
|
||||||
|
Press the start button to decompile this applet. You may change the |
||||||
|
class path and class name to point to a class file of your choice. |
||||||
|
But note that most browsers doesn't allow loading files from a |
||||||
|
different server.<br><br> |
||||||
|
|
||||||
|
Save probably doesn't work, because it is forbidden by the browser.<br><br> |
||||||
|
|
||||||
|
You may give multiple entries in the class path field separated by a |
||||||
|
comma. The components may be local or remote zip or jar files or |
||||||
|
directories. Note that browsers forbid accesses to different hosts or |
||||||
|
local files that are not in a subdirectory of the applet |
||||||
|
directory.<br><br> |
||||||
|
|
||||||
|
BTW: If you just want to read the source, you may <a |
||||||
|
href="http://www.informatik.uni-oldenburg.de/~delwi/jode">browse it |
||||||
|
online</a> <code>:-)</code><br><br> |
||||||
|
|
||||||
|
You can download this, look <a href="jode-useapplet.html">here</a> for |
||||||
|
a description. |
||||||
|
|
||||||
|
</body> |
||||||
|
</html> |
@ -0,0 +1,15 @@ |
|||||||
|
<!DOCTYPE HTML PUBLIC "-//IETF//DTD HTML 3.0//EN"> |
||||||
|
<html> |
||||||
|
<head> |
||||||
|
<title>Using the obfuscator</title> |
||||||
|
</head> |
||||||
|
<body> |
||||||
|
<a href="jode.html">Up</a> |
||||||
|
|
||||||
|
The obfuscator currently takes a lot of options (I plan to use an |
||||||
|
extra file containing the options). You should therefore create a |
||||||
|
script (or batch file under Windows) that invokes the obfuscator.<br> |
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
</body> |
@ -0,0 +1,97 @@ |
|||||||
|
<!DOCTYPE HTML PUBLIC "-//IETF//DTD HTML 3.0//EN"> |
||||||
|
<html> |
||||||
|
<head> |
||||||
|
<title>Using the decompiler under Unix</title> |
||||||
|
</head> |
||||||
|
<body> |
||||||
|
<a href="jode.html">Up</a> |
||||||
|
|
||||||
|
|
||||||
|
<h1>Step by Step</h1> |
||||||
|
|
||||||
|
You need java version 1.1 or higher. In the following description I |
||||||
|
assume you have the JDK 1.1, residing in <code>/usr/lib/java</code>. |
||||||
|
For other installations you have to adopt the paths. Also I use the |
||||||
|
bourne shell syntax. |
||||||
|
|
||||||
|
<ol> |
||||||
|
<li> Set the classpath. It should include the jode_cls.zip as well as |
||||||
|
the directory where the class files you want to decompile resides. |
||||||
|
You can also specify a zip file instead of a directory. It is |
||||||
|
also a good idea to include the zip resp. jar file containing the |
||||||
|
basic <code>java.*</code> class files. |
||||||
|
<pre> |
||||||
|
export CLASSPATH=$HOME/jode_cls.zip:$HOME/download:/usr/lib/java/lib/classes.zip |
||||||
|
</pre> |
||||||
|
</li> |
||||||
|
<li> Now you can start the graphical interface as following (Note the |
||||||
|
case of the parameter) |
||||||
|
<pre> |
||||||
|
java jode.JodeWindow |
||||||
|
</pre> |
||||||
|
</li> |
||||||
|
<li> The classpath field should already contain the classpath you set |
||||||
|
above. The class field contains <code>jode.JodeWindow</code> and |
||||||
|
you may push start immediately to decompile this class. |
||||||
|
</li> |
||||||
|
<li> If you want to decompile your own <code>.class</code> file, enter |
||||||
|
the name of the file without <code>.class</code> extension and |
||||||
|
push the start button. Change the class path if it doesn't point |
||||||
|
to the right directory. |
||||||
|
</li> |
||||||
|
<li> After decompiling, you can save the file using the save button. |
||||||
|
</li> |
||||||
|
</ol> |
||||||
|
|
||||||
|
<h1>Packaged classes</h1> |
||||||
|
|
||||||
|
If the class file belongs to a package (like jode.JodeWindow) you |
||||||
|
have to give the full qualified class name (the package names |
||||||
|
separated by a dot followed by the class name). The class path should |
||||||
|
point to the directory containing the package sub directories in this |
||||||
|
case. <br><br> |
||||||
|
|
||||||
|
<h1>Command line utility</h1> |
||||||
|
|
||||||
|
There is also a command line utility which is much more powerful, but |
||||||
|
also more difficult to use. You can start it (after setting the |
||||||
|
classpath) with |
||||||
|
<pre> |
||||||
|
java jode.Decompiler |
||||||
|
</pre> |
||||||
|
and get a list of the supported parameters. To decompile the whole |
||||||
|
decompiler you can use these magic lines: |
||||||
|
<pre> |
||||||
|
mkdir src |
||||||
|
CLASSPATH=jode_cls.zip java jode.Decompiler --dest src \ |
||||||
|
`unzip -v jode_cls.zip|grep .class|cut -c59-|sed s/.class//|sed s?/?.?g` |
||||||
|
</pre> |
||||||
|
|
||||||
|
<h1>Obfuscator</h1> |
||||||
|
|
||||||
|
So you want to protect your classes from decompiling? Well that is |
||||||
|
your choice. You may use my obfuscator. The class files are |
||||||
|
decompileable again (except when using -strong option, but this is |
||||||
|
reversable by obfuscating again), but at least the information about |
||||||
|
the names of identifiers are completely lost. <br><br> |
||||||
|
|
||||||
|
The obfuscator is quite difficult to use (this is why I hided this |
||||||
|
section here) and there is only a short description of the command |
||||||
|
line parameters: |
||||||
|
<pre> |
||||||
|
CLASSPATH=jode_cls.zip java jode.Obfuscator |
||||||
|
</pre> |
||||||
|
|
||||||
|
As a hint, to obfuscate the obfuscator use the following command line: |
||||||
|
<pre> |
||||||
|
CLASSPATH=jode_cls.zip java jode.Obfuscator \ |
||||||
|
-cp jode_cls.zip:/usr/lib/java/lib/classes.zip -d obfuscated.zip \ |
||||||
|
-weak -revtable translate.tbl -swaporder \ |
||||||
|
-preserve jode.Obfuscator.main jode |
||||||
|
</pre> |
||||||
|
|
||||||
|
The options <code>-unique</code> and <code>-table</code> can be |
||||||
|
helpful to deobfuscate obfuscated code. |
||||||
|
</body> |
||||||
|
|
||||||
|
|
@ -0,0 +1,49 @@ |
|||||||
|
<!DOCTYPE HTML PUBLIC "-//IETF//DTD HTML 3.0//EN"> |
||||||
|
<html> |
||||||
|
<head> |
||||||
|
<title>Using the decompiler as applet (locally)</title> |
||||||
|
</head> |
||||||
|
<body> |
||||||
|
<a href="jode.html">Up</a> |
||||||
|
|
||||||
|
<h1>Step by Step</h1> |
||||||
|
|
||||||
|
If you want to use the applet version you need a recent Internet |
||||||
|
Explorer or Netscape which supports java 1.1. You can also use the |
||||||
|
appletviewer of the java development kit. |
||||||
|
|
||||||
|
<ol> |
||||||
|
<li> Copy <a |
||||||
|
href="http://www.informatik.uni-oldenburg.de/~delwi/jode/jode-applet.html" |
||||||
|
>jode-applet.html</a> into a local directory. |
||||||
|
</li> |
||||||
|
<li> Copy <a |
||||||
|
href="http://www.informatik.uni-oldenburg.de/~delwi/jode/jode_cls.zip" |
||||||
|
>jode_cls.zip</a> to the <b>same</b> directory. |
||||||
|
</li> |
||||||
|
<li> Copy the <code>.class</code> file or <code>zip</code> file, you |
||||||
|
want to decompile, to that directory. |
||||||
|
</li> |
||||||
|
<li> Load the html file into Netscape or Internet Explorer. |
||||||
|
</li> |
||||||
|
<li> Set the classpath simply to `<code>.</code>' (without quotes). |
||||||
|
You may also specify a zip or jar file here. Note that applet and |
||||||
|
class files must be in the same directory due to security policy. <br> |
||||||
|
You can also change the default classpath in the html file. |
||||||
|
</li> |
||||||
|
<li> Enter the name of the class without <code>.class</code> |
||||||
|
extension. |
||||||
|
</li> |
||||||
|
<li> Press start button in applet. </li> |
||||||
|
<li> Press save button to save the decompiled code. </li> |
||||||
|
</ol> |
||||||
|
|
||||||
|
<h1>Packaged classes</h1> |
||||||
|
|
||||||
|
If the class file belongs to a package (like jode.JodeWindow) you |
||||||
|
have to give the full qualified class name (the package names |
||||||
|
separated by a dot followed by the class name). The class path should |
||||||
|
point to the directory containing the package sub directories in this |
||||||
|
case. |
||||||
|
|
||||||
|
</body> |
@ -0,0 +1,62 @@ |
|||||||
|
<!DOCTYPE HTML PUBLIC "-//IETF//DTD HTML 3.0//EN"> |
||||||
|
<html> |
||||||
|
<head> |
||||||
|
<title>Using the decompiler under Windows</title> |
||||||
|
</head> |
||||||
|
<body> |
||||||
|
<a href="jode.html">Up</a> |
||||||
|
|
||||||
|
<h1>Step by Step</h1> |
||||||
|
|
||||||
|
You need java version 1.1 or higher. I suggest using the Sun JDK or |
||||||
|
JRE 1.1 or 1.2. In the following description I assume Sun JDK 1.2, |
||||||
|
for other virtual machines the paths and the name of the java |
||||||
|
interpreter (<code>c:\jdk1.2\java</code>) may differ. <br><br> |
||||||
|
|
||||||
|
<ol> |
||||||
|
<li> Set the classpath. It should include the jode_cls.zip as well as |
||||||
|
the directory where the class files you want to decompile resides. |
||||||
|
You can also specify a zip file instead of a directory. It is |
||||||
|
also a good Idea to include the zip resp. jar file containing the |
||||||
|
basic <code>java.*</code> class files. |
||||||
|
<pre> |
||||||
|
set CLASSPATH=c:\temp\jode_cls.zip;c:\temp;c:\jdk1.2\jre\lib\rt.jar |
||||||
|
</pre> |
||||||
|
</li> |
||||||
|
<li> Now you can start the graphical interface as following (Note the |
||||||
|
case of the parameter) |
||||||
|
<pre> |
||||||
|
c:\jdk1.2\java jode.JodeWindow |
||||||
|
</pre> |
||||||
|
</li> |
||||||
|
<li> The classpath field should already contain the classpath you set |
||||||
|
above. The class field contains <code>jode.JodeWindow</code> and |
||||||
|
you may push start immediately to decompile this class. |
||||||
|
</li> |
||||||
|
<li> If you want to decompile your own <code>.class</code> file, enter |
||||||
|
the name of the file without <code>.class</code> extension and |
||||||
|
push the start button. Change the class path if it doesn't point |
||||||
|
to the right directory. |
||||||
|
</li> |
||||||
|
<li> After decompiling, you can save the file using the save button. |
||||||
|
</li> |
||||||
|
</ol> |
||||||
|
|
||||||
|
<h1>Packaged classes</h1> |
||||||
|
|
||||||
|
If the class file belongs to a package (like jode.JodeWindow) you |
||||||
|
have to give the full qualified class name (the package names |
||||||
|
separated by a dot followed by the class name). The class path should |
||||||
|
point to the directory containing the package sub directories in this |
||||||
|
case. <br><br> |
||||||
|
|
||||||
|
<h1>Command line utility</h1> |
||||||
|
|
||||||
|
There is also a command line utility which is much more powerful, but |
||||||
|
also more difficult to use. You can start it (after setting the |
||||||
|
classpath) with |
||||||
|
<pre> |
||||||
|
c:\jdk1.2\java jode.Decompiler |
||||||
|
</pre> |
||||||
|
and get a list of the supported parameters. |
||||||
|
</body> |
@ -0,0 +1,125 @@ |
|||||||
|
<!DOCTYPE HTML PUBLIC "-//IETF//DTD HTML 3.0//EN"> |
||||||
|
<html> |
||||||
|
<head> |
||||||
|
<title> JOchens' java-DEcompiler (JODE) </title> |
||||||
|
<meta name="description" content="The home page of jode, my Java decompiler."> |
||||||
|
<meta name="author" content="Jochen Hoenicke"> |
||||||
|
<meta name="keywords" content="jode, java, decompile, decompiler, |
||||||
|
java-decompiler, reverse engineering, free, GPL"> |
||||||
|
<meta name="robots" content="index"> |
||||||
|
<meta name="robots" content="nofollow"> |
||||||
|
<meta name="date" content="1999-03-08"> |
||||||
|
</head> |
||||||
|
|
||||||
|
<body> |
||||||
|
<a href="http://www.informatik.uni-oldenbur.de/~delwi/jode/jode.html"> |
||||||
|
An uptodate version of this page is located here.</a><p> |
||||||
|
|
||||||
|
<h2>What is it?</h2> |
||||||
|
|
||||||
|
<P>This is a decompiler for java I have written in my spare time. It |
||||||
|
takes class-files as input and produces something similar to the |
||||||
|
original java-File. Of course this can't be perfect: There is no way |
||||||
|
to produce the comments or the names of local variables (except when |
||||||
|
compiled with <code>-g</code>) and there are often more ways to write |
||||||
|
the same thing. But it does its job quite well.</P> |
||||||
|
|
||||||
|
<h2>Quick Test</h2> |
||||||
|
I have now an applet interface to the decompiler. |
||||||
|
<a href="jode-applet.html">Check it out</a>. |
||||||
|
|
||||||
|
<h2>How to get it</h2> |
||||||
|
<P>You can donwload the files in zip form. |
||||||
|
The <a href="jode_src.zip">sources</a> contain only the |
||||||
|
<code>java</code> files, the <a href="jode_cls.zip">classes</a> |
||||||
|
contain only the <code>class</code> files. </p> |
||||||
|
|
||||||
|
<p>I also have a <a href="jode.tar.gz">tar.gz file</a> containing only |
||||||
|
the <code>RCS</code> directories. This is the form I maintain the |
||||||
|
project, but you probably need unix and a few tools to use them.</p> |
||||||
|
|
||||||
|
<p>There are also some <a href="snapshot/">snapshots</a> that have new |
||||||
|
features like inner and anonymous classes. </p> |
||||||
|
|
||||||
|
<p><a href=".">Click here</a> to browse the files online. |
||||||
|
</p> |
||||||
|
|
||||||
|
|
||||||
|
<h2>How to use it</h2> |
||||||
|
|
||||||
|
<p>I have some simple step by step pages. There are three |
||||||
|
possibilities: |
||||||
|
<ul> |
||||||
|
<li> <a href="jode-useapplet.html"> Using the applet version</a>. |
||||||
|
This can make problem due to java's security policy, but is the |
||||||
|
simplest way and works on most platforms. |
||||||
|
</li> |
||||||
|
<li> If you use Windows, you should look on <a |
||||||
|
href="jode-win.html">this page</a>.</li> |
||||||
|
<li> Unix users should look on <a href="jode-unix.html">this page</a>. |
||||||
|
</ul> |
||||||
|
|
||||||
|
<h2>Known bugs</h2> |
||||||
|
|
||||||
|
<p>There may be situations, where the code doesn't understand complex |
||||||
|
expressions. In this many ugly temporary variables are used, but the |
||||||
|
code should still be compileable. This does especially happen when |
||||||
|
you compile with `-O' flag and javac has inlined some methods. </p> |
||||||
|
|
||||||
|
<p>Sometimes this program may exit with an <code>Exception</code> or |
||||||
|
produce incorrect code. Most time the code can't be compiled, so that |
||||||
|
it can be easily spotted. If you have one of these problems (except |
||||||
|
those that occur on some of the <code>jode.test</code> files, I would |
||||||
|
be very interested in a bug report (including the <code>class</code> |
||||||
|
file, if possible).</p> |
||||||
|
|
||||||
|
<p>Sometimes it generates some <code>GOTO</code> expression and |
||||||
|
labels. This can't be compiled, but shouldn't happen any more with |
||||||
|
javac or jikes.</p> |
||||||
|
|
||||||
|
<p>It doesn't handle inner and anonymous classes, yet. You can |
||||||
|
decompile them separately, though (use `<code>+$</code>' switch under |
||||||
|
jikes), but there is a bug in javac, so that a final variable is twice |
||||||
|
initialized. If you encounter this problem just remove the doubled |
||||||
|
line by hand. </p> |
||||||
|
|
||||||
|
<p><b>New!</b> The latest <a href="snapshot">snapshot</a> can handle |
||||||
|
inner and anonymous classes.</p> |
||||||
|
|
||||||
|
|
||||||
|
<h2>Why did I wrote it?</h2> |
||||||
|
|
||||||
|
<p>Someday I found <code>guavad</code>, a disassembler for java byte |
||||||
|
code (it does similar things like <code>javap -c</code>). I used |
||||||
|
it on a class file, and found that it was possible to reconstruct the |
||||||
|
original java code. First I did it by hand on some small routines, |
||||||
|
but I soon realized that it was a rather stupid task, and that I could |
||||||
|
write a <a href="../perl/dasm_to_java.perl"><code>perl</code> script</a> |
||||||
|
that does the same. At the end of the next day I had a working |
||||||
|
decompiler.</p> |
||||||
|
|
||||||
|
<p>Now while it was working, it was not easy to use. You had to |
||||||
|
decompile the code first with a disassembler, cut the method, you |
||||||
|
wanted to decompile and then run the perl script on it. So I decided |
||||||
|
to get some information of the class files and do this all |
||||||
|
automatically. I decided to write it in <code>java</code> now, |
||||||
|
because it suited best.</p> |
||||||
|
|
||||||
|
<p>Just for the records: the java code is now more than 50 times |
||||||
|
bigger than the original perl script and is still growing.</p> |
||||||
|
|
||||||
|
<h2>License</h2> |
||||||
|
|
||||||
|
<p>This code is under GNU GPL. That basically means, that you can copy |
||||||
|
or modify this code, as long as you put all your modification under |
||||||
|
the GPL again. <A HREF="http://www.gnu.org/copyleft/gpl.html"> Look |
||||||
|
here for the complete license</a>.</p> |
||||||
|
|
||||||
|
<hr> |
||||||
|
|
||||||
|
<p><A HREF="mailto:Jochen.Hoenicke@Informatik.Uni-Oldenburg.DE"> |
||||||
|
http://www.informatik.uni-oldenburg.de/~delwi/jode/jode.html</A>, last |
||||||
|
updated on <em>17-Jun-1999</em>.</p> |
||||||
|
|
||||||
|
</body> |
||||||
|
</html> |
@ -0,0 +1,4 @@ |
|||||||
|
Makefile |
||||||
|
Makefile.in |
||||||
|
.java.deps |
||||||
|
jode.jar |
@ -0,0 +1,107 @@ |
|||||||
|
/* GlobalOptions Copyright (C) 1999 Jochen Hoenicke. |
||||||
|
* |
||||||
|
* This program is free software; you can redistribute it and/or modify |
||||||
|
* it under the terms of the GNU General Public License as published by |
||||||
|
* the Free Software Foundation; either version 2, or (at your option) |
||||||
|
* any later version. |
||||||
|
* |
||||||
|
* 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 General Public License for more details. |
||||||
|
* |
||||||
|
* You should have received a copy of the GNU General Public License |
||||||
|
* along with this program; see the file COPYING. If not, write to |
||||||
|
* the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. |
||||||
|
* |
||||||
|
* $Id$ |
||||||
|
*/ |
||||||
|
|
||||||
|
package jode; |
||||||
|
import java.io.PrintWriter; |
||||||
|
import java.util.StringTokenizer; |
||||||
|
|
||||||
|
public class GlobalOptions { |
||||||
|
public final static String version = "@VERSION@"; |
||||||
|
public final static String email = "jochen@gnu.org"; |
||||||
|
public final static String copyright = |
||||||
|
"Jode (c) 1998,1999 Jochen Hoenicke <"+email+">"; |
||||||
|
public final static String URL = |
||||||
|
"http://www.informatik.uni-oldenburg.de/~delwi/jode/jode.html"; |
||||||
|
|
||||||
|
public static PrintWriter err = new PrintWriter(System.err, true); |
||||||
|
public static int verboseLevel = 0; |
||||||
|
public static int debuggingFlags = 0; |
||||||
|
|
||||||
|
public static final int DEBUG_BYTECODE = 0x001; |
||||||
|
public static final int DEBUG_VERIFIER = 0x002; |
||||||
|
public static final int DEBUG_TYPES = 0x004; |
||||||
|
public static final int DEBUG_FLOW = 0x008; |
||||||
|
public static final int DEBUG_INOUT = 0x010; |
||||||
|
public static final int DEBUG_ANALYZE = 0x020; |
||||||
|
public static final int DEBUG_LVT = 0x040; |
||||||
|
public static final int DEBUG_CHECK = 0x080; |
||||||
|
public static final int DEBUG_LOCALS = 0x100; |
||||||
|
public static final int DEBUG_CONSTRS = 0x200; |
||||||
|
public static final int DEBUG_INTERPRT = 0x400; |
||||||
|
|
||||||
|
public static final String[] debuggingNames = { |
||||||
|
"bytecode", "verifier", "types", "flow", |
||||||
|
"inout", "analyze", "lvt", "check", "locals", |
||||||
|
"constructors", "interpreter" |
||||||
|
}; |
||||||
|
|
||||||
|
public static void usageDebugging() { |
||||||
|
err.println("Debugging option: --debug=flag1,flag2,..."); |
||||||
|
err.println("possible flags:"); |
||||||
|
err.println(" bytecode " + |
||||||
|
"show bytecode, as it is read from class file."); |
||||||
|
err.println(" verifier " + |
||||||
|
"show result of bytecode verification."); |
||||||
|
err.println(" types " + |
||||||
|
"show type intersections"); |
||||||
|
err.println(" flow " + |
||||||
|
"show flow block merging."); |
||||||
|
err.println(" analyze " + |
||||||
|
"show T1/T2 analyzation of flow blocks."); |
||||||
|
err.println(" inout " + |
||||||
|
"show in/out set analysis."); |
||||||
|
err.println(" lvt " + |
||||||
|
"dump LocalVariableTable."); |
||||||
|
err.println(" check " + |
||||||
|
"do time consuming sanity checks."); |
||||||
|
err.println(" locals " + |
||||||
|
"dump local merging information."); |
||||||
|
err.println(" constructors " + |
||||||
|
"dump constructor simplification."); |
||||||
|
err.println(" interpreter " + |
||||||
|
"debug execution of interpreter."); |
||||||
|
System.exit(0); |
||||||
|
} |
||||||
|
|
||||||
|
/** |
||||||
|
* Parse the argument given to the debugging flag. |
||||||
|
* @return true, if the argument parsed without problems. |
||||||
|
*/ |
||||||
|
public static boolean setDebugging(String debuggingString) { |
||||||
|
if (debuggingString.length() == 0 || debuggingString.equals("help")) { |
||||||
|
usageDebugging(); |
||||||
|
return false; |
||||||
|
} |
||||||
|
|
||||||
|
StringTokenizer st = new StringTokenizer(debuggingString, ","); |
||||||
|
next_token: |
||||||
|
while (st.hasMoreTokens()) { |
||||||
|
String token = st.nextToken().intern(); |
||||||
|
for (int i=0; i<debuggingNames.length; i++) { |
||||||
|
if (token == debuggingNames[i]) { |
||||||
|
debuggingFlags |= 1 << i; |
||||||
|
continue next_token; |
||||||
|
} |
||||||
|
} |
||||||
|
err.println("Illegal debugging flag: "+token); |
||||||
|
return false; |
||||||
|
} |
||||||
|
return true; |
||||||
|
} |
||||||
|
} |
@ -0,0 +1,231 @@ |
|||||||
|
## Input file for automake to generate the Makefile.in used by configure
|
||||||
|
|
||||||
|
EXTRA_DIST = \
|
||||||
|
AssertError.java \
|
||||||
|
bytecode/BinaryInfo.java \
|
||||||
|
bytecode/BytecodeInfo.java \
|
||||||
|
bytecode/ClassFormatException.java \
|
||||||
|
bytecode/ClassInfo.java \
|
||||||
|
bytecode/ConstantPool.java \
|
||||||
|
bytecode/FieldInfo.java \
|
||||||
|
bytecode/GrowableConstantPool.java \
|
||||||
|
bytecode/Handler.java \
|
||||||
|
bytecode/InnerClassInfo.java \
|
||||||
|
bytecode/Instruction.java \
|
||||||
|
bytecode/LineNumber.java \
|
||||||
|
bytecode/LocalVariableInfo.java \
|
||||||
|
bytecode/MethodInfo.java \
|
||||||
|
bytecode/Opcodes.java \
|
||||||
|
bytecode/Reference.java \
|
||||||
|
bytecode/SearchPath.java \
|
||||||
|
decompiler/Analyzer.java \
|
||||||
|
decompiler/ClassAnalyzer.java \
|
||||||
|
decompiler/ClassDeclarer.java \
|
||||||
|
decompiler/DeadCodeAnalysis.java \
|
||||||
|
decompiler/Declarable.java \
|
||||||
|
decompiler/FieldAnalyzer.java \
|
||||||
|
decompiler/ImportHandler.java \
|
||||||
|
decompiler/LocalInfo.java \
|
||||||
|
decompiler/LocalVarEntry.java \
|
||||||
|
decompiler/LocalVariableRangeList.java \
|
||||||
|
decompiler/LocalVariableTable.java \
|
||||||
|
decompiler/MethodAnalyzer.java \
|
||||||
|
decompiler/Opcodes.java \
|
||||||
|
decompiler/OuterValueListener.java \
|
||||||
|
decompiler/Scope.java \
|
||||||
|
decompiler/TabbedPrintWriter.java \
|
||||||
|
Decompiler.java \
|
||||||
|
expr/ArrayLengthOperator.java \
|
||||||
|
expr/ArrayLoadOperator.java \
|
||||||
|
expr/ArrayStoreOperator.java \
|
||||||
|
expr/BinaryOperator.java \
|
||||||
|
expr/CheckCastOperator.java \
|
||||||
|
expr/CheckNullOperator.java \
|
||||||
|
expr/ClassFieldOperator.java \
|
||||||
|
expr/CombineableOperator.java \
|
||||||
|
expr/CompareBinaryOperator.java \
|
||||||
|
expr/CompareToIntOperator.java \
|
||||||
|
expr/CompareUnaryOperator.java \
|
||||||
|
expr/ConstOperator.java \
|
||||||
|
expr/ConstantArrayOperator.java \
|
||||||
|
expr/ConstructorOperator.java \
|
||||||
|
expr/ConvertOperator.java \
|
||||||
|
expr/Expression.java \
|
||||||
|
expr/GetFieldOperator.java \
|
||||||
|
expr/IIncOperator.java \
|
||||||
|
expr/IfThenElseOperator.java \
|
||||||
|
expr/InstanceOfOperator.java \
|
||||||
|
expr/InvokeOperator.java \
|
||||||
|
expr/LValueExpression.java \
|
||||||
|
expr/LocalLoadOperator.java \
|
||||||
|
expr/LocalStoreOperator.java \
|
||||||
|
expr/LocalVarOperator.java \
|
||||||
|
expr/MatchableOperator.java \
|
||||||
|
expr/MonitorEnterOperator.java \
|
||||||
|
expr/MonitorExitOperator.java \
|
||||||
|
expr/NewArrayOperator.java \
|
||||||
|
expr/NewOperator.java \
|
||||||
|
expr/NoArgOperator.java \
|
||||||
|
expr/NopOperator.java \
|
||||||
|
expr/Operator.java \
|
||||||
|
expr/OuterLocalOperator.java \
|
||||||
|
expr/PopOperator.java \
|
||||||
|
expr/PrePostFixOperator.java \
|
||||||
|
expr/PutFieldOperator.java \
|
||||||
|
expr/ShiftOperator.java \
|
||||||
|
expr/SimpleOperator.java \
|
||||||
|
expr/StoreInstruction.java \
|
||||||
|
expr/StringAddOperator.java \
|
||||||
|
expr/ThisOperator.java \
|
||||||
|
expr/UnaryOperator.java \
|
||||||
|
flow/BreakBlock.java \
|
||||||
|
flow/BreakableBlock.java \
|
||||||
|
flow/CaseBlock.java \
|
||||||
|
flow/CatchBlock.java \
|
||||||
|
flow/CombineIfGotoExpressions.java \
|
||||||
|
flow/CompleteSynchronized.java \
|
||||||
|
flow/ConditionalBlock.java \
|
||||||
|
flow/ContinueBlock.java \
|
||||||
|
flow/CreateAssignExpression.java \
|
||||||
|
flow/CreateCheckNull.java \
|
||||||
|
flow/CreateClassField.java \
|
||||||
|
flow/CreateConstantArray.java \
|
||||||
|
flow/CreateExpression.java \
|
||||||
|
flow/CreateForInitializer.java \
|
||||||
|
flow/CreateIfThenElseOperator.java \
|
||||||
|
flow/CreateNewConstructor.java \
|
||||||
|
flow/CreatePrePostIncExpression.java \
|
||||||
|
flow/DescriptionBlock.java \
|
||||||
|
flow/EmptyBlock.java \
|
||||||
|
flow/FinallyBlock.java \
|
||||||
|
flow/FlowBlock.java \
|
||||||
|
flow/IfThenElseBlock.java \
|
||||||
|
flow/InstructionBlock.java \
|
||||||
|
flow/InstructionContainer.java \
|
||||||
|
flow/JsrBlock.java \
|
||||||
|
flow/Jump.java \
|
||||||
|
flow/LoopBlock.java \
|
||||||
|
flow/RetBlock.java \
|
||||||
|
flow/ReturnBlock.java \
|
||||||
|
flow/SequentialBlock.java \
|
||||||
|
flow/SlotSet.java \
|
||||||
|
flow/SpecialBlock.java \
|
||||||
|
flow/StructuredBlock.java \
|
||||||
|
flow/SwitchBlock.java \
|
||||||
|
flow/SynchronizedBlock.java \
|
||||||
|
flow/ThrowBlock.java \
|
||||||
|
flow/TransformConstructors.java \
|
||||||
|
flow/TransformExceptionHandlers.java \
|
||||||
|
flow/TryBlock.java \
|
||||||
|
flow/VariableSet.java \
|
||||||
|
flow/VariableStack.java \
|
||||||
|
GlobalOptions.java.in \
|
||||||
|
JodeApplet.java \
|
||||||
|
JodeWindow.java \
|
||||||
|
jvm/CodeVerifier.java \
|
||||||
|
jvm/Interpreter.java \
|
||||||
|
jvm/InterpreterException.java \
|
||||||
|
jvm/NewObject.java \
|
||||||
|
jvm/RuntimeEnvironment.java \
|
||||||
|
jvm/SimpleRuntimeEnvironment.java \
|
||||||
|
jvm/SyntheticAnalyzer.java \
|
||||||
|
jvm/Value.java \
|
||||||
|
jvm/VerifyException.java \
|
||||||
|
obfuscator/ClassBundle.java \
|
||||||
|
obfuscator/ClassIdentifier.java \
|
||||||
|
obfuscator/CodeAnalyzer.java \
|
||||||
|
obfuscator/CodeTransformer.java \
|
||||||
|
obfuscator/ConstantAnalyzer.java \
|
||||||
|
obfuscator/ConstantRuntimeEnvironment.java \
|
||||||
|
obfuscator/FieldIdentifier.java \
|
||||||
|
obfuscator/Identifier.java \
|
||||||
|
obfuscator/IdentifierMatcher.java \
|
||||||
|
obfuscator/LocalIdentifier.java \
|
||||||
|
obfuscator/LocalOptimizer.java \
|
||||||
|
obfuscator/LocalizeFieldTransformer.java \
|
||||||
|
obfuscator/Main.java \
|
||||||
|
obfuscator/MethodIdentifier.java \
|
||||||
|
obfuscator/ModifierMatcher.java \
|
||||||
|
obfuscator/NameSwapper.java \
|
||||||
|
obfuscator/PackageIdentifier.java \
|
||||||
|
obfuscator/RemovePopAnalyzer.java \
|
||||||
|
obfuscator/Renamer.java \
|
||||||
|
obfuscator/SimpleAnalyzer.java \
|
||||||
|
obfuscator/StrongRenamer.java \
|
||||||
|
obfuscator/TranslationTable.java \
|
||||||
|
obfuscator/WildCard.java \
|
||||||
|
swingui/Main.java \
|
||||||
|
swingui/Main.java.in \
|
||||||
|
swingui/PackagesTreeModel.java.in \
|
||||||
|
swingui/PackagesTreeModel.java \
|
||||||
|
type/ArrayType.java \
|
||||||
|
type/ClassInterfacesType.java \
|
||||||
|
type/IntegerType.java \
|
||||||
|
type/MethodType.java \
|
||||||
|
type/NullType.java \
|
||||||
|
type/RangeType.java \
|
||||||
|
type/ReferenceType.java \
|
||||||
|
type/Type.java \
|
||||||
|
util/AbstractCollection.java \
|
||||||
|
util/AbstractList.java \
|
||||||
|
util/AbstractMap.java \
|
||||||
|
util/AbstractSequentialList.java \
|
||||||
|
util/AbstractSet.java \
|
||||||
|
util/ArrayEnum.java \
|
||||||
|
util/ArrayList.java \
|
||||||
|
util/Arrays.java \
|
||||||
|
util/BasicMapEntry.java \
|
||||||
|
util/Bucket.java \
|
||||||
|
util/Collection.java \
|
||||||
|
util/Collections.java \
|
||||||
|
util/Comparable.java \
|
||||||
|
util/Comparator.java \
|
||||||
|
util/ConcurrentModificationException.java \
|
||||||
|
util/HashMap.java \
|
||||||
|
util/HashSet.java \
|
||||||
|
util/Iterator.java \
|
||||||
|
util/LinkedList.java \
|
||||||
|
util/List.java \
|
||||||
|
util/ListIterator.java \
|
||||||
|
util/Map.java \
|
||||||
|
util/Set.java \
|
||||||
|
util/SimpleMap.java \
|
||||||
|
util/SimpleSet.java \
|
||||||
|
util/SortedMap.java \
|
||||||
|
util/SortedSet.java \
|
||||||
|
util/TreeMap.java \
|
||||||
|
util/TreeSet.java \
|
||||||
|
util/UnsupportedOperationException.java
|
||||||
|
|
||||||
|
JAR = @JAR@
|
||||||
|
JAVAC = @JAVAC@
|
||||||
|
JIKES = @JIKES@
|
||||||
|
CLASSPATH = @CLASSPATH@
|
||||||
|
CLASSLIB = @CLASSLIB@
|
||||||
|
BUILD_CLASSPATH = $(top_srcdir):$(top_builddir):.:$(CLASSPATH)
|
||||||
|
VPATH=$(srcdir):$(top_srcdir):$(top_builddir)
|
||||||
|
|
||||||
|
MY_CLASSES = jode/Decompiler.class jode/JodeApplet.class jode/JodeWindow.class jode/obfuscator/Main.class @SWING_CLASSES@
|
||||||
|
|
||||||
|
pkgdata_DATA = jode.jar
|
||||||
|
|
||||||
|
if HAVE_JIKES |
||||||
|
|
||||||
|
@QUOTE@-include .java.deps |
||||||
|
|
||||||
|
%.class: %.java |
||||||
|
$(JIKES) -classpath $(BUILD_CLASSPATH):$(CLASSLIB) +M=.java.deps -d . $<
|
||||||
|
|
||||||
|
else |
||||||
|
|
||||||
|
%.class: %.java |
||||||
|
$(JAVAC) -classpath $(BUILD_CLASSPATH):$(CLASSLIB) -depend -d . $<
|
||||||
|
|
||||||
|
endif |
||||||
|
|
||||||
|
clean-local: |
||||||
|
@rm -rf jode
|
||||||
|
@rm -f jode.jar .java.deps
|
||||||
|
|
||||||
|
jode.jar: $(MY_CLASSES) |
||||||
|
CLASSPATH= $(JAR) -cf jode.jar jode
|
@ -0,0 +1,278 @@ |
|||||||
|
/* Main Copyright (C) 1999 Jochen Hoenicke. |
||||||
|
* |
||||||
|
* This program is free software; you can redistribute it and/or modify |
||||||
|
* it under the terms of the GNU General Public License as published by |
||||||
|
* the Free Software Foundation; either version 2, or (at your option) |
||||||
|
* any later version. |
||||||
|
* |
||||||
|
* 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 General Public License for more details. |
||||||
|
* |
||||||
|
* You should have received a copy of the GNU General Public License |
||||||
|
* along with this program; see the file COPYING. If not, write to |
||||||
|
* the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. |
||||||
|
* |
||||||
|
* $Id$ |
||||||
|
*/ |
||||||
|
|
||||||
|
package jode.swingui; |
||||||
|
import jode.GlobalOptions; |
||||||
|
import jode.decompiler.*; |
||||||
|
import jode.bytecode.ClassInfo; |
||||||
|
import jode.bytecode.SearchPath; |
||||||
|
|
||||||
|
import @JAVAX_SWING@.*; |
||||||
|
import @JAVAX_SWING@.event.*; |
||||||
|
import @JAVAX_SWING@.tree.*; |
||||||
|
|
||||||
|
import java.awt.*; |
||||||
|
import java.awt.event.*; |
||||||
|
import java.io.*; |
||||||
|
|
||||||
|
public class Main |
||||||
|
implements ActionListener, Runnable, TreeSelectionListener { |
||||||
|
JFrame frame; |
||||||
|
JTree classTree; |
||||||
|
PackagesTreeModel classModel; |
||||||
|
JTextArea sourcecodeArea, errorArea; |
||||||
|
Thread decompileThread; |
||||||
|
String currentClassPath, lastClassName; |
||||||
|
|
||||||
|
public Main(String classpath) { |
||||||
|
setClasspath(classpath); |
||||||
|
frame = new JFrame(GlobalOptions.copyright); |
||||||
|
fillContentPane(frame.getContentPane()); |
||||||
|
addMenu(frame); |
||||||
|
frame.setDefaultCloseOperation(WindowConstants.DISPOSE_ON_CLOSE); |
||||||
|
frame.addWindowListener(new WindowAdapter() { |
||||||
|
public void windowClosing(WindowEvent e) { |
||||||
|
System.exit(0); |
||||||
|
} |
||||||
|
}); |
||||||
|
} |
||||||
|
|
||||||
|
public void show() { |
||||||
|
frame.pack(); |
||||||
|
frame.show(); |
||||||
|
} |
||||||
|
|
||||||
|
public void fillContentPane(Container contentPane) { |
||||||
|
Font monospaced = new Font("monospaced", Font.PLAIN, 12); |
||||||
|
classModel = new PackagesTreeModel(); |
||||||
|
classTree = new JTree(classModel); |
||||||
|
classTree.setRootVisible(false); |
||||||
|
DefaultTreeSelectionModel selModel = new DefaultTreeSelectionModel(); |
||||||
|
selModel.setSelectionMode(selModel.SINGLE_TREE_SELECTION); |
||||||
|
classTree.setSelectionModel(selModel); |
||||||
|
classTree.addTreeSelectionListener(this); |
||||||
|
JScrollPane spClassTree = new JScrollPane(classTree); |
||||||
|
sourcecodeArea = new JTextArea(20, 80); |
||||||
|
sourcecodeArea.setFont(monospaced); |
||||||
|
JScrollPane spText = new JScrollPane(sourcecodeArea); |
||||||
|
errorArea = new JTextArea(3, 80); |
||||||
|
errorArea.setFont(monospaced); |
||||||
|
JScrollPane spError = new JScrollPane(errorArea); |
||||||
|
|
||||||
|
JSplitPane rightPane = new JSplitPane(JSplitPane.VERTICAL_SPLIT, |
||||||
|
spText, spError); |
||||||
|
JSplitPane allPane = new JSplitPane(JSplitPane.HORIZONTAL_SPLIT, |
||||||
|
spClassTree, rightPane); |
||||||
|
contentPane.add(allPane); |
||||||
|
rightPane.setDividerLocation(300); |
||||||
|
rightPane.setDividerSize(4); |
||||||
|
allPane.setDividerLocation(200); |
||||||
|
allPane.setDividerSize(4); |
||||||
|
GlobalOptions.err = new PrintWriter(new AreaWriter(errorArea), true); |
||||||
|
} |
||||||
|
|
||||||
|
public synchronized void valueChanged(TreeSelectionEvent e) { |
||||||
|
if (decompileThread != null) |
||||||
|
return; |
||||||
|
TreePath path = e.getNewLeadSelectionPath(); |
||||||
|
if (path == null) |
||||||
|
return; |
||||||
|
Object node = path.getLastPathComponent(); |
||||||
|
if (node != null && classModel.isLeaf(node)) { |
||||||
|
lastClassName = classModel.getFullName(node); |
||||||
|
decompileThread = new Thread(this); |
||||||
|
decompileThread.setPriority(Thread.MIN_PRIORITY); |
||||||
|
sourcecodeArea.setText("Please wait, while decompiling...\n"); |
||||||
|
decompileThread.start(); |
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
public synchronized void actionPerformed(ActionEvent e) { |
||||||
|
if (e.getSource() == classTree && decompileThread == null) { |
||||||
|
// startButton.setEnabled(false);
|
||||||
|
decompileThread = new Thread(this); |
||||||
|
sourcecodeArea.setText("Please wait, while decompiling...\n"); |
||||||
|
decompileThread.start(); |
||||||
|
// } else if (e.getSource() == saveButton) {
|
||||||
|
// if (frame == null)
|
||||||
|
// frame = new Frame(); //XXX
|
||||||
|
// FileDialog fd = new FileDialog(frame,
|
||||||
|
// "Save decompiled code",
|
||||||
|
// FileDialog.SAVE);
|
||||||
|
// fd.setFile(lastClassName.substring
|
||||||
|
// (lastClassName.lastIndexOf('.')+1).concat(".java"));
|
||||||
|
// fd.show();
|
||||||
|
// String fileName = fd.getFile();
|
||||||
|
// if (fileName == null)
|
||||||
|
// return;
|
||||||
|
// try {
|
||||||
|
// File f = new File(new File(fd.getDirectory()), fileName);
|
||||||
|
// FileWriter out = new FileWriter(f);
|
||||||
|
// out.write(sourcecodeArea.getText());
|
||||||
|
// out.close();
|
||||||
|
// } catch (IOException ex) {
|
||||||
|
// errorArea.setText("");
|
||||||
|
// GlobalOptions.err.println("Couldn't write to file "
|
||||||
|
// + fileName + ": ");
|
||||||
|
// ex.printStackTrace(GlobalOptions.err);
|
||||||
|
// }
|
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
public class AreaWriter extends Writer { |
||||||
|
boolean initialized = false; |
||||||
|
private JTextArea area; |
||||||
|
|
||||||
|
public AreaWriter(JTextArea a) { |
||||||
|
area = a; |
||||||
|
} |
||||||
|
|
||||||
|
public void write(char[] b, int off, int len) throws IOException { |
||||||
|
if (!initialized) { |
||||||
|
area.setText(""); |
||||||
|
initialized = true; |
||||||
|
} |
||||||
|
///#ifdef AWT10
|
||||||
|
/// area.appendText(new String(b, off, len));
|
||||||
|
///#else
|
||||||
|
area.append(new String(b, off, len)); |
||||||
|
///#endif
|
||||||
|
} |
||||||
|
|
||||||
|
public void flush() { |
||||||
|
} |
||||||
|
|
||||||
|
public void close() { |
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
public void run() { |
||||||
|
// Decompiler.isVerbose = verboseCheck.getState();
|
||||||
|
// if (prettyCheck.getState())
|
||||||
|
// Decompiler.options |= Decompiler.OPTION_PRETTY;
|
||||||
|
// else
|
||||||
|
// Decompiler.options &= ~Decompiler.OPTION_PRETTY;
|
||||||
|
errorArea.setText(""); |
||||||
|
// saveButton.setEnabled(false);
|
||||||
|
|
||||||
|
ImportHandler imports = new ImportHandler(); |
||||||
|
try { |
||||||
|
ClassInfo clazz = ClassInfo.forName(lastClassName); |
||||||
|
|
||||||
|
imports.init(lastClassName); |
||||||
|
ClassAnalyzer clazzAna = new ClassAnalyzer(null, clazz, imports); |
||||||
|
clazzAna.analyze(); |
||||||
|
clazzAna.analyzeInnerClasses(); |
||||||
|
clazzAna.makeDeclaration(); |
||||||
|
|
||||||
|
sourcecodeArea.setText(""); |
||||||
|
TabbedPrintWriter writer = |
||||||
|
new TabbedPrintWriter |
||||||
|
(new BufferedWriter |
||||||
|
(new AreaWriter(sourcecodeArea), 1024), imports, false); |
||||||
|
|
||||||
|
imports.dumpHeader(writer); |
||||||
|
clazzAna.dumpSource(writer); |
||||||
|
writer.close(); |
||||||
|
|
||||||
|
// saveButton.setEnabled(true);
|
||||||
|
} catch (Throwable t) { |
||||||
|
sourcecodeArea.setText("Didn't succeed.\n" |
||||||
|
+"Check the below area for more info."); |
||||||
|
t.printStackTrace(GlobalOptions.err); |
||||||
|
} finally { |
||||||
|
synchronized(this) { |
||||||
|
decompileThread = null; |
||||||
|
// startButton.setEnabled(true);
|
||||||
|
} |
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
public void addMenu(JFrame frame) { |
||||||
|
JMenuBar bar = new JMenuBar(); |
||||||
|
JMenu menu; |
||||||
|
JMenuItem item; |
||||||
|
menu = new JMenu("File"); |
||||||
|
item = new JMenuItem("Garbage collect"); |
||||||
|
item.addActionListener(new ActionListener() { |
||||||
|
public void actionPerformed(ActionEvent ev) { |
||||||
|
System.gc(); |
||||||
|
System.runFinalization(); |
||||||
|
} |
||||||
|
}); |
||||||
|
menu.add(item); |
||||||
|
item = new JMenuItem("Exit"); |
||||||
|
item.addActionListener(new ActionListener() { |
||||||
|
public void actionPerformed(ActionEvent ev) { |
||||||
|
System.exit(0); |
||||||
|
} |
||||||
|
}); |
||||||
|
menu.add(item); |
||||||
|
bar.add(menu); |
||||||
|
menu = new JMenu("Options"); |
||||||
|
item = new JMenuItem("Set classpath..."); |
||||||
|
item.addActionListener(new ActionListener() { |
||||||
|
public void actionPerformed(ActionEvent ev) { |
||||||
|
|
||||||
|
String newClassPath = (String) JOptionPane.showInputDialog |
||||||
|
(null, "New classpath:", null, |
||||||
|
JOptionPane.QUESTION_MESSAGE, null, |
||||||
|
null, currentClassPath); |
||||||
|
if (newClassPath != null |
||||||
|
&& !newClassPath.equals(currentClassPath)) |
||||||
|
setClasspath(newClassPath); |
||||||
|
} |
||||||
|
}); |
||||||
|
menu.add(item); |
||||||
|
item = new JMenuItem("Reload classpath"); |
||||||
|
item.addActionListener(new ActionListener() { |
||||||
|
public void actionPerformed(ActionEvent ev) { |
||||||
|
setClasspath(currentClassPath); |
||||||
|
} |
||||||
|
}); |
||||||
|
menu.add(item); |
||||||
|
bar.add(menu); |
||||||
|
frame.setJMenuBar(bar); |
||||||
|
} |
||||||
|
|
||||||
|
public void setClasspath(String classpath) { |
||||||
|
if (classpath == null || classpath.length() == 0) |
||||||
|
classpath = "."; |
||||||
|
currentClassPath = classpath; |
||||||
|
ClassInfo.setClassPath(classpath); |
||||||
|
if (classModel != null) { |
||||||
|
classTree.clearSelection(); |
||||||
|
classModel.rebuild(); |
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
public static void main(String[] params) { |
||||||
|
String cp = System.getProperty("java.class.path", ""); |
||||||
|
cp = cp.replace(File.pathSeparatorChar, SearchPath.pathSeparatorChar); |
||||||
|
for (int i=0; i<params.length; i++) { |
||||||
|
if (params[i].equals("--cp")) |
||||||
|
cp = params[++i]; |
||||||
|
else |
||||||
|
return; |
||||||
|
} |
||||||
|
GlobalOptions.verboseLevel = 1; |
||||||
|
Main win = new Main(cp); |
||||||
|
win.show(); |
||||||
|
} |
||||||
|
} |
@ -0,0 +1,176 @@ |
|||||||
|
/* PackagesTreeModel Copyright (C) 1999 Jochen Hoenicke. |
||||||
|
* |
||||||
|
* This program is free software; you can redistribute it and/or modify |
||||||
|
* it under the terms of the GNU General Public License as published by |
||||||
|
* the Free Software Foundation; either version 2, or (at your option) |
||||||
|
* any later version. |
||||||
|
* |
||||||
|
* 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 General Public License for more details. |
||||||
|
* |
||||||
|
* You should have received a copy of the GNU General Public License |
||||||
|
* along with this program; see the file COPYING. If not, write to |
||||||
|
* the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. |
||||||
|
* |
||||||
|
* $Id$ |
||||||
|
*/ |
||||||
|
|
||||||
|
package jode.swingui; |
||||||
|
import jode.Decompiler; |
||||||
|
import jode.bytecode.ClassInfo; |
||||||
|
|
||||||
|
import @JAVAX_SWING@.tree.TreeModel; |
||||||
|
import @JAVAX_SWING@.tree.TreePath; |
||||||
|
import @JAVAX_SWING@.event.TreeModelListener; |
||||||
|
import @JAVAX_SWING@.event.TreeModelEvent; |
||||||
|
|
||||||
|
///#ifndef JDK12
|
||||||
|
///import java.util.Arrays;
|
||||||
|
///import java.util.TreeSet;
|
||||||
|
///import java.util.HashSet;
|
||||||
|
///import java.util.Set;
|
||||||
|
///import java.util.HashMap;
|
||||||
|
///import java.util.Map;
|
||||||
|
///#else
|
||||||
|
import jode.util.Comparable; |
||||||
|
import jode.util.Arrays; |
||||||
|
import jode.util.TreeSet; |
||||||
|
import jode.util.HashSet; |
||||||
|
import jode.util.Set; |
||||||
|
import jode.util.HashMap; |
||||||
|
import jode.util.Map; |
||||||
|
///#endif
|
||||||
|
|
||||||
|
|
||||||
|
import java.util.Enumeration; |
||||||
|
import java.util.NoSuchElementException; |
||||||
|
|
||||||
|
public class PackagesTreeModel implements TreeModel { |
||||||
|
Map cachedChildrens = new HashMap(); |
||||||
|
|
||||||
|
class TreeElement implements Comparable { |
||||||
|
String fullName; |
||||||
|
String name; |
||||||
|
boolean leaf; |
||||||
|
|
||||||
|
public TreeElement(String prefix, String name, boolean isLeaf) { |
||||||
|
this.fullName = prefix+name; |
||||||
|
this.name = name; |
||||||
|
this.leaf = isLeaf; |
||||||
|
} |
||||||
|
|
||||||
|
public String getFullName() { |
||||||
|
return fullName; |
||||||
|
} |
||||||
|
|
||||||
|
public String getName() { |
||||||
|
return name; |
||||||
|
} |
||||||
|
|
||||||
|
public boolean isLeaf() { |
||||||
|
return leaf; |
||||||
|
} |
||||||
|
|
||||||
|
public String toString() { |
||||||
|
return name; |
||||||
|
} |
||||||
|
|
||||||
|
public int compareTo(Object o) { |
||||||
|
TreeElement other = (TreeElement) o; |
||||||
|
if (leaf != other.leaf) |
||||||
|
// files come after directories
|
||||||
|
return leaf ? 1 : -1; |
||||||
|
return fullName.compareTo(other.fullName); |
||||||
|
} |
||||||
|
|
||||||
|
public boolean equals(Object o) { |
||||||
|
return (o instanceof TreeElement) |
||||||
|
&& fullName.equals(((TreeElement)o).fullName); |
||||||
|
} |
||||||
|
|
||||||
|
public int hashCode() { |
||||||
|
return fullName.hashCode(); |
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
TreeElement root = new TreeElement("", "", false); |
||||||
|
Set listeners = new HashSet(); |
||||||
|
|
||||||
|
public void rebuild() { |
||||||
|
cachedChildrens.clear(); |
||||||
|
TreeModelListener[] ls; |
||||||
|
synchronized (listeners) { |
||||||
|
ls = (TreeModelListener[]) |
||||||
|
listeners.toArray(new TreeModelListener[listeners.size()]); |
||||||
|
} |
||||||
|
TreeModelEvent ev = new TreeModelEvent(this, new Object[] { root }); |
||||||
|
for (int i=0; i< ls.length; i++) |
||||||
|
ls[i].treeStructureChanged(ev); |
||||||
|
} |
||||||
|
|
||||||
|
public TreeElement[] getChildrens(TreeElement parent) { |
||||||
|
TreeElement[] result = |
||||||
|
(TreeElement[]) cachedChildrens.get(parent); |
||||||
|
if (result == null) { |
||||||
|
TreeSet v = new TreeSet(); |
||||||
|
String prefix = parent == root ? "" : parent.getFullName() + "."; |
||||||
|
Enumeration enum = |
||||||
|
ClassInfo.getClassesAndPackages(parent.getFullName()); |
||||||
|
while (enum.hasMoreElements()) { |
||||||
|
//insert sorted and remove double elements;
|
||||||
|
String name = (String)enum.nextElement(); |
||||||
|
String fqn = prefix + name; |
||||||
|
boolean isClass = !ClassInfo.isPackage(fqn); |
||||||
|
|
||||||
|
if (isClass && Decompiler.skipClass(ClassInfo.forName(fqn))) |
||||||
|
continue; |
||||||
|
TreeElement newElem = new TreeElement(prefix, name, isClass); |
||||||
|
v.add(newElem); |
||||||
|
} |
||||||
|
result = (TreeElement[]) v.toArray(new TreeElement[v.size()]); |
||||||
|
cachedChildrens.put(parent, result); |
||||||
|
} |
||||||
|
return result; |
||||||
|
} |
||||||
|
|
||||||
|
public void addTreeModelListener(TreeModelListener l) { |
||||||
|
listeners.add(l); |
||||||
|
} |
||||||
|
public void removeTreeModelListener(TreeModelListener l) { |
||||||
|
listeners.remove(l); |
||||||
|
} |
||||||
|
public void valueForPathChanged(TreePath path, Object newValue) { |
||||||
|
// we don't allow values
|
||||||
|
} |
||||||
|
|
||||||
|
public Object getChild(Object parent, int index) { |
||||||
|
return getChildrens((TreeElement) parent)[index]; |
||||||
|
} |
||||||
|
|
||||||
|
public int getChildCount(Object parent) { |
||||||
|
return getChildrens((TreeElement) parent).length; |
||||||
|
} |
||||||
|
|
||||||
|
public int getIndexOfChild(Object parent, Object child) { |
||||||
|
TreeElement[] childrens = getChildrens((TreeElement) parent); |
||||||
|
int i = Arrays.binarySearch(childrens, child); |
||||||
|
if (i >= 0) |
||||||
|
return i; |
||||||
|
throw new NoSuchElementException |
||||||
|
(((TreeElement)parent).getFullName() + "." + child); |
||||||
|
} |
||||||
|
|
||||||
|
public Object getRoot() { |
||||||
|
return root; |
||||||
|
} |
||||||
|
|
||||||
|
public boolean isLeaf(Object node) { |
||||||
|
return ((TreeElement)node).isLeaf(); |
||||||
|
} |
||||||
|
|
||||||
|
public String getFullName(Object node) { |
||||||
|
return ((TreeElement) node).getFullName(); |
||||||
|
} |
||||||
|
} |
@ -0,0 +1,2 @@ |
|||||||
|
Makefile |
||||||
|
Makefile.in |
Loading…
Reference in new issue