diff options
Diffstat (limited to 'plugins/java-decompiler/engine/src/org/jetbrains/java/decompiler/main/rels/ClassWrapper.java')
-rw-r--r-- | plugins/java-decompiler/engine/src/org/jetbrains/java/decompiler/main/rels/ClassWrapper.java | 207 |
1 files changed, 207 insertions, 0 deletions
diff --git a/plugins/java-decompiler/engine/src/org/jetbrains/java/decompiler/main/rels/ClassWrapper.java b/plugins/java-decompiler/engine/src/org/jetbrains/java/decompiler/main/rels/ClassWrapper.java new file mode 100644 index 000000000000..4a321799bc4b --- /dev/null +++ b/plugins/java-decompiler/engine/src/org/jetbrains/java/decompiler/main/rels/ClassWrapper.java @@ -0,0 +1,207 @@ +/* + * 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.main.rels; + +import org.jetbrains.java.decompiler.code.CodeConstants; +import org.jetbrains.java.decompiler.main.DecompilerContext; +import org.jetbrains.java.decompiler.main.collectors.CounterContainer; +import org.jetbrains.java.decompiler.main.collectors.VarNamesCollector; +import org.jetbrains.java.decompiler.main.extern.IFernflowerLogger; +import org.jetbrains.java.decompiler.main.extern.IFernflowerPreferences; +import org.jetbrains.java.decompiler.modules.decompiler.exps.Exprent; +import org.jetbrains.java.decompiler.modules.decompiler.stats.RootStatement; +import org.jetbrains.java.decompiler.modules.decompiler.vars.VarProcessor; +import org.jetbrains.java.decompiler.modules.decompiler.vars.VarVersionPaar; +import org.jetbrains.java.decompiler.struct.StructClass; +import org.jetbrains.java.decompiler.struct.StructField; +import org.jetbrains.java.decompiler.struct.StructMethod; +import org.jetbrains.java.decompiler.struct.attr.StructGeneralAttribute; +import org.jetbrains.java.decompiler.struct.attr.StructLocalVariableTableAttribute; +import org.jetbrains.java.decompiler.struct.gen.MethodDescriptor; +import org.jetbrains.java.decompiler.util.InterpreterUtil; +import org.jetbrains.java.decompiler.util.VBStyleCollection; + +import java.io.IOException; +import java.util.HashSet; +import java.util.Set; + +public class ClassWrapper { + + private StructClass classStruct; + private Set<String> hiddenMembers = new HashSet<String>(); + private VBStyleCollection<Exprent, String> staticFieldInitializers = new VBStyleCollection<Exprent, String>(); + private VBStyleCollection<Exprent, String> dynamicFieldInitializers = new VBStyleCollection<Exprent, String>(); + private VBStyleCollection<MethodWrapper, String> methods = new VBStyleCollection<MethodWrapper, String>(); + + + public ClassWrapper(StructClass classStruct) { + this.classStruct = classStruct; + } + + public void init() throws IOException { + + DecompilerContext.setProperty(DecompilerContext.CURRENT_CLASS, classStruct); + + DecompilerContext.getLogger().startClass(classStruct.qualifiedName); + + // collect field names + HashSet<String> setFieldNames = new HashSet<String>(); + for (StructField fd : classStruct.getFields()) { + setFieldNames.add(fd.getName()); + } + + int maxsec = Integer.parseInt(DecompilerContext.getProperty(IFernflowerPreferences.MAX_PROCESSING_METHOD).toString()); + + for (StructMethod mt : classStruct.getMethods()) { + + DecompilerContext.getLogger().startMethod(mt.getName() + " " + mt.getDescriptor()); + + VarNamesCollector vc = new VarNamesCollector(); + DecompilerContext.setVarNamesCollector(vc); + + CounterContainer counter = new CounterContainer(); + DecompilerContext.setCounterContainer(counter); + + DecompilerContext.setProperty(DecompilerContext.CURRENT_METHOD, mt); + DecompilerContext.setProperty(DecompilerContext.CURRENT_METHOD_DESCRIPTOR, MethodDescriptor.parseDescriptor(mt.getDescriptor())); + + VarProcessor varproc = new VarProcessor(); + DecompilerContext.setProperty(DecompilerContext.CURRENT_VAR_PROCESSOR, varproc); + + RootStatement root = null; + + boolean isError = false; + + try { + if (mt.containsCode()) { + + if (maxsec == 0) { // blocking wait + root = MethodProcessorThread.codeToJava(mt, varproc); + } + else { + MethodProcessorThread mtproc = new MethodProcessorThread(mt, varproc, DecompilerContext.getCurrentContext()); + Thread mtthread = new Thread(mtproc); + long stopAt = System.currentTimeMillis() + maxsec * 1000; + + mtthread.start(); + + while (mtthread.isAlive()) { + + synchronized (mtproc.lock) { + mtproc.lock.wait(100); + } + + if (System.currentTimeMillis() >= stopAt) { + String message = "Processing time limit exceeded for method " + mt.getName() + ", execution interrupted."; + DecompilerContext.getLogger().writeMessage(message, IFernflowerLogger.Severity.ERROR); + killThread(mtthread); + isError = true; + break; + } + } + + if (!isError) { + root = mtproc.getResult(); + } + } + } + else { + boolean thisvar = !mt.hasModifier(CodeConstants.ACC_STATIC); + MethodDescriptor md = MethodDescriptor.parseDescriptor(mt.getDescriptor()); + + int paramcount = 0; + if (thisvar) { + varproc.getThisvars().put(new VarVersionPaar(0, 0), classStruct.qualifiedName); + paramcount = 1; + } + paramcount += md.params.length; + + int varindex = 0; + for (int i = 0; i < paramcount; i++) { + varproc.setVarName(new VarVersionPaar(varindex, 0), vc.getFreeName(varindex)); + + if (thisvar) { + if (i == 0) { + varindex++; + } + else { + varindex += md.params[i - 1].stack_size; + } + } + else { + varindex += md.params[i].stack_size; + } + } + } + } + catch (Throwable ex) { + DecompilerContext.getLogger().writeMessage("Method " + mt.getName() + " " + mt.getDescriptor() + " couldn't be decompiled.", ex); + isError = true; + } + + MethodWrapper meth = new MethodWrapper(root, varproc, mt, counter); + meth.decompiledWithErrors = isError; + + methods.addWithKey(meth, InterpreterUtil.makeUniqueKey(mt.getName(), mt.getDescriptor())); + + // rename vars so that no one has the same name as a field + varproc.refreshVarNames(new VarNamesCollector(setFieldNames)); + + // if debug information present and should be used + if (DecompilerContext.getOption(IFernflowerPreferences.USE_DEBUG_VAR_NAMES)) { + StructLocalVariableTableAttribute attr = (StructLocalVariableTableAttribute)mt.getAttributes().getWithKey( + StructGeneralAttribute.ATTRIBUTE_LOCAL_VARIABLE_TABLE); + + if (attr != null) { + varproc.setDebugVarNames(attr.getMapVarNames()); + } + } + + DecompilerContext.getLogger().endMethod(); + } + + DecompilerContext.getLogger().endClass(); + } + + @SuppressWarnings("deprecation") + private static void killThread(Thread thread) { + thread.stop(); + } + + public MethodWrapper getMethodWrapper(String name, String descriptor) { + return methods.getWithKey(InterpreterUtil.makeUniqueKey(name, descriptor)); + } + + public StructClass getClassStruct() { + return classStruct; + } + + public VBStyleCollection<MethodWrapper, String> getMethods() { + return methods; + } + + public Set<String> getHiddenMembers() { + return hiddenMembers; + } + + public VBStyleCollection<Exprent, String> getStaticFieldInitializers() { + return staticFieldInitializers; + } + + public VBStyleCollection<Exprent, String> getDynamicFieldInitializers() { + return dynamicFieldInitializers; + } +} |