java-decompiler: post-import cleanup (formatting and copyright)
This commit is contained in:
@@ -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>();
|
||||
public static final int TYPE_FOLDER = 0;
|
||||
public static final int TYPE_JAR = 1;
|
||||
public static final int TYPE_ZIP = 2;
|
||||
|
||||
// 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 static final String MANIFEST_ENTRY = "META-INF/MANIFEST.MF";
|
||||
|
||||
private List<String> direntries = new ArrayList<String>();
|
||||
|
||||
private List<String[]> otherentries = new ArrayList<String[]>();
|
||||
|
||||
private Manifest manifest;
|
||||
|
||||
private IDecompilatSaver decompilatSaver;
|
||||
|
||||
private IDecompiledData decompiledData;
|
||||
// *****************************************************************************
|
||||
// private fields
|
||||
// *****************************************************************************
|
||||
|
||||
private boolean own = true;
|
||||
|
||||
// *****************************************************************************
|
||||
// constructors
|
||||
// *****************************************************************************
|
||||
private int type;
|
||||
|
||||
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});
|
||||
}
|
||||
// relative path to jar/zip
|
||||
private String archivepath;
|
||||
|
||||
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);
|
||||
// folder: relative path
|
||||
// archive: file name
|
||||
private String filename;
|
||||
|
||||
// non-class files
|
||||
for(String[] arr: otherentries) {
|
||||
decompilatSaver.copyFile(arr[0], filename, arr[0]);
|
||||
}
|
||||
|
||||
// classes
|
||||
for(int i=0;i<classes.size();i++) {
|
||||
private List<StructClass> classes = new ArrayList<StructClass>();
|
||||
|
||||
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);
|
||||
}
|
||||
// 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>();
|
||||
|
||||
// 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++) {
|
||||
private List<String> direntries = new ArrayList<String>();
|
||||
|
||||
StructClass cl = classes.get(i);
|
||||
String entryname = classentries.get(i);
|
||||
private List<String[]> otherentries = new ArrayList<String[]>();
|
||||
|
||||
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;
|
||||
}
|
||||
private Manifest manifest;
|
||||
|
||||
public boolean isOwn() {
|
||||
return own;
|
||||
}
|
||||
private IDecompilatSaver decompilatSaver;
|
||||
|
||||
public List<StructClass> getClasses() {
|
||||
return classes;
|
||||
}
|
||||
private IDecompiledData decompiledData;
|
||||
|
||||
public int getType() {
|
||||
return type;
|
||||
}
|
||||
private boolean own = true;
|
||||
|
||||
public void setDecompilatSaver(IDecompilatSaver decompilatSaver) {
|
||||
this.decompilatSaver = decompilatSaver;
|
||||
}
|
||||
// *****************************************************************************
|
||||
// constructors
|
||||
// *****************************************************************************
|
||||
|
||||
public void setDecompiledData(IDecompiledData decompiledData) {
|
||||
this.decompiledData = decompiledData;
|
||||
}
|
||||
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;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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);
|
||||
}
|
||||
|
||||
@@ -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 saveClassToStream(StructClass cl, DataOutputStream out);
|
||||
|
||||
public void saveClassToFile(StructClass cl, File file) throws FileNotFoundException, IOException;
|
||||
|
||||
public void saveClassToStream(StructClass cl, DataOutputStream out);
|
||||
}
|
||||
|
||||
@@ -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 fields
|
||||
// *****************************************************************************
|
||||
|
||||
public int major_version;
|
||||
public int minor_version;
|
||||
|
||||
public int access_flags;
|
||||
|
||||
public int this_class;
|
||||
|
||||
public int super_class;
|
||||
|
||||
public PrimitiveConstant thisClass;
|
||||
public int major_version;
|
||||
|
||||
public PrimitiveConstant superClass;
|
||||
public int access_flags;
|
||||
|
||||
public String qualifiedName;
|
||||
|
||||
|
||||
// *****************************************************************************
|
||||
// private fields
|
||||
// *****************************************************************************
|
||||
|
||||
private ConstantPool pool;
|
||||
|
||||
private int[] interfaces;
|
||||
public int this_class;
|
||||
|
||||
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 int super_class;
|
||||
|
||||
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 PrimitiveConstant thisClass;
|
||||
|
||||
public StructClass(DataInputFullStream inStream, boolean own, LazyLoader loader) throws FileNotFoundException, IOException {
|
||||
this.own = own;
|
||||
this.loader = loader;
|
||||
|
||||
initStruct(inStream);
|
||||
}
|
||||
|
||||
// *****************************************************************************
|
||||
// public methods
|
||||
// *****************************************************************************
|
||||
public PrimitiveConstant superClass;
|
||||
|
||||
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);
|
||||
public String qualifiedName;
|
||||
|
||||
|
||||
// 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
|
||||
// *****************************************************************************
|
||||
// *****************************************************************************
|
||||
// private fields
|
||||
// *****************************************************************************
|
||||
|
||||
public ConstantPool getPool() {
|
||||
|
||||
if(pool == null && loader != null) {
|
||||
pool = loader.loadPool(qualifiedName);
|
||||
}
|
||||
|
||||
return pool;
|
||||
}
|
||||
private ConstantPool pool;
|
||||
|
||||
public int[] getInterfaces() {
|
||||
return interfaces;
|
||||
}
|
||||
private int[] interfaces;
|
||||
|
||||
public String[] getInterfaceNames() {
|
||||
return interfaceNames;
|
||||
}
|
||||
|
||||
public VBStyleCollection<StructMethod, String> getMethods() {
|
||||
return methods;
|
||||
}
|
||||
|
||||
public VBStyleCollection<StructField, String> getFields() {
|
||||
return fields;
|
||||
}
|
||||
private String[] interfaceNames;
|
||||
|
||||
public VBStyleCollection<StructGeneralAttribute, String> getAttributes() {
|
||||
return attributes;
|
||||
}
|
||||
private VBStyleCollection<StructField, String> fields = new VBStyleCollection<StructField, String>();
|
||||
|
||||
public boolean isOwn() {
|
||||
return own;
|
||||
}
|
||||
private VBStyleCollection<StructMethod, String> methods = new VBStyleCollection<StructMethod, String>();
|
||||
|
||||
public LazyLoader getLoader() {
|
||||
return loader;
|
||||
}
|
||||
private VBStyleCollection<StructGeneralAttribute, String> attributes = new VBStyleCollection<StructGeneralAttribute, String>();
|
||||
|
||||
public boolean isVersionGE_1_5() {
|
||||
return (major_version > 48 || (major_version == 48 && minor_version > 0)); // FIXME: check second condition
|
||||
}
|
||||
private boolean own = true;
|
||||
|
||||
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;
|
||||
}
|
||||
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;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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 fields
|
||||
// *****************************************************************************
|
||||
|
||||
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 {
|
||||
private LazyLoader loader;
|
||||
|
||||
if(file.isDirectory()) {
|
||||
private HashMap<String, StructClass> classes = new HashMap<String, StructClass>();
|
||||
|
||||
File[] files = file.listFiles();
|
||||
path += "/" + (path.length()==0?"":file.getName());
|
||||
private HashMap<String, ContextUnit> units = new HashMap<String, ContextUnit>();
|
||||
|
||||
for(int i=files.length-1;i>=0;i--) {
|
||||
addSpace(path, files[i], isOwn);
|
||||
}
|
||||
private ContextUnit defaultUnit;
|
||||
|
||||
} else {
|
||||
private IDecompilatSaver saver;
|
||||
|
||||
String filename = file.getName();
|
||||
private IDecompiledData decdata;
|
||||
|
||||
boolean isArchive = false;
|
||||
public StructContext(IDecompilatSaver saver, IDecompiledData decdata, LazyLoader loader) {
|
||||
|
||||
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);
|
||||
}
|
||||
this.saver = saver;
|
||||
this.decdata = decdata;
|
||||
this.loader = loader;
|
||||
|
||||
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);
|
||||
}
|
||||
defaultUnit = new ContextUnit(ContextUnit.TYPE_FOLDER, null, "", true, saver, decdata);
|
||||
units.put("", defaultUnit);
|
||||
}
|
||||
|
||||
boolean isClass = false;
|
||||
// *****************************************************************************
|
||||
// public methods
|
||||
// *****************************************************************************
|
||||
|
||||
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 {
|
||||
public StructClass getClass(String name) {
|
||||
return classes.get(name);
|
||||
}
|
||||
|
||||
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;
|
||||
}
|
||||
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;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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;
|
||||
// *****************************************************************************
|
||||
// public fields
|
||||
// *****************************************************************************
|
||||
|
||||
// *****************************************************************************
|
||||
// constructors
|
||||
// *****************************************************************************
|
||||
|
||||
public StructField() {}
|
||||
|
||||
// *****************************************************************************
|
||||
// public methods
|
||||
// *****************************************************************************
|
||||
|
||||
public void writeToStream(DataOutputStream out) throws IOException {
|
||||
public int access_flags;
|
||||
public int name_index;
|
||||
public int descriptor_index;
|
||||
|
||||
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;
|
||||
}
|
||||
private String name;
|
||||
private String descriptor;
|
||||
|
||||
public void setAttributes(VBStyleCollection<StructGeneralAttribute, String> attributes) {
|
||||
this.attributes = attributes;
|
||||
}
|
||||
// *****************************************************************************
|
||||
// private fields
|
||||
// *****************************************************************************
|
||||
|
||||
public String getDescriptor() {
|
||||
return descriptor;
|
||||
}
|
||||
private VBStyleCollection<StructGeneralAttribute, String> attributes;
|
||||
|
||||
public void setDescriptor(String descriptor) {
|
||||
this.descriptor = descriptor;
|
||||
}
|
||||
// *****************************************************************************
|
||||
// constructors
|
||||
// *****************************************************************************
|
||||
|
||||
public String getName() {
|
||||
return name;
|
||||
}
|
||||
public StructField() {
|
||||
}
|
||||
|
||||
public void setName(String name) {
|
||||
this.name = name;
|
||||
}
|
||||
|
||||
// *****************************************************************************
|
||||
// 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;
|
||||
}
|
||||
}
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
@@ -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) {
|
||||
private Exprent defaultValue;
|
||||
|
||||
name = ATTRIBUTE_ANNOTATION_DEFAULT;
|
||||
|
||||
DataInputStream data = new DataInputStream(new ByteArrayInputStream(info));
|
||||
defaultValue = StructAnnotationAttribute.parseAnnotationElement(data, pool);
|
||||
}
|
||||
|
||||
public Exprent getDefaultValue() {
|
||||
return 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;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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 org.jetbrains.java.decompiler.code.CodeConstants;
|
||||
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;
|
||||
|
||||
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.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;
|
||||
|
||||
public class StructAnnotationAttribute extends StructGeneralAttribute {
|
||||
|
||||
private List<AnnotationExprent> annotations;
|
||||
|
||||
public void initContent(ConstantPool pool) {
|
||||
private List<AnnotationExprent> annotations;
|
||||
|
||||
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) {
|
||||
public void initContent(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) {
|
||||
super.initContent(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);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
annotations = new ArrayList<AnnotationExprent>();
|
||||
DataInputStream data = new DataInputStream(new ByteArrayInputStream(info, 2, info.length));
|
||||
|
||||
public List<AnnotationExprent> getAnnotations() {
|
||||
return annotations;
|
||||
}
|
||||
|
||||
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;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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) {
|
||||
private List<List<AnnotationExprent>> paramAnnotations;
|
||||
|
||||
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();
|
||||
public void initContent(ConstantPool pool) {
|
||||
|
||||
for(int j=0;j<annsize;j++) {
|
||||
lst.add(StructAnnotationAttribute.parseAnnotation(data, pool));
|
||||
}
|
||||
paramAnnotations.add(lst);
|
||||
}
|
||||
} catch(IOException ex) {
|
||||
throw new RuntimeException(ex);
|
||||
}
|
||||
super.initContent(pool);
|
||||
|
||||
}
|
||||
paramAnnotations = new ArrayList<List<AnnotationExprent>>();
|
||||
DataInputStream data = new DataInputStream(new ByteArrayInputStream(info));
|
||||
|
||||
public List<List<AnnotationExprent>> getParamAnnotations() {
|
||||
return paramAnnotations;
|
||||
}
|
||||
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;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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) {
|
||||
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;
|
||||
|
||||
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 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;
|
||||
|
||||
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()};
|
||||
}
|
||||
List<AnnotationLocation> locations = new ArrayList<AnnotationLocation>();
|
||||
List<AnnotationExprent> annotations = new ArrayList<AnnotationExprent>();
|
||||
|
||||
// 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 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;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -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;
|
||||
private List<LinkConstant> method_refs = new ArrayList<LinkConstant>();
|
||||
private List<List<PooledConstant>> method_arguments = new ArrayList<List<PooledConstant>>();
|
||||
|
||||
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 void initContent(ConstantPool pool) {
|
||||
|
||||
public int getMethodsNumber() {
|
||||
return method_refs.size();
|
||||
}
|
||||
|
||||
public LinkConstant getMethodReference(int index) {
|
||||
return method_refs.get(index);
|
||||
}
|
||||
name = ATTRIBUTE_BOOTSTRAP_METHODS;
|
||||
|
||||
public List<PooledConstant> getMethodArguments(int index) {
|
||||
return method_arguments.get(index);
|
||||
}
|
||||
|
||||
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);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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);
|
||||
}
|
||||
|
||||
public int getIndex() {
|
||||
return index;
|
||||
}
|
||||
|
||||
|
||||
name = ATTRIBUTE_CONSTANT_VALUE;
|
||||
index = ((info[0] & 0xFF) << 8) | (info[1] & 0xFF);
|
||||
}
|
||||
|
||||
public int getIndex() {
|
||||
return index;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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) {
|
||||
private String classname;
|
||||
|
||||
name = ATTRIBUTE_ENCLOSING_METHOD;
|
||||
private String mtname;
|
||||
|
||||
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;
|
||||
}
|
||||
}
|
||||
private String methodDescriptor;
|
||||
|
||||
public String getClassname() {
|
||||
return classname;
|
||||
}
|
||||
public void initContent(ConstantPool pool) {
|
||||
|
||||
public String getMethodDescriptor() {
|
||||
return methodDescriptor;
|
||||
}
|
||||
name = ATTRIBUTE_ENCLOSING_METHOD;
|
||||
|
||||
public String getMethodName() {
|
||||
return mtname;
|
||||
}
|
||||
|
||||
|
||||
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;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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;
|
||||
private List<Integer> throwsExceptions = new ArrayList<Integer>();
|
||||
|
||||
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 initContent(ConstantPool pool) {
|
||||
|
||||
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);
|
||||
name = ATTRIBUTE_EXCEPTIONS;
|
||||
|
||||
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();
|
||||
}
|
||||
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 List<Integer> getThrowsExceptions() {
|
||||
return throwsExceptions;
|
||||
}
|
||||
public void writeToStream(DataOutputStream out) throws IOException {
|
||||
|
||||
public void setThrowsExceptions(List<Integer> throwsExceptions) {
|
||||
this.throwsExceptions = throwsExceptions;
|
||||
}
|
||||
|
||||
|
||||
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;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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
|
||||
// *****************************************************************************
|
||||
// *****************************************************************************
|
||||
// private fields
|
||||
// *****************************************************************************
|
||||
|
||||
protected int attribute_name_index;
|
||||
|
||||
protected byte[] info;
|
||||
|
||||
protected String name;
|
||||
protected int attribute_name_index;
|
||||
|
||||
// *****************************************************************************
|
||||
// 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;
|
||||
}
|
||||
protected byte[] info;
|
||||
|
||||
public void setInfo(byte[] info) {
|
||||
this.info = info;
|
||||
}
|
||||
|
||||
public String getName() {
|
||||
return name;
|
||||
}
|
||||
protected String name;
|
||||
|
||||
public void setName(String name) {
|
||||
this.name = name;
|
||||
}
|
||||
// *****************************************************************************
|
||||
// public methods
|
||||
// *****************************************************************************
|
||||
|
||||
public int getAttribute_name_index() {
|
||||
return attribute_name_index;
|
||||
}
|
||||
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 setAttribute_name_index(int attribute_name_index) {
|
||||
this.attribute_name_index = attribute_name_index;
|
||||
}
|
||||
|
||||
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;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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();
|
||||
}
|
||||
|
||||
public String getSignature() {
|
||||
return signature;
|
||||
}
|
||||
|
||||
|
||||
name = ATTRIBUTE_SIGNATURE;
|
||||
signature = pool.getPrimitiveConstant(((info[0] & 0xFF) << 8) | (info[1] & 0xFF)).getString();
|
||||
}
|
||||
|
||||
public String getSignature() {
|
||||
return signature;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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<int[]> classentries = new ArrayList<int[]>();
|
||||
|
||||
private List<String[]> stringentries = new ArrayList<String[]>();
|
||||
|
||||
public void initContent(ConstantPool pool) {
|
||||
|
||||
name = ATTRIBUTE_INNER_CLASSES;
|
||||
private List<String[]> stringentries = new ArrayList<String[]>();
|
||||
|
||||
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;
|
||||
}
|
||||
public void initContent(ConstantPool pool) {
|
||||
|
||||
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);
|
||||
}
|
||||
|
||||
}
|
||||
name = ATTRIBUTE_INNER_CLASSES;
|
||||
|
||||
public List<int[]> getClassentries() {
|
||||
return classentries;
|
||||
}
|
||||
int length = 2 + (((info[0] & 0xFF) << 8) | (info[1] & 0xFF)) * 8;
|
||||
int i = 2;
|
||||
|
||||
public List<String[]> getStringentries() {
|
||||
return stringentries;
|
||||
}
|
||||
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;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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) {
|
||||
private HashMap<Integer, String> mapVarNames = new HashMap<Integer, String>();
|
||||
|
||||
name = ATTRIBUTE_LOCAL_VARIABLE_TABLE;
|
||||
public void initContent(ConstantPool pool) {
|
||||
|
||||
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());
|
||||
}
|
||||
}
|
||||
name = ATTRIBUTE_LOCAL_VARIABLE_TABLE;
|
||||
|
||||
public void addLocalVariableTable(StructLocalVariableTableAttribute attr) {
|
||||
mapVarNames.putAll(attr.getMapVarNames());
|
||||
}
|
||||
|
||||
public HashMap<Integer, String> getMapVarNames() {
|
||||
return mapVarNames;
|
||||
}
|
||||
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;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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;
|
||||
public static final int FIELD = 1;
|
||||
|
||||
// *****************************************************************************
|
||||
// constructors
|
||||
// *****************************************************************************
|
||||
|
||||
public ConstantPool(DataInputStream in) throws IOException {
|
||||
|
||||
int size = in.readUnsignedShort();
|
||||
public static final int METHOD = 2;
|
||||
|
||||
int[] pass = new int[size];
|
||||
|
||||
// first dummy constant
|
||||
pool.add(null);
|
||||
|
||||
// first pass: read the elements
|
||||
for (int i = 1; i < size; i++) {
|
||||
// *****************************************************************************
|
||||
// private fields
|
||||
// *****************************************************************************
|
||||
|
||||
byte tag = (byte)in.readUnsignedByte();
|
||||
private List<PooledConstant> pool = new ArrayList<PooledConstant>();
|
||||
|
||||
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();
|
||||
}
|
||||
private PoolInterceptor interceptor;
|
||||
|
||||
// *****************************************************************************
|
||||
// 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);
|
||||
}
|
||||
}
|
||||
}
|
||||
// *****************************************************************************
|
||||
// constructors
|
||||
// *****************************************************************************
|
||||
|
||||
public static void skipPool(DataInputStream in) throws IOException {
|
||||
|
||||
int size = in.readUnsignedShort();
|
||||
public ConstantPool(DataInputStream in) throws IOException {
|
||||
|
||||
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;
|
||||
}
|
||||
}
|
||||
int size = in.readUnsignedShort();
|
||||
|
||||
return new String[] {elementname, descriptor};
|
||||
}
|
||||
|
||||
public PooledConstant getConstant(int index) {
|
||||
return pool.get(index);
|
||||
}
|
||||
int[] pass = new int[size];
|
||||
|
||||
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;
|
||||
}
|
||||
// first dummy constant
|
||||
pool.add(null);
|
||||
|
||||
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();
|
||||
}
|
||||
// first pass: read the elements
|
||||
for (int i = 1; i < size; i++) {
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
private String buildNewDescriptor(int type, String descriptor) {
|
||||
byte tag = (byte)in.readUnsignedByte();
|
||||
|
||||
boolean updated = false;
|
||||
|
||||
if(type == CodeConstants.CONSTANT_Fieldref) {
|
||||
FieldDescriptor fd = FieldDescriptor.parseDescriptor(descriptor);
|
||||
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;
|
||||
}
|
||||
}
|
||||
|
||||
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;
|
||||
}
|
||||
|
||||
|
||||
// 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;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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 fields
|
||||
// *****************************************************************************
|
||||
|
||||
public String descriptor;
|
||||
|
||||
public int paramCount = 0;
|
||||
|
||||
public boolean isVoid = false;;
|
||||
|
||||
public boolean returnCategory2 = false;
|
||||
|
||||
|
||||
// *****************************************************************************
|
||||
// constructors
|
||||
// *****************************************************************************
|
||||
public int index1, index2;
|
||||
|
||||
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 String classname;
|
||||
|
||||
// *****************************************************************************
|
||||
// public methods
|
||||
// *****************************************************************************
|
||||
|
||||
public void resolveConstant(ConstantPool pool) {
|
||||
public String elementname;
|
||||
|
||||
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 String descriptor;
|
||||
|
||||
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));
|
||||
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();
|
||||
}
|
||||
|
||||
// *****************************************************************************
|
||||
// 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]));
|
||||
}
|
||||
|
||||
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));
|
||||
}
|
||||
|
||||
// *****************************************************************************
|
||||
// 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]));
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -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 fields
|
||||
// *****************************************************************************
|
||||
|
||||
public boolean own = false;
|
||||
|
||||
public int returnType;
|
||||
public int type;
|
||||
|
||||
public boolean own = false;
|
||||
|
||||
public int returnType;
|
||||
|
||||
|
||||
// *****************************************************************************
|
||||
// private fields
|
||||
// *****************************************************************************
|
||||
// *****************************************************************************
|
||||
// private fields
|
||||
// *****************************************************************************
|
||||
|
||||
private Object[] values;
|
||||
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?");
|
||||
}
|
||||
}
|
||||
// *****************************************************************************
|
||||
// constructors
|
||||
// *****************************************************************************
|
||||
|
||||
public Object getValue(int index){
|
||||
return values[index];
|
||||
}
|
||||
|
||||
|
||||
// *****************************************************************************
|
||||
// getter and setter methods
|
||||
// *****************************************************************************
|
||||
|
||||
public Object[] getValues() {
|
||||
return values;
|
||||
}
|
||||
public PooledConstant() {
|
||||
}
|
||||
|
||||
public void setValues(Object[] values) {
|
||||
this.values = values;
|
||||
}
|
||||
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;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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 fields
|
||||
// *****************************************************************************
|
||||
|
||||
public int index;
|
||||
public int index;
|
||||
|
||||
public Object value;
|
||||
|
||||
public boolean isArray;
|
||||
|
||||
// *****************************************************************************
|
||||
// constructors
|
||||
// *****************************************************************************
|
||||
|
||||
public PrimitiveConstant(int type, Object value) {
|
||||
this.type = type;
|
||||
this.value = value;
|
||||
|
||||
initConstant();
|
||||
}
|
||||
public Object value;
|
||||
|
||||
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 boolean isArray;
|
||||
|
||||
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) {
|
||||
// *****************************************************************************
|
||||
// constructors
|
||||
// *****************************************************************************
|
||||
|
||||
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 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
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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);
|
||||
}
|
||||
|
||||
@@ -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>();
|
||||
private List<VarType> localVariables = new ArrayList<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;
|
||||
}
|
||||
private ListStack<VarType> stack = new ListStack<VarType>();
|
||||
|
||||
public void setLocalVariables(List<VarType> localVariables) {
|
||||
this.localVariables = localVariables;
|
||||
}
|
||||
|
||||
public ListStack<VarType> getStack() {
|
||||
return stack;
|
||||
}
|
||||
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));
|
||||
}
|
||||
}
|
||||
|
||||
public void setStack(ListStack<VarType> stack) {
|
||||
this.stack = stack;
|
||||
}
|
||||
|
||||
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;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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();
|
||||
}
|
||||
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;");
|
||||
|
||||
@Override
|
||||
public boolean equals(Object o) {
|
||||
if(o == this) return true;
|
||||
if(o == null || !(o instanceof FieldDescriptor)) return false;
|
||||
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();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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();
|
||||
}
|
||||
public VarType[] params;
|
||||
|
||||
res+=")"+ret.toString();
|
||||
|
||||
return res;
|
||||
}
|
||||
public VarType ret;
|
||||
|
||||
@Override
|
||||
public boolean equals(Object o) {
|
||||
if(o == this) return true;
|
||||
if(o == null || !(o instanceof MethodDescriptor)) return false;
|
||||
|
||||
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;
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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;
|
||||
public static final int FALSEBOOLEAN = 1;
|
||||
|
||||
value = getChar(type);
|
||||
setStackSize(type);
|
||||
setFamily();
|
||||
}
|
||||
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 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 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 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 int type;
|
||||
|
||||
public boolean isFalseBoolean() {
|
||||
return (convinfo & VarType.FALSEBOOLEAN) != 0;
|
||||
}
|
||||
public int type_family;
|
||||
|
||||
public boolean isSuperset(VarType val) {
|
||||
public int arraydim;
|
||||
|
||||
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);
|
||||
}
|
||||
public String value;
|
||||
|
||||
boolean res = false;
|
||||
public int stack_size;
|
||||
|
||||
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;
|
||||
}
|
||||
public int convinfo;
|
||||
|
||||
// type1 and type2 must not be null
|
||||
public static VarType getCommonMinType(VarType type1, VarType type2) {
|
||||
public VarType(int type) {
|
||||
this.type = type;
|
||||
this.arraydim = 0;
|
||||
|
||||
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;
|
||||
}
|
||||
}
|
||||
value = getChar(type);
|
||||
setStackSize(type);
|
||||
setFamily();
|
||||
}
|
||||
|
||||
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;
|
||||
}
|
||||
public VarType(int type, int arraydim) {
|
||||
this(type);
|
||||
this.arraydim = arraydim;
|
||||
setFamily();
|
||||
}
|
||||
|
||||
VarType vt = (VarType) o;
|
||||
return type == vt.type && arraydim == vt.arraydim && InterpreterUtil.equalObjects(value, vt.value);
|
||||
}
|
||||
public VarType(int type, int arraydim, String value) {
|
||||
this(type);
|
||||
this.arraydim = arraydim;
|
||||
this.value = value;
|
||||
setFamily();
|
||||
}
|
||||
|
||||
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");
|
||||
}
|
||||
}
|
||||
public VarType(String strtype) {
|
||||
this(strtype, false);
|
||||
}
|
||||
|
||||
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 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;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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<List<GenericType>> fbounds = new ArrayList<List<GenericType>>();
|
||||
|
||||
public List<GenericType> superinterfaces = new ArrayList<GenericType>();
|
||||
|
||||
public List<String> fparameters = new ArrayList<String>();
|
||||
|
||||
public List<List<GenericType>> fbounds = new ArrayList<List<GenericType>>();
|
||||
}
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
|
||||
@@ -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);
|
||||
private static final String[] typeNames = new String[]{
|
||||
"byte",
|
||||
"char",
|
||||
"double",
|
||||
"float",
|
||||
"int",
|
||||
"long",
|
||||
"short",
|
||||
"boolean",
|
||||
};
|
||||
|
||||
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 GenericClassDescriptor parseClassSignature(String signature) {
|
||||
|
||||
public static GenericFieldDescriptor parseFieldSignature(String signature) {
|
||||
GenericFieldDescriptor descriptor = new GenericFieldDescriptor();
|
||||
descriptor.type = new GenericType(signature);
|
||||
return descriptor;
|
||||
}
|
||||
GenericClassDescriptor descriptor = new GenericClassDescriptor();
|
||||
|
||||
public static GenericMethodDescriptor parseMethodSignature(String signature) {
|
||||
|
||||
GenericMethodDescriptor descriptor = new GenericMethodDescriptor();
|
||||
signature = parseFormalParameters(signature, descriptor.fparameters, descriptor.fbounds);
|
||||
|
||||
signature = parseFormalParameters(signature, descriptor.fparameters, descriptor.fbounds);
|
||||
String supercl = GenericType.getNextType(signature);
|
||||
descriptor.superclass = new GenericType(supercl);
|
||||
|
||||
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());
|
||||
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());
|
||||
}
|
||||
|
||||
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);
|
||||
}
|
||||
}
|
||||
return descriptor;
|
||||
}
|
||||
|
||||
fparameters.add(param);
|
||||
fbounds.add(lstBounds);
|
||||
}
|
||||
|
||||
return signature;
|
||||
}
|
||||
public static GenericFieldDescriptor parseFieldSignature(String signature) {
|
||||
GenericFieldDescriptor descriptor = new GenericFieldDescriptor();
|
||||
descriptor.type = new GenericType(signature);
|
||||
return descriptor;
|
||||
}
|
||||
|
||||
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;
|
||||
}
|
||||
|
||||
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;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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<List<GenericType>> fbounds = new ArrayList<List<GenericType>>();
|
||||
|
||||
public List<GenericType> params = new ArrayList<GenericType>();
|
||||
|
||||
public GenericType ret;
|
||||
|
||||
public List<GenericType> exceptions = new ArrayList<GenericType>();
|
||||
|
||||
public List<GenericType> params = new ArrayList<GenericType>();
|
||||
|
||||
public GenericType ret;
|
||||
|
||||
public List<GenericType> exceptions = new ArrayList<GenericType>();
|
||||
}
|
||||
|
||||
@@ -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 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 arraydim;
|
||||
|
||||
public String value;
|
||||
public int type;
|
||||
|
||||
|
||||
private List<GenericType> enclosingClasses = new ArrayList<GenericType>();
|
||||
|
||||
private List<GenericType> arguments = new ArrayList<GenericType>();
|
||||
|
||||
private List<Integer> wildcards = new ArrayList<Integer>();
|
||||
public int arraydim;
|
||||
|
||||
|
||||
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 String value;
|
||||
|
||||
|
||||
public List<GenericType> getArguments() {
|
||||
return arguments;
|
||||
}
|
||||
private List<GenericType> enclosingClasses = new ArrayList<GenericType>();
|
||||
|
||||
private List<GenericType> arguments = new ArrayList<GenericType>();
|
||||
|
||||
private List<Integer> wildcards = new ArrayList<Integer>();
|
||||
|
||||
|
||||
public List<GenericType> getEnclosingClasses() {
|
||||
return enclosingClasses;
|
||||
}
|
||||
public GenericType(int type, int arraydim, String value) {
|
||||
this.type = type;
|
||||
this.arraydim = arraydim;
|
||||
this.value = value;
|
||||
}
|
||||
|
||||
|
||||
public List<Integer> getWildcards() {
|
||||
return wildcards;
|
||||
}
|
||||
|
||||
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;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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);
|
||||
}
|
||||
private HashMap<String, Link> mapClassLinks = new HashMap<String, Link>();
|
||||
|
||||
public void removeClassLink(String classname) {
|
||||
mapClassLinks.remove(classname);
|
||||
}
|
||||
|
||||
public Link getClassLink(String classname) {
|
||||
return mapClassLinks.get(classname);
|
||||
}
|
||||
|
||||
|
||||
public ConstantPool loadPool(String classname) {
|
||||
private IBytecodeProvider provider;
|
||||
|
||||
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 {
|
||||
public LazyLoader(IBytecodeProvider provider) {
|
||||
this.provider = provider;
|
||||
}
|
||||
|
||||
DataInputFullStream in = getClassStream(mt.getClassStruct().qualifiedName);
|
||||
if(in == null) {
|
||||
return null;
|
||||
}
|
||||
public void addClassLink(String classname, Link link) {
|
||||
mapClassLinks.put(classname, link);
|
||||
}
|
||||
|
||||
byte[] res = null;
|
||||
|
||||
in.skip(8);
|
||||
public void removeClassLink(String classname) {
|
||||
mapClassLinks.remove(classname);
|
||||
}
|
||||
|
||||
ConstantPool pool = mt.getClassStruct().getPool();
|
||||
if(pool == null) {
|
||||
pool = new ConstantPool(in);
|
||||
} else {
|
||||
ConstantPool.skipPool(in);
|
||||
}
|
||||
public Link getClassLink(String classname) {
|
||||
return mapClassLinks.get(classname);
|
||||
}
|
||||
|
||||
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);
|
||||
}
|
||||
public ConstantPool loadPool(String classname) {
|
||||
|
||||
// methods
|
||||
size = in.readUnsignedShort();
|
||||
for (int i = 0; i < size; i++) {
|
||||
in.skip(2);
|
||||
try {
|
||||
|
||||
int name_index = in.readUnsignedShort();
|
||||
int descriptor_index = in.readUnsignedShort();
|
||||
DataInputFullStream in = getClassStream(classname);
|
||||
if (in == null) {
|
||||
return null;
|
||||
}
|
||||
|
||||
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)) {
|
||||
in.skip(8);
|
||||
|
||||
int len = in.readUnsignedShort();
|
||||
for(int j=0;j<len;j++) {
|
||||
return new ConstantPool(in);
|
||||
}
|
||||
catch (IOException ex) {
|
||||
throw new RuntimeException(ex);
|
||||
}
|
||||
}
|
||||
|
||||
int attr_nameindex = in.readUnsignedShort();
|
||||
String attrname = pool.getPrimitiveConstant(attr_nameindex).getString();
|
||||
public byte[] loadBytecode(StructMethod mt, int code_fulllength) {
|
||||
|
||||
if(StructGeneralAttribute.ATTRIBUTE_CODE.equals(attrname)) {
|
||||
in.skip(12);
|
||||
try {
|
||||
|
||||
res = new byte[code_fulllength];
|
||||
in.readFull(res);
|
||||
return res;
|
||||
} else {
|
||||
in.skip(in.readInt());
|
||||
}
|
||||
}
|
||||
DataInputFullStream in = getClassStream(mt.getClassStruct().qualifiedName);
|
||||
if (in == null) {
|
||||
return null;
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
}
|
||||
byte[] res = null;
|
||||
|
||||
skipAttributes(in);
|
||||
}
|
||||
in.skip(8);
|
||||
|
||||
return null;
|
||||
ConstantPool pool = mt.getClassStruct().getPool();
|
||||
if (pool == null) {
|
||||
pool = new ConstantPool(in);
|
||||
}
|
||||
else {
|
||||
ConstantPool.skipPool(in);
|
||||
}
|
||||
|
||||
} catch(IOException ex) {
|
||||
throw new RuntimeException(ex);
|
||||
}
|
||||
|
||||
}
|
||||
in.skip(2);
|
||||
int this_class = in.readUnsignedShort();
|
||||
in.skip(2);
|
||||
|
||||
public DataInputFullStream getClassStream(String externPath, String internPath) throws IOException {
|
||||
InputStream instream = provider.getBytecodeStream(externPath, internPath);
|
||||
return instream == null?null:new DataInputFullStream(instream);
|
||||
}
|
||||
// interfaces
|
||||
in.skip(in.readUnsignedShort() * 2);
|
||||
|
||||
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 {
|
||||
// fields
|
||||
int size = in.readUnsignedShort();
|
||||
for (int i = 0; i < size; i++) {
|
||||
in.skip(6);
|
||||
skipAttributes(in);
|
||||
}
|
||||
|
||||
int length = in.readUnsignedShort();
|
||||
for (int i = 0; i < length; i++) {
|
||||
in.skip(2);
|
||||
in.skip(in.readInt());
|
||||
}
|
||||
|
||||
}
|
||||
// methods
|
||||
size = in.readUnsignedShort();
|
||||
for (int i = 0; i < size; i++) {
|
||||
in.skip(2);
|
||||
|
||||
|
||||
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;
|
||||
}
|
||||
}
|
||||
|
||||
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;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user