/* * 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); ex.printStackTrace(); 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; } }