diff options
Diffstat (limited to 'src/org/jetbrains/java/decompiler/struct')
34 files changed, 4203 insertions, 4141 deletions
diff --git a/src/org/jetbrains/java/decompiler/struct/ContextUnit.java b/src/org/jetbrains/java/decompiler/struct/ContextUnit.java index d859b29..c942e76 100644 --- a/src/org/jetbrains/java/decompiler/struct/ContextUnit.java +++ b/src/org/jetbrains/java/decompiler/struct/ContextUnit.java @@ -1,210 +1,210 @@ /* - * Fernflower - The Analytical Java Decompiler - * http://www.reversed-java.com + * Copyright 2000-2014 JetBrains s.r.o. * - * (C) 2008 - 2010, Stiver + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at * - * This software is NEITHER public domain NOR free software - * as per GNU License. See license.txt for more details. + * http://www.apache.org/licenses/LICENSE-2.0 * - * This software is distributed WITHOUT ANY WARRANTY; without - * even the implied warranty of MERCHANTABILITY or FITNESS FOR - * A PARTICULAR PURPOSE. + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. */ - package org.jetbrains.java.decompiler.struct; +import org.jetbrains.java.decompiler.main.extern.IDecompilatSaver; +import org.jetbrains.java.decompiler.struct.lazy.LazyLoader; +import org.jetbrains.java.decompiler.struct.lazy.LazyLoader.Link; + import java.io.IOException; import java.util.ArrayList; import java.util.List; import java.util.jar.Manifest; -import org.jetbrains.java.decompiler.main.extern.IDecompilatSaver; -import org.jetbrains.java.decompiler.struct.lazy.LazyLoader; -import org.jetbrains.java.decompiler.struct.lazy.LazyLoader.Link; - public class ContextUnit { - - public static final int TYPE_FOLDER = 0; - public static final int TYPE_JAR = 1; - public static final int TYPE_ZIP = 2; - - private static final String MANIFEST_ENTRY = "META-INF/MANIFEST.MF"; - - // ***************************************************************************** - // private fields - // ***************************************************************************** - - private int type; - - // relative path to jar/zip - private String archivepath; - - // folder: relative path - // archive: file name - private String filename; - - private List<StructClass> classes = new ArrayList<StructClass>(); - - // class file or jar/zip entry. Should, but doesn't have to be the same as qualifiedName of the class - private List<String> classentries = new ArrayList<String>(); - - private List<String> direntries = new ArrayList<String>(); - - private List<String[]> otherentries = new ArrayList<String[]>(); - - private Manifest manifest; - - private IDecompilatSaver decompilatSaver; - - private IDecompiledData decompiledData; - - private boolean own = true; - - // ***************************************************************************** - // constructors - // ***************************************************************************** - - public ContextUnit(int type, String archivepath, String filename, boolean own, - IDecompilatSaver decompilatSaver, IDecompiledData decompiledData) { - this.type = type; - this.own = own; - this.archivepath = archivepath; - this.filename = filename; - this.decompilatSaver = decompilatSaver; - this.decompiledData = decompiledData; - } - - // ***************************************************************************** - // public methods - // ***************************************************************************** - - public void addClass(StructClass cl, String entryname) { - classes.add(cl); - classentries.add(entryname); - } - - public void addDirEntry(String entry) { - direntries.add(entry); - } - - public void addOtherEntry(String fullpath, String entry) { - otherentries.add(new String[]{fullpath, entry}); - } - - public void reload(LazyLoader loader) throws IOException { - - List<StructClass> lstClasses = new ArrayList<StructClass>(); - for(StructClass cl : classes) { - String oldname = cl.qualifiedName; - StructClass newcl = new StructClass(loader.getClassStream(oldname), cl.isOwn(), loader); - - lstClasses.add(newcl); - - Link lnk = loader.getClassLink(oldname); - loader.removeClassLink(oldname); - loader.addClassLink(newcl.qualifiedName, lnk); - } - - classes = lstClasses; - } - - public void save() { - - switch(type) { - case TYPE_FOLDER: - - // create folder - decompilatSaver.saveFolder(filename); - - // non-class files - for(String[] arr: otherentries) { - decompilatSaver.copyFile(arr[0], filename, arr[0]); - } - - // classes - for(int i=0;i<classes.size();i++) { - - StructClass cl = classes.get(i); - String entryname = classentries.get(i); - - entryname = decompiledData.getClassEntryName(cl, entryname); - if(entryname != null) { - String content = decompiledData.getClassContent(cl); - if(content != null) { - decompilatSaver.saveClassFile(filename, cl.qualifiedName, entryname, content); - } - } - } - - break; - case TYPE_JAR: - case TYPE_ZIP: - - // create archive file - decompilatSaver.saveFolder(archivepath); - decompilatSaver.createArchive(archivepath, filename, manifest); - - // directory entries - for(String direntry: direntries) { - decompilatSaver.saveEntry(archivepath, filename, direntry, null); - } - - // non-class entries - for(String[] arr: otherentries) { - // manifest was defined by constructor invocation - if(type != TYPE_JAR || !MANIFEST_ENTRY.equalsIgnoreCase(arr[1])) { - decompilatSaver.copyEntry(arr[0], archivepath, filename, arr[1]); - } - } - - // classes - for(int i=0;i<classes.size();i++) { - - StructClass cl = classes.get(i); - String entryname = classentries.get(i); - - entryname = decompiledData.getClassEntryName(cl, entryname); - if(entryname != null) { - String content = decompiledData.getClassContent(cl); - decompilatSaver.saveClassEntry(archivepath, filename, cl.qualifiedName, entryname, content); - } - } - - decompilatSaver.closeArchive(archivepath, filename); - } - } - - // ***************************************************************************** - // private methods - // ***************************************************************************** - - // ***************************************************************************** - // getter and setter methods - // ***************************************************************************** - - public void setManifest(Manifest manifest) { - this.manifest = manifest; - } - - public boolean isOwn() { - return own; - } - - public List<StructClass> getClasses() { - return classes; - } - - public int getType() { - return type; - } - - public void setDecompilatSaver(IDecompilatSaver decompilatSaver) { - this.decompilatSaver = decompilatSaver; - } - - public void setDecompiledData(IDecompiledData decompiledData) { - this.decompiledData = decompiledData; - } + public static final int TYPE_FOLDER = 0; + public static final int TYPE_JAR = 1; + public static final int TYPE_ZIP = 2; + + private static final String MANIFEST_ENTRY = "META-INF/MANIFEST.MF"; + + // ***************************************************************************** + // private fields + // ***************************************************************************** + + private int type; + + // relative path to jar/zip + private String archivepath; + + // folder: relative path + // archive: file name + private String filename; + + private List<StructClass> classes = new ArrayList<StructClass>(); + + // class file or jar/zip entry. Should, but doesn't have to be the same as qualifiedName of the class + private List<String> classentries = new ArrayList<String>(); + + private List<String> direntries = new ArrayList<String>(); + + private List<String[]> otherentries = new ArrayList<String[]>(); + + private Manifest manifest; + + private IDecompilatSaver decompilatSaver; + + private IDecompiledData decompiledData; + + private boolean own = true; + + // ***************************************************************************** + // constructors + // ***************************************************************************** + + public ContextUnit(int type, String archivepath, String filename, boolean own, + IDecompilatSaver decompilatSaver, IDecompiledData decompiledData) { + this.type = type; + this.own = own; + this.archivepath = archivepath; + this.filename = filename; + this.decompilatSaver = decompilatSaver; + this.decompiledData = decompiledData; + } + + // ***************************************************************************** + // public methods + // ***************************************************************************** + + public void addClass(StructClass cl, String entryname) { + classes.add(cl); + classentries.add(entryname); + } + + public void addDirEntry(String entry) { + direntries.add(entry); + } + + public void addOtherEntry(String fullpath, String entry) { + otherentries.add(new String[]{fullpath, entry}); + } + + public void reload(LazyLoader loader) throws IOException { + + List<StructClass> lstClasses = new ArrayList<StructClass>(); + for (StructClass cl : classes) { + String oldname = cl.qualifiedName; + StructClass newcl = new StructClass(loader.getClassStream(oldname), cl.isOwn(), loader); + + lstClasses.add(newcl); + + Link lnk = loader.getClassLink(oldname); + loader.removeClassLink(oldname); + loader.addClassLink(newcl.qualifiedName, lnk); + } + + classes = lstClasses; + } + + public void save() { + + switch (type) { + case TYPE_FOLDER: + + // create folder + decompilatSaver.saveFolder(filename); + + // non-class files + for (String[] arr : otherentries) { + decompilatSaver.copyFile(arr[0], filename, arr[0]); + } + + // classes + for (int i = 0; i < classes.size(); i++) { + + StructClass cl = classes.get(i); + String entryname = classentries.get(i); + + entryname = decompiledData.getClassEntryName(cl, entryname); + if (entryname != null) { + String content = decompiledData.getClassContent(cl); + if (content != null) { + decompilatSaver.saveClassFile(filename, cl.qualifiedName, entryname, content); + } + } + } + + break; + case TYPE_JAR: + case TYPE_ZIP: + + // create archive file + decompilatSaver.saveFolder(archivepath); + decompilatSaver.createArchive(archivepath, filename, manifest); + + // directory entries + for (String direntry : direntries) { + decompilatSaver.saveEntry(archivepath, filename, direntry, null); + } + + // non-class entries + for (String[] arr : otherentries) { + // manifest was defined by constructor invocation + if (type != TYPE_JAR || !MANIFEST_ENTRY.equalsIgnoreCase(arr[1])) { + decompilatSaver.copyEntry(arr[0], archivepath, filename, arr[1]); + } + } + + // classes + for (int i = 0; i < classes.size(); i++) { + + StructClass cl = classes.get(i); + String entryname = classentries.get(i); + + entryname = decompiledData.getClassEntryName(cl, entryname); + if (entryname != null) { + String content = decompiledData.getClassContent(cl); + decompilatSaver.saveClassEntry(archivepath, filename, cl.qualifiedName, entryname, content); + } + } + + decompilatSaver.closeArchive(archivepath, filename); + } + } + + // ***************************************************************************** + // private methods + // ***************************************************************************** + + // ***************************************************************************** + // getter and setter methods + // ***************************************************************************** + + public void setManifest(Manifest manifest) { + this.manifest = manifest; + } + + public boolean isOwn() { + return own; + } + + public List<StructClass> getClasses() { + return classes; + } + + public int getType() { + return type; + } + + public void setDecompilatSaver(IDecompilatSaver decompilatSaver) { + this.decompilatSaver = decompilatSaver; + } + + public void setDecompiledData(IDecompiledData decompiledData) { + this.decompiledData = decompiledData; + } } diff --git a/src/org/jetbrains/java/decompiler/struct/IDecompiledData.java b/src/org/jetbrains/java/decompiler/struct/IDecompiledData.java index 9c8bc14..1976216 100644 --- a/src/org/jetbrains/java/decompiler/struct/IDecompiledData.java +++ b/src/org/jetbrains/java/decompiler/struct/IDecompiledData.java @@ -1,23 +1,23 @@ /* - * Fernflower - The Analytical Java Decompiler - * http://www.reversed-java.com + * Copyright 2000-2014 JetBrains s.r.o. * - * (C) 2008 - 2010, Stiver + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at * - * This software is NEITHER public domain NOR free software - * as per GNU License. See license.txt for more details. + * http://www.apache.org/licenses/LICENSE-2.0 * - * This software is distributed WITHOUT ANY WARRANTY; without - * even the implied warranty of MERCHANTABILITY or FITNESS FOR - * A PARTICULAR PURPOSE. + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. */ - package org.jetbrains.java.decompiler.struct; public interface IDecompiledData { - public String getClassEntryName(StructClass cl, String entryname); + public String getClassEntryName(StructClass cl, String entryname); - public String getClassContent(StructClass cl); - + public String getClassContent(StructClass cl); } diff --git a/src/org/jetbrains/java/decompiler/struct/ISaveClass.java b/src/org/jetbrains/java/decompiler/struct/ISaveClass.java index 6fbfb9c..69a90f9 100644 --- a/src/org/jetbrains/java/decompiler/struct/ISaveClass.java +++ b/src/org/jetbrains/java/decompiler/struct/ISaveClass.java @@ -1,17 +1,18 @@ /* - * Fernflower - The Analytical Java Decompiler - * http://www.reversed-java.com + * Copyright 2000-2014 JetBrains s.r.o. * - * (C) 2008 - 2010, Stiver + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at * - * This software is NEITHER public domain NOR free software - * as per GNU License. See license.txt for more details. + * http://www.apache.org/licenses/LICENSE-2.0 * - * This software is distributed WITHOUT ANY WARRANTY; without - * even the implied warranty of MERCHANTABILITY or FITNESS FOR - * A PARTICULAR PURPOSE. + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. */ - package org.jetbrains.java.decompiler.struct; import java.io.DataOutputStream; @@ -21,10 +22,9 @@ import java.io.IOException; public interface ISaveClass { - public String getClassEntryName(StructClass cl, String entryname); - - public void saveClassToFile(StructClass cl, File file) throws FileNotFoundException, IOException; + public String getClassEntryName(StructClass cl, String entryname); + + public void saveClassToFile(StructClass cl, File file) throws FileNotFoundException, IOException; - public void saveClassToStream(StructClass cl, DataOutputStream out); - + public void saveClassToStream(StructClass cl, DataOutputStream out); } diff --git a/src/org/jetbrains/java/decompiler/struct/StructClass.java b/src/org/jetbrains/java/decompiler/struct/StructClass.java index 456cc70..19946a0 100644 --- a/src/org/jetbrains/java/decompiler/struct/StructClass.java +++ b/src/org/jetbrains/java/decompiler/struct/StructClass.java @@ -1,27 +1,20 @@ /* - * Fernflower - The Analytical Java Decompiler - * http://www.reversed-java.com + * Copyright 2000-2014 JetBrains s.r.o. * - * (C) 2008 - 2010, Stiver + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at * - * This software is NEITHER public domain NOR free software - * as per GNU License. See license.txt for more details. + * http://www.apache.org/licenses/LICENSE-2.0 * - * This software is distributed WITHOUT ANY WARRANTY; without - * even the implied warranty of MERCHANTABILITY or FITNESS FOR - * A PARTICULAR PURPOSE. + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. */ - package org.jetbrains.java.decompiler.struct; -import java.io.DataOutputStream; -import java.io.File; -import java.io.FileInputStream; -import java.io.FileNotFoundException; -import java.io.FileOutputStream; -import java.io.IOException; -import java.io.InputStream; - import org.jetbrains.java.decompiler.code.CodeConstants; import org.jetbrains.java.decompiler.struct.attr.StructGeneralAttribute; import org.jetbrains.java.decompiler.struct.consts.ConstantPool; @@ -31,6 +24,8 @@ import org.jetbrains.java.decompiler.util.DataInputFullStream; import org.jetbrains.java.decompiler.util.InterpreterUtil; import org.jetbrains.java.decompiler.util.VBStyleCollection; +import java.io.*; + /* ClassFile { u4 magic; @@ -54,299 +49,298 @@ import org.jetbrains.java.decompiler.util.VBStyleCollection; public class StructClass { - // ***************************************************************************** - // public fields - // ***************************************************************************** - - public int minor_version; - - public int major_version; - - public int access_flags; - - public int this_class; - - public int super_class; - - public PrimitiveConstant thisClass; - - public PrimitiveConstant superClass; - - public String qualifiedName; - - - // ***************************************************************************** - // private fields - // ***************************************************************************** - - private ConstantPool pool; - - private int[] interfaces; - - private String[] interfaceNames; - - private VBStyleCollection<StructField, String> fields = new VBStyleCollection<StructField, String>(); - - private VBStyleCollection<StructMethod, String> methods = new VBStyleCollection<StructMethod, String>(); - - private VBStyleCollection<StructGeneralAttribute, String> attributes = new VBStyleCollection<StructGeneralAttribute, String>(); - - private boolean own = true; - - private LazyLoader loader; - - // ***************************************************************************** - // constructors - // ***************************************************************************** - - public StructClass(String filename, boolean own, LazyLoader loader) throws FileNotFoundException, IOException { - this(new FileInputStream(filename), own, loader); - } - - public StructClass(InputStream inStream, boolean own, LazyLoader loader) throws FileNotFoundException, IOException { - this(new DataInputFullStream(inStream), own, loader); - } - - public StructClass(DataInputFullStream inStream, boolean own, LazyLoader loader) throws FileNotFoundException, IOException { - this.own = own; - this.loader = loader; - - initStruct(inStream); - } - - // ***************************************************************************** - // public methods - // ***************************************************************************** - - public boolean hasField(String name, String descriptor) { - return getField(name, descriptor) != null; - } - - public StructField getField(String name, String descriptor) { - return fields.getWithKey(InterpreterUtil.makeUniqueKey(name, descriptor)); - } - - public StructMethod getMethod(String key) { - return methods.getWithKey(key); - } - - public StructMethod getMethod(String name, String descriptor) { - return methods.getWithKey(InterpreterUtil.makeUniqueKey(name, descriptor)); - } - - public void writeToFile(File file) throws IOException { - DataOutputStream out = new DataOutputStream(new FileOutputStream(file)); - writeToOutputStream(out); - out.close(); - } - - public void writeToOutputStream(DataOutputStream out) throws IOException { - - out.writeInt(0xCAFEBABE); - out.writeShort(minor_version); - out.writeShort(major_version); - - getPool().writeToOutputStream(out); - - out.writeShort(access_flags); - out.writeShort(this_class); - out.writeShort(super_class); - - out.writeShort(interfaces.length); - for(int i=0;i<interfaces.length;i++) { - out.writeShort(interfaces[i]); - } - - out.writeShort(fields.size()); - for(int i=0;i<fields.size();i++) { - fields.get(i).writeToStream(out); - } - - out.writeShort(methods.size()); - for(int i=0;i<methods.size();i++) { - methods.get(i).writeToStream(out); - } - - out.writeShort(attributes.size()); - for(StructGeneralAttribute attr: attributes) { - attr.writeToStream(out); - } - - } - - public String getInterface(int i) { - return interfaceNames[i]; - } - - public void releaseResources() { - if(loader != null) { - pool = null; - } - } - - // ***************************************************************************** - // private methods - // ***************************************************************************** - - private void initStruct(DataInputFullStream in) throws IOException { - - in.skip(4); - - this.minor_version = in.readUnsignedShort(); - this.major_version = in.readUnsignedShort(); - - pool = new ConstantPool(in); - - this.access_flags = in.readUnsignedShort(); - - this_class = in.readUnsignedShort(); - thisClass = pool.getPrimitiveConstant(this_class); - qualifiedName = thisClass.getString(); - - super_class = in.readUnsignedShort(); - superClass = pool.getPrimitiveConstant(super_class); - - // interfaces - int length = in.readUnsignedShort(); - int[] arrInterfaces = new int[length]; - String[] arrInterfaceNames = new String[length]; - - for (int i = 0; i < length; i++) { - arrInterfaces[i] = in.readUnsignedShort(); - arrInterfaceNames[i] = pool.getPrimitiveConstant(arrInterfaces[i]).getString(); - } - this.interfaces = arrInterfaces; - this.interfaceNames = arrInterfaceNames; - - // fields - VBStyleCollection<StructField, String> lstFields = new VBStyleCollection<StructField, String>(); - length = in.readUnsignedShort(); - for (int i = 0; i < length; i++) { - StructField field = new StructField(); - field.access_flags = in.readUnsignedShort(); - field.name_index = in.readUnsignedShort(); - field.descriptor_index = in.readUnsignedShort(); - - field.initStrings(pool, this_class); - - field.setAttributes(readAttributes(in)); - - lstFields.addWithKey(field, InterpreterUtil.makeUniqueKey(field.getName(), field.getDescriptor())); - } - this.fields = lstFields; - - // methods - length = in.readUnsignedShort(); - for (int i = 0; i < length; i++) { - StructMethod meth = new StructMethod(in, own, this); - - //if(qualifiedName.endsWith("JUnitStatusLine") && !meth.getName().equals("onProcessStarted") && !meth.getName().startsWith("access")) { - //if(!meth.getName().equals("run")) { - // continue; - //} - - methods.addWithKey(meth, InterpreterUtil.makeUniqueKey(meth.getName(), meth.getDescriptor())); - } - - // attributes - this.attributes = readAttributes(in); - - - // release memory - if(loader != null) { - pool = null; - } - } - - private VBStyleCollection<StructGeneralAttribute, String> readAttributes(DataInputFullStream in) throws IOException { - - VBStyleCollection<StructGeneralAttribute, String> lstAttribute = new VBStyleCollection<StructGeneralAttribute, String>(); - - int length = in.readUnsignedShort(); - for (int i = 0; i < length; i++) { - int attr_nameindex = in.readUnsignedShort(); - String attrname = pool.getPrimitiveConstant(attr_nameindex).getString(); - - StructGeneralAttribute attr = StructGeneralAttribute.getMatchingAttributeInstance(attr_nameindex, attrname); - - if(attr != null) { - byte[] arr = new byte[in.readInt()]; - in.readFull(arr); - attr.setInfo(arr); - - attr.initContent(pool); - lstAttribute.addWithKey(attr, attr.getName()); - } else { - in.skip(in.readInt()); - } - } - - return lstAttribute; - } - - - - // ***************************************************************************** - // getter and setter methods - // ***************************************************************************** - - public ConstantPool getPool() { - - if(pool == null && loader != null) { - pool = loader.loadPool(qualifiedName); - } - - return pool; - } - - public int[] getInterfaces() { - return interfaces; - } - - public String[] getInterfaceNames() { - return interfaceNames; - } - - public VBStyleCollection<StructMethod, String> getMethods() { - return methods; - } - - public VBStyleCollection<StructField, String> getFields() { - return fields; - } - - public VBStyleCollection<StructGeneralAttribute, String> getAttributes() { - return attributes; - } - - public boolean isOwn() { - return own; - } - - public LazyLoader getLoader() { - return loader; - } - - public boolean isVersionGE_1_5() { - return (major_version > 48 || (major_version == 48 && minor_version > 0)); // FIXME: check second condition - } - - public boolean isVersionGE_1_7() { - return (major_version >= 51); - } - - public int getBytecodeVersion() { - switch(major_version) { - case 52: - return CodeConstants.BYTECODE_JAVA_8; - case 51: - return CodeConstants.BYTECODE_JAVA_7; - case 50: - return CodeConstants.BYTECODE_JAVA_6; - case 49: - return CodeConstants.BYTECODE_JAVA_5; - } - - return CodeConstants.BYTECODE_JAVA_LE_4; - } + // ***************************************************************************** + // public fields + // ***************************************************************************** + + public int minor_version; + + public int major_version; + + public int access_flags; + + public int this_class; + + public int super_class; + + public PrimitiveConstant thisClass; + + public PrimitiveConstant superClass; + + public String qualifiedName; + + + // ***************************************************************************** + // private fields + // ***************************************************************************** + + private ConstantPool pool; + + private int[] interfaces; + + private String[] interfaceNames; + + private VBStyleCollection<StructField, String> fields = new VBStyleCollection<StructField, String>(); + + private VBStyleCollection<StructMethod, String> methods = new VBStyleCollection<StructMethod, String>(); + + private VBStyleCollection<StructGeneralAttribute, String> attributes = new VBStyleCollection<StructGeneralAttribute, String>(); + + private boolean own = true; + + private LazyLoader loader; + + // ***************************************************************************** + // constructors + // ***************************************************************************** + + public StructClass(String filename, boolean own, LazyLoader loader) throws FileNotFoundException, IOException { + this(new FileInputStream(filename), own, loader); + } + + public StructClass(InputStream inStream, boolean own, LazyLoader loader) throws FileNotFoundException, IOException { + this(new DataInputFullStream(inStream), own, loader); + } + + public StructClass(DataInputFullStream inStream, boolean own, LazyLoader loader) throws FileNotFoundException, IOException { + this.own = own; + this.loader = loader; + + initStruct(inStream); + } + + // ***************************************************************************** + // public methods + // ***************************************************************************** + + public boolean hasField(String name, String descriptor) { + return getField(name, descriptor) != null; + } + + public StructField getField(String name, String descriptor) { + return fields.getWithKey(InterpreterUtil.makeUniqueKey(name, descriptor)); + } + + public StructMethod getMethod(String key) { + return methods.getWithKey(key); + } + + public StructMethod getMethod(String name, String descriptor) { + return methods.getWithKey(InterpreterUtil.makeUniqueKey(name, descriptor)); + } + + public void writeToFile(File file) throws IOException { + DataOutputStream out = new DataOutputStream(new FileOutputStream(file)); + writeToOutputStream(out); + out.close(); + } + + public void writeToOutputStream(DataOutputStream out) throws IOException { + + out.writeInt(0xCAFEBABE); + out.writeShort(minor_version); + out.writeShort(major_version); + + getPool().writeToOutputStream(out); + + out.writeShort(access_flags); + out.writeShort(this_class); + out.writeShort(super_class); + + out.writeShort(interfaces.length); + for (int i = 0; i < interfaces.length; i++) { + out.writeShort(interfaces[i]); + } + + out.writeShort(fields.size()); + for (int i = 0; i < fields.size(); i++) { + fields.get(i).writeToStream(out); + } + + out.writeShort(methods.size()); + for (int i = 0; i < methods.size(); i++) { + methods.get(i).writeToStream(out); + } + + out.writeShort(attributes.size()); + for (StructGeneralAttribute attr : attributes) { + attr.writeToStream(out); + } + } + + public String getInterface(int i) { + return interfaceNames[i]; + } + + public void releaseResources() { + if (loader != null) { + pool = null; + } + } + + // ***************************************************************************** + // private methods + // ***************************************************************************** + + private void initStruct(DataInputFullStream in) throws IOException { + + in.skip(4); + + this.minor_version = in.readUnsignedShort(); + this.major_version = in.readUnsignedShort(); + + pool = new ConstantPool(in); + + this.access_flags = in.readUnsignedShort(); + + this_class = in.readUnsignedShort(); + thisClass = pool.getPrimitiveConstant(this_class); + qualifiedName = thisClass.getString(); + + super_class = in.readUnsignedShort(); + superClass = pool.getPrimitiveConstant(super_class); + + // interfaces + int length = in.readUnsignedShort(); + int[] arrInterfaces = new int[length]; + String[] arrInterfaceNames = new String[length]; + + for (int i = 0; i < length; i++) { + arrInterfaces[i] = in.readUnsignedShort(); + arrInterfaceNames[i] = pool.getPrimitiveConstant(arrInterfaces[i]).getString(); + } + this.interfaces = arrInterfaces; + this.interfaceNames = arrInterfaceNames; + + // fields + VBStyleCollection<StructField, String> lstFields = new VBStyleCollection<StructField, String>(); + length = in.readUnsignedShort(); + for (int i = 0; i < length; i++) { + StructField field = new StructField(); + field.access_flags = in.readUnsignedShort(); + field.name_index = in.readUnsignedShort(); + field.descriptor_index = in.readUnsignedShort(); + + field.initStrings(pool, this_class); + + field.setAttributes(readAttributes(in)); + + lstFields.addWithKey(field, InterpreterUtil.makeUniqueKey(field.getName(), field.getDescriptor())); + } + this.fields = lstFields; + + // methods + length = in.readUnsignedShort(); + for (int i = 0; i < length; i++) { + StructMethod meth = new StructMethod(in, own, this); + + //if(qualifiedName.endsWith("JUnitStatusLine") && !meth.getName().equals("onProcessStarted") && !meth.getName().startsWith("access")) { + //if(!meth.getName().equals("run")) { + // continue; + //} + + methods.addWithKey(meth, InterpreterUtil.makeUniqueKey(meth.getName(), meth.getDescriptor())); + } + + // attributes + this.attributes = readAttributes(in); + + + // release memory + if (loader != null) { + pool = null; + } + } + + private VBStyleCollection<StructGeneralAttribute, String> readAttributes(DataInputFullStream in) throws IOException { + + VBStyleCollection<StructGeneralAttribute, String> lstAttribute = new VBStyleCollection<StructGeneralAttribute, String>(); + + int length = in.readUnsignedShort(); + for (int i = 0; i < length; i++) { + int attr_nameindex = in.readUnsignedShort(); + String attrname = pool.getPrimitiveConstant(attr_nameindex).getString(); + + StructGeneralAttribute attr = StructGeneralAttribute.getMatchingAttributeInstance(attr_nameindex, attrname); + + if (attr != null) { + byte[] arr = new byte[in.readInt()]; + in.readFull(arr); + attr.setInfo(arr); + + attr.initContent(pool); + lstAttribute.addWithKey(attr, attr.getName()); + } + else { + in.skip(in.readInt()); + } + } + + return lstAttribute; + } + + + // ***************************************************************************** + // getter and setter methods + // ***************************************************************************** + + public ConstantPool getPool() { + + if (pool == null && loader != null) { + pool = loader.loadPool(qualifiedName); + } + + return pool; + } + + public int[] getInterfaces() { + return interfaces; + } + + public String[] getInterfaceNames() { + return interfaceNames; + } + + public VBStyleCollection<StructMethod, String> getMethods() { + return methods; + } + + public VBStyleCollection<StructField, String> getFields() { + return fields; + } + + public VBStyleCollection<StructGeneralAttribute, String> getAttributes() { + return attributes; + } + + public boolean isOwn() { + return own; + } + + public LazyLoader getLoader() { + return loader; + } + + public boolean isVersionGE_1_5() { + return (major_version > 48 || (major_version == 48 && minor_version > 0)); // FIXME: check second condition + } + + public boolean isVersionGE_1_7() { + return (major_version >= 51); + } + + public int getBytecodeVersion() { + switch (major_version) { + case 52: + return CodeConstants.BYTECODE_JAVA_8; + case 51: + return CodeConstants.BYTECODE_JAVA_7; + case 50: + return CodeConstants.BYTECODE_JAVA_6; + case 49: + return CodeConstants.BYTECODE_JAVA_5; + } + + return CodeConstants.BYTECODE_JAVA_LE_4; + } } diff --git a/src/org/jetbrains/java/decompiler/struct/StructContext.java b/src/org/jetbrains/java/decompiler/struct/StructContext.java index c253a10..3728a2a 100644 --- a/src/org/jetbrains/java/decompiler/struct/StructContext.java +++ b/src/org/jetbrains/java/decompiler/struct/StructContext.java @@ -1,19 +1,25 @@ /* - * Fernflower - The Analytical Java Decompiler - * http://www.reversed-java.com + * Copyright 2000-2014 JetBrains s.r.o. * - * (C) 2008 - 2010, Stiver + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at * - * This software is NEITHER public domain NOR free software - * as per GNU License. See license.txt for more details. + * http://www.apache.org/licenses/LICENSE-2.0 * - * This software is distributed WITHOUT ANY WARRANTY; without - * even the implied warranty of MERCHANTABILITY or FITNESS FOR - * A PARTICULAR PURPOSE. + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. */ - package org.jetbrains.java.decompiler.struct; +import org.jetbrains.java.decompiler.main.DecompilerContext; +import org.jetbrains.java.decompiler.main.extern.IDecompilatSaver; +import org.jetbrains.java.decompiler.main.extern.IFernflowerLogger; +import org.jetbrains.java.decompiler.struct.lazy.LazyLoader; + import java.io.File; import java.io.IOException; import java.util.Enumeration; @@ -22,190 +28,189 @@ import java.util.jar.JarFile; import java.util.zip.ZipEntry; import java.util.zip.ZipFile; -import org.jetbrains.java.decompiler.main.DecompilerContext; -import org.jetbrains.java.decompiler.main.extern.IDecompilatSaver; -import org.jetbrains.java.decompiler.main.extern.IFernflowerLogger; -import org.jetbrains.java.decompiler.struct.lazy.LazyLoader; - public class StructContext { - // ***************************************************************************** - // private fields - // ***************************************************************************** - - private LazyLoader loader; - - private HashMap<String, StructClass> classes = new HashMap<String, StructClass>(); - - private HashMap<String, ContextUnit> units = new HashMap<String, ContextUnit>(); - - private ContextUnit defaultUnit; - - private IDecompilatSaver saver; - - private IDecompiledData decdata; - - public StructContext(IDecompilatSaver saver, IDecompiledData decdata, LazyLoader loader) { - - this.saver = saver; - this.decdata = decdata; - this.loader = loader; - - defaultUnit = new ContextUnit(ContextUnit.TYPE_FOLDER, null, "", true, saver, decdata); - units.put("", defaultUnit); - } - - // ***************************************************************************** - // public methods - // ***************************************************************************** - - public StructClass getClass(String name) { - return classes.get(name); - } - - public void reloadContext() throws IOException { - - for(ContextUnit unit: units.values()) { - - for(StructClass cl : unit.getClasses()) { - classes.remove(cl.qualifiedName); - } - - unit.reload(loader); - - // adjust lobal class collection - for(StructClass cl : unit.getClasses()) { - classes.put(cl.qualifiedName, cl); - } - } - } - - public void saveContext() { - - for(ContextUnit unit: units.values()) { - if(unit.isOwn()) { - unit.save(); - } - } - } - - public void addSpace(File file, boolean isOwn) throws IOException { - addSpace("", file, isOwn); - } - - private void addSpace(String path, File file, boolean isOwn) throws IOException { - - if(file.isDirectory()) { - - File[] files = file.listFiles(); - path += "/" + (path.length()==0?"":file.getName()); - - for(int i=files.length-1;i>=0;i--) { - addSpace(path, files[i], isOwn); - } - - } else { - - String filename = file.getName(); - - boolean isArchive = false; - - try { - if(filename.endsWith(".jar")) { - addArchive(path, file, ContextUnit.TYPE_JAR, isOwn); - isArchive = true; - } else if(filename.endsWith(".zip")) { - addArchive(path, file, ContextUnit.TYPE_ZIP, isOwn); - isArchive = true; - } - } catch(IOException ex) { - DecompilerContext.getLogger() - .writeMessage("Invalid archive file: "+(path.length()>0?path+"/":"")+filename, IFernflowerLogger.ERROR); - } - - if(!isArchive) { - ContextUnit unit = units.get(path); - if(unit == null) { - unit = new ContextUnit(ContextUnit.TYPE_FOLDER, null, path, isOwn, saver, decdata); - units.put(path, unit); - } - - boolean isClass = false; - - if(filename.endsWith(".class")) { - try { - StructClass cl = new StructClass(loader.getClassStream(file.getAbsolutePath(), null), isOwn, loader); - - classes.put(cl.qualifiedName, cl); - unit.addClass(cl, filename); - loader.addClassLink(cl.qualifiedName, new LazyLoader.Link(LazyLoader.Link.CLASS, file.getAbsolutePath(), null)); - - isClass = true; - } catch(IOException ex) { - DecompilerContext.getLogger() - .writeMessage("Invalid class file: "+(path.length()>0?path+"/":"")+filename, IFernflowerLogger.ERROR); - } - } - - if(!isClass) { - unit.addOtherEntry(file.getAbsolutePath(), filename); - } - } - } - } - - - private void addArchive(String path, File file, int type, boolean isOwn) throws IOException { - - ZipFile archive; - - if(type == ContextUnit.TYPE_JAR) { // jar - archive = new JarFile(file); - } else { // zip - archive = new ZipFile(file); - } - - Enumeration<? extends ZipEntry> en = archive.entries(); - while(en.hasMoreElements()) { - ZipEntry entr = en.nextElement(); - - ContextUnit unit = units.get(path+"/"+file.getName()); - if(unit == null) { - unit = new ContextUnit(type, path, file.getName(), isOwn, saver, decdata); - if(type == ContextUnit.TYPE_JAR) { - unit.setManifest(((JarFile)archive).getManifest()); - } - units.put(path+"/"+file.getName(), unit); - } - - String name = entr.getName(); - if(!entr.isDirectory()) { - if(name.endsWith(".class")) { - StructClass cl = new StructClass(archive.getInputStream(entr), isOwn, loader); - classes.put(cl.qualifiedName, cl); - - unit.addClass(cl, name); - - if(loader != null) { - loader.addClassLink(cl.qualifiedName, new LazyLoader.Link(LazyLoader.Link.ENTRY, file.getAbsolutePath(), name)); - } - - } else { - unit.addOtherEntry(file.getAbsolutePath(), name); - } - } else if(entr.isDirectory()) { - unit.addDirEntry(name); - } - } - } - - // ***************************************************************************** - // getter and setter methods - // ***************************************************************************** - - public HashMap<String, StructClass> getClasses() { - return classes; - } + // ***************************************************************************** + // private fields + // ***************************************************************************** + + private LazyLoader loader; + + private HashMap<String, StructClass> classes = new HashMap<String, StructClass>(); + + private HashMap<String, ContextUnit> units = new HashMap<String, ContextUnit>(); + + private ContextUnit defaultUnit; + + private IDecompilatSaver saver; + + private IDecompiledData decdata; + + public StructContext(IDecompilatSaver saver, IDecompiledData decdata, LazyLoader loader) { + + this.saver = saver; + this.decdata = decdata; + this.loader = loader; + + defaultUnit = new ContextUnit(ContextUnit.TYPE_FOLDER, null, "", true, saver, decdata); + units.put("", defaultUnit); + } + + // ***************************************************************************** + // public methods + // ***************************************************************************** + + public StructClass getClass(String name) { + return classes.get(name); + } + + public void reloadContext() throws IOException { + + for (ContextUnit unit : units.values()) { + + for (StructClass cl : unit.getClasses()) { + classes.remove(cl.qualifiedName); + } + + unit.reload(loader); + + // adjust lobal class collection + for (StructClass cl : unit.getClasses()) { + classes.put(cl.qualifiedName, cl); + } + } + } + + public void saveContext() { + + for (ContextUnit unit : units.values()) { + if (unit.isOwn()) { + unit.save(); + } + } + } + + public void addSpace(File file, boolean isOwn) throws IOException { + addSpace("", file, isOwn); + } + + private void addSpace(String path, File file, boolean isOwn) throws IOException { + + if (file.isDirectory()) { + File[] files = file.listFiles(); + path += "/" + (path.length() == 0 ? "" : file.getName()); + + for (int i = files.length - 1; i >= 0; i--) { + addSpace(path, files[i], isOwn); + } + } + else { + + String filename = file.getName(); + + boolean isArchive = false; + + try { + if (filename.endsWith(".jar")) { + addArchive(path, file, ContextUnit.TYPE_JAR, isOwn); + isArchive = true; + } + else if (filename.endsWith(".zip")) { + addArchive(path, file, ContextUnit.TYPE_ZIP, isOwn); + isArchive = true; + } + } + catch (IOException ex) { + DecompilerContext.getLogger() + .writeMessage("Invalid archive file: " + (path.length() > 0 ? path + "/" : "") + filename, IFernflowerLogger.ERROR); + } + + if (!isArchive) { + ContextUnit unit = units.get(path); + if (unit == null) { + unit = new ContextUnit(ContextUnit.TYPE_FOLDER, null, path, isOwn, saver, decdata); + units.put(path, unit); + } + + boolean isClass = false; + + if (filename.endsWith(".class")) { + try { + StructClass cl = new StructClass(loader.getClassStream(file.getAbsolutePath(), null), isOwn, loader); + + classes.put(cl.qualifiedName, cl); + unit.addClass(cl, filename); + loader.addClassLink(cl.qualifiedName, new LazyLoader.Link(LazyLoader.Link.CLASS, file.getAbsolutePath(), null)); + + isClass = true; + } + catch (IOException ex) { + DecompilerContext.getLogger() + .writeMessage("Invalid class file: " + (path.length() > 0 ? path + "/" : "") + filename, IFernflowerLogger.ERROR); + } + } + + if (!isClass) { + unit.addOtherEntry(file.getAbsolutePath(), filename); + } + } + } + } + + + private void addArchive(String path, File file, int type, boolean isOwn) throws IOException { + + ZipFile archive; + + if (type == ContextUnit.TYPE_JAR) { // jar + archive = new JarFile(file); + } + else { // zip + archive = new ZipFile(file); + } + + Enumeration<? extends ZipEntry> en = archive.entries(); + while (en.hasMoreElements()) { + ZipEntry entr = en.nextElement(); + + ContextUnit unit = units.get(path + "/" + file.getName()); + if (unit == null) { + unit = new ContextUnit(type, path, file.getName(), isOwn, saver, decdata); + if (type == ContextUnit.TYPE_JAR) { + unit.setManifest(((JarFile)archive).getManifest()); + } + units.put(path + "/" + file.getName(), unit); + } + + String name = entr.getName(); + if (!entr.isDirectory()) { + if (name.endsWith(".class")) { + StructClass cl = new StructClass(archive.getInputStream(entr), isOwn, loader); + classes.put(cl.qualifiedName, cl); + + unit.addClass(cl, name); + + if (loader != null) { + loader.addClassLink(cl.qualifiedName, new LazyLoader.Link(LazyLoader.Link.ENTRY, file.getAbsolutePath(), name)); + } + } + else { + unit.addOtherEntry(file.getAbsolutePath(), name); + } + } + else if (entr.isDirectory()) { + unit.addDirEntry(name); + } + } + } + + // ***************************************************************************** + // getter and setter methods + // ***************************************************************************** + + public HashMap<String, StructClass> getClasses() { + return classes; + } } diff --git a/src/org/jetbrains/java/decompiler/struct/StructField.java b/src/org/jetbrains/java/decompiler/struct/StructField.java index 2537e7b..4c0f25d 100644 --- a/src/org/jetbrains/java/decompiler/struct/StructField.java +++ b/src/org/jetbrains/java/decompiler/struct/StructField.java @@ -1,28 +1,29 @@ /* - * Fernflower - The Analytical Java Decompiler - * http://www.reversed-java.com + * Copyright 2000-2014 JetBrains s.r.o. * - * (C) 2008 - 2010, Stiver + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at * - * This software is NEITHER public domain NOR free software - * as per GNU License. See license.txt for more details. + * http://www.apache.org/licenses/LICENSE-2.0 * - * This software is distributed WITHOUT ANY WARRANTY; without - * even the implied warranty of MERCHANTABILITY or FITNESS FOR - * A PARTICULAR PURPOSE. + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. */ - package org.jetbrains.java.decompiler.struct; -import java.io.DataOutputStream; -import java.io.IOException; - import org.jetbrains.java.decompiler.struct.attr.StructGeneralAttribute; import org.jetbrains.java.decompiler.struct.consts.ConstantPool; import org.jetbrains.java.decompiler.util.VBStyleCollection; +import java.io.DataOutputStream; +import java.io.IOException; + /* - field_info { + field_info { u2 access_flags; u2 name_index; u2 descriptor_index; @@ -33,77 +34,77 @@ import org.jetbrains.java.decompiler.util.VBStyleCollection; public class StructField { - // ***************************************************************************** - // public fields - // ***************************************************************************** - - public int access_flags; - public int name_index; - public int descriptor_index; - - private String name; - private String descriptor; - - // ***************************************************************************** - // private fields - // ***************************************************************************** - - private VBStyleCollection<StructGeneralAttribute, String> attributes; - - // ***************************************************************************** - // constructors - // ***************************************************************************** - - public StructField() {} - - // ***************************************************************************** - // public methods - // ***************************************************************************** - - public void writeToStream(DataOutputStream out) throws IOException { - - out.writeShort(access_flags); - out.writeShort(name_index); - out.writeShort(descriptor_index); - - out.writeShort(attributes.size()); - for(StructGeneralAttribute attr: attributes) { - attr.writeToStream(out); - } - } - - public void initStrings(ConstantPool pool, int class_index) { - String[] values = pool.getClassElement(ConstantPool.FIELD, class_index, name_index, descriptor_index); - name = values[0]; - descriptor = values[1]; - } - - // ***************************************************************************** - // getter and setter methods - // ***************************************************************************** - - public VBStyleCollection<StructGeneralAttribute, String> getAttributes() { - return attributes; - } - - public void setAttributes(VBStyleCollection<StructGeneralAttribute, String> attributes) { - this.attributes = attributes; - } - - public String getDescriptor() { - return descriptor; - } - - public void setDescriptor(String descriptor) { - this.descriptor = descriptor; - } - - public String getName() { - return name; - } - - public void setName(String name) { - this.name = name; - } - + // ***************************************************************************** + // public fields + // ***************************************************************************** + + public int access_flags; + public int name_index; + public int descriptor_index; + + private String name; + private String descriptor; + + // ***************************************************************************** + // private fields + // ***************************************************************************** + + private VBStyleCollection<StructGeneralAttribute, String> attributes; + + // ***************************************************************************** + // constructors + // ***************************************************************************** + + public StructField() { + } + + // ***************************************************************************** + // public methods + // ***************************************************************************** + + public void writeToStream(DataOutputStream out) throws IOException { + + out.writeShort(access_flags); + out.writeShort(name_index); + out.writeShort(descriptor_index); + + out.writeShort(attributes.size()); + for (StructGeneralAttribute attr : attributes) { + attr.writeToStream(out); + } + } + + public void initStrings(ConstantPool pool, int class_index) { + String[] values = pool.getClassElement(ConstantPool.FIELD, class_index, name_index, descriptor_index); + name = values[0]; + descriptor = values[1]; + } + + // ***************************************************************************** + // getter and setter methods + // ***************************************************************************** + + public VBStyleCollection<StructGeneralAttribute, String> getAttributes() { + return attributes; + } + + public void setAttributes(VBStyleCollection<StructGeneralAttribute, String> attributes) { + this.attributes = attributes; + } + + public String getDescriptor() { + return descriptor; + } + + public void setDescriptor(String descriptor) { + this.descriptor = descriptor; + } + + public String getName() { + return name; + } + + public void setName(String name) { + this.name = name; + } } diff --git a/src/org/jetbrains/java/decompiler/struct/StructMethod.java b/src/org/jetbrains/java/decompiler/struct/StructMethod.java index 20fdae9..baaf633 100644 --- a/src/org/jetbrains/java/decompiler/struct/StructMethod.java +++ b/src/org/jetbrains/java/decompiler/struct/StructMethod.java @@ -1,19 +1,27 @@ /* - * Fernflower - The Analytical Java Decompiler - * http://www.reversed-java.com + * Copyright 2000-2014 JetBrains s.r.o. * - * (C) 2008 - 2010, Stiver + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at * - * This software is NEITHER public domain NOR free software - * as per GNU License. See license.txt for more details. + * http://www.apache.org/licenses/LICENSE-2.0 * - * This software is distributed WITHOUT ANY WARRANTY; without - * even the implied warranty of MERCHANTABILITY or FITNESS FOR - * A PARTICULAR PURPOSE. + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. */ - package org.jetbrains.java.decompiler.struct; +import org.jetbrains.java.decompiler.code.*; +import org.jetbrains.java.decompiler.struct.attr.StructGeneralAttribute; +import org.jetbrains.java.decompiler.struct.attr.StructLocalVariableTableAttribute; +import org.jetbrains.java.decompiler.struct.consts.ConstantPool; +import org.jetbrains.java.decompiler.util.DataInputFullStream; +import org.jetbrains.java.decompiler.util.VBStyleCollection; + import java.io.ByteArrayInputStream; import java.io.ByteArrayOutputStream; import java.io.DataOutputStream; @@ -21,19 +29,6 @@ import java.io.IOException; import java.util.ArrayList; import java.util.List; -import org.jetbrains.java.decompiler.code.CodeConstants; -import org.jetbrains.java.decompiler.code.ConstantsUtil; -import org.jetbrains.java.decompiler.code.ExceptionHandler; -import org.jetbrains.java.decompiler.code.ExceptionTable; -import org.jetbrains.java.decompiler.code.FullInstructionSequence; -import org.jetbrains.java.decompiler.code.Instruction; -import org.jetbrains.java.decompiler.code.InstructionSequence; -import org.jetbrains.java.decompiler.struct.attr.StructGeneralAttribute; -import org.jetbrains.java.decompiler.struct.attr.StructLocalVariableTableAttribute; -import org.jetbrains.java.decompiler.struct.consts.ConstantPool; -import org.jetbrains.java.decompiler.util.DataInputFullStream; -import org.jetbrains.java.decompiler.util.VBStyleCollection; - /* method_info { u2 access_flags; @@ -45,516 +40,525 @@ import org.jetbrains.java.decompiler.util.VBStyleCollection; */ public class StructMethod implements CodeConstants { - - // ***************************************************************************** - // public fields - // ***************************************************************************** - - public int name_index; - - public int descriptor_index; - - // ***************************************************************************** - // private fields - // ***************************************************************************** - - private static final int[] opr_iconst = new int[] {-1,0,1,2,3,4,5}; - - private static final int[] opr_loadstore = new int[] {0,1,2,3,0,1,2,3,0,1,2,3,0,1,2,3,0,1,2,3}; - - private static final int[] opcs_load = new int[] {opc_iload,opc_lload,opc_fload,opc_dload,opc_aload}; - - private static final int[] opcs_store = new int[] {opc_istore,opc_lstore,opc_fstore,opc_dstore,opc_astore}; - - - private int accessFlags; - - private VBStyleCollection<StructGeneralAttribute, String> attributes; - - private int localVariables; - - private int maxStack; - - private String name; - - private String descriptor; - - private InstructionSequence seq; - - private boolean containsCode = false; - - private boolean own; - - private StructClass classStruct; - - - // lazy properties - private boolean lazy; - - private boolean expanded; - - private byte[] code_content; - - private int code_length = 0; - - private int code_fulllength = 0; - - // ***************************************************************************** - // constructors - // ***************************************************************************** - - public StructMethod(DataInputFullStream in, boolean own, StructClass clstruct) throws IOException { - this(in, true, own, clstruct); - } - - public StructMethod(DataInputFullStream in, boolean lazy, boolean own, StructClass clstruct) throws IOException { - - this.own = own; - this.lazy = lazy; - this.expanded = !lazy; - this.classStruct = clstruct; - - accessFlags = in.readUnsignedShort(); - name_index = in.readUnsignedShort(); - descriptor_index = in.readUnsignedShort(); - - ConstantPool pool = clstruct.getPool(); - - initStrings(pool, clstruct.this_class); - - VBStyleCollection<StructGeneralAttribute, String> lstAttribute = new VBStyleCollection<StructGeneralAttribute, String>(); - int len = in.readUnsignedShort(); - for(int i=0;i<len;i++) { - - int attr_nameindex = in.readUnsignedShort(); - String attrname = pool.getPrimitiveConstant(attr_nameindex).getString(); - - if(StructGeneralAttribute.ATTRIBUTE_CODE.equals(attrname)) { - if(!this.own) { - // skip code in foreign classes - in.skip(8); - in.skip(in.readInt()); - in.skip(8*in.readUnsignedShort()); - } else { - containsCode = true; - - in.skip(4); - - maxStack = in.readUnsignedShort(); - localVariables = in.readUnsignedShort(); - - if(lazy) { - code_length = in.readInt(); - - in.skip(code_length); - - int exc_length = in.readUnsignedShort(); - code_fulllength = code_length + exc_length*8+2; - - in.skip(exc_length*8); - - } else { - seq = parseBytecode(in, in.readInt(), pool); - } - } - - // code attributes - int length = in.readUnsignedShort(); - for (int j = 0; j < length; j++) { - int codeattr_nameindex = in.readUnsignedShort(); - String codeattrname = pool.getPrimitiveConstant(codeattr_nameindex).getString(); - - readAttribute(in, pool, lstAttribute, codeattr_nameindex, codeattrname); - } - } else { - readAttribute(in, pool, lstAttribute, attr_nameindex, attrname); - } - } - - attributes = lstAttribute; - } - - - - // ***************************************************************************** - // public methods - // ***************************************************************************** - - public void writeToStream(DataOutputStream out) throws IOException { - - out.writeShort(accessFlags); - out.writeShort(name_index); - out.writeShort(descriptor_index); - - out.writeShort(attributes.size()); - - for(StructGeneralAttribute attr: attributes) { - if(StructGeneralAttribute.ATTRIBUTE_CODE.equals(attr.getName())){ - out.writeShort(attr.getAttribute_name_index()); - - if(lazy && !expanded) { - out.writeInt(10+code_content.length); - out.writeShort(maxStack); - out.writeShort(localVariables); - out.writeInt(code_length); - out.write(code_content); - } else { - ByteArrayOutputStream codeout = new ByteArrayOutputStream(); - seq.writeCodeToStream(new DataOutputStream(codeout)); - - ByteArrayOutputStream excout = new ByteArrayOutputStream(); - seq.writeExceptionsToStream(new DataOutputStream(excout)); - - out.writeInt(10+codeout.size()+excout.size()); - - out.writeShort(maxStack); - out.writeShort(localVariables); - out.writeInt(codeout.size()); - codeout.writeTo(out); - excout.writeTo(out); - } - // no attributes - out.writeShort(0); - } else { - attr.writeToStream(out); - } - } - - } - - private void readAttribute(DataInputFullStream in, ConstantPool pool, VBStyleCollection<StructGeneralAttribute, String> lstAttribute, - int attr_nameindex, String attrname) throws IOException { - - StructGeneralAttribute attribute = StructGeneralAttribute.getMatchingAttributeInstance(attr_nameindex, attrname); - - if(attribute != null) { - attrname = attribute.getName(); - - byte[] arr = new byte[in.readInt()]; - in.readFull(arr); - attribute.setInfo(arr); - - attribute.initContent(pool); - - if(StructGeneralAttribute.ATTRIBUTE_LOCAL_VARIABLE_TABLE.equals(attrname) && - lstAttribute.containsKey(attrname)) { - // merge all variable tables - StructLocalVariableTableAttribute oldattr = (StructLocalVariableTableAttribute)lstAttribute.getWithKey(attrname); - oldattr.addLocalVariableTable((StructLocalVariableTableAttribute)attribute); - } else { - lstAttribute.addWithKey(attribute, attribute.getName()); - } - } else { - in.skip(in.readInt()); - } - } - - private void initStrings(ConstantPool pool, int class_index) { - String[] values = pool.getClassElement(ConstantPool.METHOD, class_index, name_index, descriptor_index); - name = values[0]; - descriptor = values[1]; - } - - public void expandData() throws IOException { - if(containsCode && lazy && !expanded) { - - byte[] codearr = classStruct.getLoader().loadBytecode(this, code_fulllength); - - seq = parseBytecode(new DataInputFullStream(new ByteArrayInputStream(codearr)), code_length, classStruct.getPool()); - expanded = true; - } - } - - public void releaseResources() throws IOException { - if(containsCode && lazy && expanded) { - seq = null; - expanded = false; - } - } - - // ***************************************************************************** - // private methods - // ***************************************************************************** - - private InstructionSequence parseBytecode(DataInputFullStream in, int length, ConstantPool pool) throws IOException { - - VBStyleCollection<Instruction, Integer> collinstr = new VBStyleCollection<Instruction, Integer>(); - - int bytecode_version = classStruct.getBytecodeVersion(); - - for(int i=0;i<length;) { - - int offset = i; - - int opcode = in.readUnsignedByte(); - int group = GROUP_GENERAL; - - boolean wide = (opcode == opc_wide); - - if(wide) { - i++; - opcode = in.readUnsignedByte(); - } - - List<Integer> operands = new ArrayList<Integer>(); - - if(opcode>=opc_iconst_m1 && opcode<=opc_iconst_5) { - operands.add(new Integer(opr_iconst[opcode-opc_iconst_m1])); - opcode = opc_bipush; - }else if(opcode>=opc_iload_0 && opcode<=opc_aload_3) { - operands.add(new Integer(opr_loadstore[opcode-opc_iload_0])); - opcode = opcs_load[(opcode-opc_iload_0)/4]; - }else if(opcode>=opc_istore_0 && opcode<=opc_astore_3) { - operands.add(new Integer(opr_loadstore[opcode-opc_istore_0])); - opcode = opcs_store[(opcode-opc_istore_0)/4]; - } else { - switch (opcode) { - case opc_bipush: - operands.add(new Integer(in.readByte())); - i++; - break; - case opc_ldc: - case opc_newarray: - operands.add(new Integer(in.readUnsignedByte())); - i++; - break; - case opc_sipush: - case opc_ifeq: - case opc_ifne: - case opc_iflt: - case opc_ifge: - case opc_ifgt: - case opc_ifle: - case opc_if_icmpeq: - case opc_if_icmpne: - case opc_if_icmplt: - case opc_if_icmpge: - case opc_if_icmpgt: - case opc_if_icmple: - case opc_if_acmpeq: - case opc_if_acmpne: - case opc_goto: - case opc_jsr: - case opc_ifnull: - case opc_ifnonnull: - if(opcode!=opc_sipush) { - group = GROUP_JUMP; - } - operands.add(new Integer(in.readShort())); - i+=2; - break; - case opc_ldc_w: - case opc_ldc2_w: - case opc_getstatic: - case opc_putstatic: - case opc_getfield: - case opc_putfield: - case opc_invokevirtual: - case opc_invokespecial: - case opc_invokestatic: - case opc_new: - case opc_anewarray: - case opc_checkcast: - case opc_instanceof: - operands.add(new Integer(in.readUnsignedShort())); - i+=2; - if(opcode>=opc_getstatic && opcode<=opc_putfield) { - group = GROUP_FIELDACCESS; - } else if(opcode>=opc_invokevirtual && opcode<=opc_invokestatic) { - group = GROUP_INVOCATION; - } - break; - case opc_invokedynamic: - if(classStruct.isVersionGE_1_7()) { // instruction unused in Java 6 and before - operands.add(new Integer(in.readUnsignedShort())); - in.skip(2); - group = GROUP_INVOCATION; - i+=4; - } - break; - case opc_iload: - case opc_lload: - case opc_fload: - case opc_dload: - case opc_aload: - case opc_istore: - case opc_lstore: - case opc_fstore: - case opc_dstore: - case opc_astore: - case opc_ret: - if(wide) { - operands.add(new Integer(in.readUnsignedShort())); - i+=2; - } else { - operands.add(new Integer(in.readUnsignedByte())); - i++; - } - if(opcode == opc_ret) { - group = GROUP_RETURN; - } - break; - case opc_iinc: - if (wide) { - operands.add(new Integer(in.readUnsignedShort())); - operands.add(new Integer(in.readShort())); - i+=4; - } else { - operands.add(new Integer(in.readUnsignedByte())); - operands.add(new Integer(in.readByte())); - i+=2; - } - break; - case opc_goto_w: - case opc_jsr_w: - opcode = opcode == opc_jsr_w?opc_jsr:opc_goto; - operands.add(new Integer(in.readInt())); - group = GROUP_JUMP; - i+=4; - break; - case opc_invokeinterface: - operands.add(new Integer(in.readUnsignedShort())); - operands.add(new Integer(in.readUnsignedByte())); - in.skip(1); - group = GROUP_INVOCATION; - i+=4; - break; - case opc_multianewarray: - operands.add(new Integer(in.readUnsignedShort())); - operands.add(new Integer(in.readUnsignedByte())); - i+=3; - break; - case opc_tableswitch: - in.skip((4-(i+1)%4)%4); - i+=((4-(i+1)%4)%4); // padding - operands.add(new Integer(in.readInt())); - i+=4; - int low = in.readInt(); - operands.add(new Integer(low)); - i+=4; - int high = in.readInt(); - operands.add(new Integer(high)); - i+=4; - - for(int j=0;j<high-low+1;j++) { - operands.add(new Integer(in.readInt())); - i+=4; - } - group = GROUP_SWITCH; - - break; - case opc_lookupswitch: - in.skip((4-(i+1)%4)%4); - i+=((4-(i+1)%4)%4); // padding - operands.add(new Integer(in.readInt())); - i+=4; - int npairs = in.readInt(); - operands.add(new Integer(npairs)); - i+=4; - - for(int j=0;j<npairs;j++) { - operands.add(new Integer(in.readInt())); - i+=4; - operands.add(new Integer(in.readInt())); - i+=4; - } - group = GROUP_SWITCH; - break; - case opc_ireturn: - case opc_lreturn: - case opc_freturn: - case opc_dreturn: - case opc_areturn: - case opc_return: - case opc_athrow: - group = GROUP_RETURN; - } - } - - int[] ops = new int[operands.size()]; - for(int j=0;j<operands.size();j++) { - ops[j] = ((Integer)operands.get(j)).intValue(); - } - - Instruction instr = ConstantsUtil.getInstructionInstance(opcode, wide, group, bytecode_version, ops); - - collinstr.addWithKey(instr, new Integer(offset)); - - i++; - } - - // initialize exception table - List<ExceptionHandler> lstHandlers = new ArrayList<ExceptionHandler>(); - - int exception_count = in.readUnsignedShort(); - for(int i=0;i<exception_count;i++) { - ExceptionHandler handler = new ExceptionHandler(); - handler.from = in.readUnsignedShort(); - handler.to = in.readUnsignedShort(); - handler.handler = in.readUnsignedShort(); - - int excclass = in.readUnsignedShort(); - handler.class_index = excclass; - if(excclass!=0) { - handler.exceptionClass = pool.getPrimitiveConstant(excclass).getString(); - } - - lstHandlers.add(handler); - } - - InstructionSequence seq = new FullInstructionSequence(collinstr, new ExceptionTable(lstHandlers)); - - // initialize instructions - int i = seq.length()-1; - seq.setPointer(i); - - while(i>=0) { - Instruction instr = seq.getInstr(i--); - if(instr.group!=GROUP_GENERAL) { - instr.initInstruction(seq); - } - seq.addToPointer(-1); - } - - return seq; - - } - - // ***************************************************************************** - // getter and setter methods - // ***************************************************************************** - - public InstructionSequence getInstructionSequence() { - return seq; - } - - public String getDescriptor() { - return descriptor; - } - - public String getName() { - return name; - } - - public int getAccessFlags() { - return accessFlags; - } - - public int getLocalVariables() { - return localVariables; - } - - public VBStyleCollection<StructGeneralAttribute, String> getAttributes() { - return attributes; - } - - public StructClass getClassStruct() { - return classStruct; - } - - public boolean containsCode() { - return containsCode; - } + + // ***************************************************************************** + // public fields + // ***************************************************************************** + + public int name_index; + + public int descriptor_index; + + // ***************************************************************************** + // private fields + // ***************************************************************************** + + private static final int[] opr_iconst = new int[]{-1, 0, 1, 2, 3, 4, 5}; + + private static final int[] opr_loadstore = new int[]{0, 1, 2, 3, 0, 1, 2, 3, 0, 1, 2, 3, 0, 1, 2, 3, 0, 1, 2, 3}; + + private static final int[] opcs_load = new int[]{opc_iload, opc_lload, opc_fload, opc_dload, opc_aload}; + + private static final int[] opcs_store = new int[]{opc_istore, opc_lstore, opc_fstore, opc_dstore, opc_astore}; + + + private int accessFlags; + + private VBStyleCollection<StructGeneralAttribute, String> attributes; + + private int localVariables; + + private int maxStack; + + private String name; + + private String descriptor; + + private InstructionSequence seq; + + private boolean containsCode = false; + + private boolean own; + + private StructClass classStruct; + + + // lazy properties + private boolean lazy; + + private boolean expanded; + + private byte[] code_content; + + private int code_length = 0; + + private int code_fulllength = 0; + + // ***************************************************************************** + // constructors + // ***************************************************************************** + + public StructMethod(DataInputFullStream in, boolean own, StructClass clstruct) throws IOException { + this(in, true, own, clstruct); + } + + public StructMethod(DataInputFullStream in, boolean lazy, boolean own, StructClass clstruct) throws IOException { + + this.own = own; + this.lazy = lazy; + this.expanded = !lazy; + this.classStruct = clstruct; + + accessFlags = in.readUnsignedShort(); + name_index = in.readUnsignedShort(); + descriptor_index = in.readUnsignedShort(); + + ConstantPool pool = clstruct.getPool(); + + initStrings(pool, clstruct.this_class); + + VBStyleCollection<StructGeneralAttribute, String> lstAttribute = new VBStyleCollection<StructGeneralAttribute, String>(); + int len = in.readUnsignedShort(); + for (int i = 0; i < len; i++) { + + int attr_nameindex = in.readUnsignedShort(); + String attrname = pool.getPrimitiveConstant(attr_nameindex).getString(); + + if (StructGeneralAttribute.ATTRIBUTE_CODE.equals(attrname)) { + if (!this.own) { + // skip code in foreign classes + in.skip(8); + in.skip(in.readInt()); + in.skip(8 * in.readUnsignedShort()); + } + else { + containsCode = true; + + in.skip(4); + + maxStack = in.readUnsignedShort(); + localVariables = in.readUnsignedShort(); + + if (lazy) { + code_length = in.readInt(); + + in.skip(code_length); + + int exc_length = in.readUnsignedShort(); + code_fulllength = code_length + exc_length * 8 + 2; + + in.skip(exc_length * 8); + } + else { + seq = parseBytecode(in, in.readInt(), pool); + } + } + + // code attributes + int length = in.readUnsignedShort(); + for (int j = 0; j < length; j++) { + int codeattr_nameindex = in.readUnsignedShort(); + String codeattrname = pool.getPrimitiveConstant(codeattr_nameindex).getString(); + + readAttribute(in, pool, lstAttribute, codeattr_nameindex, codeattrname); + } + } + else { + readAttribute(in, pool, lstAttribute, attr_nameindex, attrname); + } + } + + attributes = lstAttribute; + } + + + // ***************************************************************************** + // public methods + // ***************************************************************************** + + public void writeToStream(DataOutputStream out) throws IOException { + + out.writeShort(accessFlags); + out.writeShort(name_index); + out.writeShort(descriptor_index); + + out.writeShort(attributes.size()); + + for (StructGeneralAttribute attr : attributes) { + if (StructGeneralAttribute.ATTRIBUTE_CODE.equals(attr.getName())) { + out.writeShort(attr.getAttribute_name_index()); + + if (lazy && !expanded) { + out.writeInt(10 + code_content.length); + out.writeShort(maxStack); + out.writeShort(localVariables); + out.writeInt(code_length); + out.write(code_content); + } + else { + ByteArrayOutputStream codeout = new ByteArrayOutputStream(); + seq.writeCodeToStream(new DataOutputStream(codeout)); + + ByteArrayOutputStream excout = new ByteArrayOutputStream(); + seq.writeExceptionsToStream(new DataOutputStream(excout)); + + out.writeInt(10 + codeout.size() + excout.size()); + + out.writeShort(maxStack); + out.writeShort(localVariables); + out.writeInt(codeout.size()); + codeout.writeTo(out); + excout.writeTo(out); + } + // no attributes + out.writeShort(0); + } + else { + attr.writeToStream(out); + } + } + } + + private void readAttribute(DataInputFullStream in, ConstantPool pool, VBStyleCollection<StructGeneralAttribute, String> lstAttribute, + int attr_nameindex, String attrname) throws IOException { + + StructGeneralAttribute attribute = StructGeneralAttribute.getMatchingAttributeInstance(attr_nameindex, attrname); + + if (attribute != null) { + attrname = attribute.getName(); + + byte[] arr = new byte[in.readInt()]; + in.readFull(arr); + attribute.setInfo(arr); + + attribute.initContent(pool); + + if (StructGeneralAttribute.ATTRIBUTE_LOCAL_VARIABLE_TABLE.equals(attrname) && + lstAttribute.containsKey(attrname)) { + // merge all variable tables + StructLocalVariableTableAttribute oldattr = (StructLocalVariableTableAttribute)lstAttribute.getWithKey(attrname); + oldattr.addLocalVariableTable((StructLocalVariableTableAttribute)attribute); + } + else { + lstAttribute.addWithKey(attribute, attribute.getName()); + } + } + else { + in.skip(in.readInt()); + } + } + + private void initStrings(ConstantPool pool, int class_index) { + String[] values = pool.getClassElement(ConstantPool.METHOD, class_index, name_index, descriptor_index); + name = values[0]; + descriptor = values[1]; + } + + public void expandData() throws IOException { + if (containsCode && lazy && !expanded) { + + byte[] codearr = classStruct.getLoader().loadBytecode(this, code_fulllength); + + seq = parseBytecode(new DataInputFullStream(new ByteArrayInputStream(codearr)), code_length, classStruct.getPool()); + expanded = true; + } + } + + public void releaseResources() throws IOException { + if (containsCode && lazy && expanded) { + seq = null; + expanded = false; + } + } + + // ***************************************************************************** + // private methods + // ***************************************************************************** + + private InstructionSequence parseBytecode(DataInputFullStream in, int length, ConstantPool pool) throws IOException { + + VBStyleCollection<Instruction, Integer> collinstr = new VBStyleCollection<Instruction, Integer>(); + + int bytecode_version = classStruct.getBytecodeVersion(); + + for (int i = 0; i < length; ) { + + int offset = i; + + int opcode = in.readUnsignedByte(); + int group = GROUP_GENERAL; + + boolean wide = (opcode == opc_wide); + + if (wide) { + i++; + opcode = in.readUnsignedByte(); + } + + List<Integer> operands = new ArrayList<Integer>(); + + if (opcode >= opc_iconst_m1 && opcode <= opc_iconst_5) { + operands.add(new Integer(opr_iconst[opcode - opc_iconst_m1])); + opcode = opc_bipush; + } + else if (opcode >= opc_iload_0 && opcode <= opc_aload_3) { + operands.add(new Integer(opr_loadstore[opcode - opc_iload_0])); + opcode = opcs_load[(opcode - opc_iload_0) / 4]; + } + else if (opcode >= opc_istore_0 && opcode <= opc_astore_3) { + operands.add(new Integer(opr_loadstore[opcode - opc_istore_0])); + opcode = opcs_store[(opcode - opc_istore_0) / 4]; + } + else { + switch (opcode) { + case opc_bipush: + operands.add(new Integer(in.readByte())); + i++; + break; + case opc_ldc: + case opc_newarray: + operands.add(new Integer(in.readUnsignedByte())); + i++; + break; + case opc_sipush: + case opc_ifeq: + case opc_ifne: + case opc_iflt: + case opc_ifge: + case opc_ifgt: + case opc_ifle: + case opc_if_icmpeq: + case opc_if_icmpne: + case opc_if_icmplt: + case opc_if_icmpge: + case opc_if_icmpgt: + case opc_if_icmple: + case opc_if_acmpeq: + case opc_if_acmpne: + case opc_goto: + case opc_jsr: + case opc_ifnull: + case opc_ifnonnull: + if (opcode != opc_sipush) { + group = GROUP_JUMP; + } + operands.add(new Integer(in.readShort())); + i += 2; + break; + case opc_ldc_w: + case opc_ldc2_w: + case opc_getstatic: + case opc_putstatic: + case opc_getfield: + case opc_putfield: + case opc_invokevirtual: + case opc_invokespecial: + case opc_invokestatic: + case opc_new: + case opc_anewarray: + case opc_checkcast: + case opc_instanceof: + operands.add(new Integer(in.readUnsignedShort())); + i += 2; + if (opcode >= opc_getstatic && opcode <= opc_putfield) { + group = GROUP_FIELDACCESS; + } + else if (opcode >= opc_invokevirtual && opcode <= opc_invokestatic) { + group = GROUP_INVOCATION; + } + break; + case opc_invokedynamic: + if (classStruct.isVersionGE_1_7()) { // instruction unused in Java 6 and before + operands.add(new Integer(in.readUnsignedShort())); + in.skip(2); + group = GROUP_INVOCATION; + i += 4; + } + break; + case opc_iload: + case opc_lload: + case opc_fload: + case opc_dload: + case opc_aload: + case opc_istore: + case opc_lstore: + case opc_fstore: + case opc_dstore: + case opc_astore: + case opc_ret: + if (wide) { + operands.add(new Integer(in.readUnsignedShort())); + i += 2; + } + else { + operands.add(new Integer(in.readUnsignedByte())); + i++; + } + if (opcode == opc_ret) { + group = GROUP_RETURN; + } + break; + case opc_iinc: + if (wide) { + operands.add(new Integer(in.readUnsignedShort())); + operands.add(new Integer(in.readShort())); + i += 4; + } + else { + operands.add(new Integer(in.readUnsignedByte())); + operands.add(new Integer(in.readByte())); + i += 2; + } + break; + case opc_goto_w: + case opc_jsr_w: + opcode = opcode == opc_jsr_w ? opc_jsr : opc_goto; + operands.add(new Integer(in.readInt())); + group = GROUP_JUMP; + i += 4; + break; + case opc_invokeinterface: + operands.add(new Integer(in.readUnsignedShort())); + operands.add(new Integer(in.readUnsignedByte())); + in.skip(1); + group = GROUP_INVOCATION; + i += 4; + break; + case opc_multianewarray: + operands.add(new Integer(in.readUnsignedShort())); + operands.add(new Integer(in.readUnsignedByte())); + i += 3; + break; + case opc_tableswitch: + in.skip((4 - (i + 1) % 4) % 4); + i += ((4 - (i + 1) % 4) % 4); // padding + operands.add(new Integer(in.readInt())); + i += 4; + int low = in.readInt(); + operands.add(new Integer(low)); + i += 4; + int high = in.readInt(); + operands.add(new Integer(high)); + i += 4; + + for (int j = 0; j < high - low + 1; j++) { + operands.add(new Integer(in.readInt())); + i += 4; + } + group = GROUP_SWITCH; + + break; + case opc_lookupswitch: + in.skip((4 - (i + 1) % 4) % 4); + i += ((4 - (i + 1) % 4) % 4); // padding + operands.add(new Integer(in.readInt())); + i += 4; + int npairs = in.readInt(); + operands.add(new Integer(npairs)); + i += 4; + + for (int j = 0; j < npairs; j++) { + operands.add(new Integer(in.readInt())); + i += 4; + operands.add(new Integer(in.readInt())); + i += 4; + } + group = GROUP_SWITCH; + break; + case opc_ireturn: + case opc_lreturn: + case opc_freturn: + case opc_dreturn: + case opc_areturn: + case opc_return: + case opc_athrow: + group = GROUP_RETURN; + } + } + + int[] ops = new int[operands.size()]; + for (int j = 0; j < operands.size(); j++) { + ops[j] = ((Integer)operands.get(j)).intValue(); + } + + Instruction instr = ConstantsUtil.getInstructionInstance(opcode, wide, group, bytecode_version, ops); + + collinstr.addWithKey(instr, new Integer(offset)); + + i++; + } + + // initialize exception table + List<ExceptionHandler> lstHandlers = new ArrayList<ExceptionHandler>(); + + int exception_count = in.readUnsignedShort(); + for (int i = 0; i < exception_count; i++) { + ExceptionHandler handler = new ExceptionHandler(); + handler.from = in.readUnsignedShort(); + handler.to = in.readUnsignedShort(); + handler.handler = in.readUnsignedShort(); + + int excclass = in.readUnsignedShort(); + handler.class_index = excclass; + if (excclass != 0) { + handler.exceptionClass = pool.getPrimitiveConstant(excclass).getString(); + } + + lstHandlers.add(handler); + } + + InstructionSequence seq = new FullInstructionSequence(collinstr, new ExceptionTable(lstHandlers)); + + // initialize instructions + int i = seq.length() - 1; + seq.setPointer(i); + + while (i >= 0) { + Instruction instr = seq.getInstr(i--); + if (instr.group != GROUP_GENERAL) { + instr.initInstruction(seq); + } + seq.addToPointer(-1); + } + + return seq; + } + + // ***************************************************************************** + // getter and setter methods + // ***************************************************************************** + + public InstructionSequence getInstructionSequence() { + return seq; + } + + public String getDescriptor() { + return descriptor; + } + + public String getName() { + return name; + } + + public int getAccessFlags() { + return accessFlags; + } + + public int getLocalVariables() { + return localVariables; + } + + public VBStyleCollection<StructGeneralAttribute, String> getAttributes() { + return attributes; + } + + public StructClass getClassStruct() { + return classStruct; + } + + public boolean containsCode() { + return containsCode; + } } diff --git a/src/org/jetbrains/java/decompiler/struct/attr/StructAnnDefaultAttribute.java b/src/org/jetbrains/java/decompiler/struct/attr/StructAnnDefaultAttribute.java index d171349..f36df6d 100644 --- a/src/org/jetbrains/java/decompiler/struct/attr/StructAnnDefaultAttribute.java +++ b/src/org/jetbrains/java/decompiler/struct/attr/StructAnnDefaultAttribute.java @@ -1,40 +1,40 @@ /* - * Fernflower - The Analytical Java Decompiler - * http://www.reversed-java.com + * Copyright 2000-2014 JetBrains s.r.o. * - * (C) 2008 - 2010, Stiver + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at * - * This software is NEITHER public domain NOR free software - * as per GNU License. See license.txt for more details. + * http://www.apache.org/licenses/LICENSE-2.0 * - * This software is distributed WITHOUT ANY WARRANTY; without - * even the implied warranty of MERCHANTABILITY or FITNESS FOR - * A PARTICULAR PURPOSE. + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. */ - package org.jetbrains.java.decompiler.struct.attr; -import java.io.ByteArrayInputStream; -import java.io.DataInputStream; - import org.jetbrains.java.decompiler.modules.decompiler.exps.Exprent; import org.jetbrains.java.decompiler.struct.consts.ConstantPool; +import java.io.ByteArrayInputStream; +import java.io.DataInputStream; + public class StructAnnDefaultAttribute extends StructGeneralAttribute { - private Exprent defaultValue; - - public void initContent(ConstantPool pool) { - - name = ATTRIBUTE_ANNOTATION_DEFAULT; - - DataInputStream data = new DataInputStream(new ByteArrayInputStream(info)); - defaultValue = StructAnnotationAttribute.parseAnnotationElement(data, pool); - } - - public Exprent getDefaultValue() { - return defaultValue; - } - + private Exprent defaultValue; + + public void initContent(ConstantPool pool) { + + name = ATTRIBUTE_ANNOTATION_DEFAULT; + + DataInputStream data = new DataInputStream(new ByteArrayInputStream(info)); + defaultValue = StructAnnotationAttribute.parseAnnotationElement(data, pool); + } + + public Exprent getDefaultValue() { + return defaultValue; + } } diff --git a/src/org/jetbrains/java/decompiler/struct/attr/StructAnnotationAttribute.java b/src/org/jetbrains/java/decompiler/struct/attr/StructAnnotationAttribute.java index 8958299..2a2c74c 100644 --- a/src/org/jetbrains/java/decompiler/struct/attr/StructAnnotationAttribute.java +++ b/src/org/jetbrains/java/decompiler/struct/attr/StructAnnotationAttribute.java @@ -1,187 +1,182 @@ /* - * Fernflower - The Analytical Java Decompiler - * http://www.reversed-java.com + * Copyright 2000-2014 JetBrains s.r.o. * - * (C) 2008 - 2010, Stiver + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at * - * This software is NEITHER public domain NOR free software - * as per GNU License. See license.txt for more details. + * http://www.apache.org/licenses/LICENSE-2.0 * - * This software is distributed WITHOUT ANY WARRANTY; without - * even the implied warranty of MERCHANTABILITY or FITNESS FOR - * A PARTICULAR PURPOSE. + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. */ - package org.jetbrains.java.decompiler.struct.attr; -import java.io.ByteArrayInputStream; -import java.io.DataInputStream; -import java.io.IOException; -import java.util.ArrayList; -import java.util.List; - import org.jetbrains.java.decompiler.code.CodeConstants; -import org.jetbrains.java.decompiler.modules.decompiler.exps.AnnotationExprent; -import org.jetbrains.java.decompiler.modules.decompiler.exps.ConstExprent; -import org.jetbrains.java.decompiler.modules.decompiler.exps.Exprent; -import org.jetbrains.java.decompiler.modules.decompiler.exps.FieldExprent; -import org.jetbrains.java.decompiler.modules.decompiler.exps.NewExprent; +import org.jetbrains.java.decompiler.modules.decompiler.exps.*; import org.jetbrains.java.decompiler.struct.consts.ConstantPool; import org.jetbrains.java.decompiler.struct.consts.PrimitiveConstant; import org.jetbrains.java.decompiler.struct.gen.FieldDescriptor; import org.jetbrains.java.decompiler.struct.gen.VarType; +import java.io.ByteArrayInputStream; +import java.io.DataInputStream; +import java.io.IOException; +import java.util.ArrayList; +import java.util.List; + public class StructAnnotationAttribute extends StructGeneralAttribute { - private List<AnnotationExprent> annotations; - - public void initContent(ConstantPool pool) { - - super.initContent(pool); - - annotations = new ArrayList<AnnotationExprent>(); - DataInputStream data = new DataInputStream(new ByteArrayInputStream(info, 2, info.length)); - - int len = (((info[0] & 0xFF)<<8) | (info[1] & 0xFF)); - for(int i=0;i<len;i++) { - annotations.add(parseAnnotation(data, pool)); - } - - } - - public static AnnotationExprent parseAnnotation(DataInputStream data, ConstantPool pool) { - - try { - - String classname = pool.getPrimitiveConstant(data.readUnsignedShort()).getString(); - VarType cltype = new VarType(classname); - - int len = data.readUnsignedShort(); - - List<String> parnames = new ArrayList<String>(); - List<Exprent> parvalues = new ArrayList<Exprent>(); - - for(int i=0;i<len;i++) { - parnames.add(pool.getPrimitiveConstant(data.readUnsignedShort()).getString()); - parvalues.add(parseAnnotationElement(data, pool)); - } - - return new AnnotationExprent(cltype.value, parnames, parvalues); - - } catch(IOException ex) { - throw new RuntimeException(ex); - } - - } - - public static Exprent parseAnnotationElement(DataInputStream data, ConstantPool pool) { - - try { - int tag = data.readUnsignedByte(); - - switch(tag) { - case 'e': // enum constant - String classname = pool.getPrimitiveConstant(data.readUnsignedShort()).getString(); - String constname = pool.getPrimitiveConstant(data.readUnsignedShort()).getString(); - - FieldDescriptor descr = FieldDescriptor.parseDescriptor(classname); - return new FieldExprent(constname, descr.type.value, true, null, descr); - case 'c': // class - String descriptor = pool.getPrimitiveConstant(data.readUnsignedShort()).getString(); - VarType type = FieldDescriptor.parseDescriptor(descriptor).type; - - String value; - switch(type.type) { - case CodeConstants.TYPE_OBJECT: - value = type.value; - break; - case CodeConstants.TYPE_BYTE: - value = byte.class.getName(); - break; - case CodeConstants.TYPE_CHAR: - value = char.class.getName(); - break; - case CodeConstants.TYPE_DOUBLE: - value = double.class.getName(); - break; - case CodeConstants.TYPE_FLOAT: - value = float.class.getName(); - break; - case CodeConstants.TYPE_INT: - value = int.class.getName(); - break; - case CodeConstants.TYPE_LONG: - value = long.class.getName(); - break; - case CodeConstants.TYPE_SHORT: - value = short.class.getName(); - break; - case CodeConstants.TYPE_BOOLEAN: - value = boolean.class.getName(); - break; - case CodeConstants.TYPE_VOID: - value = void.class.getName(); - break; - default: - throw new RuntimeException("invalid class type: " + type.type); - } - return new ConstExprent(VarType.VARTYPE_CLASS, value); - case '[': // array - int len = data.readUnsignedShort(); - List<Exprent> lst = new ArrayList<Exprent>(); - - for(int i=0;i<len;i++) { - lst.add(parseAnnotationElement(data, pool)); - } - - VarType newtype; - if(lst.isEmpty()) { - newtype = new VarType(CodeConstants.TYPE_OBJECT, 1, "java/lang/Object"); - } else { - VarType eltype = lst.get(0).getExprType(); - newtype = new VarType(eltype.type, 1, eltype.value); - } - - NewExprent newexpr = new NewExprent(newtype, new ArrayList<Exprent>()); - newexpr.setDirectArrayInit(true); - newexpr.setLstArrayElements(lst); - return newexpr; - case '@': // annotation - return parseAnnotation(data, pool); - default: - PrimitiveConstant cn = pool.getPrimitiveConstant(data.readUnsignedShort()); - switch(tag) { - case 'B': - return new ConstExprent(VarType.VARTYPE_BYTE, cn.value); - case 'C': - return new ConstExprent(VarType.VARTYPE_CHAR, cn.value); - case 'D': - return new ConstExprent(VarType.VARTYPE_DOUBLE, cn.value); - case 'F': - return new ConstExprent(VarType.VARTYPE_FLOAT, cn.value); - case 'I': - return new ConstExprent(VarType.VARTYPE_INT, cn.value); - case 'J': - return new ConstExprent(VarType.VARTYPE_LONG, cn.value); - case 'S': - return new ConstExprent(VarType.VARTYPE_SHORT, cn.value); - case 'Z': - return new ConstExprent(VarType.VARTYPE_BOOLEAN, cn.value); - case 's': - return new ConstExprent(VarType.VARTYPE_STRING, cn.value); - default: - throw new RuntimeException("invalid element type!"); - } - } - } catch(IOException ex) { - throw new RuntimeException(ex); - } - - } - - - public List<AnnotationExprent> getAnnotations() { - return annotations; - } - + private List<AnnotationExprent> annotations; + + public void initContent(ConstantPool pool) { + + super.initContent(pool); + + annotations = new ArrayList<AnnotationExprent>(); + DataInputStream data = new DataInputStream(new ByteArrayInputStream(info, 2, info.length)); + + int len = (((info[0] & 0xFF) << 8) | (info[1] & 0xFF)); + for (int i = 0; i < len; i++) { + annotations.add(parseAnnotation(data, pool)); + } + } + + public static AnnotationExprent parseAnnotation(DataInputStream data, ConstantPool pool) { + + try { + + String classname = pool.getPrimitiveConstant(data.readUnsignedShort()).getString(); + VarType cltype = new VarType(classname); + + int len = data.readUnsignedShort(); + + List<String> parnames = new ArrayList<String>(); + List<Exprent> parvalues = new ArrayList<Exprent>(); + + for (int i = 0; i < len; i++) { + parnames.add(pool.getPrimitiveConstant(data.readUnsignedShort()).getString()); + parvalues.add(parseAnnotationElement(data, pool)); + } + + return new AnnotationExprent(cltype.value, parnames, parvalues); + } + catch (IOException ex) { + throw new RuntimeException(ex); + } + } + + public static Exprent parseAnnotationElement(DataInputStream data, ConstantPool pool) { + + try { + int tag = data.readUnsignedByte(); + + switch (tag) { + case 'e': // enum constant + String classname = pool.getPrimitiveConstant(data.readUnsignedShort()).getString(); + String constname = pool.getPrimitiveConstant(data.readUnsignedShort()).getString(); + + FieldDescriptor descr = FieldDescriptor.parseDescriptor(classname); + return new FieldExprent(constname, descr.type.value, true, null, descr); + case 'c': // class + String descriptor = pool.getPrimitiveConstant(data.readUnsignedShort()).getString(); + VarType type = FieldDescriptor.parseDescriptor(descriptor).type; + + String value; + switch (type.type) { + case CodeConstants.TYPE_OBJECT: + value = type.value; + break; + case CodeConstants.TYPE_BYTE: + value = byte.class.getName(); + break; + case CodeConstants.TYPE_CHAR: + value = char.class.getName(); + break; + case CodeConstants.TYPE_DOUBLE: + value = double.class.getName(); + break; + case CodeConstants.TYPE_FLOAT: + value = float.class.getName(); + break; + case CodeConstants.TYPE_INT: + value = int.class.getName(); + break; + case CodeConstants.TYPE_LONG: + value = long.class.getName(); + break; + case CodeConstants.TYPE_SHORT: + value = short.class.getName(); + break; + case CodeConstants.TYPE_BOOLEAN: + value = boolean.class.getName(); + break; + case CodeConstants.TYPE_VOID: + value = void.class.getName(); + break; + default: + throw new RuntimeException("invalid class type: " + type.type); + } + return new ConstExprent(VarType.VARTYPE_CLASS, value); + case '[': // array + int len = data.readUnsignedShort(); + List<Exprent> lst = new ArrayList<Exprent>(); + + for (int i = 0; i < len; i++) { + lst.add(parseAnnotationElement(data, pool)); + } + + VarType newtype; + if (lst.isEmpty()) { + newtype = new VarType(CodeConstants.TYPE_OBJECT, 1, "java/lang/Object"); + } + else { + VarType eltype = lst.get(0).getExprType(); + newtype = new VarType(eltype.type, 1, eltype.value); + } + + NewExprent newexpr = new NewExprent(newtype, new ArrayList<Exprent>()); + newexpr.setDirectArrayInit(true); + newexpr.setLstArrayElements(lst); + return newexpr; + case '@': // annotation + return parseAnnotation(data, pool); + default: + PrimitiveConstant cn = pool.getPrimitiveConstant(data.readUnsignedShort()); + switch (tag) { + case 'B': + return new ConstExprent(VarType.VARTYPE_BYTE, cn.value); + case 'C': + return new ConstExprent(VarType.VARTYPE_CHAR, cn.value); + case 'D': + return new ConstExprent(VarType.VARTYPE_DOUBLE, cn.value); + case 'F': + return new ConstExprent(VarType.VARTYPE_FLOAT, cn.value); + case 'I': + return new ConstExprent(VarType.VARTYPE_INT, cn.value); + case 'J': + return new ConstExprent(VarType.VARTYPE_LONG, cn.value); + case 'S': + return new ConstExprent(VarType.VARTYPE_SHORT, cn.value); + case 'Z': + return new ConstExprent(VarType.VARTYPE_BOOLEAN, cn.value); + case 's': + return new ConstExprent(VarType.VARTYPE_STRING, cn.value); + default: + throw new RuntimeException("invalid element type!"); + } + } + } + catch (IOException ex) { + throw new RuntimeException(ex); + } + } + + + public List<AnnotationExprent> getAnnotations() { + return annotations; + } } diff --git a/src/org/jetbrains/java/decompiler/struct/attr/StructAnnotationParameterAttribute.java b/src/org/jetbrains/java/decompiler/struct/attr/StructAnnotationParameterAttribute.java index dd28aa7..432d3b6 100644 --- a/src/org/jetbrains/java/decompiler/struct/attr/StructAnnotationParameterAttribute.java +++ b/src/org/jetbrains/java/decompiler/struct/attr/StructAnnotationParameterAttribute.java @@ -1,57 +1,58 @@ /* - * Fernflower - The Analytical Java Decompiler - * http://www.reversed-java.com + * Copyright 2000-2014 JetBrains s.r.o. * - * (C) 2008 - 2010, Stiver + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at * - * This software is NEITHER public domain NOR free software - * as per GNU License. See license.txt for more details. + * http://www.apache.org/licenses/LICENSE-2.0 * - * This software is distributed WITHOUT ANY WARRANTY; without - * even the implied warranty of MERCHANTABILITY or FITNESS FOR - * A PARTICULAR PURPOSE. + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. */ - package org.jetbrains.java.decompiler.struct.attr; +import org.jetbrains.java.decompiler.modules.decompiler.exps.AnnotationExprent; +import org.jetbrains.java.decompiler.struct.consts.ConstantPool; + import java.io.ByteArrayInputStream; import java.io.DataInputStream; import java.io.IOException; import java.util.ArrayList; import java.util.List; -import org.jetbrains.java.decompiler.modules.decompiler.exps.AnnotationExprent; -import org.jetbrains.java.decompiler.struct.consts.ConstantPool; - public class StructAnnotationParameterAttribute extends StructGeneralAttribute { - private List<List<AnnotationExprent>> paramAnnotations; - - public void initContent(ConstantPool pool) { - - super.initContent(pool); - - paramAnnotations = new ArrayList<List<AnnotationExprent>>(); - DataInputStream data = new DataInputStream(new ByteArrayInputStream(info)); - - try { - int len = data.readUnsignedByte(); - for(int i=0;i<len;i++) { - List<AnnotationExprent> lst = new ArrayList<AnnotationExprent>(); - int annsize = data.readUnsignedShort(); - - for(int j=0;j<annsize;j++) { - lst.add(StructAnnotationAttribute.parseAnnotation(data, pool)); - } - paramAnnotations.add(lst); - } - } catch(IOException ex) { - throw new RuntimeException(ex); - } - - } - - public List<List<AnnotationExprent>> getParamAnnotations() { - return paramAnnotations; - } + private List<List<AnnotationExprent>> paramAnnotations; + + public void initContent(ConstantPool pool) { + + super.initContent(pool); + + paramAnnotations = new ArrayList<List<AnnotationExprent>>(); + DataInputStream data = new DataInputStream(new ByteArrayInputStream(info)); + + try { + int len = data.readUnsignedByte(); + for (int i = 0; i < len; i++) { + List<AnnotationExprent> lst = new ArrayList<AnnotationExprent>(); + int annsize = data.readUnsignedShort(); + + for (int j = 0; j < annsize; j++) { + lst.add(StructAnnotationAttribute.parseAnnotation(data, pool)); + } + paramAnnotations.add(lst); + } + } + catch (IOException ex) { + throw new RuntimeException(ex); + } + } + + public List<List<AnnotationExprent>> getParamAnnotations() { + return paramAnnotations; + } } diff --git a/src/org/jetbrains/java/decompiler/struct/attr/StructAnnotationTypeAttribute.java b/src/org/jetbrains/java/decompiler/struct/attr/StructAnnotationTypeAttribute.java index 9677ddd..f228ed5 100644 --- a/src/org/jetbrains/java/decompiler/struct/attr/StructAnnotationTypeAttribute.java +++ b/src/org/jetbrains/java/decompiler/struct/attr/StructAnnotationTypeAttribute.java @@ -1,188 +1,203 @@ +/* + * Copyright 2000-2014 JetBrains s.r.o. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ package org.jetbrains.java.decompiler.struct.attr; +import org.jetbrains.java.decompiler.modules.decompiler.exps.AnnotationExprent; +import org.jetbrains.java.decompiler.struct.consts.ConstantPool; + import java.io.ByteArrayInputStream; import java.io.DataInputStream; import java.io.IOException; import java.util.ArrayList; import java.util.List; -import org.jetbrains.java.decompiler.modules.decompiler.exps.AnnotationExprent; -import org.jetbrains.java.decompiler.struct.consts.ConstantPool; - public class StructAnnotationTypeAttribute extends StructGeneralAttribute { - - public static final int ANNOTATION_TARGET_TYPE_GENERIC_CLASS = 0x00; - public static final int ANNOTATION_TARGET_TYPE_GENERIC_METHOD = 0x01; - public static final int ANNOTATION_TARGET_TYPE_EXTENDS_IMPLEMENTS = 0x10; - public static final int ANNOTATION_TARGET_TYPE_GENERIC_CLASS_BOUND = 0x11; - public static final int ANNOTATION_TARGET_TYPE_GENERIC_METHOD_BOUND = 0x12; - public static final int ANNOTATION_TARGET_TYPE_FIELD = 0x13; - public static final int ANNOTATION_TARGET_TYPE_RETURN = 0x14; - public static final int ANNOTATION_TARGET_TYPE_RECEIVER = 0x15; - public static final int ANNOTATION_TARGET_TYPE_FORMAL = 0x16; - public static final int ANNOTATION_TARGET_TYPE_THROWS = 0x17; - public static final int ANNOTATION_TARGET_TYPE_LOCAL_VARIABLE = 0x40; - public static final int ANNOTATION_TARGET_TYPE_RESOURCE_VARIABLE = 0x41; - public static final int ANNOTATION_TARGET_TYPE_EXCEPTION = 0x42; - public static final int ANNOTATION_TARGET_TYPE_INSTANCEOF = 0x43; - public static final int ANNOTATION_TARGET_TYPE_NEW = 0x44; - public static final int ANNOTATION_TARGET_TYPE_DOUBLECOLON_NEW = 0x45; - public static final int ANNOTATION_TARGET_TYPE_DOUBLECOLON_ID = 0x46; - public static final int ANNOTATION_TARGET_TYPE_CAST = 0x47; - public static final int ANNOTATION_TARGET_TYPE_INVOKATION_CONSTRUCTOR = 0x48; - public static final int ANNOTATION_TARGET_TYPE_INVOKATION_METHOD = 0x49; - public static final int ANNOTATION_TARGET_TYPE_GENERIC_DOUBLECOLON_NEW = 0x4A; - public static final int ANNOTATION_TARGET_TYPE_GENERIC_DOUBLECOLON_ID = 0x4B; - - public static final int ANNOTATION_TARGET_UNION_TYPE_PARAMETER = 1; - public static final int ANNOTATION_TARGET_UNION_SUPERTYPE = 2; - public static final int ANNOTATION_TARGET_UNION_TYPE_PARAMETER_BOUND = 3; - public static final int ANNOTATION_TARGET_UNION_EMPTY = 4; - public static final int ANNOTATION_TARGET_UNION_FORMAL_PARAMETER = 5; - public static final int ANNOTATION_TARGET_UNION_THROWS = 6; - public static final int ANNOTATION_TARGET_UNION_LOCALVAR = 7; - public static final int ANNOTATION_TARGET_UNION_CATCH = 8; - public static final int ANNOTATION_TARGET_UNION_OFFSET = 9; - public static final int ANNOTATION_TARGET_UNION_TYPE_ARGUMENT = 10; - - - List<AnnotationLocation> locations = new ArrayList<AnnotationLocation>(); - List<AnnotationExprent> annotations = new ArrayList<AnnotationExprent>(); - - public void initContent(ConstantPool pool) { - - super.initContent(pool); - - DataInputStream data = new DataInputStream(new ByteArrayInputStream(info)); - - try { - - int ann_number = data.readUnsignedByte(); - for(int i = 0; i < ann_number; i++) { - locations.add(parseAnnotationLocation(data)); - annotations.add(StructAnnotationAttribute.parseAnnotation(data, pool)); - } - - } catch(IOException ex) { - throw new RuntimeException(ex); - } - } - - public AnnotationLocation parseAnnotationLocation(DataInputStream data) throws IOException { - - AnnotationLocation ann_location = new AnnotationLocation(); - - // target type - - ann_location.target_type = data.readUnsignedByte(); - - // target union - - switch(ann_location.target_type) { - case ANNOTATION_TARGET_TYPE_GENERIC_CLASS: - case ANNOTATION_TARGET_TYPE_GENERIC_METHOD: - ann_location.target_union = ANNOTATION_TARGET_UNION_TYPE_PARAMETER; - break; - case ANNOTATION_TARGET_TYPE_EXTENDS_IMPLEMENTS: - ann_location.target_union = ANNOTATION_TARGET_UNION_SUPERTYPE; - break; - case ANNOTATION_TARGET_TYPE_GENERIC_CLASS_BOUND: - case ANNOTATION_TARGET_TYPE_GENERIC_METHOD_BOUND: - ann_location.target_union = ANNOTATION_TARGET_UNION_TYPE_PARAMETER_BOUND; - break; - case ANNOTATION_TARGET_TYPE_FIELD: - case ANNOTATION_TARGET_TYPE_RETURN: - case ANNOTATION_TARGET_TYPE_RECEIVER: - ann_location.target_union = ANNOTATION_TARGET_UNION_EMPTY; - break; - case ANNOTATION_TARGET_TYPE_FORMAL: - ann_location.target_union = ANNOTATION_TARGET_UNION_FORMAL_PARAMETER; - break; - case ANNOTATION_TARGET_TYPE_THROWS: - ann_location.target_union = ANNOTATION_TARGET_UNION_THROWS; - break; - case ANNOTATION_TARGET_TYPE_LOCAL_VARIABLE: - case ANNOTATION_TARGET_TYPE_RESOURCE_VARIABLE: - ann_location.target_union = ANNOTATION_TARGET_UNION_LOCALVAR; - break; - case ANNOTATION_TARGET_TYPE_EXCEPTION: - ann_location.target_union = ANNOTATION_TARGET_UNION_CATCH; - break; - case ANNOTATION_TARGET_TYPE_INSTANCEOF: - case ANNOTATION_TARGET_TYPE_NEW: - case ANNOTATION_TARGET_TYPE_DOUBLECOLON_NEW: - case ANNOTATION_TARGET_TYPE_DOUBLECOLON_ID: - ann_location.target_union = ANNOTATION_TARGET_UNION_OFFSET; - break; - case ANNOTATION_TARGET_TYPE_CAST: - case ANNOTATION_TARGET_TYPE_INVOKATION_CONSTRUCTOR: - case ANNOTATION_TARGET_TYPE_INVOKATION_METHOD: - case ANNOTATION_TARGET_TYPE_GENERIC_DOUBLECOLON_NEW: - case ANNOTATION_TARGET_TYPE_GENERIC_DOUBLECOLON_ID: - ann_location.target_union = ANNOTATION_TARGET_UNION_TYPE_ARGUMENT; - break; - default: - throw new RuntimeException("Unknown target type in a type annotation!"); - } - - // target union data - - switch(ann_location.target_union) { - case ANNOTATION_TARGET_UNION_TYPE_PARAMETER: - case ANNOTATION_TARGET_UNION_FORMAL_PARAMETER: - ann_location.data = new int[] {data.readUnsignedByte()}; - break; - case ANNOTATION_TARGET_UNION_SUPERTYPE: - case ANNOTATION_TARGET_UNION_THROWS: - case ANNOTATION_TARGET_UNION_CATCH: - case ANNOTATION_TARGET_UNION_OFFSET: - ann_location.data = new int[] {data.readUnsignedShort()}; - break; - case ANNOTATION_TARGET_UNION_TYPE_PARAMETER_BOUND: - ann_location.data = new int[] {data.readUnsignedByte(), data.readUnsignedByte()}; - break; - case ANNOTATION_TARGET_UNION_EMPTY: - break; - case ANNOTATION_TARGET_UNION_LOCALVAR: - int table_length = data.readUnsignedShort(); - - ann_location.data = new int[table_length * 3 + 1]; - ann_location.data[0] = table_length; - - for(int i = 0; i < table_length; ++i) { - ann_location.data[3 * i + 1] = data.readUnsignedShort(); - ann_location.data[3 * i + 2] = data.readUnsignedShort(); - ann_location.data[3 * i + 3] = data.readUnsignedShort(); - } - break; - case ANNOTATION_TARGET_UNION_TYPE_ARGUMENT: - ann_location.data = new int[] {data.readUnsignedShort(), data.readUnsignedByte()}; - } - - // target path - - int path_length = data.readUnsignedByte(); - - ann_location.target_path_kind = new int[path_length]; - ann_location.target_argument_index = new int[path_length]; - - for(int i = 0; i < path_length; ++i) { - ann_location.target_path_kind[i] = data.readUnsignedByte(); - ann_location.target_argument_index[i] = data.readUnsignedByte(); - } - - return ann_location; - } - - private static class AnnotationLocation { - - public int target_type; - public int target_union; - - public int[] data; - - public int[] target_path_kind; - public int[] target_argument_index; - } + + public static final int ANNOTATION_TARGET_TYPE_GENERIC_CLASS = 0x00; + public static final int ANNOTATION_TARGET_TYPE_GENERIC_METHOD = 0x01; + public static final int ANNOTATION_TARGET_TYPE_EXTENDS_IMPLEMENTS = 0x10; + public static final int ANNOTATION_TARGET_TYPE_GENERIC_CLASS_BOUND = 0x11; + public static final int ANNOTATION_TARGET_TYPE_GENERIC_METHOD_BOUND = 0x12; + public static final int ANNOTATION_TARGET_TYPE_FIELD = 0x13; + public static final int ANNOTATION_TARGET_TYPE_RETURN = 0x14; + public static final int ANNOTATION_TARGET_TYPE_RECEIVER = 0x15; + public static final int ANNOTATION_TARGET_TYPE_FORMAL = 0x16; + public static final int ANNOTATION_TARGET_TYPE_THROWS = 0x17; + public static final int ANNOTATION_TARGET_TYPE_LOCAL_VARIABLE = 0x40; + public static final int ANNOTATION_TARGET_TYPE_RESOURCE_VARIABLE = 0x41; + public static final int ANNOTATION_TARGET_TYPE_EXCEPTION = 0x42; + public static final int ANNOTATION_TARGET_TYPE_INSTANCEOF = 0x43; + public static final int ANNOTATION_TARGET_TYPE_NEW = 0x44; + public static final int ANNOTATION_TARGET_TYPE_DOUBLECOLON_NEW = 0x45; + public static final int ANNOTATION_TARGET_TYPE_DOUBLECOLON_ID = 0x46; + public static final int ANNOTATION_TARGET_TYPE_CAST = 0x47; + public static final int ANNOTATION_TARGET_TYPE_INVOKATION_CONSTRUCTOR = 0x48; + public static final int ANNOTATION_TARGET_TYPE_INVOKATION_METHOD = 0x49; + public static final int ANNOTATION_TARGET_TYPE_GENERIC_DOUBLECOLON_NEW = 0x4A; + public static final int ANNOTATION_TARGET_TYPE_GENERIC_DOUBLECOLON_ID = 0x4B; + + public static final int ANNOTATION_TARGET_UNION_TYPE_PARAMETER = 1; + public static final int ANNOTATION_TARGET_UNION_SUPERTYPE = 2; + public static final int ANNOTATION_TARGET_UNION_TYPE_PARAMETER_BOUND = 3; + public static final int ANNOTATION_TARGET_UNION_EMPTY = 4; + public static final int ANNOTATION_TARGET_UNION_FORMAL_PARAMETER = 5; + public static final int ANNOTATION_TARGET_UNION_THROWS = 6; + public static final int ANNOTATION_TARGET_UNION_LOCALVAR = 7; + public static final int ANNOTATION_TARGET_UNION_CATCH = 8; + public static final int ANNOTATION_TARGET_UNION_OFFSET = 9; + public static final int ANNOTATION_TARGET_UNION_TYPE_ARGUMENT = 10; + + + List<AnnotationLocation> locations = new ArrayList<AnnotationLocation>(); + List<AnnotationExprent> annotations = new ArrayList<AnnotationExprent>(); + + public void initContent(ConstantPool pool) { + + super.initContent(pool); + + DataInputStream data = new DataInputStream(new ByteArrayInputStream(info)); + + try { + + int ann_number = data.readUnsignedByte(); + for (int i = 0; i < ann_number; i++) { + locations.add(parseAnnotationLocation(data)); + annotations.add(StructAnnotationAttribute.parseAnnotation(data, pool)); + } + } + catch (IOException ex) { + throw new RuntimeException(ex); + } + } + + public AnnotationLocation parseAnnotationLocation(DataInputStream data) throws IOException { + + AnnotationLocation ann_location = new AnnotationLocation(); + + // target type + + ann_location.target_type = data.readUnsignedByte(); + + // target union + + switch (ann_location.target_type) { + case ANNOTATION_TARGET_TYPE_GENERIC_CLASS: + case ANNOTATION_TARGET_TYPE_GENERIC_METHOD: + ann_location.target_union = ANNOTATION_TARGET_UNION_TYPE_PARAMETER; + break; + case ANNOTATION_TARGET_TYPE_EXTENDS_IMPLEMENTS: + ann_location.target_union = ANNOTATION_TARGET_UNION_SUPERTYPE; + break; + case ANNOTATION_TARGET_TYPE_GENERIC_CLASS_BOUND: + case ANNOTATION_TARGET_TYPE_GENERIC_METHOD_BOUND: + ann_location.target_union = ANNOTATION_TARGET_UNION_TYPE_PARAMETER_BOUND; + break; + case ANNOTATION_TARGET_TYPE_FIELD: + case ANNOTATION_TARGET_TYPE_RETURN: + case ANNOTATION_TARGET_TYPE_RECEIVER: + ann_location.target_union = ANNOTATION_TARGET_UNION_EMPTY; + break; + case ANNOTATION_TARGET_TYPE_FORMAL: + ann_location.target_union = ANNOTATION_TARGET_UNION_FORMAL_PARAMETER; + break; + case ANNOTATION_TARGET_TYPE_THROWS: + ann_location.target_union = ANNOTATION_TARGET_UNION_THROWS; + break; + case ANNOTATION_TARGET_TYPE_LOCAL_VARIABLE: + case ANNOTATION_TARGET_TYPE_RESOURCE_VARIABLE: + ann_location.target_union = ANNOTATION_TARGET_UNION_LOCALVAR; + break; + case ANNOTATION_TARGET_TYPE_EXCEPTION: + ann_location.target_union = ANNOTATION_TARGET_UNION_CATCH; + break; + case ANNOTATION_TARGET_TYPE_INSTANCEOF: + case ANNOTATION_TARGET_TYPE_NEW: + case ANNOTATION_TARGET_TYPE_DOUBLECOLON_NEW: + case ANNOTATION_TARGET_TYPE_DOUBLECOLON_ID: + ann_location.target_union = ANNOTATION_TARGET_UNION_OFFSET; + break; + case ANNOTATION_TARGET_TYPE_CAST: + case ANNOTATION_TARGET_TYPE_INVOKATION_CONSTRUCTOR: + case ANNOTATION_TARGET_TYPE_INVOKATION_METHOD: + case ANNOTATION_TARGET_TYPE_GENERIC_DOUBLECOLON_NEW: + case ANNOTATION_TARGET_TYPE_GENERIC_DOUBLECOLON_ID: + ann_location.target_union = ANNOTATION_TARGET_UNION_TYPE_ARGUMENT; + break; + default: + throw new RuntimeException("Unknown target type in a type annotation!"); + } + + // target union data + + switch (ann_location.target_union) { + case ANNOTATION_TARGET_UNION_TYPE_PARAMETER: + case ANNOTATION_TARGET_UNION_FORMAL_PARAMETER: + ann_location.data = new int[]{data.readUnsignedByte()}; + break; + case ANNOTATION_TARGET_UNION_SUPERTYPE: + case ANNOTATION_TARGET_UNION_THROWS: + case ANNOTATION_TARGET_UNION_CATCH: + case ANNOTATION_TARGET_UNION_OFFSET: + ann_location.data = new int[]{data.readUnsignedShort()}; + break; + case ANNOTATION_TARGET_UNION_TYPE_PARAMETER_BOUND: + ann_location.data = new int[]{data.readUnsignedByte(), data.readUnsignedByte()}; + break; + case ANNOTATION_TARGET_UNION_EMPTY: + break; + case ANNOTATION_TARGET_UNION_LOCALVAR: + int table_length = data.readUnsignedShort(); + + ann_location.data = new int[table_length * 3 + 1]; + ann_location.data[0] = table_length; + + for (int i = 0; i < table_length; ++i) { + ann_location.data[3 * i + 1] = data.readUnsignedShort(); + ann_location.data[3 * i + 2] = data.readUnsignedShort(); + ann_location.data[3 * i + 3] = data.readUnsignedShort(); + } + break; + case ANNOTATION_TARGET_UNION_TYPE_ARGUMENT: + ann_location.data = new int[]{data.readUnsignedShort(), data.readUnsignedByte()}; + } + + // target path + + int path_length = data.readUnsignedByte(); + + ann_location.target_path_kind = new int[path_length]; + ann_location.target_argument_index = new int[path_length]; + + for (int i = 0; i < path_length; ++i) { + ann_location.target_path_kind[i] = data.readUnsignedByte(); + ann_location.target_argument_index[i] = data.readUnsignedByte(); + } + + return ann_location; + } + + private static class AnnotationLocation { + + public int target_type; + public int target_union; + + public int[] data; + + public int[] target_path_kind; + public int[] target_argument_index; + } } diff --git a/src/org/jetbrains/java/decompiler/struct/attr/StructBootstrapMethodsAttribute.java b/src/org/jetbrains/java/decompiler/struct/attr/StructBootstrapMethodsAttribute.java index ac51027..717bad9 100644 --- a/src/org/jetbrains/java/decompiler/struct/attr/StructBootstrapMethodsAttribute.java +++ b/src/org/jetbrains/java/decompiler/struct/attr/StructBootstrapMethodsAttribute.java @@ -1,62 +1,75 @@ +/* + * Copyright 2000-2014 JetBrains s.r.o. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ package org.jetbrains.java.decompiler.struct.attr; +import org.jetbrains.java.decompiler.struct.consts.ConstantPool; +import org.jetbrains.java.decompiler.struct.consts.LinkConstant; +import org.jetbrains.java.decompiler.struct.consts.PooledConstant; + import java.io.ByteArrayInputStream; import java.io.DataInputStream; import java.io.IOException; import java.util.ArrayList; import java.util.List; -import org.jetbrains.java.decompiler.struct.consts.ConstantPool; -import org.jetbrains.java.decompiler.struct.consts.LinkConstant; -import org.jetbrains.java.decompiler.struct.consts.PooledConstant; - public class StructBootstrapMethodsAttribute extends StructGeneralAttribute { - - private List<LinkConstant> method_refs = new ArrayList<LinkConstant>(); - private List<List<PooledConstant>> method_arguments = new ArrayList<List<PooledConstant>>(); - - public void initContent(ConstantPool pool) { - - name = ATTRIBUTE_BOOTSTRAP_METHODS; - - try { - - DataInputStream data = new DataInputStream(new ByteArrayInputStream(info, 0, info.length)); - - int method_number = data.readUnsignedShort(); - - for(int i = 0; i < method_number; ++i) { - int bootstrap_method_ref = data.readUnsignedShort(); - int num_bootstrap_arguments = data.readUnsignedShort(); - - List<PooledConstant> list_arguments = new ArrayList<PooledConstant>(); - - for(int j = 0; j < num_bootstrap_arguments; ++j) { - int bootstrap_argument_ref = data.readUnsignedShort(); - - list_arguments.add(pool.getConstant(bootstrap_argument_ref)); - } - - method_refs.add(pool.getLinkConstant(bootstrap_method_ref)); - method_arguments.add(list_arguments); - } - - } catch(IOException ex) { - throw new RuntimeException(ex); - } - - } - - public int getMethodsNumber() { - return method_refs.size(); - } - - public LinkConstant getMethodReference(int index) { - return method_refs.get(index); - } - - public List<PooledConstant> getMethodArguments(int index) { - return method_arguments.get(index); - } - + + private List<LinkConstant> method_refs = new ArrayList<LinkConstant>(); + private List<List<PooledConstant>> method_arguments = new ArrayList<List<PooledConstant>>(); + + public void initContent(ConstantPool pool) { + + name = ATTRIBUTE_BOOTSTRAP_METHODS; + + try { + + DataInputStream data = new DataInputStream(new ByteArrayInputStream(info, 0, info.length)); + + int method_number = data.readUnsignedShort(); + + for (int i = 0; i < method_number; ++i) { + int bootstrap_method_ref = data.readUnsignedShort(); + int num_bootstrap_arguments = data.readUnsignedShort(); + + List<PooledConstant> list_arguments = new ArrayList<PooledConstant>(); + + for (int j = 0; j < num_bootstrap_arguments; ++j) { + int bootstrap_argument_ref = data.readUnsignedShort(); + + list_arguments.add(pool.getConstant(bootstrap_argument_ref)); + } + + method_refs.add(pool.getLinkConstant(bootstrap_method_ref)); + method_arguments.add(list_arguments); + } + } + catch (IOException ex) { + throw new RuntimeException(ex); + } + } + + public int getMethodsNumber() { + return method_refs.size(); + } + + public LinkConstant getMethodReference(int index) { + return method_refs.get(index); + } + + public List<PooledConstant> getMethodArguments(int index) { + return method_arguments.get(index); + } } diff --git a/src/org/jetbrains/java/decompiler/struct/attr/StructConstantValueAttribute.java b/src/org/jetbrains/java/decompiler/struct/attr/StructConstantValueAttribute.java index f186767..ae3bd1d 100644 --- a/src/org/jetbrains/java/decompiler/struct/attr/StructConstantValueAttribute.java +++ b/src/org/jetbrains/java/decompiler/struct/attr/StructConstantValueAttribute.java @@ -1,34 +1,33 @@ /* - * Fernflower - The Analytical Java Decompiler - * http://www.reversed-java.com + * Copyright 2000-2014 JetBrains s.r.o. * - * (C) 2008 - 2010, Stiver + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at * - * This software is NEITHER public domain NOR free software - * as per GNU License. See license.txt for more details. + * http://www.apache.org/licenses/LICENSE-2.0 * - * This software is distributed WITHOUT ANY WARRANTY; without - * even the implied warranty of MERCHANTABILITY or FITNESS FOR - * A PARTICULAR PURPOSE. + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. */ - package org.jetbrains.java.decompiler.struct.attr; import org.jetbrains.java.decompiler.struct.consts.ConstantPool; public class StructConstantValueAttribute extends StructGeneralAttribute { - private int index; + private int index; + + public void initContent(ConstantPool pool) { - public void initContent(ConstantPool pool) { + name = ATTRIBUTE_CONSTANT_VALUE; + index = ((info[0] & 0xFF) << 8) | (info[1] & 0xFF); + } - name = ATTRIBUTE_CONSTANT_VALUE; - index = ((info[0] & 0xFF)<<8) | (info[1] & 0xFF); - } - - public int getIndex() { - return index; - } - - + public int getIndex() { + return index; + } } diff --git a/src/org/jetbrains/java/decompiler/struct/attr/StructEnclosingMethodAttribute.java b/src/org/jetbrains/java/decompiler/struct/attr/StructEnclosingMethodAttribute.java index 61bb886..ebf9407 100644 --- a/src/org/jetbrains/java/decompiler/struct/attr/StructEnclosingMethodAttribute.java +++ b/src/org/jetbrains/java/decompiler/struct/attr/StructEnclosingMethodAttribute.java @@ -1,17 +1,18 @@ /* - * Fernflower - The Analytical Java Decompiler - * http://www.reversed-java.com + * Copyright 2000-2014 JetBrains s.r.o. * - * (C) 2008 - 2010, Stiver + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at * - * This software is NEITHER public domain NOR free software - * as per GNU License. See license.txt for more details. + * http://www.apache.org/licenses/LICENSE-2.0 * - * This software is distributed WITHOUT ANY WARRANTY; without - * even the implied warranty of MERCHANTABILITY or FITNESS FOR - * A PARTICULAR PURPOSE. + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. */ - package org.jetbrains.java.decompiler.struct.attr; import org.jetbrains.java.decompiler.struct.consts.ConstantPool; @@ -19,39 +20,37 @@ import org.jetbrains.java.decompiler.struct.consts.LinkConstant; public class StructEnclosingMethodAttribute extends StructGeneralAttribute { - private String classname; - - private String mtname; - - private String methodDescriptor; - - public void initContent(ConstantPool pool) { - - name = ATTRIBUTE_ENCLOSING_METHOD; - - int clindex = (((info[0] & 0xFF)<<8) | (info[1] & 0xFF)); - int mtindex = (((info[2] & 0xFF)<<8) | (info[3] & 0xFF)); - - classname = pool.getPrimitiveConstant(clindex).getString(); - if(mtindex != 0) { - LinkConstant lk = pool.getLinkConstant(mtindex); - - mtname = lk.elementname; - methodDescriptor = lk.descriptor; - } - } - - public String getClassname() { - return classname; - } - - public String getMethodDescriptor() { - return methodDescriptor; - } - - public String getMethodName() { - return mtname; - } - - + private String classname; + + private String mtname; + + private String methodDescriptor; + + public void initContent(ConstantPool pool) { + + name = ATTRIBUTE_ENCLOSING_METHOD; + + int clindex = (((info[0] & 0xFF) << 8) | (info[1] & 0xFF)); + int mtindex = (((info[2] & 0xFF) << 8) | (info[3] & 0xFF)); + + classname = pool.getPrimitiveConstant(clindex).getString(); + if (mtindex != 0) { + LinkConstant lk = pool.getLinkConstant(mtindex); + + mtname = lk.elementname; + methodDescriptor = lk.descriptor; + } + } + + public String getClassname() { + return classname; + } + + public String getMethodDescriptor() { + return methodDescriptor; + } + + public String getMethodName() { + return mtname; + } } diff --git a/src/org/jetbrains/java/decompiler/struct/attr/StructExceptionsAttribute.java b/src/org/jetbrains/java/decompiler/struct/attr/StructExceptionsAttribute.java index 4d6bd4c..930db78 100644 --- a/src/org/jetbrains/java/decompiler/struct/attr/StructExceptionsAttribute.java +++ b/src/org/jetbrains/java/decompiler/struct/attr/StructExceptionsAttribute.java @@ -1,78 +1,76 @@ /* - * Fernflower - The Analytical Java Decompiler - * http://www.reversed-java.com + * Copyright 2000-2014 JetBrains s.r.o. * - * (C) 2008 - 2010, Stiver + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at * - * This software is NEITHER public domain NOR free software - * as per GNU License. See license.txt for more details. + * http://www.apache.org/licenses/LICENSE-2.0 * - * This software is distributed WITHOUT ANY WARRANTY; without - * even the implied warranty of MERCHANTABILITY or FITNESS FOR - * A PARTICULAR PURPOSE. + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. */ - package org.jetbrains.java.decompiler.struct.attr; +import org.jetbrains.java.decompiler.struct.consts.ConstantPool; + import java.io.ByteArrayOutputStream; import java.io.DataOutputStream; import java.io.IOException; import java.util.ArrayList; import java.util.List; -import org.jetbrains.java.decompiler.struct.consts.ConstantPool; - public class StructExceptionsAttribute extends StructGeneralAttribute { - private List<Integer> throwsExceptions = new ArrayList<Integer>(); - - public void initContent(ConstantPool pool) { - - name = ATTRIBUTE_EXCEPTIONS; - - int length = 2+(((info[0] & 0xFF)<<8) | (info[1] & 0xFF))*2; - for(int i=2;i<length;i+=2) { - int index = ((info[i] & 0xFF)<<8) | (info[i+1] & 0xFF); - throwsExceptions.add(index); - } - - } - - public void writeToStream(DataOutputStream out) throws IOException { - - out.writeShort(attribute_name_index); - - ByteArrayOutputStream codeout = new ByteArrayOutputStream(); - DataOutputStream dataout = new DataOutputStream(codeout); - - int len = throwsExceptions.size(); - dataout.writeShort(len); - - if(len>0) { - info = new byte[len*2]; - for(int i=0,j=0;i<len;i++,j+=2) { - int index = ((Integer)throwsExceptions.get(i)).intValue(); - info[j] = (byte)(index >> 8); - info[j+1] = (byte)(index & 0xFF); - } - dataout.write(info); - } - - out.writeInt(codeout.size()); - out.write(codeout.toByteArray()); - } - - public String getExcClassname(int index, ConstantPool pool) { - return pool.getPrimitiveConstant(((Integer)throwsExceptions.get(index)).intValue()).getString(); - } - - public List<Integer> getThrowsExceptions() { - return throwsExceptions; - } - - public void setThrowsExceptions(List<Integer> throwsExceptions) { - this.throwsExceptions = throwsExceptions; - } - - + private List<Integer> throwsExceptions = new ArrayList<Integer>(); + + public void initContent(ConstantPool pool) { + + name = ATTRIBUTE_EXCEPTIONS; + + int length = 2 + (((info[0] & 0xFF) << 8) | (info[1] & 0xFF)) * 2; + for (int i = 2; i < length; i += 2) { + int index = ((info[i] & 0xFF) << 8) | (info[i + 1] & 0xFF); + throwsExceptions.add(index); + } + } + + public void writeToStream(DataOutputStream out) throws IOException { + + out.writeShort(attribute_name_index); + + ByteArrayOutputStream codeout = new ByteArrayOutputStream(); + DataOutputStream dataout = new DataOutputStream(codeout); + + int len = throwsExceptions.size(); + dataout.writeShort(len); + + if (len > 0) { + info = new byte[len * 2]; + for (int i = 0, j = 0; i < len; i++, j += 2) { + int index = ((Integer)throwsExceptions.get(i)).intValue(); + info[j] = (byte)(index >> 8); + info[j + 1] = (byte)(index & 0xFF); + } + dataout.write(info); + } + + out.writeInt(codeout.size()); + out.write(codeout.toByteArray()); + } + + public String getExcClassname(int index, ConstantPool pool) { + return pool.getPrimitiveConstant(((Integer)throwsExceptions.get(index)).intValue()).getString(); + } + + public List<Integer> getThrowsExceptions() { + return throwsExceptions; + } + + public void setThrowsExceptions(List<Integer> throwsExceptions) { + this.throwsExceptions = throwsExceptions; + } } diff --git a/src/org/jetbrains/java/decompiler/struct/attr/StructGeneralAttribute.java b/src/org/jetbrains/java/decompiler/struct/attr/StructGeneralAttribute.java index 2648b3c..bd0596a 100644 --- a/src/org/jetbrains/java/decompiler/struct/attr/StructGeneralAttribute.java +++ b/src/org/jetbrains/java/decompiler/struct/attr/StructGeneralAttribute.java @@ -1,24 +1,25 @@ /* - * Fernflower - The Analytical Java Decompiler - * http://www.reversed-java.com + * Copyright 2000-2014 JetBrains s.r.o. * - * (C) 2008 - 2010, Stiver + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at * - * This software is NEITHER public domain NOR free software - * as per GNU License. See license.txt for more details. + * http://www.apache.org/licenses/LICENSE-2.0 * - * This software is distributed WITHOUT ANY WARRANTY; without - * even the implied warranty of MERCHANTABILITY or FITNESS FOR - * A PARTICULAR PURPOSE. + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. */ - package org.jetbrains.java.decompiler.struct.attr; +import org.jetbrains.java.decompiler.struct.consts.ConstantPool; + import java.io.DataOutputStream; import java.io.IOException; -import org.jetbrains.java.decompiler.struct.consts.ConstantPool; - /* attribute_info { u2 attribute_name_index; @@ -29,117 +30,128 @@ import org.jetbrains.java.decompiler.struct.consts.ConstantPool; public class StructGeneralAttribute { - public static final String ATTRIBUTE_CODE = "Code"; - public static final String ATTRIBUTE_INNER_CLASSES = "InnerClasses"; - public static final String ATTRIBUTE_SIGNATURE = "Signature"; - public static final String ATTRIBUTE_ANNOTATION_DEFAULT = "AnnotationDefault"; - public static final String ATTRIBUTE_EXCEPTIONS = "Exceptions"; - public static final String ATTRIBUTE_ENCLOSING_METHOD = "EnclosingMethod"; - public static final String ATTRIBUTE_RUNTIME_VISIBLE_ANNOTATIONS = "RuntimeVisibleAnnotations"; - public static final String ATTRIBUTE_RUNTIME_INVISIBLE_ANNOTATIONS = "RuntimeInvisibleAnnotations"; - public static final String ATTRIBUTE_RUNTIME_VISIBLE_PARAMETER_ANNOTATIONS = "RuntimeVisibleParameterAnnotations"; - public static final String ATTRIBUTE_RUNTIME_INVISIBLE_PARAMETER_ANNOTATIONS = "RuntimeInvisibleParameterAnnotations"; - public static final String ATTRIBUTE_RUNTIME_VISIBLE_TYPE_ANNOTATIONS = "RuntimeVisibleTypeAnnotations"; - public static final String ATTRIBUTE_RUNTIME_INVISIBLE_TYPE_ANNOTATIONS = "RuntimeInvisibleTypeAnnotations"; - public static final String ATTRIBUTE_LOCAL_VARIABLE_TABLE = "LocalVariableTable"; - public static final String ATTRIBUTE_CONSTANT_VALUE = "ConstantValue"; - public static final String ATTRIBUTE_BOOTSTRAP_METHODS = "BootstrapMethods"; + public static final String ATTRIBUTE_CODE = "Code"; + public static final String ATTRIBUTE_INNER_CLASSES = "InnerClasses"; + public static final String ATTRIBUTE_SIGNATURE = "Signature"; + public static final String ATTRIBUTE_ANNOTATION_DEFAULT = "AnnotationDefault"; + public static final String ATTRIBUTE_EXCEPTIONS = "Exceptions"; + public static final String ATTRIBUTE_ENCLOSING_METHOD = "EnclosingMethod"; + public static final String ATTRIBUTE_RUNTIME_VISIBLE_ANNOTATIONS = "RuntimeVisibleAnnotations"; + public static final String ATTRIBUTE_RUNTIME_INVISIBLE_ANNOTATIONS = "RuntimeInvisibleAnnotations"; + public static final String ATTRIBUTE_RUNTIME_VISIBLE_PARAMETER_ANNOTATIONS = "RuntimeVisibleParameterAnnotations"; + public static final String ATTRIBUTE_RUNTIME_INVISIBLE_PARAMETER_ANNOTATIONS = "RuntimeInvisibleParameterAnnotations"; + public static final String ATTRIBUTE_RUNTIME_VISIBLE_TYPE_ANNOTATIONS = "RuntimeVisibleTypeAnnotations"; + public static final String ATTRIBUTE_RUNTIME_INVISIBLE_TYPE_ANNOTATIONS = "RuntimeInvisibleTypeAnnotations"; + public static final String ATTRIBUTE_LOCAL_VARIABLE_TABLE = "LocalVariableTable"; + public static final String ATTRIBUTE_CONSTANT_VALUE = "ConstantValue"; + public static final String ATTRIBUTE_BOOTSTRAP_METHODS = "BootstrapMethods"; public static final String ATTRIBUTE_SYNTHETIC = "Synthetic"; public static final String ATTRIBUTE_DEPRECATED = "Deprecated"; - // ***************************************************************************** - // private fields - // ***************************************************************************** - - protected int attribute_name_index; - - protected byte[] info; - - protected String name; - - // ***************************************************************************** - // public methods - // ***************************************************************************** - - public void writeToStream(DataOutputStream out) throws IOException { - out.writeShort(attribute_name_index); - out.writeInt(info.length); - if(info.length>0) { - out.write(info); - } - } - - public void initContent(ConstantPool pool) { - name = pool.getPrimitiveConstant(attribute_name_index).getString(); - } - - public static StructGeneralAttribute getMatchingAttributeInstance(int nameindex, String attrname) { - - StructGeneralAttribute attr; - - if(ATTRIBUTE_INNER_CLASSES.equals(attrname)) { - attr = new StructInnerClassesAttribute(); - } else if(ATTRIBUTE_CONSTANT_VALUE.equals(attrname)) { - attr = new StructConstantValueAttribute(); - } else if(ATTRIBUTE_SIGNATURE.equals(attrname)) { - attr = new StructGenericSignatureAttribute(); - } else if(ATTRIBUTE_ANNOTATION_DEFAULT.equals(attrname)) { - attr = new StructAnnDefaultAttribute(); - } else if(ATTRIBUTE_EXCEPTIONS.equals(attrname)) { - attr = new StructExceptionsAttribute(); - } else if(ATTRIBUTE_ENCLOSING_METHOD.equals(attrname)) { - attr = new StructEnclosingMethodAttribute(); - } else if(ATTRIBUTE_RUNTIME_VISIBLE_ANNOTATIONS.equals(attrname) || - ATTRIBUTE_RUNTIME_INVISIBLE_ANNOTATIONS.equals(attrname)) { - attr = new StructAnnotationAttribute(); - } else if(ATTRIBUTE_RUNTIME_VISIBLE_PARAMETER_ANNOTATIONS.equals(attrname) || - ATTRIBUTE_RUNTIME_INVISIBLE_PARAMETER_ANNOTATIONS.equals(attrname)) { - attr = new StructAnnotationParameterAttribute(); - } else if(ATTRIBUTE_RUNTIME_VISIBLE_TYPE_ANNOTATIONS.equals(attrname) || - ATTRIBUTE_RUNTIME_INVISIBLE_TYPE_ANNOTATIONS.equals(attrname)) { - attr = new StructAnnotationTypeAttribute(); - } else if(ATTRIBUTE_LOCAL_VARIABLE_TABLE.equals(attrname)) { - attr = new StructLocalVariableTableAttribute(); - } else if(ATTRIBUTE_BOOTSTRAP_METHODS.equals(attrname)) { - attr = new StructBootstrapMethodsAttribute(); - } else if(ATTRIBUTE_SYNTHETIC.equals(attrname) || ATTRIBUTE_DEPRECATED.equals(attrname)) { - attr = new StructGeneralAttribute(); - } else { - // unsupported attribute - return null; - } - - attr.setAttribute_name_index(nameindex); - return attr; - } - - // ***************************************************************************** - // getter and setter methods - // ***************************************************************************** - - public byte[] getInfo() { - return info; - } - - public void setInfo(byte[] info) { - this.info = info; - } - - public String getName() { - return name; - } - - public void setName(String name) { - this.name = name; - } - - public int getAttribute_name_index() { - return attribute_name_index; - } - - public void setAttribute_name_index(int attribute_name_index) { - this.attribute_name_index = attribute_name_index; - } - + // ***************************************************************************** + // private fields + // ***************************************************************************** + + protected int attribute_name_index; + + protected byte[] info; + + protected String name; + + // ***************************************************************************** + // public methods + // ***************************************************************************** + + public void writeToStream(DataOutputStream out) throws IOException { + out.writeShort(attribute_name_index); + out.writeInt(info.length); + if (info.length > 0) { + out.write(info); + } + } + + public void initContent(ConstantPool pool) { + name = pool.getPrimitiveConstant(attribute_name_index).getString(); + } + + public static StructGeneralAttribute getMatchingAttributeInstance(int nameindex, String attrname) { + + StructGeneralAttribute attr; + + if (ATTRIBUTE_INNER_CLASSES.equals(attrname)) { + attr = new StructInnerClassesAttribute(); + } + else if (ATTRIBUTE_CONSTANT_VALUE.equals(attrname)) { + attr = new StructConstantValueAttribute(); + } + else if (ATTRIBUTE_SIGNATURE.equals(attrname)) { + attr = new StructGenericSignatureAttribute(); + } + else if (ATTRIBUTE_ANNOTATION_DEFAULT.equals(attrname)) { + attr = new StructAnnDefaultAttribute(); + } + else if (ATTRIBUTE_EXCEPTIONS.equals(attrname)) { + attr = new StructExceptionsAttribute(); + } + else if (ATTRIBUTE_ENCLOSING_METHOD.equals(attrname)) { + attr = new StructEnclosingMethodAttribute(); + } + else if (ATTRIBUTE_RUNTIME_VISIBLE_ANNOTATIONS.equals(attrname) || + ATTRIBUTE_RUNTIME_INVISIBLE_ANNOTATIONS.equals(attrname)) { + attr = new StructAnnotationAttribute(); + } + else if (ATTRIBUTE_RUNTIME_VISIBLE_PARAMETER_ANNOTATIONS.equals(attrname) || + ATTRIBUTE_RUNTIME_INVISIBLE_PARAMETER_ANNOTATIONS.equals(attrname)) { + attr = new StructAnnotationParameterAttribute(); + } + else if (ATTRIBUTE_RUNTIME_VISIBLE_TYPE_ANNOTATIONS.equals(attrname) || + ATTRIBUTE_RUNTIME_INVISIBLE_TYPE_ANNOTATIONS.equals(attrname)) { + attr = new StructAnnotationTypeAttribute(); + } + else if (ATTRIBUTE_LOCAL_VARIABLE_TABLE.equals(attrname)) { + attr = new StructLocalVariableTableAttribute(); + } + else if (ATTRIBUTE_BOOTSTRAP_METHODS.equals(attrname)) { + attr = new StructBootstrapMethodsAttribute(); + } + else if (ATTRIBUTE_SYNTHETIC.equals(attrname) || ATTRIBUTE_DEPRECATED.equals(attrname)) { + attr = new StructGeneralAttribute(); + } + else { + // unsupported attribute + return null; + } + + attr.setAttribute_name_index(nameindex); + return attr; + } + + // ***************************************************************************** + // getter and setter methods + // ***************************************************************************** + + public byte[] getInfo() { + return info; + } + + public void setInfo(byte[] info) { + this.info = info; + } + + public String getName() { + return name; + } + + public void setName(String name) { + this.name = name; + } + + public int getAttribute_name_index() { + return attribute_name_index; + } + + public void setAttribute_name_index(int attribute_name_index) { + this.attribute_name_index = attribute_name_index; + } } diff --git a/src/org/jetbrains/java/decompiler/struct/attr/StructGenericSignatureAttribute.java b/src/org/jetbrains/java/decompiler/struct/attr/StructGenericSignatureAttribute.java index 11206e0..6f2224c 100644 --- a/src/org/jetbrains/java/decompiler/struct/attr/StructGenericSignatureAttribute.java +++ b/src/org/jetbrains/java/decompiler/struct/attr/StructGenericSignatureAttribute.java @@ -1,34 +1,33 @@ /* - * Fernflower - The Analytical Java Decompiler - * http://www.reversed-java.com + * Copyright 2000-2014 JetBrains s.r.o. * - * (C) 2008 - 2010, Stiver + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at * - * This software is NEITHER public domain NOR free software - * as per GNU License. See license.txt for more details. + * http://www.apache.org/licenses/LICENSE-2.0 * - * This software is distributed WITHOUT ANY WARRANTY; without - * even the implied warranty of MERCHANTABILITY or FITNESS FOR - * A PARTICULAR PURPOSE. + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. */ - package org.jetbrains.java.decompiler.struct.attr; import org.jetbrains.java.decompiler.struct.consts.ConstantPool; public class StructGenericSignatureAttribute extends StructGeneralAttribute { - private String signature; + private String signature; + + public void initContent(ConstantPool pool) { - public void initContent(ConstantPool pool) { + name = ATTRIBUTE_SIGNATURE; + signature = pool.getPrimitiveConstant(((info[0] & 0xFF) << 8) | (info[1] & 0xFF)).getString(); + } - name = ATTRIBUTE_SIGNATURE; - signature = pool.getPrimitiveConstant(((info[0] & 0xFF)<<8) | (info[1] & 0xFF)).getString(); - } - - public String getSignature() { - return signature; - } - - + public String getSignature() { + return signature; + } } diff --git a/src/org/jetbrains/java/decompiler/struct/attr/StructInnerClassesAttribute.java b/src/org/jetbrains/java/decompiler/struct/attr/StructInnerClassesAttribute.java index 794da15..14ecd36 100644 --- a/src/org/jetbrains/java/decompiler/struct/attr/StructInnerClassesAttribute.java +++ b/src/org/jetbrains/java/decompiler/struct/attr/StructInnerClassesAttribute.java @@ -1,73 +1,72 @@ /* - * Fernflower - The Analytical Java Decompiler - * http://www.reversed-java.com + * Copyright 2000-2014 JetBrains s.r.o. * - * (C) 2008 - 2010, Stiver + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at * - * This software is NEITHER public domain NOR free software - * as per GNU License. See license.txt for more details. + * http://www.apache.org/licenses/LICENSE-2.0 * - * This software is distributed WITHOUT ANY WARRANTY; without - * even the implied warranty of MERCHANTABILITY or FITNESS FOR - * A PARTICULAR PURPOSE. + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. */ - package org.jetbrains.java.decompiler.struct.attr; +import org.jetbrains.java.decompiler.struct.consts.ConstantPool; + import java.util.ArrayList; import java.util.List; -import org.jetbrains.java.decompiler.struct.consts.ConstantPool; - public class StructInnerClassesAttribute extends StructGeneralAttribute { - private List<int[]> classentries = new ArrayList<int[]>(); - - private List<String[]> stringentries = new ArrayList<String[]>(); - - public void initContent(ConstantPool pool) { - - name = ATTRIBUTE_INNER_CLASSES; - - int length = 2+(((info[0] & 0xFF)<<8) | (info[1] & 0xFF))*8; - int i=2; - - while(i<length) { - - int[] arr = new int[4]; - for(int j=0;j<4;j++) { - arr[j] = ((info[i] & 0xFF)<<8) | (info[i+1] & 0xFF); - i+=2; - } - - classentries.add(arr); - } - - for(int[] entry: classentries) { - - String[] arr = new String[3]; - // inner name - arr[0] = pool.getPrimitiveConstant(entry[0]).getString(); - //enclosing class - if(entry[1] != 0) { - arr[1] = pool.getPrimitiveConstant(entry[1]).getString(); - } - // original simple name - if(entry[2]!=0) { - arr[2] = pool.getPrimitiveConstant(entry[2]).getString(); - } - - stringentries.add(arr); - } - - } - - public List<int[]> getClassentries() { - return classentries; - } - - public List<String[]> getStringentries() { - return stringentries; - } + private List<int[]> classentries = new ArrayList<int[]>(); + + private List<String[]> stringentries = new ArrayList<String[]>(); + + public void initContent(ConstantPool pool) { + + name = ATTRIBUTE_INNER_CLASSES; + + int length = 2 + (((info[0] & 0xFF) << 8) | (info[1] & 0xFF)) * 8; + int i = 2; + + while (i < length) { + + int[] arr = new int[4]; + for (int j = 0; j < 4; j++) { + arr[j] = ((info[i] & 0xFF) << 8) | (info[i + 1] & 0xFF); + i += 2; + } + + classentries.add(arr); + } + + for (int[] entry : classentries) { + + String[] arr = new String[3]; + // inner name + arr[0] = pool.getPrimitiveConstant(entry[0]).getString(); + //enclosing class + if (entry[1] != 0) { + arr[1] = pool.getPrimitiveConstant(entry[1]).getString(); + } + // original simple name + if (entry[2] != 0) { + arr[2] = pool.getPrimitiveConstant(entry[2]).getString(); + } + + stringentries.add(arr); + } + } + + public List<int[]> getClassentries() { + return classentries; + } + public List<String[]> getStringentries() { + return stringentries; + } } diff --git a/src/org/jetbrains/java/decompiler/struct/attr/StructLocalVariableTableAttribute.java b/src/org/jetbrains/java/decompiler/struct/attr/StructLocalVariableTableAttribute.java index 119d1ff..0cf2a89 100644 --- a/src/org/jetbrains/java/decompiler/struct/attr/StructLocalVariableTableAttribute.java +++ b/src/org/jetbrains/java/decompiler/struct/attr/StructLocalVariableTableAttribute.java @@ -1,47 +1,48 @@ /* - * Fernflower - The Analytical Java Decompiler - * http://www.reversed-java.com + * Copyright 2000-2014 JetBrains s.r.o. * - * (C) 2008 - 2010, Stiver + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at * - * This software is NEITHER public domain NOR free software - * as per GNU License. See license.txt for more details. + * http://www.apache.org/licenses/LICENSE-2.0 * - * This software is distributed WITHOUT ANY WARRANTY; without - * even the implied warranty of MERCHANTABILITY or FITNESS FOR - * A PARTICULAR PURPOSE. + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. */ - package org.jetbrains.java.decompiler.struct.attr; -import java.util.HashMap; - import org.jetbrains.java.decompiler.struct.consts.ConstantPool; +import java.util.HashMap; + public class StructLocalVariableTableAttribute extends StructGeneralAttribute { - private HashMap<Integer, String> mapVarNames = new HashMap<Integer, String>(); - - public void initContent(ConstantPool pool) { - - name = ATTRIBUTE_LOCAL_VARIABLE_TABLE; - - int len = ((info[0] & 0xFF)<<8) | (info[1] & 0xFF); - - int ind = 6; - for(int i=0;i<len;i++, ind+=10) { - int nindex = ((info[ind] & 0xFF)<<8) | (info[ind+1] & 0xFF); - int vindex = ((info[ind+4] & 0xFF)<<8) | (info[ind+5] & 0xFF); - - mapVarNames.put(vindex, pool.getPrimitiveConstant(nindex).getString()); - } - } - - public void addLocalVariableTable(StructLocalVariableTableAttribute attr) { - mapVarNames.putAll(attr.getMapVarNames()); - } - - public HashMap<Integer, String> getMapVarNames() { - return mapVarNames; - } + private HashMap<Integer, String> mapVarNames = new HashMap<Integer, String>(); + + public void initContent(ConstantPool pool) { + + name = ATTRIBUTE_LOCAL_VARIABLE_TABLE; + + int len = ((info[0] & 0xFF) << 8) | (info[1] & 0xFF); + + int ind = 6; + for (int i = 0; i < len; i++, ind += 10) { + int nindex = ((info[ind] & 0xFF) << 8) | (info[ind + 1] & 0xFF); + int vindex = ((info[ind + 4] & 0xFF) << 8) | (info[ind + 5] & 0xFF); + + mapVarNames.put(vindex, pool.getPrimitiveConstant(nindex).getString()); + } + } + + public void addLocalVariableTable(StructLocalVariableTableAttribute attr) { + mapVarNames.putAll(attr.getMapVarNames()); + } + + public HashMap<Integer, String> getMapVarNames() { + return mapVarNames; + } } diff --git a/src/org/jetbrains/java/decompiler/struct/consts/ConstantPool.java b/src/org/jetbrains/java/decompiler/struct/consts/ConstantPool.java index 8951cd1..5a593af 100644 --- a/src/org/jetbrains/java/decompiler/struct/consts/ConstantPool.java +++ b/src/org/jetbrains/java/decompiler/struct/consts/ConstantPool.java @@ -1,26 +1,20 @@ /* - * Fernflower - The Analytical Java Decompiler - * http://www.reversed-java.com + * Copyright 2000-2014 JetBrains s.r.o. * - * (C) 2008 - 2010, Stiver + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at * - * This software is NEITHER public domain NOR free software - * as per GNU License. See license.txt for more details. + * http://www.apache.org/licenses/LICENSE-2.0 * - * This software is distributed WITHOUT ANY WARRANTY; without - * even the implied warranty of MERCHANTABILITY or FITNESS FOR - * A PARTICULAR PURPOSE. + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. */ - package org.jetbrains.java.decompiler.struct.consts; -import java.io.DataInputStream; -import java.io.DataOutputStream; -import java.io.FileNotFoundException; -import java.io.IOException; -import java.util.ArrayList; -import java.util.List; - import org.jetbrains.java.decompiler.code.CodeConstants; import org.jetbrains.java.decompiler.main.DecompilerContext; import org.jetbrains.java.decompiler.modules.renamer.PoolInterceptor; @@ -28,289 +22,297 @@ import org.jetbrains.java.decompiler.struct.gen.FieldDescriptor; import org.jetbrains.java.decompiler.struct.gen.MethodDescriptor; import org.jetbrains.java.decompiler.struct.gen.VarType; +import java.io.DataInputStream; +import java.io.DataOutputStream; +import java.io.FileNotFoundException; +import java.io.IOException; +import java.util.ArrayList; +import java.util.List; + public class ConstantPool { - - public static final int FIELD = 1; - - public static final int METHOD = 2; - - // ***************************************************************************** - // private fields - // ***************************************************************************** - - private List<PooledConstant> pool = new ArrayList<PooledConstant>(); - - private PoolInterceptor interceptor; - - // ***************************************************************************** - // constructors - // ***************************************************************************** - - public ConstantPool(DataInputStream in) throws IOException { - - int size = in.readUnsignedShort(); - - int[] pass = new int[size]; - - // first dummy constant - pool.add(null); - - // first pass: read the elements - for (int i = 1; i < size; i++) { - - byte tag = (byte)in.readUnsignedByte(); - - switch (tag) { - case CodeConstants.CONSTANT_Utf8: - pool.add(new PrimitiveConstant(CodeConstants.CONSTANT_Utf8, in.readUTF())); - break; - case CodeConstants.CONSTANT_Integer: - pool.add(new PrimitiveConstant(CodeConstants.CONSTANT_Integer, new Integer(in.readInt()))); - break; - case CodeConstants.CONSTANT_Float: - pool.add(new PrimitiveConstant(CodeConstants.CONSTANT_Float, new Float(in.readFloat()))); - break; - case CodeConstants.CONSTANT_Long: - pool.add(new PrimitiveConstant(CodeConstants.CONSTANT_Long, new Long(in.readLong()))); - pool.add(null); - i++; - break; - case CodeConstants.CONSTANT_Double: - pool.add(new PrimitiveConstant(CodeConstants.CONSTANT_Double, new Double(in.readDouble()))); - pool.add(null); - i++; - break; - case CodeConstants.CONSTANT_Class: - case CodeConstants.CONSTANT_String: - case CodeConstants.CONSTANT_MethodType: - pool.add(new PrimitiveConstant(tag, in.readUnsignedShort())); - pass[i] = 1; - break; - case CodeConstants.CONSTANT_Fieldref: - case CodeConstants.CONSTANT_Methodref: - case CodeConstants.CONSTANT_InterfaceMethodref: - case CodeConstants.CONSTANT_NameAndType: - case CodeConstants.CONSTANT_InvokeDynamic: - pool.add(new LinkConstant(tag, in.readUnsignedShort(), in.readUnsignedShort())); - if(tag == CodeConstants.CONSTANT_NameAndType) { - pass[i] = 1; - } else { - pass[i] = 2; - } - break; - case CodeConstants.CONSTANT_MethodHandle: - pool.add(new LinkConstant(tag, in.readUnsignedByte(), in.readUnsignedShort())); - pass[i] = 3; - break; - } - } - - - // resolving complex pool elements - for(int pass_index = 1; pass_index <= 3; pass_index++) { - for(int i = 1; i < size; i++) { - if(pass[i] == pass_index) { - pool.get(i).resolveConstant(this); - } - } - } - - // get global constant pool interceptor instance, if any available - interceptor = DecompilerContext.getPoolInterceptor(); - } - - // ***************************************************************************** - // public methods - // ***************************************************************************** - - public void writeToOutputStream(DataOutputStream out) throws FileNotFoundException, IOException { - - out.writeShort(pool.size()); - for(int i=1;i<pool.size();i++) { - PooledConstant cnst = (PooledConstant)pool.get(i); - if(cnst!=null) { - cnst.writeToStream(out); - } - } - } - - public static void skipPool(DataInputStream in) throws IOException { - - int size = in.readUnsignedShort(); - - for (int i = 1; i < size; i++) { - switch (in.readUnsignedByte()) { - case CodeConstants.CONSTANT_Utf8: - in.readUTF(); - break; - case CodeConstants.CONSTANT_Integer: - case CodeConstants.CONSTANT_Float: - case CodeConstants.CONSTANT_Fieldref: - case CodeConstants.CONSTANT_Methodref: - case CodeConstants.CONSTANT_InterfaceMethodref: - case CodeConstants.CONSTANT_NameAndType: - case CodeConstants.CONSTANT_InvokeDynamic: - in.skip(4); - break; - case CodeConstants.CONSTANT_Long: - case CodeConstants.CONSTANT_Double: - in.skip(8); - i++; - break; - case CodeConstants.CONSTANT_Class: - case CodeConstants.CONSTANT_String: - case CodeConstants.CONSTANT_MethodType: - in.skip(2); - break; - case CodeConstants.CONSTANT_MethodHandle: - in.skip(3); - } - } - } - - public int size() { - return pool.size(); - } - - public String[] getClassElement(int element_type, int class_index, int name_index, int descriptor_index) { - - String classname = ((PrimitiveConstant)getConstant(class_index)).getString(); - String elementname = ((PrimitiveConstant)getConstant(name_index)).getString(); - String descriptor = ((PrimitiveConstant)getConstant(descriptor_index)).getString(); - - if(interceptor != null) { - String new_element = interceptor.getName(classname+" "+elementname+" "+descriptor); - - if(new_element != null) { - elementname = new_element.split(" ")[1]; - } - - String new_descriptor = buildNewDescriptor(element_type == FIELD?CodeConstants.CONSTANT_Fieldref:CodeConstants.CONSTANT_Methodref, - descriptor); - if(new_descriptor != null) { - descriptor = new_descriptor; - } - } - - return new String[] {elementname, descriptor}; - } - - public PooledConstant getConstant(int index) { - return pool.get(index); - } - - public PrimitiveConstant getPrimitiveConstant(int index) { - PrimitiveConstant cn = (PrimitiveConstant)getConstant(index); - - if(cn != null && interceptor != null) { - if(cn.type == CodeConstants.CONSTANT_Class) { - String newname = buildNewClassname(cn.getString()); - if(newname != null) { - cn = new PrimitiveConstant(CodeConstants.CONSTANT_Class, newname); - } - } - } - - return cn; - } - - public LinkConstant getLinkConstant(int index) { - LinkConstant ln = (LinkConstant)getConstant(index); - - if(ln != null && interceptor != null) { - if(ln.type == CodeConstants.CONSTANT_Fieldref || - ln.type == CodeConstants.CONSTANT_Methodref || - ln.type == CodeConstants.CONSTANT_InterfaceMethodref) { - - String new_classname = buildNewClassname(ln.classname); - String new_element = interceptor.getName(ln.classname+" "+ln.elementname+" "+ln.descriptor); - String new_descriptor = buildNewDescriptor(ln.type, ln.descriptor); - - if(new_classname != null || new_element != null || new_descriptor != null) { - - ln = new LinkConstant(ln.type, new_classname==null?ln.classname:new_classname, - new_element==null?ln.elementname:new_element.split(" ")[1], - new_descriptor==null?ln.descriptor:new_descriptor); - } - } - } - - return ln; - } - - private String buildNewClassname(String classname) { - - VarType vt = new VarType(classname, true); - - String newname = interceptor.getName(vt.value); - if(newname != null) { - StringBuilder buffer = new StringBuilder(); - - if(vt.arraydim > 0) { - for(int i=0;i<vt.arraydim;i++) { - buffer.append("["); - } - - buffer.append("L"+newname+";"); - } else { - buffer.append(newname); - } - - return buffer.toString(); - } - - return null; - } - - private String buildNewDescriptor(int type, String descriptor) { - - boolean updated = false; - - if(type == CodeConstants.CONSTANT_Fieldref) { - FieldDescriptor fd = FieldDescriptor.parseDescriptor(descriptor); - - VarType ftype = fd.type; - if(ftype.type == CodeConstants.TYPE_OBJECT) { - String newclname = buildNewClassname(ftype.value); - if(newclname != null) { - ftype.value = newclname; - updated = true; - } - } - - if(updated) { - return fd.getDescriptor(); - } - - } else { - - MethodDescriptor md = MethodDescriptor.parseDescriptor(descriptor); - // params - for(VarType partype : md.params) { - if(partype.type == CodeConstants.TYPE_OBJECT) { - String newclname = buildNewClassname(partype.value); - if(newclname != null) { - partype.value = newclname; - updated = true; - } - } - } - - // return value - if(md.ret.type == CodeConstants.TYPE_OBJECT) { - String newclname = buildNewClassname(md.ret.value); - if(newclname!=null) { - md.ret.value = newclname; - updated = true; - } - } - - if(updated) { - return md.getDescriptor(); - } - } - - return null; - } - + + public static final int FIELD = 1; + + public static final int METHOD = 2; + + // ***************************************************************************** + // private fields + // ***************************************************************************** + + private List<PooledConstant> pool = new ArrayList<PooledConstant>(); + + private PoolInterceptor interceptor; + + // ***************************************************************************** + // constructors + // ***************************************************************************** + + public ConstantPool(DataInputStream in) throws IOException { + + int size = in.readUnsignedShort(); + + int[] pass = new int[size]; + + // first dummy constant + pool.add(null); + + // first pass: read the elements + for (int i = 1; i < size; i++) { + + byte tag = (byte)in.readUnsignedByte(); + + switch (tag) { + case CodeConstants.CONSTANT_Utf8: + pool.add(new PrimitiveConstant(CodeConstants.CONSTANT_Utf8, in.readUTF())); + break; + case CodeConstants.CONSTANT_Integer: + pool.add(new PrimitiveConstant(CodeConstants.CONSTANT_Integer, new Integer(in.readInt()))); + break; + case CodeConstants.CONSTANT_Float: + pool.add(new PrimitiveConstant(CodeConstants.CONSTANT_Float, new Float(in.readFloat()))); + break; + case CodeConstants.CONSTANT_Long: + pool.add(new PrimitiveConstant(CodeConstants.CONSTANT_Long, new Long(in.readLong()))); + pool.add(null); + i++; + break; + case CodeConstants.CONSTANT_Double: + pool.add(new PrimitiveConstant(CodeConstants.CONSTANT_Double, new Double(in.readDouble()))); + pool.add(null); + i++; + break; + case CodeConstants.CONSTANT_Class: + case CodeConstants.CONSTANT_String: + case CodeConstants.CONSTANT_MethodType: + pool.add(new PrimitiveConstant(tag, in.readUnsignedShort())); + pass[i] = 1; + break; + case CodeConstants.CONSTANT_Fieldref: + case CodeConstants.CONSTANT_Methodref: + case CodeConstants.CONSTANT_InterfaceMethodref: + case CodeConstants.CONSTANT_NameAndType: + case CodeConstants.CONSTANT_InvokeDynamic: + pool.add(new LinkConstant(tag, in.readUnsignedShort(), in.readUnsignedShort())); + if (tag == CodeConstants.CONSTANT_NameAndType) { + pass[i] = 1; + } + else { + pass[i] = 2; + } + break; + case CodeConstants.CONSTANT_MethodHandle: + pool.add(new LinkConstant(tag, in.readUnsignedByte(), in.readUnsignedShort())); + pass[i] = 3; + break; + } + } + + + // resolving complex pool elements + for (int pass_index = 1; pass_index <= 3; pass_index++) { + for (int i = 1; i < size; i++) { + if (pass[i] == pass_index) { + pool.get(i).resolveConstant(this); + } + } + } + + // get global constant pool interceptor instance, if any available + interceptor = DecompilerContext.getPoolInterceptor(); + } + + // ***************************************************************************** + // public methods + // ***************************************************************************** + + public void writeToOutputStream(DataOutputStream out) throws FileNotFoundException, IOException { + + out.writeShort(pool.size()); + for (int i = 1; i < pool.size(); i++) { + PooledConstant cnst = (PooledConstant)pool.get(i); + if (cnst != null) { + cnst.writeToStream(out); + } + } + } + + public static void skipPool(DataInputStream in) throws IOException { + + int size = in.readUnsignedShort(); + + for (int i = 1; i < size; i++) { + switch (in.readUnsignedByte()) { + case CodeConstants.CONSTANT_Utf8: + in.readUTF(); + break; + case CodeConstants.CONSTANT_Integer: + case CodeConstants.CONSTANT_Float: + case CodeConstants.CONSTANT_Fieldref: + case CodeConstants.CONSTANT_Methodref: + case CodeConstants.CONSTANT_InterfaceMethodref: + case CodeConstants.CONSTANT_NameAndType: + case CodeConstants.CONSTANT_InvokeDynamic: + in.skip(4); + break; + case CodeConstants.CONSTANT_Long: + case CodeConstants.CONSTANT_Double: + in.skip(8); + i++; + break; + case CodeConstants.CONSTANT_Class: + case CodeConstants.CONSTANT_String: + case CodeConstants.CONSTANT_MethodType: + in.skip(2); + break; + case CodeConstants.CONSTANT_MethodHandle: + in.skip(3); + } + } + } + + public int size() { + return pool.size(); + } + + public String[] getClassElement(int element_type, int class_index, int name_index, int descriptor_index) { + + String classname = ((PrimitiveConstant)getConstant(class_index)).getString(); + String elementname = ((PrimitiveConstant)getConstant(name_index)).getString(); + String descriptor = ((PrimitiveConstant)getConstant(descriptor_index)).getString(); + + if (interceptor != null) { + String new_element = interceptor.getName(classname + " " + elementname + " " + descriptor); + + if (new_element != null) { + elementname = new_element.split(" ")[1]; + } + + String new_descriptor = buildNewDescriptor(element_type == FIELD ? CodeConstants.CONSTANT_Fieldref : CodeConstants.CONSTANT_Methodref, + descriptor); + if (new_descriptor != null) { + descriptor = new_descriptor; + } + } + + return new String[]{elementname, descriptor}; + } + + public PooledConstant getConstant(int index) { + return pool.get(index); + } + + public PrimitiveConstant getPrimitiveConstant(int index) { + PrimitiveConstant cn = (PrimitiveConstant)getConstant(index); + + if (cn != null && interceptor != null) { + if (cn.type == CodeConstants.CONSTANT_Class) { + String newname = buildNewClassname(cn.getString()); + if (newname != null) { + cn = new PrimitiveConstant(CodeConstants.CONSTANT_Class, newname); + } + } + } + + return cn; + } + + public LinkConstant getLinkConstant(int index) { + LinkConstant ln = (LinkConstant)getConstant(index); + + if (ln != null && interceptor != null) { + if (ln.type == CodeConstants.CONSTANT_Fieldref || + ln.type == CodeConstants.CONSTANT_Methodref || + ln.type == CodeConstants.CONSTANT_InterfaceMethodref) { + + String new_classname = buildNewClassname(ln.classname); + String new_element = interceptor.getName(ln.classname + " " + ln.elementname + " " + ln.descriptor); + String new_descriptor = buildNewDescriptor(ln.type, ln.descriptor); + + if (new_classname != null || new_element != null || new_descriptor != null) { + + ln = new LinkConstant(ln.type, new_classname == null ? ln.classname : new_classname, + new_element == null ? ln.elementname : new_element.split(" ")[1], + new_descriptor == null ? ln.descriptor : new_descriptor); + } + } + } + + return ln; + } + + private String buildNewClassname(String classname) { + + VarType vt = new VarType(classname, true); + + String newname = interceptor.getName(vt.value); + if (newname != null) { + StringBuilder buffer = new StringBuilder(); + + if (vt.arraydim > 0) { + for (int i = 0; i < vt.arraydim; i++) { + buffer.append("["); + } + + buffer.append("L" + newname + ";"); + } + else { + buffer.append(newname); + } + + return buffer.toString(); + } + + return null; + } + + private String buildNewDescriptor(int type, String descriptor) { + + boolean updated = false; + + if (type == CodeConstants.CONSTANT_Fieldref) { + FieldDescriptor fd = FieldDescriptor.parseDescriptor(descriptor); + + VarType ftype = fd.type; + if (ftype.type == CodeConstants.TYPE_OBJECT) { + String newclname = buildNewClassname(ftype.value); + if (newclname != null) { + ftype.value = newclname; + updated = true; + } + } + + if (updated) { + return fd.getDescriptor(); + } + } + else { + + MethodDescriptor md = MethodDescriptor.parseDescriptor(descriptor); + // params + for (VarType partype : md.params) { + if (partype.type == CodeConstants.TYPE_OBJECT) { + String newclname = buildNewClassname(partype.value); + if (newclname != null) { + partype.value = newclname; + updated = true; + } + } + } + + // return value + if (md.ret.type == CodeConstants.TYPE_OBJECT) { + String newclname = buildNewClassname(md.ret.value); + if (newclname != null) { + md.ret.value = newclname; + updated = true; + } + } + + if (updated) { + return md.getDescriptor(); + } + } + + return null; + } } diff --git a/src/org/jetbrains/java/decompiler/struct/consts/LinkConstant.java b/src/org/jetbrains/java/decompiler/struct/consts/LinkConstant.java index 770a5e3..c20b5af 100644 --- a/src/org/jetbrains/java/decompiler/struct/consts/LinkConstant.java +++ b/src/org/jetbrains/java/decompiler/struct/consts/LinkConstant.java @@ -1,17 +1,18 @@ /* - * Fernflower - The Analytical Java Decompiler - * http://www.reversed-java.com + * Copyright 2000-2014 JetBrains s.r.o. * - * (C) 2008 - 2010, Stiver + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at * - * This software is NEITHER public domain NOR free software - * as per GNU License. See license.txt for more details. + * http://www.apache.org/licenses/LICENSE-2.0 * - * This software is distributed WITHOUT ANY WARRANTY; without - * even the implied warranty of MERCHANTABILITY or FITNESS FOR - * A PARTICULAR PURPOSE. + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. */ - package org.jetbrains.java.decompiler.struct.consts; import java.io.DataOutputStream; @@ -24,136 +25,142 @@ import java.io.IOException; public class LinkConstant extends PooledConstant { - // ***************************************************************************** - // public fields - // ***************************************************************************** - - public int index1, index2; - - public String classname; - - public String elementname; - - public String descriptor; - - public int paramCount = 0; - - public boolean isVoid = false;; - - public boolean returnCategory2 = false; - - - // ***************************************************************************** - // constructors - // ***************************************************************************** - - public LinkConstant(int type, String classname, String elementname, String descriptor) { - this.type = type; - this.classname = classname; - this.elementname = elementname; - this.descriptor = descriptor; - - initConstant(); - } - - public LinkConstant(int type, int index1, int index2) { - this.type = type; - this.index1 = index1; - this.index2 = index2; - } - - - // ***************************************************************************** - // public methods - // ***************************************************************************** - - public void resolveConstant(ConstantPool pool) { - - if(type == CONSTANT_NameAndType) { - elementname = pool.getPrimitiveConstant(index1).getString(); - descriptor = pool.getPrimitiveConstant(index2).getString(); - } else if(type == CONSTANT_MethodHandle) { - LinkConstant ref_info = pool.getLinkConstant(index2); - - classname = ref_info.classname; - elementname = ref_info.elementname; - descriptor = ref_info.descriptor; - - } else { - if(type != CONSTANT_InvokeDynamic) { - classname = pool.getPrimitiveConstant(index1).getString(); - } - - LinkConstant nametype = pool.getLinkConstant(index2); - elementname = nametype.elementname; - descriptor = nametype.descriptor; - } - - initConstant(); - } - - public void writeToStream(DataOutputStream out) throws IOException { - out.writeByte(type); - if(type == CONSTANT_MethodHandle) { - out.writeByte(index1); - } else { - out.writeShort(index1); - } - out.writeShort(index2); - } - - - public boolean equals(Object o) { - if(o == this) return true; - if(o == null || !(o instanceof LinkConstant)) return false; - - LinkConstant cn = (LinkConstant)o; + // ***************************************************************************** + // public fields + // ***************************************************************************** + + public int index1, index2; + + public String classname; + + public String elementname; + + public String descriptor; + + public int paramCount = 0; + + public boolean isVoid = false; + ; + + public boolean returnCategory2 = false; + + + // ***************************************************************************** + // constructors + // ***************************************************************************** + + public LinkConstant(int type, String classname, String elementname, String descriptor) { + this.type = type; + this.classname = classname; + this.elementname = elementname; + this.descriptor = descriptor; + + initConstant(); + } + + public LinkConstant(int type, int index1, int index2) { + this.type = type; + this.index1 = index1; + this.index2 = index2; + } + + + // ***************************************************************************** + // public methods + // ***************************************************************************** + + public void resolveConstant(ConstantPool pool) { + + if (type == CONSTANT_NameAndType) { + elementname = pool.getPrimitiveConstant(index1).getString(); + descriptor = pool.getPrimitiveConstant(index2).getString(); + } + else if (type == CONSTANT_MethodHandle) { + LinkConstant ref_info = pool.getLinkConstant(index2); + + classname = ref_info.classname; + elementname = ref_info.elementname; + descriptor = ref_info.descriptor; + } + else { + if (type != CONSTANT_InvokeDynamic) { + classname = pool.getPrimitiveConstant(index1).getString(); + } + + LinkConstant nametype = pool.getLinkConstant(index2); + elementname = nametype.elementname; + descriptor = nametype.descriptor; + } + + initConstant(); + } + + public void writeToStream(DataOutputStream out) throws IOException { + out.writeByte(type); + if (type == CONSTANT_MethodHandle) { + out.writeByte(index1); + } + else { + out.writeShort(index1); + } + out.writeShort(index2); + } + + + public boolean equals(Object o) { + if (o == this) return true; + if (o == null || !(o instanceof LinkConstant)) return false; + + LinkConstant cn = (LinkConstant)o; return this.type == cn.type && - this.elementname.equals(cn.elementname) && - this.descriptor.equals(cn.descriptor) && - (this.type != CONSTANT_NameAndType || this.classname.equals(cn.classname)); + this.elementname.equals(cn.elementname) && + this.descriptor.equals(cn.descriptor) && + (this.type != CONSTANT_NameAndType || this.classname.equals(cn.classname)); + } + + // ***************************************************************************** + // private methods + // ***************************************************************************** + + private void initConstant() { + + if (type == CONSTANT_Methodref || + type == CONSTANT_InterfaceMethodref || + type == CONSTANT_InvokeDynamic || + type == CONSTANT_MethodHandle) { + resolveDescriptor(descriptor); + } + else if (type == CONSTANT_Fieldref) { + returnCategory2 = ("D".equals(descriptor) || "J".equals(descriptor)); + } + } + + private void resolveDescriptor(String descr) { + + String[] arr = descr.split("[()]"); + String par = arr[1]; + + int index = 0, counter = 0; + int len = par.length(); + + while (index < len) { + + char c = par.charAt(index); + if (c == 'L') { + index = par.indexOf(";", index); + } + else if (c == '[') { + index++; + continue; + } + + counter++; + index++; + } + + paramCount = counter; + isVoid = "V".equals(arr[2]); + returnCategory2 = ("D".equals(arr[2]) || "J".equals(arr[2])); } - - // ***************************************************************************** - // private methods - // ***************************************************************************** - - private void initConstant() { - - if(type == CONSTANT_Methodref || type == CONSTANT_InterfaceMethodref || type == CONSTANT_InvokeDynamic || type == CONSTANT_MethodHandle) { - resolveDescriptor(descriptor); - } else if(type == CONSTANT_Fieldref) { - returnCategory2 = ("D".equals(descriptor) || "J".equals(descriptor)); - } - - } - - private void resolveDescriptor(String descr){ - - String[] arr = descr.split("[()]"); - String par = arr[1]; - - int index = 0, counter = 0; - int len = par.length(); - - while(index<len) { - - char c = par.charAt(index); - if(c == 'L') { - index = par.indexOf(";", index); - } else if (c == '[') { - index++; - continue; - } - - counter++; - index++; - } - - paramCount = counter; - isVoid = "V".equals(arr[2]); - returnCategory2 = ("D".equals(arr[2]) || "J".equals(arr[2])); - } - } diff --git a/src/org/jetbrains/java/decompiler/struct/consts/PooledConstant.java b/src/org/jetbrains/java/decompiler/struct/consts/PooledConstant.java index ae46604..d3d30c0 100644 --- a/src/org/jetbrains/java/decompiler/struct/consts/PooledConstant.java +++ b/src/org/jetbrains/java/decompiler/struct/consts/PooledConstant.java @@ -1,24 +1,25 @@ /* - * Fernflower - The Analytical Java Decompiler - * http://www.reversed-java.com + * Copyright 2000-2014 JetBrains s.r.o. * - * (C) 2008 - 2010, Stiver + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at * - * This software is NEITHER public domain NOR free software - * as per GNU License. See license.txt for more details. + * http://www.apache.org/licenses/LICENSE-2.0 * - * This software is distributed WITHOUT ANY WARRANTY; without - * even the implied warranty of MERCHANTABILITY or FITNESS FOR - * A PARTICULAR PURPOSE. + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. */ - package org.jetbrains.java.decompiler.struct.consts; +import org.jetbrains.java.decompiler.code.CodeConstants; + import java.io.DataOutputStream; import java.io.IOException; -import org.jetbrains.java.decompiler.code.CodeConstants; - /* cp_info { u1 tag; @@ -29,88 +30,88 @@ import org.jetbrains.java.decompiler.code.CodeConstants; public class PooledConstant implements CodeConstants, VariableTypeEnum { - // ***************************************************************************** - // public fields - // ***************************************************************************** - - public int type; - - public boolean own = false; - - public int returnType; - - - // ***************************************************************************** - // private fields - // ***************************************************************************** - - private Object[] values; - - // ***************************************************************************** - // constructors - // ***************************************************************************** - - public PooledConstant() {} - - public PooledConstant(int type, Object[] values) { - this.type = type; - this.values = values; - this.returnType = poolTypeToIntern(type); - } - - public PooledConstant(int type, boolean own, Object[] values) { - this.type = type; - this.own = own; - this.values = values; - this.returnType = poolTypeToIntern(type); - } - - // ***************************************************************************** - // public methods - // ***************************************************************************** - - public void resolveConstant(ConstantPool pool) { - // to be overwritten - } - - public void writeToStream(DataOutputStream out) throws IOException { - // to be overwritten - } - - public int poolTypeToIntern(int type) { - - switch(type){ - case CONSTANT_Integer: - return INT; - case CONSTANT_Float: - return FLOAT; - case CONSTANT_Long: - return LONG; - case CONSTANT_Double: - return DOUBLE; - case CONSTANT_String: - case CONSTANT_Class: // 1.5 -> ldc class - return REFERENCE; - default: - throw new RuntimeException("Huh?? What are you trying to load?"); - } - } - - public Object getValue(int index){ - return values[index]; - } - - - // ***************************************************************************** - // getter and setter methods - // ***************************************************************************** - - public Object[] getValues() { - return values; - } - - public void setValues(Object[] values) { - this.values = values; - } + // ***************************************************************************** + // public fields + // ***************************************************************************** + + public int type; + + public boolean own = false; + + public int returnType; + + + // ***************************************************************************** + // private fields + // ***************************************************************************** + + private Object[] values; + + // ***************************************************************************** + // constructors + // ***************************************************************************** + + public PooledConstant() { + } + + public PooledConstant(int type, Object[] values) { + this.type = type; + this.values = values; + this.returnType = poolTypeToIntern(type); + } + + public PooledConstant(int type, boolean own, Object[] values) { + this.type = type; + this.own = own; + this.values = values; + this.returnType = poolTypeToIntern(type); + } + + // ***************************************************************************** + // public methods + // ***************************************************************************** + + public void resolveConstant(ConstantPool pool) { + // to be overwritten + } + + public void writeToStream(DataOutputStream out) throws IOException { + // to be overwritten + } + + public int poolTypeToIntern(int type) { + + switch (type) { + case CONSTANT_Integer: + return INT; + case CONSTANT_Float: + return FLOAT; + case CONSTANT_Long: + return LONG; + case CONSTANT_Double: + return DOUBLE; + case CONSTANT_String: + case CONSTANT_Class: // 1.5 -> ldc class + return REFERENCE; + default: + throw new RuntimeException("Huh?? What are you trying to load?"); + } + } + + public Object getValue(int index) { + return values[index]; + } + + + // ***************************************************************************** + // getter and setter methods + // ***************************************************************************** + + public Object[] getValues() { + return values; + } + public void setValues(Object[] values) { + this.values = values; + } } diff --git a/src/org/jetbrains/java/decompiler/struct/consts/PrimitiveConstant.java b/src/org/jetbrains/java/decompiler/struct/consts/PrimitiveConstant.java index f01a695..4cd4dd8 100644 --- a/src/org/jetbrains/java/decompiler/struct/consts/PrimitiveConstant.java +++ b/src/org/jetbrains/java/decompiler/struct/consts/PrimitiveConstant.java @@ -1,17 +1,18 @@ /* - * Fernflower - The Analytical Java Decompiler - * http://www.reversed-java.com + * Copyright 2000-2014 JetBrains s.r.o. * - * (C) 2008 - 2010, Stiver + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at * - * This software is NEITHER public domain NOR free software - * as per GNU License. See license.txt for more details. + * http://www.apache.org/licenses/LICENSE-2.0 * - * This software is distributed WITHOUT ANY WARRANTY; without - * even the implied warranty of MERCHANTABILITY or FITNESS FOR - * A PARTICULAR PURPOSE. + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. */ - package org.jetbrains.java.decompiler.struct.consts; import java.io.DataOutputStream; @@ -23,104 +24,103 @@ import java.io.IOException; public class PrimitiveConstant extends PooledConstant { - // ***************************************************************************** - // public fields - // ***************************************************************************** - - public int index; - - public Object value; - - public boolean isArray; - - // ***************************************************************************** - // constructors - // ***************************************************************************** - - public PrimitiveConstant(int type, Object value) { - this.type = type; - this.value = value; - - initConstant(); - } - - public PrimitiveConstant(int type, int index) { - this.type = type; - this.index = index; - } - - // ***************************************************************************** - // public methods - // ***************************************************************************** - - public int getInt() { - return ((Integer)value).intValue(); - } - - public long getLong() { - return ((Long)value).longValue(); - } - - public float getFloat() { - return ((Float)value).floatValue(); - } - - public double getDouble() { - return ((Double)value).doubleValue(); - } - - public String getString() { - return (String)value; - } - - public void resolveConstant(ConstantPool pool) { - - if(type == CONSTANT_Class || type == CONSTANT_String || type == CONSTANT_MethodType) { - value = pool.getPrimitiveConstant(index).getString(); - initConstant(); - } - } - - public void writeToStream(DataOutputStream out) throws IOException { - - out.writeByte(type); - switch(type) { - case CONSTANT_Integer: - out.writeInt(getInt()); - break; - case CONSTANT_Float: - out.writeFloat(getFloat()); - break; - case CONSTANT_Long: - out.writeLong(getLong()); - break; - case CONSTANT_Double: - out.writeDouble(getDouble()); - break; - case CONSTANT_Utf8: - out.writeUTF(getString()); - break; - default: // CONSTANT_Class, CONSTANT_String, CONSTANT_MethodType - out.writeShort(index); - } - } - - public boolean equals(Object o) { - if(o == this) return true; - if(o == null || !(o instanceof PrimitiveConstant)) return false; - - PrimitiveConstant cn = (PrimitiveConstant)o; - return this.type == cn.type && - this.isArray == cn.isArray && - this.value.equals(cn.value); - - } - - private void initConstant() { - if(type == CONSTANT_Class) { - String className = getString(); - isArray = (className.length() > 0 && className.charAt(0)=='['); // empty string for a class name seems to be possible in some android files - } - } - + // ***************************************************************************** + // public fields + // ***************************************************************************** + + public int index; + + public Object value; + + public boolean isArray; + + // ***************************************************************************** + // constructors + // ***************************************************************************** + + public PrimitiveConstant(int type, Object value) { + this.type = type; + this.value = value; + + initConstant(); + } + + public PrimitiveConstant(int type, int index) { + this.type = type; + this.index = index; + } + + // ***************************************************************************** + // public methods + // ***************************************************************************** + + public int getInt() { + return ((Integer)value).intValue(); + } + + public long getLong() { + return ((Long)value).longValue(); + } + + public float getFloat() { + return ((Float)value).floatValue(); + } + + public double getDouble() { + return ((Double)value).doubleValue(); + } + + public String getString() { + return (String)value; + } + + public void resolveConstant(ConstantPool pool) { + + if (type == CONSTANT_Class || type == CONSTANT_String || type == CONSTANT_MethodType) { + value = pool.getPrimitiveConstant(index).getString(); + initConstant(); + } + } + + public void writeToStream(DataOutputStream out) throws IOException { + + out.writeByte(type); + switch (type) { + case CONSTANT_Integer: + out.writeInt(getInt()); + break; + case CONSTANT_Float: + out.writeFloat(getFloat()); + break; + case CONSTANT_Long: + out.writeLong(getLong()); + break; + case CONSTANT_Double: + out.writeDouble(getDouble()); + break; + case CONSTANT_Utf8: + out.writeUTF(getString()); + break; + default: // CONSTANT_Class, CONSTANT_String, CONSTANT_MethodType + out.writeShort(index); + } + } + + public boolean equals(Object o) { + if (o == this) return true; + if (o == null || !(o instanceof PrimitiveConstant)) return false; + + PrimitiveConstant cn = (PrimitiveConstant)o; + return this.type == cn.type && + this.isArray == cn.isArray && + this.value.equals(cn.value); + } + + private void initConstant() { + if (type == CONSTANT_Class) { + String className = getString(); + isArray = + (className.length() > 0 && className.charAt(0) == '['); // empty string for a class name seems to be possible in some android files + } + } } diff --git a/src/org/jetbrains/java/decompiler/struct/consts/VariableTypeEnum.java b/src/org/jetbrains/java/decompiler/struct/consts/VariableTypeEnum.java index fc58c7e..ef949aa 100644 --- a/src/org/jetbrains/java/decompiler/struct/consts/VariableTypeEnum.java +++ b/src/org/jetbrains/java/decompiler/struct/consts/VariableTypeEnum.java @@ -1,47 +1,47 @@ /* - * Fernflower - The Analytical Java Decompiler - * http://www.reversed-java.com + * Copyright 2000-2014 JetBrains s.r.o. * - * (C) 2008 - 2010, Stiver + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at * - * This software is NEITHER public domain NOR free software - * as per GNU License. See license.txt for more details. + * http://www.apache.org/licenses/LICENSE-2.0 * - * This software is distributed WITHOUT ANY WARRANTY; without - * even the implied warranty of MERCHANTABILITY or FITNESS FOR - * A PARTICULAR PURPOSE. + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. */ - package org.jetbrains.java.decompiler.struct.consts; public interface VariableTypeEnum { - public final static int BOOLEAN = 1; - public final static int BYTE = 2; - public final static int CHAR = 3; - public final static int SHORT = 4; - public final static int INT = 5; - public final static int FLOAT = 6; - public final static int LONG = 7; - public final static int DOUBLE = 8; - public final static int RETURN_ADDRESS = 9; - public final static int REFERENCE = 10; - public final static int INSTANCE_UNINITIALIZED = 11; - public final static int VALUE_UNKNOWN = 12; - public final static int VOID = 13; - - public final static Integer BOOLEAN_OBJ = new Integer(BOOLEAN); - public final static Integer BYTE_OBJ = new Integer(BYTE); - public final static Integer CHAR_OBJ = new Integer(CHAR); - public final static Integer SHORT_OBJ = new Integer(SHORT); - public final static Integer INT_OBJ = new Integer(INT); - public final static Integer FLOAT_OBJ = new Integer(FLOAT); - public final static Integer LONG_OBJ = new Integer(LONG); - public final static Integer DOUBLE_OBJ = new Integer(DOUBLE); - public final static Integer RETURN_ADDRESS_OBJ = new Integer(RETURN_ADDRESS); - public final static Integer REFERENCE_OBJ = new Integer(REFERENCE); - public final static Integer INSTANCE_UNINITIALIZED_OBJ = new Integer(INSTANCE_UNINITIALIZED); - public final static Integer VALUE_UNKNOWN_OBJ = new Integer(VALUE_UNKNOWN); - public final static Integer VOID_OBJ = new Integer(VOID); - + public final static int BOOLEAN = 1; + public final static int BYTE = 2; + public final static int CHAR = 3; + public final static int SHORT = 4; + public final static int INT = 5; + public final static int FLOAT = 6; + public final static int LONG = 7; + public final static int DOUBLE = 8; + public final static int RETURN_ADDRESS = 9; + public final static int REFERENCE = 10; + public final static int INSTANCE_UNINITIALIZED = 11; + public final static int VALUE_UNKNOWN = 12; + public final static int VOID = 13; + + public final static Integer BOOLEAN_OBJ = new Integer(BOOLEAN); + public final static Integer BYTE_OBJ = new Integer(BYTE); + public final static Integer CHAR_OBJ = new Integer(CHAR); + public final static Integer SHORT_OBJ = new Integer(SHORT); + public final static Integer INT_OBJ = new Integer(INT); + public final static Integer FLOAT_OBJ = new Integer(FLOAT); + public final static Integer LONG_OBJ = new Integer(LONG); + public final static Integer DOUBLE_OBJ = new Integer(DOUBLE); + public final static Integer RETURN_ADDRESS_OBJ = new Integer(RETURN_ADDRESS); + public final static Integer REFERENCE_OBJ = new Integer(REFERENCE); + public final static Integer INSTANCE_UNINITIALIZED_OBJ = new Integer(INSTANCE_UNINITIALIZED); + public final static Integer VALUE_UNKNOWN_OBJ = new Integer(VALUE_UNKNOWN); + public final static Integer VOID_OBJ = new Integer(VOID); } diff --git a/src/org/jetbrains/java/decompiler/struct/gen/DataPoint.java b/src/org/jetbrains/java/decompiler/struct/gen/DataPoint.java index db6ecd1..53269da 100644 --- a/src/org/jetbrains/java/decompiler/struct/gen/DataPoint.java +++ b/src/org/jetbrains/java/decompiler/struct/gen/DataPoint.java @@ -1,98 +1,100 @@ /* - * Fernflower - The Analytical Java Decompiler - * http://www.reversed-java.com + * Copyright 2000-2014 JetBrains s.r.o. * - * (C) 2008 - 2010, Stiver + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at * - * This software is NEITHER public domain NOR free software - * as per GNU License. See license.txt for more details. + * http://www.apache.org/licenses/LICENSE-2.0 * - * This software is distributed WITHOUT ANY WARRANTY; without - * even the implied warranty of MERCHANTABILITY or FITNESS FOR - * A PARTICULAR PURPOSE. + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. */ - package org.jetbrains.java.decompiler.struct.gen; -import java.util.ArrayList; -import java.util.List; - import org.jetbrains.java.decompiler.code.CodeConstants; import org.jetbrains.java.decompiler.struct.StructMethod; import org.jetbrains.java.decompiler.util.ListStack; +import java.util.ArrayList; +import java.util.List; + public class DataPoint { - private List<VarType> localVariables = new ArrayList<VarType>(); - - private ListStack<VarType> stack = new ListStack<VarType>(); - - - public void setVariable(int index, VarType value) { - if(index>=localVariables.size()) { - for(int i=localVariables.size();i<=index;i++) { - localVariables.add(new VarType(CodeConstants.TYPE_NOTINITIALIZED)); - } - } - - localVariables.set(index, value); - } - - public VarType getVariable(int index) { - if(index<localVariables.size()) { - return localVariables.get(index); - } else if(index<0) { - throw new IndexOutOfBoundsException(); - } else { - return new VarType(CodeConstants.TYPE_NOTINITIALIZED); - } - } - - public DataPoint copy() { - DataPoint point = new DataPoint(); - point.setLocalVariables(new ArrayList<VarType>(localVariables)); - point.setStack(stack.clone()); - return point; - } - - public static DataPoint getInitialDataPoint(StructMethod mt) { - - DataPoint point = new DataPoint(); - - MethodDescriptor md = MethodDescriptor.parseDescriptor(mt.getDescriptor()); - - int k = 0; - if((mt.getAccessFlags() & CodeConstants.ACC_STATIC) == 0) { - point.setVariable(k++, new VarType(CodeConstants.TYPE_OBJECT, 0, null)); - } - - for(int i=0;i<md.params.length;i++) { - VarType var = md.params[i]; - - point.setVariable(k++, var); - if(var.stack_size == 2) { - point.setVariable(k++, new VarType(CodeConstants.TYPE_GROUP2EMPTY)); - } - } - - return point; - } - - - public List<VarType> getLocalVariables() { - return localVariables; - } - - public void setLocalVariables(List<VarType> localVariables) { - this.localVariables = localVariables; - } - - public ListStack<VarType> getStack() { - return stack; - } - - public void setStack(ListStack<VarType> stack) { - this.stack = stack; - } - + private List<VarType> localVariables = new ArrayList<VarType>(); + + private ListStack<VarType> stack = new ListStack<VarType>(); + + + public void setVariable(int index, VarType value) { + if (index >= localVariables.size()) { + for (int i = localVariables.size(); i <= index; i++) { + localVariables.add(new VarType(CodeConstants.TYPE_NOTINITIALIZED)); + } + } + + localVariables.set(index, value); + } + + public VarType getVariable(int index) { + if (index < localVariables.size()) { + return localVariables.get(index); + } + else if (index < 0) { + throw new IndexOutOfBoundsException(); + } + else { + return new VarType(CodeConstants.TYPE_NOTINITIALIZED); + } + } + + public DataPoint copy() { + DataPoint point = new DataPoint(); + point.setLocalVariables(new ArrayList<VarType>(localVariables)); + point.setStack(stack.clone()); + return point; + } + + public static DataPoint getInitialDataPoint(StructMethod mt) { + + DataPoint point = new DataPoint(); + + MethodDescriptor md = MethodDescriptor.parseDescriptor(mt.getDescriptor()); + + int k = 0; + if ((mt.getAccessFlags() & CodeConstants.ACC_STATIC) == 0) { + point.setVariable(k++, new VarType(CodeConstants.TYPE_OBJECT, 0, null)); + } + + for (int i = 0; i < md.params.length; i++) { + VarType var = md.params[i]; + + point.setVariable(k++, var); + if (var.stack_size == 2) { + point.setVariable(k++, new VarType(CodeConstants.TYPE_GROUP2EMPTY)); + } + } + + return point; + } + + + public List<VarType> getLocalVariables() { + return localVariables; + } + + public void setLocalVariables(List<VarType> localVariables) { + this.localVariables = localVariables; + } + + public ListStack<VarType> getStack() { + return stack; + } + + public void setStack(ListStack<VarType> stack) { + this.stack = stack; + } } diff --git a/src/org/jetbrains/java/decompiler/struct/gen/FieldDescriptor.java b/src/org/jetbrains/java/decompiler/struct/gen/FieldDescriptor.java index a475937..ff731ae 100644 --- a/src/org/jetbrains/java/decompiler/struct/gen/FieldDescriptor.java +++ b/src/org/jetbrains/java/decompiler/struct/gen/FieldDescriptor.java @@ -1,58 +1,59 @@ /* - * Fernflower - The Analytical Java Decompiler - * http://www.reversed-java.com + * Copyright 2000-2014 JetBrains s.r.o. * - * (C) 2008 - 2010, Stiver + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at * - * This software is NEITHER public domain NOR free software - * as per GNU License. See license.txt for more details. + * http://www.apache.org/licenses/LICENSE-2.0 * - * This software is distributed WITHOUT ANY WARRANTY; without - * even the implied warranty of MERCHANTABILITY or FITNESS FOR - * A PARTICULAR PURPOSE. + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. */ - package org.jetbrains.java.decompiler.struct.gen; public class FieldDescriptor { - - public static final FieldDescriptor INTEGER_DESCRIPTOR = FieldDescriptor.parseDescriptor("Ljava/lang/Integer;"); - public static final FieldDescriptor LONG_DESCRIPTOR = FieldDescriptor.parseDescriptor("Ljava/lang/Long;"); - public static final FieldDescriptor FLOAT_DESCRIPTOR = FieldDescriptor.parseDescriptor("Ljava/lang/Float;"); - public static final FieldDescriptor DOUBLE_DESCRIPTOR = FieldDescriptor.parseDescriptor("Ljava/lang/Double;"); - - public VarType type; - - public String descriptorString; - - private FieldDescriptor() {} - - public static FieldDescriptor parseDescriptor(String descr) { - - FieldDescriptor fd = new FieldDescriptor(); - - fd.type = new VarType(descr); - fd.descriptorString = descr; - - return fd; - } - - public String getDescriptor() { - return type.toString(); - } - - @Override - public boolean equals(Object o) { - if(o == this) return true; - if(o == null || !(o instanceof FieldDescriptor)) return false; + + public static final FieldDescriptor INTEGER_DESCRIPTOR = FieldDescriptor.parseDescriptor("Ljava/lang/Integer;"); + public static final FieldDescriptor LONG_DESCRIPTOR = FieldDescriptor.parseDescriptor("Ljava/lang/Long;"); + public static final FieldDescriptor FLOAT_DESCRIPTOR = FieldDescriptor.parseDescriptor("Ljava/lang/Float;"); + public static final FieldDescriptor DOUBLE_DESCRIPTOR = FieldDescriptor.parseDescriptor("Ljava/lang/Double;"); + + public VarType type; + + public String descriptorString; + + private FieldDescriptor() { + } + + public static FieldDescriptor parseDescriptor(String descr) { + + FieldDescriptor fd = new FieldDescriptor(); + + fd.type = new VarType(descr); + fd.descriptorString = descr; + + return fd; + } + + public String getDescriptor() { + return type.toString(); + } + + @Override + public boolean equals(Object o) { + if (o == this) return true; + if (o == null || !(o instanceof FieldDescriptor)) return false; FieldDescriptor fd = (FieldDescriptor)o; return type.equals(fd.type); } - @Override - public int hashCode() { - return type.hashCode(); - } - + @Override + public int hashCode() { + return type.hashCode(); + } } diff --git a/src/org/jetbrains/java/decompiler/struct/gen/MethodDescriptor.java b/src/org/jetbrains/java/decompiler/struct/gen/MethodDescriptor.java index 77a8394..7dbc16c 100644 --- a/src/org/jetbrains/java/decompiler/struct/gen/MethodDescriptor.java +++ b/src/org/jetbrains/java/decompiler/struct/gen/MethodDescriptor.java @@ -1,17 +1,18 @@ /* - * Fernflower - The Analytical Java Decompiler - * http://www.reversed-java.com + * Copyright 2000-2014 JetBrains s.r.o. * - * (C) 2008 - 2010, Stiver + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at * - * This software is NEITHER public domain NOR free software - * as per GNU License. See license.txt for more details. + * http://www.apache.org/licenses/LICENSE-2.0 * - * This software is distributed WITHOUT ANY WARRANTY; without - * even the implied warranty of MERCHANTABILITY or FITNESS FOR - * A PARTICULAR PURPOSE. + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. */ - package org.jetbrains.java.decompiler.struct.gen; import java.util.ArrayList; @@ -20,83 +21,82 @@ import java.util.List; public class MethodDescriptor { - public VarType[] params; - - public VarType ret; - - - public static MethodDescriptor parseDescriptor(String mdescr) { - - MethodDescriptor md = new MethodDescriptor(); - - List<String> lst = new ArrayList<String>(); - String[] pars = mdescr.split("[()]"); - - String par = pars[1]; - - int indexFrom = -1, ind,index = 0; - int len = par.length(); - - for(;index<len;index++) { - - switch(par.charAt(index)){ - case '[': - if(indexFrom<0){ - indexFrom = index; - } - break; - case 'L': - ind = par.indexOf(";", index); - lst.add(par.substring(indexFrom<0?index:indexFrom, ind+1)); - index = ind; - indexFrom = -1; - break; - default: - lst.add(par.substring(indexFrom<0?index:indexFrom, index+1)); - indexFrom = -1; - } - } - - lst.add(pars[2]); - - - md.params = new VarType[lst.size()-1]; - - int i = 0; - for(;i<lst.size()-1;i++) { - md.params[i] = new VarType(lst.get(i)); - } - md.ret = new VarType(lst.get(i)); - - return md; - } - - public String getDescriptor() { - String res = "("; - - for(int j = 0;j<params.length;j++) { - res+=params[j].toString(); - } - - res+=")"+ret.toString(); - - return res; - } - - @Override - public boolean equals(Object o) { - if(o == this) return true; - if(o == null || !(o instanceof MethodDescriptor)) return false; + public VarType[] params; + + public VarType ret; + + + public static MethodDescriptor parseDescriptor(String mdescr) { + + MethodDescriptor md = new MethodDescriptor(); + + List<String> lst = new ArrayList<String>(); + String[] pars = mdescr.split("[()]"); + + String par = pars[1]; + + int indexFrom = -1, ind, index = 0; + int len = par.length(); + + for (; index < len; index++) { + + switch (par.charAt(index)) { + case '[': + if (indexFrom < 0) { + indexFrom = index; + } + break; + case 'L': + ind = par.indexOf(";", index); + lst.add(par.substring(indexFrom < 0 ? index : indexFrom, ind + 1)); + index = ind; + indexFrom = -1; + break; + default: + lst.add(par.substring(indexFrom < 0 ? index : indexFrom, index + 1)); + indexFrom = -1; + } + } + + lst.add(pars[2]); + + + md.params = new VarType[lst.size() - 1]; + + int i = 0; + for (; i < lst.size() - 1; i++) { + md.params[i] = new VarType(lst.get(i)); + } + md.ret = new VarType(lst.get(i)); + + return md; + } + + public String getDescriptor() { + String res = "("; + + for (int j = 0; j < params.length; j++) { + res += params[j].toString(); + } + + res += ")" + ret.toString(); + + return res; + } + + @Override + public boolean equals(Object o) { + if (o == this) return true; + if (o == null || !(o instanceof MethodDescriptor)) return false; MethodDescriptor md = (MethodDescriptor)o; return ret.equals(md.ret) && Arrays.equals(params, md.params); } - @Override - public int hashCode() { + @Override + public int hashCode() { int result = ret.hashCode(); result = 31 * result + params.length; return result; - } - + } } diff --git a/src/org/jetbrains/java/decompiler/struct/gen/VarType.java b/src/org/jetbrains/java/decompiler/struct/gen/VarType.java index 5ee0c4b..79e2cbf 100644 --- a/src/org/jetbrains/java/decompiler/struct/gen/VarType.java +++ b/src/org/jetbrains/java/decompiler/struct/gen/VarType.java @@ -1,410 +1,422 @@ /* - * Fernflower - The Analytical Java Decompiler - * http://www.reversed-java.com + * Copyright 2000-2014 JetBrains s.r.o. * - * (C) 2008 - 2010, Stiver + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at * - * This software is NEITHER public domain NOR free software - * as per GNU License. See license.txt for more details. + * http://www.apache.org/licenses/LICENSE-2.0 * - * This software is distributed WITHOUT ANY WARRANTY; without - * even the implied warranty of MERCHANTABILITY or FITNESS FOR - * A PARTICULAR PURPOSE. + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. */ - package org.jetbrains.java.decompiler.struct.gen; import org.jetbrains.java.decompiler.code.CodeConstants; import org.jetbrains.java.decompiler.util.InterpreterUtil; public class VarType { // TODO: optimize switch - - public static final int FALSEBOOLEAN = 1; - - public static final VarType VARTYPE_UNKNOWN = new VarType(CodeConstants.TYPE_UNKNOWN); - public static final VarType VARTYPE_INT = new VarType(CodeConstants.TYPE_INT); - public static final VarType VARTYPE_FLOAT = new VarType(CodeConstants.TYPE_FLOAT); - public static final VarType VARTYPE_LONG = new VarType(CodeConstants.TYPE_LONG); - public static final VarType VARTYPE_DOUBLE = new VarType(CodeConstants.TYPE_DOUBLE); - public static final VarType VARTYPE_BYTE = new VarType(CodeConstants.TYPE_BYTE); - public static final VarType VARTYPE_CHAR = new VarType(CodeConstants.TYPE_CHAR); - public static final VarType VARTYPE_SHORT = new VarType(CodeConstants.TYPE_SHORT); - public static final VarType VARTYPE_BOOLEAN = new VarType(CodeConstants.TYPE_BOOLEAN); - public static final VarType VARTYPE_BYTECHAR = new VarType(CodeConstants.TYPE_BYTECHAR); - public static final VarType VARTYPE_SHORTCHAR = new VarType(CodeConstants.TYPE_SHORTCHAR); - - public static final VarType VARTYPE_NULL = new VarType(CodeConstants.TYPE_NULL,0,null); - public static final VarType VARTYPE_GROUP2EMPTY = new VarType(CodeConstants.TYPE_GROUP2EMPTY); - public static final VarType VARTYPE_STRING = new VarType(CodeConstants.TYPE_OBJECT, 0, "java/lang/String"); - public static final VarType VARTYPE_CLASS = new VarType(CodeConstants.TYPE_OBJECT, 0, "java/lang/Class"); - public static final VarType VARTYPE_OBJECT = new VarType(CodeConstants.TYPE_OBJECT, 0, "java/lang/Object"); - public static final VarType VARTYPE_VOID = new VarType(CodeConstants.TYPE_VOID); - - public int type; - - public int type_family; - - public int arraydim; - - public String value; - - public int stack_size; - - public int convinfo; - - public VarType(int type) { - this.type = type; - this.arraydim = 0; - - value = getChar(type); - setStackSize(type); - setFamily(); - } - - public VarType(int type, int arraydim) { - this(type); - this.arraydim = arraydim; - setFamily(); - } - - public VarType(int type, int arraydim, String value) { - this(type); - this.arraydim = arraydim; - this.value = value; - setFamily(); - } - - public VarType(String strtype) { - this(strtype, false); - } - - public VarType(String strtype, boolean cltype) { - parseTypeString(strtype, cltype); - setStackSize(type); - setFamily(); - } - - public void decArrayDim() { - if(arraydim > 0) { - arraydim--; - setFamily(); - } else { - // throw new RuntimeException("array dimension equals 0!"); FIXME: investigate this case - } - } - - public String toString() { - String res = ""; - - for(int i=0;i<arraydim;i++) { - res+="["; - } - - if(type == CodeConstants.TYPE_OBJECT) { - res+="L"+value+";"; - } else { - res+=value; - } - - return res; - } - - public VarType copy() { - VarType v = new VarType(type, arraydim, value); - v.convinfo = convinfo; - return v; - } - - public boolean isFalseBoolean() { - return (convinfo & VarType.FALSEBOOLEAN) != 0; - } - - public boolean isSuperset(VarType val) { - - return this.equals(val) || this.isStrictSuperset(val); - } - - public boolean isStrictSuperset(VarType val) { - - int valtype = val.type; - - if(valtype == CodeConstants.TYPE_UNKNOWN && type != CodeConstants.TYPE_UNKNOWN) { - return true; - } - - if(val.arraydim > 0) { - return this.equals(VARTYPE_OBJECT); - } else if(arraydim > 0) { - return (valtype == CodeConstants.TYPE_NULL); - } - - boolean res = false; - - switch(type) { - case CodeConstants.TYPE_INT: - res |= (valtype == CodeConstants.TYPE_SHORT || - valtype == CodeConstants.TYPE_CHAR); - case CodeConstants.TYPE_SHORT: - res |= (valtype == CodeConstants.TYPE_BYTE); - case CodeConstants.TYPE_CHAR: - res |= (valtype == CodeConstants.TYPE_SHORTCHAR); - case CodeConstants.TYPE_BYTE: - case CodeConstants.TYPE_SHORTCHAR: - res |= (valtype == CodeConstants.TYPE_BYTECHAR); - case CodeConstants.TYPE_BYTECHAR: - res |= (valtype == CodeConstants.TYPE_BOOLEAN); - break; - case CodeConstants.TYPE_OBJECT: - if(valtype == CodeConstants.TYPE_NULL) { - return true; - } else if(this.equals(VARTYPE_OBJECT)) { - return valtype == CodeConstants.TYPE_OBJECT && - !val.equals(VARTYPE_OBJECT); - } - } - - return res; - } - - // type1 and type2 must not be null - public static VarType getCommonMinType(VarType type1, VarType type2) { - - if(type1.type == CodeConstants.TYPE_BOOLEAN && type2.type == CodeConstants.TYPE_BOOLEAN) { // special case booleans - return type1.isFalseBoolean() ? type2 : type1; - } - - if(type1.isSuperset(type2)) { - return type2; - } else if(type2.isSuperset(type1)) { - return type1; - } else if(type1.type_family == type2.type_family) { - switch(type1.type_family) { - case CodeConstants.TYPE_FAMILY_INTEGER: - if((type1.type == CodeConstants.TYPE_CHAR && type2.type == CodeConstants.TYPE_SHORT) - || (type1.type == CodeConstants.TYPE_SHORT && type2.type == CodeConstants.TYPE_CHAR)) { - return VarType.VARTYPE_SHORTCHAR; - } else { - return VarType.VARTYPE_BYTECHAR; - } - case CodeConstants.TYPE_FAMILY_OBJECT: - return VarType.VARTYPE_NULL; - } - } - - return null; - } - - // type1 and type2 must not be null - public static VarType getCommonSupertype(VarType type1, VarType type2) { - - if(type1.type == CodeConstants.TYPE_BOOLEAN && type2.type == CodeConstants.TYPE_BOOLEAN) { // special case booleans - return type1.isFalseBoolean() ? type1 : type2; - } - - if(type1.isSuperset(type2)) { - return type1; - } else if(type2.isSuperset(type1)) { - return type2; - } else if(type1.type_family == type2.type_family) { - switch(type1.type_family) { - case CodeConstants.TYPE_FAMILY_INTEGER: - if((type1.type == CodeConstants.TYPE_SHORTCHAR && type2.type == CodeConstants.TYPE_BYTE) - || (type1.type == CodeConstants.TYPE_BYTE && type2.type == CodeConstants.TYPE_SHORTCHAR)) { - return VarType.VARTYPE_SHORT; - } else { - return VarType.VARTYPE_INT; - } - case CodeConstants.TYPE_FAMILY_OBJECT: - return VarType.VARTYPE_OBJECT; - } - } - - return null; - } - - public static VarType getMinTypeInFamily(int family) { - switch(family) { - case CodeConstants.TYPE_FAMILY_BOOLEAN: - return VarType.VARTYPE_BOOLEAN; - case CodeConstants.TYPE_FAMILY_INTEGER: - return VarType.VARTYPE_BYTECHAR; - case CodeConstants.TYPE_FAMILY_OBJECT: - return VarType.VARTYPE_NULL; - case CodeConstants.TYPE_FAMILY_FLOAT: - return VarType.VARTYPE_FLOAT; - case CodeConstants.TYPE_FAMILY_LONG: - return VarType.VARTYPE_LONG; - case CodeConstants.TYPE_FAMILY_DOUBLE: - return VarType.VARTYPE_DOUBLE; - case CodeConstants.TYPE_FAMILY_UNKNOWN: - return VarType.VARTYPE_UNKNOWN; - default: - throw new RuntimeException("invalid type family!"); - } - } - - public boolean equals(Object o) { - - if(o == this) { - return true; - } - - if(o == null || !(o instanceof VarType)) { - return false; - } - - VarType vt = (VarType) o; - return type == vt.type && arraydim == vt.arraydim && InterpreterUtil.equalObjects(value, vt.value); - } - - private void parseTypeString(String strtype, boolean cltype) { - - for(int i=0;i<strtype.length();i++) { - switch(strtype.charAt(i)){ - case '[': - arraydim++; - break; - case 'L': - if(strtype.charAt(strtype.length()-1) == ';') { - type = CodeConstants.TYPE_OBJECT; - value = strtype.substring(i+1, strtype.length()-1); - return; - } - default: - value = strtype.substring(i, strtype.length()); - if((cltype && i == 0) || value.length()>1) { - type = CodeConstants.TYPE_OBJECT; - } else { - type = getType(value.charAt(0)); - } - return; - } - } - } - - private void setStackSize(int type) { - if(arraydim > 0) { - stack_size = 1; - } else { - stack_size = (type == CodeConstants.TYPE_DOUBLE || - type == CodeConstants.TYPE_LONG)?2: - ((type == CodeConstants.TYPE_VOID || - type == CodeConstants.TYPE_GROUP2EMPTY)?0:1); - } - } - - private int getType(char c) { - switch(c) { - case 'B': - return CodeConstants.TYPE_BYTE; - case 'C': - return CodeConstants.TYPE_CHAR; - case 'D': - return CodeConstants.TYPE_DOUBLE; - case 'F': - return CodeConstants.TYPE_FLOAT; - case 'I': - return CodeConstants.TYPE_INT; - case 'J': - return CodeConstants.TYPE_LONG; - case 'S': - return CodeConstants.TYPE_SHORT; - case 'Z': - return CodeConstants.TYPE_BOOLEAN; - case 'V': - return CodeConstants.TYPE_VOID; - case 'G': - return CodeConstants.TYPE_GROUP2EMPTY; - case 'N': - return CodeConstants.TYPE_NOTINITIALIZED; - case 'A': - return CodeConstants.TYPE_ADDRESS; - case 'X': - return CodeConstants.TYPE_BYTECHAR; - case 'Y': - return CodeConstants.TYPE_SHORTCHAR; - case 'U': - return CodeConstants.TYPE_UNKNOWN; - default: - throw new RuntimeException("Invalid type"); - } - } - - private String getChar(int type) { - switch(type) { - case CodeConstants.TYPE_BYTE: - return "B"; - case CodeConstants.TYPE_CHAR: - return "C"; - case CodeConstants.TYPE_DOUBLE: - return "D"; - case CodeConstants.TYPE_FLOAT: - return "F"; - case CodeConstants.TYPE_INT: - return "I"; - case CodeConstants.TYPE_LONG: - return "J"; - case CodeConstants.TYPE_SHORT: - return "S"; - case CodeConstants.TYPE_BOOLEAN: - return "Z"; - case CodeConstants.TYPE_VOID: - return "V"; - case CodeConstants.TYPE_GROUP2EMPTY: - return "G"; - case CodeConstants.TYPE_NOTINITIALIZED: - return "N"; - case CodeConstants.TYPE_ADDRESS: - return "A"; - case CodeConstants.TYPE_BYTECHAR: - return "X"; - case CodeConstants.TYPE_SHORTCHAR: - return "Y"; - case CodeConstants.TYPE_UNKNOWN: - return "U"; - case CodeConstants.TYPE_NULL: - case CodeConstants.TYPE_OBJECT: - return null; - default: - throw new RuntimeException("Invalid type"); - } - } - - public void setFamily() { - - if(arraydim > 0) { - this.type_family = CodeConstants.TYPE_FAMILY_OBJECT; - return; - } - - switch(type) { - case CodeConstants.TYPE_BYTE: - case CodeConstants.TYPE_BYTECHAR: - case CodeConstants.TYPE_SHORTCHAR: - case CodeConstants.TYPE_CHAR: - case CodeConstants.TYPE_SHORT: - case CodeConstants.TYPE_INT: - this.type_family = CodeConstants.TYPE_FAMILY_INTEGER; - break; - case CodeConstants.TYPE_DOUBLE: - this.type_family = CodeConstants.TYPE_FAMILY_DOUBLE; - break; - case CodeConstants.TYPE_FLOAT: - this.type_family = CodeConstants.TYPE_FAMILY_FLOAT; - break; - case CodeConstants.TYPE_LONG: - this.type_family = CodeConstants.TYPE_FAMILY_LONG; - break; - case CodeConstants.TYPE_BOOLEAN: - this.type_family = CodeConstants.TYPE_FAMILY_BOOLEAN; - break; - case CodeConstants.TYPE_NULL: - case CodeConstants.TYPE_OBJECT: - this.type_family = CodeConstants.TYPE_FAMILY_OBJECT; - break; - default: - this.type_family = CodeConstants.TYPE_FAMILY_UNKNOWN; - } - } - + + public static final int FALSEBOOLEAN = 1; + + public static final VarType VARTYPE_UNKNOWN = new VarType(CodeConstants.TYPE_UNKNOWN); + public static final VarType VARTYPE_INT = new VarType(CodeConstants.TYPE_INT); + public static final VarType VARTYPE_FLOAT = new VarType(CodeConstants.TYPE_FLOAT); + public static final VarType VARTYPE_LONG = new VarType(CodeConstants.TYPE_LONG); + public static final VarType VARTYPE_DOUBLE = new VarType(CodeConstants.TYPE_DOUBLE); + public static final VarType VARTYPE_BYTE = new VarType(CodeConstants.TYPE_BYTE); + public static final VarType VARTYPE_CHAR = new VarType(CodeConstants.TYPE_CHAR); + public static final VarType VARTYPE_SHORT = new VarType(CodeConstants.TYPE_SHORT); + public static final VarType VARTYPE_BOOLEAN = new VarType(CodeConstants.TYPE_BOOLEAN); + public static final VarType VARTYPE_BYTECHAR = new VarType(CodeConstants.TYPE_BYTECHAR); + public static final VarType VARTYPE_SHORTCHAR = new VarType(CodeConstants.TYPE_SHORTCHAR); + + public static final VarType VARTYPE_NULL = new VarType(CodeConstants.TYPE_NULL, 0, null); + public static final VarType VARTYPE_GROUP2EMPTY = new VarType(CodeConstants.TYPE_GROUP2EMPTY); + public static final VarType VARTYPE_STRING = new VarType(CodeConstants.TYPE_OBJECT, 0, "java/lang/String"); + public static final VarType VARTYPE_CLASS = new VarType(CodeConstants.TYPE_OBJECT, 0, "java/lang/Class"); + public static final VarType VARTYPE_OBJECT = new VarType(CodeConstants.TYPE_OBJECT, 0, "java/lang/Object"); + public static final VarType VARTYPE_VOID = new VarType(CodeConstants.TYPE_VOID); + + public int type; + + public int type_family; + + public int arraydim; + + public String value; + + public int stack_size; + + public int convinfo; + + public VarType(int type) { + this.type = type; + this.arraydim = 0; + + value = getChar(type); + setStackSize(type); + setFamily(); + } + + public VarType(int type, int arraydim) { + this(type); + this.arraydim = arraydim; + setFamily(); + } + + public VarType(int type, int arraydim, String value) { + this(type); + this.arraydim = arraydim; + this.value = value; + setFamily(); + } + + public VarType(String strtype) { + this(strtype, false); + } + + public VarType(String strtype, boolean cltype) { + parseTypeString(strtype, cltype); + setStackSize(type); + setFamily(); + } + + public void decArrayDim() { + if (arraydim > 0) { + arraydim--; + setFamily(); + } + else { + // throw new RuntimeException("array dimension equals 0!"); FIXME: investigate this case + } + } + + public String toString() { + String res = ""; + + for (int i = 0; i < arraydim; i++) { + res += "["; + } + + if (type == CodeConstants.TYPE_OBJECT) { + res += "L" + value + ";"; + } + else { + res += value; + } + + return res; + } + + public VarType copy() { + VarType v = new VarType(type, arraydim, value); + v.convinfo = convinfo; + return v; + } + + public boolean isFalseBoolean() { + return (convinfo & VarType.FALSEBOOLEAN) != 0; + } + + public boolean isSuperset(VarType val) { + + return this.equals(val) || this.isStrictSuperset(val); + } + + public boolean isStrictSuperset(VarType val) { + + int valtype = val.type; + + if (valtype == CodeConstants.TYPE_UNKNOWN && type != CodeConstants.TYPE_UNKNOWN) { + return true; + } + + if (val.arraydim > 0) { + return this.equals(VARTYPE_OBJECT); + } + else if (arraydim > 0) { + return (valtype == CodeConstants.TYPE_NULL); + } + + boolean res = false; + + switch (type) { + case CodeConstants.TYPE_INT: + res |= (valtype == CodeConstants.TYPE_SHORT || + valtype == CodeConstants.TYPE_CHAR); + case CodeConstants.TYPE_SHORT: + res |= (valtype == CodeConstants.TYPE_BYTE); + case CodeConstants.TYPE_CHAR: + res |= (valtype == CodeConstants.TYPE_SHORTCHAR); + case CodeConstants.TYPE_BYTE: + case CodeConstants.TYPE_SHORTCHAR: + res |= (valtype == CodeConstants.TYPE_BYTECHAR); + case CodeConstants.TYPE_BYTECHAR: + res |= (valtype == CodeConstants.TYPE_BOOLEAN); + break; + case CodeConstants.TYPE_OBJECT: + if (valtype == CodeConstants.TYPE_NULL) { + return true; + } + else if (this.equals(VARTYPE_OBJECT)) { + return valtype == CodeConstants.TYPE_OBJECT && + !val.equals(VARTYPE_OBJECT); + } + } + + return res; + } + + // type1 and type2 must not be null + public static VarType getCommonMinType(VarType type1, VarType type2) { + + if (type1.type == CodeConstants.TYPE_BOOLEAN && type2.type == CodeConstants.TYPE_BOOLEAN) { // special case booleans + return type1.isFalseBoolean() ? type2 : type1; + } + + if (type1.isSuperset(type2)) { + return type2; + } + else if (type2.isSuperset(type1)) { + return type1; + } + else if (type1.type_family == type2.type_family) { + switch (type1.type_family) { + case CodeConstants.TYPE_FAMILY_INTEGER: + if ((type1.type == CodeConstants.TYPE_CHAR && type2.type == CodeConstants.TYPE_SHORT) + || (type1.type == CodeConstants.TYPE_SHORT && type2.type == CodeConstants.TYPE_CHAR)) { + return VarType.VARTYPE_SHORTCHAR; + } + else { + return VarType.VARTYPE_BYTECHAR; + } + case CodeConstants.TYPE_FAMILY_OBJECT: + return VarType.VARTYPE_NULL; + } + } + + return null; + } + + // type1 and type2 must not be null + public static VarType getCommonSupertype(VarType type1, VarType type2) { + + if (type1.type == CodeConstants.TYPE_BOOLEAN && type2.type == CodeConstants.TYPE_BOOLEAN) { // special case booleans + return type1.isFalseBoolean() ? type1 : type2; + } + + if (type1.isSuperset(type2)) { + return type1; + } + else if (type2.isSuperset(type1)) { + return type2; + } + else if (type1.type_family == type2.type_family) { + switch (type1.type_family) { + case CodeConstants.TYPE_FAMILY_INTEGER: + if ((type1.type == CodeConstants.TYPE_SHORTCHAR && type2.type == CodeConstants.TYPE_BYTE) + || (type1.type == CodeConstants.TYPE_BYTE && type2.type == CodeConstants.TYPE_SHORTCHAR)) { + return VarType.VARTYPE_SHORT; + } + else { + return VarType.VARTYPE_INT; + } + case CodeConstants.TYPE_FAMILY_OBJECT: + return VarType.VARTYPE_OBJECT; + } + } + + return null; + } + + public static VarType getMinTypeInFamily(int family) { + switch (family) { + case CodeConstants.TYPE_FAMILY_BOOLEAN: + return VarType.VARTYPE_BOOLEAN; + case CodeConstants.TYPE_FAMILY_INTEGER: + return VarType.VARTYPE_BYTECHAR; + case CodeConstants.TYPE_FAMILY_OBJECT: + return VarType.VARTYPE_NULL; + case CodeConstants.TYPE_FAMILY_FLOAT: + return VarType.VARTYPE_FLOAT; + case CodeConstants.TYPE_FAMILY_LONG: + return VarType.VARTYPE_LONG; + case CodeConstants.TYPE_FAMILY_DOUBLE: + return VarType.VARTYPE_DOUBLE; + case CodeConstants.TYPE_FAMILY_UNKNOWN: + return VarType.VARTYPE_UNKNOWN; + default: + throw new RuntimeException("invalid type family!"); + } + } + + public boolean equals(Object o) { + + if (o == this) { + return true; + } + + if (o == null || !(o instanceof VarType)) { + return false; + } + + VarType vt = (VarType)o; + return type == vt.type && arraydim == vt.arraydim && InterpreterUtil.equalObjects(value, vt.value); + } + + private void parseTypeString(String strtype, boolean cltype) { + + for (int i = 0; i < strtype.length(); i++) { + switch (strtype.charAt(i)) { + case '[': + arraydim++; + break; + case 'L': + if (strtype.charAt(strtype.length() - 1) == ';') { + type = CodeConstants.TYPE_OBJECT; + value = strtype.substring(i + 1, strtype.length() - 1); + return; + } + default: + value = strtype.substring(i, strtype.length()); + if ((cltype && i == 0) || value.length() > 1) { + type = CodeConstants.TYPE_OBJECT; + } + else { + type = getType(value.charAt(0)); + } + return; + } + } + } + + private void setStackSize(int type) { + if (arraydim > 0) { + stack_size = 1; + } + else { + stack_size = (type == CodeConstants.TYPE_DOUBLE || + type == CodeConstants.TYPE_LONG) ? 2 : + ((type == CodeConstants.TYPE_VOID || + type == CodeConstants.TYPE_GROUP2EMPTY) ? 0 : 1); + } + } + + private int getType(char c) { + switch (c) { + case 'B': + return CodeConstants.TYPE_BYTE; + case 'C': + return CodeConstants.TYPE_CHAR; + case 'D': + return CodeConstants.TYPE_DOUBLE; + case 'F': + return CodeConstants.TYPE_FLOAT; + case 'I': + return CodeConstants.TYPE_INT; + case 'J': + return CodeConstants.TYPE_LONG; + case 'S': + return CodeConstants.TYPE_SHORT; + case 'Z': + return CodeConstants.TYPE_BOOLEAN; + case 'V': + return CodeConstants.TYPE_VOID; + case 'G': + return CodeConstants.TYPE_GROUP2EMPTY; + case 'N': + return CodeConstants.TYPE_NOTINITIALIZED; + case 'A': + return CodeConstants.TYPE_ADDRESS; + case 'X': + return CodeConstants.TYPE_BYTECHAR; + case 'Y': + return CodeConstants.TYPE_SHORTCHAR; + case 'U': + return CodeConstants.TYPE_UNKNOWN; + default: + throw new RuntimeException("Invalid type"); + } + } + + private String getChar(int type) { + switch (type) { + case CodeConstants.TYPE_BYTE: + return "B"; + case CodeConstants.TYPE_CHAR: + return "C"; + case CodeConstants.TYPE_DOUBLE: + return "D"; + case CodeConstants.TYPE_FLOAT: + return "F"; + case CodeConstants.TYPE_INT: + return "I"; + case CodeConstants.TYPE_LONG: + return "J"; + case CodeConstants.TYPE_SHORT: + return "S"; + case CodeConstants.TYPE_BOOLEAN: + return "Z"; + case CodeConstants.TYPE_VOID: + return "V"; + case CodeConstants.TYPE_GROUP2EMPTY: + return "G"; + case CodeConstants.TYPE_NOTINITIALIZED: + return "N"; + case CodeConstants.TYPE_ADDRESS: + return "A"; + case CodeConstants.TYPE_BYTECHAR: + return "X"; + case CodeConstants.TYPE_SHORTCHAR: + return "Y"; + case CodeConstants.TYPE_UNKNOWN: + return "U"; + case CodeConstants.TYPE_NULL: + case CodeConstants.TYPE_OBJECT: + return null; + default: + throw new RuntimeException("Invalid type"); + } + } + + public void setFamily() { + + if (arraydim > 0) { + this.type_family = CodeConstants.TYPE_FAMILY_OBJECT; + return; + } + + switch (type) { + case CodeConstants.TYPE_BYTE: + case CodeConstants.TYPE_BYTECHAR: + case CodeConstants.TYPE_SHORTCHAR: + case CodeConstants.TYPE_CHAR: + case CodeConstants.TYPE_SHORT: + case CodeConstants.TYPE_INT: + this.type_family = CodeConstants.TYPE_FAMILY_INTEGER; + break; + case CodeConstants.TYPE_DOUBLE: + this.type_family = CodeConstants.TYPE_FAMILY_DOUBLE; + break; + case CodeConstants.TYPE_FLOAT: + this.type_family = CodeConstants.TYPE_FAMILY_FLOAT; + break; + case CodeConstants.TYPE_LONG: + this.type_family = CodeConstants.TYPE_FAMILY_LONG; + break; + case CodeConstants.TYPE_BOOLEAN: + this.type_family = CodeConstants.TYPE_FAMILY_BOOLEAN; + break; + case CodeConstants.TYPE_NULL: + case CodeConstants.TYPE_OBJECT: + this.type_family = CodeConstants.TYPE_FAMILY_OBJECT; + break; + default: + this.type_family = CodeConstants.TYPE_FAMILY_UNKNOWN; + } + } } diff --git a/src/org/jetbrains/java/decompiler/struct/gen/generics/GenericClassDescriptor.java b/src/org/jetbrains/java/decompiler/struct/gen/generics/GenericClassDescriptor.java index d4551ac..66fab96 100644 --- a/src/org/jetbrains/java/decompiler/struct/gen/generics/GenericClassDescriptor.java +++ b/src/org/jetbrains/java/decompiler/struct/gen/generics/GenericClassDescriptor.java @@ -1,17 +1,18 @@ /* - * Fernflower - The Analytical Java Decompiler - * http://www.reversed-java.com + * Copyright 2000-2014 JetBrains s.r.o. * - * (C) 2008 - 2010, Stiver + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at * - * This software is NEITHER public domain NOR free software - * as per GNU License. See license.txt for more details. + * http://www.apache.org/licenses/LICENSE-2.0 * - * This software is distributed WITHOUT ANY WARRANTY; without - * even the implied warranty of MERCHANTABILITY or FITNESS FOR - * A PARTICULAR PURPOSE. + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. */ - package org.jetbrains.java.decompiler.struct.gen.generics; import java.util.ArrayList; @@ -19,12 +20,11 @@ import java.util.List; public class GenericClassDescriptor { - public GenericType superclass; - - public List<GenericType> superinterfaces = new ArrayList<GenericType>(); - - public List<String> fparameters = new ArrayList<String>(); + public GenericType superclass; + + public List<GenericType> superinterfaces = new ArrayList<GenericType>(); + + public List<String> fparameters = new ArrayList<String>(); - public List<List<GenericType>> fbounds = new ArrayList<List<GenericType>>(); - + public List<List<GenericType>> fbounds = new ArrayList<List<GenericType>>(); } diff --git a/src/org/jetbrains/java/decompiler/struct/gen/generics/GenericFieldDescriptor.java b/src/org/jetbrains/java/decompiler/struct/gen/generics/GenericFieldDescriptor.java index 4b4114d..598d17b 100644 --- a/src/org/jetbrains/java/decompiler/struct/gen/generics/GenericFieldDescriptor.java +++ b/src/org/jetbrains/java/decompiler/struct/gen/generics/GenericFieldDescriptor.java @@ -1,21 +1,21 @@ /* - * Fernflower - The Analytical Java Decompiler - * http://www.reversed-java.com + * Copyright 2000-2014 JetBrains s.r.o. * - * (C) 2008 - 2010, Stiver + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at * - * This software is NEITHER public domain NOR free software - * as per GNU License. See license.txt for more details. + * http://www.apache.org/licenses/LICENSE-2.0 * - * This software is distributed WITHOUT ANY WARRANTY; without - * even the implied warranty of MERCHANTABILITY or FITNESS FOR - * A PARTICULAR PURPOSE. + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. */ - package org.jetbrains.java.decompiler.struct.gen.generics; public class GenericFieldDescriptor { - public GenericType type; - + public GenericType type; } diff --git a/src/org/jetbrains/java/decompiler/struct/gen/generics/GenericMain.java b/src/org/jetbrains/java/decompiler/struct/gen/generics/GenericMain.java index 50433a9..db7d84b 100644 --- a/src/org/jetbrains/java/decompiler/struct/gen/generics/GenericMain.java +++ b/src/org/jetbrains/java/decompiler/struct/gen/generics/GenericMain.java @@ -1,229 +1,233 @@ /* - * Fernflower - The Analytical Java Decompiler - * http://www.reversed-java.com + * Copyright 2000-2014 JetBrains s.r.o. * - * (C) 2008 - 2010, Stiver + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at * - * This software is NEITHER public domain NOR free software - * as per GNU License. See license.txt for more details. + * http://www.apache.org/licenses/LICENSE-2.0 * - * This software is distributed WITHOUT ANY WARRANTY; without - * even the implied warranty of MERCHANTABILITY or FITNESS FOR - * A PARTICULAR PURPOSE. + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. */ - package org.jetbrains.java.decompiler.struct.gen.generics; -import java.util.ArrayList; -import java.util.List; - import org.jetbrains.java.decompiler.code.CodeConstants; import org.jetbrains.java.decompiler.main.DecompilerContext; import org.jetbrains.java.decompiler.struct.StructClass; +import java.util.ArrayList; +import java.util.List; + public class GenericMain { - - private static final String[] typeNames = new String[] { - "byte", - "char", - "double", - "float", - "int", - "long", - "short", - "boolean", - }; - - public static GenericClassDescriptor parseClassSignature(String signature) { - - GenericClassDescriptor descriptor = new GenericClassDescriptor(); - - signature = parseFormalParameters(signature, descriptor.fparameters, descriptor.fbounds); - - String supercl = GenericType.getNextType(signature); - descriptor.superclass = new GenericType(supercl); - - signature = signature.substring(supercl.length()); - while(signature.length() > 0) { - String superintr = GenericType.getNextType(signature); - descriptor.superinterfaces.add(new GenericType(superintr)); - signature = signature.substring(superintr.length()); - } - - return descriptor; - } - - public static GenericFieldDescriptor parseFieldSignature(String signature) { - GenericFieldDescriptor descriptor = new GenericFieldDescriptor(); - descriptor.type = new GenericType(signature); - return descriptor; - } - - public static GenericMethodDescriptor parseMethodSignature(String signature) { - - GenericMethodDescriptor descriptor = new GenericMethodDescriptor(); - - signature = parseFormalParameters(signature, descriptor.fparameters, descriptor.fbounds); - - int to = signature.indexOf(")"); - String pars = signature.substring(1, to); - signature = signature.substring(to+1); - - while(pars.length() > 0) { - String par = GenericType.getNextType(pars); - descriptor.params.add(new GenericType(par)); - pars = pars.substring(par.length()); - } - - String par = GenericType.getNextType(signature); - descriptor.ret = new GenericType(par); - signature = signature.substring(par.length()); - - if(signature.length() > 0) { - String[] excs = signature.split("\\^"); - - for(int i=1;i<excs.length;i++) { - descriptor.exceptions.add(new GenericType(excs[i])); - } - } - - return descriptor; - } - - private static String parseFormalParameters(String signature, List<String> fparameters, List<List<GenericType>> fbounds) { - - if(signature.charAt(0) != '<') { - return signature; - } - - int counter = 1; - int index = 1; - - loop: - while(index < signature.length()) { - switch(signature.charAt(index)) { - case '<': - counter++; - break; - case '>': - counter--; - if(counter == 0) { - break loop; - } - } - - index++; - } - - String value = signature.substring(1, index); - signature = signature.substring(index+1); - - while(value.length() > 0) { - int parto = value.indexOf(":"); - - String param = value.substring(0, parto); - value = value.substring(parto+1); - - List<GenericType> lstBounds = new ArrayList<GenericType>(); - - for(;;) { - if(value.charAt(0) == ':') { - // empty superclass, skip - value = value.substring(1); - } - - String bound = GenericType.getNextType(value); - lstBounds.add(new GenericType(bound)); - value = value.substring(bound.length()); - - - if(value.length() == 0 || value.charAt(0) != ':') { - break; - } else { - value = value.substring(1); - } - } - - fparameters.add(param); - fbounds.add(lstBounds); - } - - return signature; - } - - public static String getGenericCastTypeName(GenericType type) { - String s = getTypeName(type); - int dim = type.arraydim; - while(dim-->0) { - s+="[]"; - } - return s; - } - - public static String getTypeName(GenericType type) { - - int tp = type.type; - if(tp <= CodeConstants.TYPE_BOOLEAN) { - return typeNames[tp]; - } else if(tp == CodeConstants.TYPE_VOID) { - return "void"; - } else if(tp == CodeConstants.TYPE_GENVAR) { - return type.value; - } else if(tp == CodeConstants.TYPE_OBJECT) { - StringBuilder buffer = new StringBuilder(); - buffer.append(DecompilerContext.getImpcollector().getShortName(buildJavaClassName(type))); - - if(!type.getArguments().isEmpty()) { - buffer.append("<"); - for(int i=0;i<type.getArguments().size();i++) { - if(i>0) { - buffer.append(", "); - } - int wildcard = type.getWildcards().get(i); - if(wildcard != GenericType.WILDCARD_NO) { - buffer.append("?"); - - switch(wildcard){ - case GenericType.WILDCARD_EXTENDS: - buffer.append(" extends "); - break; - case GenericType.WILDCARD_SUPER: - buffer.append(" super "); - } - } - - GenericType genpar = type.getArguments().get(i); - if(genpar != null) { - buffer.append(GenericMain.getGenericCastTypeName(genpar)); - } - } - buffer.append(">"); - } - - return buffer.toString(); - } - - throw new RuntimeException("invalid type"); - } - - public static String buildJavaClassName(GenericType type) { - - String name = ""; - for(GenericType tp : type.getEnclosingClasses()) { - name += tp.value+"$"; - } - name+=type.value; - - String res = name.replace('/', '.'); - - if(res.indexOf("$") >=0) { - StructClass cl = DecompilerContext.getStructcontext().getClass(name); - if(cl == null || !cl.isOwn()) { - res = res.replace('$', '.'); - } - } - - return res; - } - + + private static final String[] typeNames = new String[]{ + "byte", + "char", + "double", + "float", + "int", + "long", + "short", + "boolean", + }; + + public static GenericClassDescriptor parseClassSignature(String signature) { + + GenericClassDescriptor descriptor = new GenericClassDescriptor(); + + signature = parseFormalParameters(signature, descriptor.fparameters, descriptor.fbounds); + + String supercl = GenericType.getNextType(signature); + descriptor.superclass = new GenericType(supercl); + + signature = signature.substring(supercl.length()); + while (signature.length() > 0) { + String superintr = GenericType.getNextType(signature); + descriptor.superinterfaces.add(new GenericType(superintr)); + signature = signature.substring(superintr.length()); + } + + return descriptor; + } + + public static GenericFieldDescriptor parseFieldSignature(String signature) { + GenericFieldDescriptor descriptor = new GenericFieldDescriptor(); + descriptor.type = new GenericType(signature); + return descriptor; + } + + public static GenericMethodDescriptor parseMethodSignature(String signature) { + + GenericMethodDescriptor descriptor = new GenericMethodDescriptor(); + + signature = parseFormalParameters(signature, descriptor.fparameters, descriptor.fbounds); + + int to = signature.indexOf(")"); + String pars = signature.substring(1, to); + signature = signature.substring(to + 1); + + while (pars.length() > 0) { + String par = GenericType.getNextType(pars); + descriptor.params.add(new GenericType(par)); + pars = pars.substring(par.length()); + } + + String par = GenericType.getNextType(signature); + descriptor.ret = new GenericType(par); + signature = signature.substring(par.length()); + + if (signature.length() > 0) { + String[] excs = signature.split("\\^"); + + for (int i = 1; i < excs.length; i++) { + descriptor.exceptions.add(new GenericType(excs[i])); + } + } + + return descriptor; + } + + private static String parseFormalParameters(String signature, List<String> fparameters, List<List<GenericType>> fbounds) { + + if (signature.charAt(0) != '<') { + return signature; + } + + int counter = 1; + int index = 1; + + loop: + while (index < signature.length()) { + switch (signature.charAt(index)) { + case '<': + counter++; + break; + case '>': + counter--; + if (counter == 0) { + break loop; + } + } + + index++; + } + + String value = signature.substring(1, index); + signature = signature.substring(index + 1); + + while (value.length() > 0) { + int parto = value.indexOf(":"); + + String param = value.substring(0, parto); + value = value.substring(parto + 1); + + List<GenericType> lstBounds = new ArrayList<GenericType>(); + + for (; ; ) { + if (value.charAt(0) == ':') { + // empty superclass, skip + value = value.substring(1); + } + + String bound = GenericType.getNextType(value); + lstBounds.add(new GenericType(bound)); + value = value.substring(bound.length()); + + + if (value.length() == 0 || value.charAt(0) != ':') { + break; + } + else { + value = value.substring(1); + } + } + + fparameters.add(param); + fbounds.add(lstBounds); + } + + return signature; + } + + public static String getGenericCastTypeName(GenericType type) { + String s = getTypeName(type); + int dim = type.arraydim; + while (dim-- > 0) { + s += "[]"; + } + return s; + } + + public static String getTypeName(GenericType type) { + + int tp = type.type; + if (tp <= CodeConstants.TYPE_BOOLEAN) { + return typeNames[tp]; + } + else if (tp == CodeConstants.TYPE_VOID) { + return "void"; + } + else if (tp == CodeConstants.TYPE_GENVAR) { + return type.value; + } + else if (tp == CodeConstants.TYPE_OBJECT) { + StringBuilder buffer = new StringBuilder(); + buffer.append(DecompilerContext.getImpcollector().getShortName(buildJavaClassName(type))); + + if (!type.getArguments().isEmpty()) { + buffer.append("<"); + for (int i = 0; i < type.getArguments().size(); i++) { + if (i > 0) { + buffer.append(", "); + } + int wildcard = type.getWildcards().get(i); + if (wildcard != GenericType.WILDCARD_NO) { + buffer.append("?"); + + switch (wildcard) { + case GenericType.WILDCARD_EXTENDS: + buffer.append(" extends "); + break; + case GenericType.WILDCARD_SUPER: + buffer.append(" super "); + } + } + + GenericType genpar = type.getArguments().get(i); + if (genpar != null) { + buffer.append(GenericMain.getGenericCastTypeName(genpar)); + } + } + buffer.append(">"); + } + + return buffer.toString(); + } + + throw new RuntimeException("invalid type"); + } + + public static String buildJavaClassName(GenericType type) { + + String name = ""; + for (GenericType tp : type.getEnclosingClasses()) { + name += tp.value + "$"; + } + name += type.value; + + String res = name.replace('/', '.'); + + if (res.indexOf("$") >= 0) { + StructClass cl = DecompilerContext.getStructcontext().getClass(name); + if (cl == null || !cl.isOwn()) { + res = res.replace('$', '.'); + } + } + + return res; + } } diff --git a/src/org/jetbrains/java/decompiler/struct/gen/generics/GenericMethodDescriptor.java b/src/org/jetbrains/java/decompiler/struct/gen/generics/GenericMethodDescriptor.java index 7a0a4d1..7b4c9dc 100644 --- a/src/org/jetbrains/java/decompiler/struct/gen/generics/GenericMethodDescriptor.java +++ b/src/org/jetbrains/java/decompiler/struct/gen/generics/GenericMethodDescriptor.java @@ -1,17 +1,18 @@ /* - * Fernflower - The Analytical Java Decompiler - * http://www.reversed-java.com + * Copyright 2000-2014 JetBrains s.r.o. * - * (C) 2008 - 2010, Stiver + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at * - * This software is NEITHER public domain NOR free software - * as per GNU License. See license.txt for more details. + * http://www.apache.org/licenses/LICENSE-2.0 * - * This software is distributed WITHOUT ANY WARRANTY; without - * even the implied warranty of MERCHANTABILITY or FITNESS FOR - * A PARTICULAR PURPOSE. + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. */ - package org.jetbrains.java.decompiler.struct.gen.generics; import java.util.ArrayList; @@ -19,14 +20,13 @@ import java.util.List; public class GenericMethodDescriptor { - public List<String> fparameters = new ArrayList<String>(); + public List<String> fparameters = new ArrayList<String>(); + + public List<List<GenericType>> fbounds = new ArrayList<List<GenericType>>(); + + public List<GenericType> params = new ArrayList<GenericType>(); - public List<List<GenericType>> fbounds = new ArrayList<List<GenericType>>(); + public GenericType ret; - public List<GenericType> params = new ArrayList<GenericType>(); - - public GenericType ret; - - public List<GenericType> exceptions = new ArrayList<GenericType>(); - + public List<GenericType> exceptions = new ArrayList<GenericType>(); } diff --git a/src/org/jetbrains/java/decompiler/struct/gen/generics/GenericType.java b/src/org/jetbrains/java/decompiler/struct/gen/generics/GenericType.java index 1f720e6..e2faa4a 100644 --- a/src/org/jetbrains/java/decompiler/struct/gen/generics/GenericType.java +++ b/src/org/jetbrains/java/decompiler/struct/gen/generics/GenericType.java @@ -1,270 +1,268 @@ /* - * Fernflower - The Analytical Java Decompiler - * http://www.reversed-java.com + * Copyright 2000-2014 JetBrains s.r.o. * - * (C) 2008 - 2010, Stiver + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at * - * This software is NEITHER public domain NOR free software - * as per GNU License. See license.txt for more details. + * http://www.apache.org/licenses/LICENSE-2.0 * - * This software is distributed WITHOUT ANY WARRANTY; without - * even the implied warranty of MERCHANTABILITY or FITNESS FOR - * A PARTICULAR PURPOSE. + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. */ - package org.jetbrains.java.decompiler.struct.gen.generics; +import org.jetbrains.java.decompiler.code.CodeConstants; + import java.util.ArrayList; import java.util.List; -import org.jetbrains.java.decompiler.code.CodeConstants; - public class GenericType { - - public static final int WILDCARD_EXTENDS = 1; - public static final int WILDCARD_SUPER = 2; - public static final int WILDCARD_UNBOUND = 3; - public static final int WILDCARD_NO = 4; - - public int type; - - public int arraydim; - - public String value; - - - private List<GenericType> enclosingClasses = new ArrayList<GenericType>(); - - private List<GenericType> arguments = new ArrayList<GenericType>(); - - private List<Integer> wildcards = new ArrayList<Integer>(); - - - public GenericType(int type, int arraydim, String value) { - this.type = type; - this.arraydim = arraydim; - this.value = value; - } - - - public GenericType(String strtype) { - - parseSignature(strtype); - - } - - private void parseSignature(String sig) { - - int index = 0; - while(index < sig.length()) { - - switch(sig.charAt(index)){ - case '[': - arraydim++; - break; - case 'T': - type = CodeConstants.TYPE_GENVAR; - value = sig.substring(index+1, sig.length()-1); - return; - case 'L': - type = CodeConstants.TYPE_OBJECT; - sig = sig.substring(index+1, sig.length()-1); - - for(;;) { - String cl = getNextClassSignature(sig); - - String name = cl; - String args = null; - - int argfrom = cl.indexOf("<"); - if(argfrom >= 0) { - name = cl.substring(0, argfrom); - args = cl.substring(argfrom+1, cl.length()-1); - } - - if(cl.length() < sig.length()) { - sig = sig.substring(cl.length()+1); // skip '.' - GenericType type = new GenericType(CodeConstants.TYPE_OBJECT, 0, name); - parseArgumentsList(args, type); - enclosingClasses.add(type); - } else { - value = name; - parseArgumentsList(args, this); - break; - } - } - - return; - default: - value = sig.substring(index, index+1); - type = getType(value.charAt(0)); - } - - index++; - } - - } - - private String getNextClassSignature(String value) { - - int counter = 0; - int index = 0; - - loop: - while(index < value.length()) { - switch(value.charAt(index)) { - case '<': - counter++; - break; - case '>': - counter--; - break; - case '.': - if(counter == 0) { - break loop; - } - } - - index++; - } - - return value.substring(0, index); - } - - private void parseArgumentsList(String value, GenericType type) { - - if(value == null) { - return; - } - - while(value.length() > 0) { - - String tstr = getNextType(value); - int len = tstr.length(); - int wildcard = WILDCARD_NO; - - switch(tstr.charAt(0)) { - case '*': - wildcard = WILDCARD_UNBOUND; - break; - case '+': - wildcard = WILDCARD_EXTENDS; - break; - case '-': - wildcard = WILDCARD_SUPER; - break; - } - - type.getWildcards().add(wildcard); - - if(wildcard != WILDCARD_NO) { - tstr = tstr.substring(1); - } - - type.getArguments().add(tstr.length() == 0?null:new GenericType(tstr)); - - value = value.substring(len); - } - - } - - public static String getNextType(String value) { - - int counter = 0; - int index = 0; - - boolean contmode = false; - - loop: - while(index < value.length()) { - switch(value.charAt(index)) { - case '*': - if(!contmode) { - break loop; - } - break; - case 'L': - case 'T': - if(!contmode) { - contmode = true; - } - case '[': - case '+': - case '-': - break; - default: - if(!contmode) { - break loop; - } - break; - case '<': - counter++; - break; - case '>': - counter--; - break; - case ';': - if(counter == 0) { - break loop; - } - } - - index++; - } - - return value.substring(0, index+1); - } - - private int getType(char c) { - switch(c) { - case 'B': - return CodeConstants.TYPE_BYTE; - case 'C': - return CodeConstants.TYPE_CHAR; - case 'D': - return CodeConstants.TYPE_DOUBLE; - case 'F': - return CodeConstants.TYPE_FLOAT; - case 'I': - return CodeConstants.TYPE_INT; - case 'J': - return CodeConstants.TYPE_LONG; - case 'S': - return CodeConstants.TYPE_SHORT; - case 'Z': - return CodeConstants.TYPE_BOOLEAN; - case 'V': - return CodeConstants.TYPE_VOID; - case 'G': - return CodeConstants.TYPE_GROUP2EMPTY; - case 'N': - return CodeConstants.TYPE_NOTINITIALIZED; - case 'A': - return CodeConstants.TYPE_ADDRESS; - case 'X': - return CodeConstants.TYPE_BYTECHAR; - case 'Y': - return CodeConstants.TYPE_SHORTCHAR; - case 'U': - return CodeConstants.TYPE_UNKNOWN; - default: - throw new RuntimeException("Invalid type"); - } - } - - - public List<GenericType> getArguments() { - return arguments; - } - - - public List<GenericType> getEnclosingClasses() { - return enclosingClasses; - } - - - public List<Integer> getWildcards() { - return wildcards; - } - + + public static final int WILDCARD_EXTENDS = 1; + public static final int WILDCARD_SUPER = 2; + public static final int WILDCARD_UNBOUND = 3; + public static final int WILDCARD_NO = 4; + + public int type; + + public int arraydim; + + public String value; + + + private List<GenericType> enclosingClasses = new ArrayList<GenericType>(); + + private List<GenericType> arguments = new ArrayList<GenericType>(); + + private List<Integer> wildcards = new ArrayList<Integer>(); + + + public GenericType(int type, int arraydim, String value) { + this.type = type; + this.arraydim = arraydim; + this.value = value; + } + + + public GenericType(String strtype) { + + parseSignature(strtype); + } + + private void parseSignature(String sig) { + + int index = 0; + while (index < sig.length()) { + + switch (sig.charAt(index)) { + case '[': + arraydim++; + break; + case 'T': + type = CodeConstants.TYPE_GENVAR; + value = sig.substring(index + 1, sig.length() - 1); + return; + case 'L': + type = CodeConstants.TYPE_OBJECT; + sig = sig.substring(index + 1, sig.length() - 1); + + for (; ; ) { + String cl = getNextClassSignature(sig); + + String name = cl; + String args = null; + + int argfrom = cl.indexOf("<"); + if (argfrom >= 0) { + name = cl.substring(0, argfrom); + args = cl.substring(argfrom + 1, cl.length() - 1); + } + + if (cl.length() < sig.length()) { + sig = sig.substring(cl.length() + 1); // skip '.' + GenericType type = new GenericType(CodeConstants.TYPE_OBJECT, 0, name); + parseArgumentsList(args, type); + enclosingClasses.add(type); + } + else { + value = name; + parseArgumentsList(args, this); + break; + } + } + + return; + default: + value = sig.substring(index, index + 1); + type = getType(value.charAt(0)); + } + + index++; + } + } + + private String getNextClassSignature(String value) { + + int counter = 0; + int index = 0; + + loop: + while (index < value.length()) { + switch (value.charAt(index)) { + case '<': + counter++; + break; + case '>': + counter--; + break; + case '.': + if (counter == 0) { + break loop; + } + } + + index++; + } + + return value.substring(0, index); + } + + private void parseArgumentsList(String value, GenericType type) { + + if (value == null) { + return; + } + + while (value.length() > 0) { + + String tstr = getNextType(value); + int len = tstr.length(); + int wildcard = WILDCARD_NO; + + switch (tstr.charAt(0)) { + case '*': + wildcard = WILDCARD_UNBOUND; + break; + case '+': + wildcard = WILDCARD_EXTENDS; + break; + case '-': + wildcard = WILDCARD_SUPER; + break; + } + + type.getWildcards().add(wildcard); + + if (wildcard != WILDCARD_NO) { + tstr = tstr.substring(1); + } + + type.getArguments().add(tstr.length() == 0 ? null : new GenericType(tstr)); + + value = value.substring(len); + } + } + + public static String getNextType(String value) { + + int counter = 0; + int index = 0; + + boolean contmode = false; + + loop: + while (index < value.length()) { + switch (value.charAt(index)) { + case '*': + if (!contmode) { + break loop; + } + break; + case 'L': + case 'T': + if (!contmode) { + contmode = true; + } + case '[': + case '+': + case '-': + break; + default: + if (!contmode) { + break loop; + } + break; + case '<': + counter++; + break; + case '>': + counter--; + break; + case ';': + if (counter == 0) { + break loop; + } + } + + index++; + } + + return value.substring(0, index + 1); + } + + private int getType(char c) { + switch (c) { + case 'B': + return CodeConstants.TYPE_BYTE; + case 'C': + return CodeConstants.TYPE_CHAR; + case 'D': + return CodeConstants.TYPE_DOUBLE; + case 'F': + return CodeConstants.TYPE_FLOAT; + case 'I': + return CodeConstants.TYPE_INT; + case 'J': + return CodeConstants.TYPE_LONG; + case 'S': + return CodeConstants.TYPE_SHORT; + case 'Z': + return CodeConstants.TYPE_BOOLEAN; + case 'V': + return CodeConstants.TYPE_VOID; + case 'G': + return CodeConstants.TYPE_GROUP2EMPTY; + case 'N': + return CodeConstants.TYPE_NOTINITIALIZED; + case 'A': + return CodeConstants.TYPE_ADDRESS; + case 'X': + return CodeConstants.TYPE_BYTECHAR; + case 'Y': + return CodeConstants.TYPE_SHORTCHAR; + case 'U': + return CodeConstants.TYPE_UNKNOWN; + default: + throw new RuntimeException("Invalid type"); + } + } + + + public List<GenericType> getArguments() { + return arguments; + } + + + public List<GenericType> getEnclosingClasses() { + return enclosingClasses; + } + + + public List<Integer> getWildcards() { + return wildcards; + } } diff --git a/src/org/jetbrains/java/decompiler/struct/lazy/LazyLoader.java b/src/org/jetbrains/java/decompiler/struct/lazy/LazyLoader.java index 94cef9a..46a334e 100644 --- a/src/org/jetbrains/java/decompiler/struct/lazy/LazyLoader.java +++ b/src/org/jetbrains/java/decompiler/struct/lazy/LazyLoader.java @@ -1,186 +1,186 @@ /* - * Fernflower - The Analytical Java Decompiler - * http://www.reversed-java.com + * Copyright 2000-2014 JetBrains s.r.o. * - * (C) 2008 - 2010, Stiver + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at * - * This software is NEITHER public domain NOR free software - * as per GNU License. See license.txt for more details. + * http://www.apache.org/licenses/LICENSE-2.0 * - * This software is distributed WITHOUT ANY WARRANTY; without - * even the implied warranty of MERCHANTABILITY or FITNESS FOR - * A PARTICULAR PURPOSE. + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. */ - package org.jetbrains.java.decompiler.struct.lazy; -import java.io.IOException; -import java.io.InputStream; -import java.util.HashMap; - import org.jetbrains.java.decompiler.main.extern.IBytecodeProvider; import org.jetbrains.java.decompiler.struct.StructMethod; import org.jetbrains.java.decompiler.struct.attr.StructGeneralAttribute; import org.jetbrains.java.decompiler.struct.consts.ConstantPool; import org.jetbrains.java.decompiler.util.DataInputFullStream; +import java.io.IOException; +import java.io.InputStream; +import java.util.HashMap; + public class LazyLoader { - private HashMap<String, Link> mapClassLinks = new HashMap<String, Link>(); - - private IBytecodeProvider provider; - - public LazyLoader(IBytecodeProvider provider) { - this.provider = provider; - } - - public void addClassLink(String classname, Link link) { - mapClassLinks.put(classname, link); - } - - public void removeClassLink(String classname) { - mapClassLinks.remove(classname); - } - - public Link getClassLink(String classname) { - return mapClassLinks.get(classname); - } - - - public ConstantPool loadPool(String classname) { - - try { - - DataInputFullStream in = getClassStream(classname); - if(in == null) { - return null; - } - - in.skip(8); - - return new ConstantPool(in); - - } catch(IOException ex) { - throw new RuntimeException(ex); - } - } - - public byte[] loadBytecode(StructMethod mt, int code_fulllength) { - - try { - - DataInputFullStream in = getClassStream(mt.getClassStruct().qualifiedName); - if(in == null) { - return null; - } - - byte[] res = null; - - in.skip(8); - - ConstantPool pool = mt.getClassStruct().getPool(); - if(pool == null) { - pool = new ConstantPool(in); - } else { - ConstantPool.skipPool(in); - } - - in.skip(2); - int this_class = in.readUnsignedShort(); - in.skip(2); - - // interfaces - in.skip(in.readUnsignedShort() * 2); - - // fields - int size = in.readUnsignedShort(); - for (int i = 0; i < size; i++) { - in.skip(6); - skipAttributes(in); - } - - // methods - size = in.readUnsignedShort(); - for (int i = 0; i < size; i++) { - in.skip(2); - - int name_index = in.readUnsignedShort(); - int descriptor_index = in.readUnsignedShort(); - - String elem_arr[] = pool.getClassElement(ConstantPool.METHOD, this_class, name_index, descriptor_index); - String name = elem_arr[0]; - - if(mt.getName().equals(name)) { - String descriptor = elem_arr[1]; - if(mt.getDescriptor().equals(descriptor)) { - - int len = in.readUnsignedShort(); - for(int j=0;j<len;j++) { - - int attr_nameindex = in.readUnsignedShort(); - String attrname = pool.getPrimitiveConstant(attr_nameindex).getString(); - - if(StructGeneralAttribute.ATTRIBUTE_CODE.equals(attrname)) { - in.skip(12); - - res = new byte[code_fulllength]; - in.readFull(res); - return res; - } else { - in.skip(in.readInt()); - } - } - - return null; - } - } - - skipAttributes(in); - } - - return null; - - } catch(IOException ex) { - throw new RuntimeException(ex); - } - - } - - public DataInputFullStream getClassStream(String externPath, String internPath) throws IOException { - InputStream instream = provider.getBytecodeStream(externPath, internPath); - return instream == null?null:new DataInputFullStream(instream); - } - - public DataInputFullStream getClassStream(String qualifiedClassName) throws IOException { - Link link = mapClassLinks.get(qualifiedClassName); - return link == null?null:getClassStream(link.externPath, link.internPath); - } - - private void skipAttributes(DataInputFullStream in) throws IOException { - - int length = in.readUnsignedShort(); - for (int i = 0; i < length; i++) { - in.skip(2); - in.skip(in.readInt()); - } - - } - - - public static class Link { - - public static final int CLASS = 1; - public static final int ENTRY = 2; - - public int type; - public String externPath; - public String internPath; - - public Link(int type, String externPath, String internPath) { - this.type = type; - this.externPath = externPath; - this.internPath = internPath; - } - } - + private HashMap<String, Link> mapClassLinks = new HashMap<String, Link>(); + + private IBytecodeProvider provider; + + public LazyLoader(IBytecodeProvider provider) { + this.provider = provider; + } + + public void addClassLink(String classname, Link link) { + mapClassLinks.put(classname, link); + } + + public void removeClassLink(String classname) { + mapClassLinks.remove(classname); + } + + public Link getClassLink(String classname) { + return mapClassLinks.get(classname); + } + + + public ConstantPool loadPool(String classname) { + + try { + + DataInputFullStream in = getClassStream(classname); + if (in == null) { + return null; + } + + in.skip(8); + + return new ConstantPool(in); + } + catch (IOException ex) { + throw new RuntimeException(ex); + } + } + + public byte[] loadBytecode(StructMethod mt, int code_fulllength) { + + try { + + DataInputFullStream in = getClassStream(mt.getClassStruct().qualifiedName); + if (in == null) { + return null; + } + + byte[] res = null; + + in.skip(8); + + ConstantPool pool = mt.getClassStruct().getPool(); + if (pool == null) { + pool = new ConstantPool(in); + } + else { + ConstantPool.skipPool(in); + } + + in.skip(2); + int this_class = in.readUnsignedShort(); + in.skip(2); + + // interfaces + in.skip(in.readUnsignedShort() * 2); + + // fields + int size = in.readUnsignedShort(); + for (int i = 0; i < size; i++) { + in.skip(6); + skipAttributes(in); + } + + // methods + size = in.readUnsignedShort(); + for (int i = 0; i < size; i++) { + in.skip(2); + + int name_index = in.readUnsignedShort(); + int descriptor_index = in.readUnsignedShort(); + + String elem_arr[] = pool.getClassElement(ConstantPool.METHOD, this_class, name_index, descriptor_index); + String name = elem_arr[0]; + + if (mt.getName().equals(name)) { + String descriptor = elem_arr[1]; + if (mt.getDescriptor().equals(descriptor)) { + + int len = in.readUnsignedShort(); + for (int j = 0; j < len; j++) { + + int attr_nameindex = in.readUnsignedShort(); + String attrname = pool.getPrimitiveConstant(attr_nameindex).getString(); + + if (StructGeneralAttribute.ATTRIBUTE_CODE.equals(attrname)) { + in.skip(12); + + res = new byte[code_fulllength]; + in.readFull(res); + return res; + } + else { + in.skip(in.readInt()); + } + } + + return null; + } + } + + skipAttributes(in); + } + + return null; + } + catch (IOException ex) { + throw new RuntimeException(ex); + } + } + + public DataInputFullStream getClassStream(String externPath, String internPath) throws IOException { + InputStream instream = provider.getBytecodeStream(externPath, internPath); + return instream == null ? null : new DataInputFullStream(instream); + } + + public DataInputFullStream getClassStream(String qualifiedClassName) throws IOException { + Link link = mapClassLinks.get(qualifiedClassName); + return link == null ? null : getClassStream(link.externPath, link.internPath); + } + + private void skipAttributes(DataInputFullStream in) throws IOException { + + int length = in.readUnsignedShort(); + for (int i = 0; i < length; i++) { + in.skip(2); + in.skip(in.readInt()); + } + } + + + public static class Link { + + public static final int CLASS = 1; + public static final int ENTRY = 2; + + public int type; + public String externPath; + public String internPath; + + public Link(int type, String externPath, String internPath) { + this.type = type; + this.externPath = externPath; + this.internPath = internPath; + } + } } |