@Override public String buildNewClassname(String className) { return interceptor.getName(className); }
private void renameAllClasses() { // order not important List<ClassWrapperNode> lstAllClasses = new ArrayList<>(getReversePostOrderListIterative(rootInterfaces)); lstAllClasses.addAll(getReversePostOrderListIterative(rootClasses)); // rename all interfaces and classes for (ClassWrapperNode node : lstAllClasses) { renameClass(node.getClassStruct()); } }
public void rename() { try { buildInheritanceTree(); renameAllClasses(); renameInterfaces(); renameClasses(); context.reloadContext(); } catch (IOException ex) { throw new RuntimeException("Renaming failed!"); } }
private void renameClasses() { List<ClassWrapperNode> lstClasses = getReversePostOrderListIterative(rootClasses); Map<String, Map<String, String>> classNameMaps = new HashMap<>(); StructClass cl = node.getClassStruct(); Map<String, String> names = new HashMap<>(); StructClass clintr = context.getClass(ifName); if (clintr != null) { names.putAll(processExternalInterface(clintr)); renameClassIdentifiers(cl, names); if (!node.getSubclasses().isEmpty()) { classNameMaps.put(cl.qualifiedName, names);
private void renameInterfaces() { List<ClassWrapperNode> lstInterfaces = getReversePostOrderListIterative(rootInterfaces); Map<String, Map<String, String>> interfaceNameMaps = new HashMap<>(); // rename methods and fields for (ClassWrapperNode node : lstInterfaces) { StructClass cl = node.getClassStruct(); Map<String, String> names = new HashMap<>(); // merge information on super interfaces for (String ifName : cl.getInterfaceNames()) { Map<String, String> mapInt = interfaceNameMaps.get(ifName); if (mapInt != null) { names.putAll(mapInt); } } renameClassIdentifiers(cl, names); interfaceNameMaps.put(cl.qualifiedName, names); } this.interfaceNameMaps = interfaceNameMaps; }
private void renameClass(StructClass cl) { if (!cl.isOwn()) { return; } String classOldFullName = cl.qualifiedName; // TODO: rename packages String clSimpleName = ConverterHelper.getSimpleClassName(classOldFullName); if (helper.toBeRenamed(IIdentifierRenamer.Type.ELEMENT_CLASS, clSimpleName, null, null)) { String classNewFullName; do { String classname = helper.getNextClassName(classOldFullName, ConverterHelper.getSimpleClassName(classOldFullName)); classNewFullName = ConverterHelper.replaceSimpleClassName(classOldFullName, classname); } while (context.getClasses().containsKey(classNewFullName)); interceptor.addName(classOldFullName, classNewFullName); } }
private void renameClassIdentifiers(StructClass cl, Map<String, String> names) { String classNewFullName = interceptor.getName(classOldFullName); interceptor.addName(classOldFullName + " " + mt.getName() + " " + mt.getDescriptor(), classNewFullName + " " + name + " " + buildNewDescriptor(false, mt.getDescriptor())); interceptor.addName(classOldFullName + " " + fd.getName() + " " + fd.getDescriptor(), classNewFullName + " " + newName + " " + buildNewDescriptor(true, fd.getDescriptor()));
private Map<String, String> processExternalInterface(StructClass cl) { Map<String, String> names = new HashMap<>(); for (String ifName : cl.getInterfaceNames()) { Map<String, String> mapInt = interfaceNameMaps.get(ifName); if (mapInt != null) { names.putAll(mapInt); } else { StructClass clintr = context.getClass(ifName); if (clintr != null) { names.putAll(processExternalInterface(clintr)); } } } renameClassIdentifiers(cl, names); return names; }
public String[] getClassElement(int elementType, String className, int nameIndex, int descriptorIndex) { String elementName = ((PrimitiveConstant)getConstant(nameIndex)).getString(); String descriptor = ((PrimitiveConstant)getConstant(descriptorIndex)).getString(); if (interceptor != null) { String oldClassName = interceptor.getOldName(className); if (oldClassName != null) { className = oldClassName; } String newElement = interceptor.getName(className + ' ' + elementName + ' ' + descriptor); if (newElement != null) { elementName = newElement.split(" ")[1]; } String newDescriptor = buildNewDescriptor(elementType == FIELD, descriptor); if (newDescriptor != null) { descriptor = newDescriptor; } } return new String[]{elementName, descriptor}; }
private static void doTest(Type elementType, String className, String element, String descriptor, boolean shallBeRenamed) { boolean result = new ConverterHelper().toBeRenamed(elementType, className, element, descriptor); String assertionMessage = shallBeRenamed ? "Identifier { %s, %s, %s, %s } shall be renamed" : "Identifier { %s, %s, %s, %s } shall not be renamed"; assertTrue(String.format(assertionMessage, elementType.toString(), className, element, descriptor), result == shallBeRenamed); } }
public Fernflower(IBytecodeProvider provider, IResultSaver saver, Map<String, Object> customProperties, IFernflowerLogger logger) { Map<String, Object> properties = new HashMap<>(IFernflowerPreferences.DEFAULTS); if (customProperties != null) { properties.putAll(customProperties); } String level = (String)properties.get(IFernflowerPreferences.LOG_LEVEL); if (level != null) { try { logger.setSeverity(IFernflowerLogger.Severity.valueOf(level.toUpperCase(Locale.US))); } catch (IllegalArgumentException ignore) { } } structContext = new StructContext(saver, this, new LazyLoader(provider)); classProcessor = new ClassesProcessor(structContext); PoolInterceptor interceptor = null; if ("1".equals(properties.get(IFernflowerPreferences.RENAME_ENTITIES))) { helper = loadHelper((String)properties.get(IFernflowerPreferences.USER_RENAMER_CLASS), logger); interceptor = new PoolInterceptor(); converter = new IdentifierConverter(structContext, helper, interceptor); } else { helper = null; converter = null; } DecompilerContext context = new DecompilerContext(properties, logger, structContext, classProcessor, interceptor); DecompilerContext.setCurrentContext(context); }
nodes.put(clStr.qualifiedName, node = new ClassWrapperNode(clStr)); node.addSubclass(child);
private static IIdentifierRenamer loadHelper(String className, IFernflowerLogger logger) { if (className != null) { try { Class<?> renamerClass = Fernflower.class.getClassLoader().loadClass(className); return (IIdentifierRenamer) renamerClass.getDeclaredConstructor().newInstance(); } catch (Exception e) { logger.writeMessage("Cannot load renamer '" + className + "'", IFernflowerLogger.Severity.WARN, e); } } return new ConverterHelper(); }
String oldName = interceptor.getOldName(cl.qualifiedName); appendRenameComment(buffer, oldName, MType.CLASS, indent);
public void decompileContext() { if (converter != null) { converter.rename(); } classProcessor.loadClasses(helper); structContext.saveContext(); }
private static List<ClassWrapperNode> getReversePostOrderListIterative(List<ClassWrapperNode> roots) { List<ClassWrapperNode> res = new ArrayList<>(); LinkedList<ClassWrapperNode> stackNode = new LinkedList<>(); LinkedList<Integer> stackIndex = new LinkedList<>(); Set<ClassWrapperNode> setVisited = new HashSet<>(); for (ClassWrapperNode root : roots) { stackNode.add(root); stackIndex.add(0); } while (!stackNode.isEmpty()) { ClassWrapperNode node = stackNode.getLast(); int index = stackIndex.removeLast(); setVisited.add(node); List<ClassWrapperNode> lstSubs = node.getSubclasses(); for (; index < lstSubs.size(); index++) { ClassWrapperNode sub = lstSubs.get(index); if (!setVisited.contains(sub)) { stackIndex.add(index + 1); stackNode.add(sub); stackIndex.add(0); break; } } if (index == lstSubs.size()) { res.add(0, node); stackNode.removeLast(); } } return res; }
@Override public boolean toBeRenamed(Type elementType, String className, String element, String descriptor) { String value = elementType == Type.ELEMENT_CLASS ? className : element; return value == null || value.length() <= 2 || !isValidIdentifier(elementType == Type.ELEMENT_METHOD, value) || KEYWORDS.contains(value) || elementType == Type.ELEMENT_CLASS && ( RESERVED_WINDOWS_NAMESPACE.contains(value.toLowerCase(Locale.US)) || value.length() > 255 - ".class".length()); }
@Override public 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').append(newName).append(';'); } else { buffer.append(newName); } return buffer.toString(); } return null; }
String oldName = interceptor.getOldName(cl.qualifiedName + " " + fd.getName() + " " + fd.getDescriptor()); appendRenameComment(buffer, oldName, MType.FIELD, indent);
public LinkConstant getLinkConstant(int index) { LinkConstant ln = (LinkConstant)getConstant(index); if (ln != null && interceptor != null && (ln.type == CodeConstants.CONSTANT_Fieldref || ln.type == CodeConstants.CONSTANT_Methodref || ln.type == CodeConstants.CONSTANT_InterfaceMethodref)) { String newClassName = buildNewClassname(ln.classname); String newElement = interceptor.getName(ln.classname + ' ' + ln.elementname + ' ' + ln.descriptor); String newDescriptor = buildNewDescriptor(ln.type == CodeConstants.CONSTANT_Fieldref, ln.descriptor); //TODO: Fix newElement being null caused by ln.classname being a leaf class instead of the class that declared the field/method. //See the comments of IDEA-137253 for more information. if (newClassName != null || newElement != null || newDescriptor != null) { String className = newClassName == null ? ln.classname : newClassName; String elementName = newElement == null ? ln.elementname : newElement.split(" ")[1]; String descriptor = newDescriptor == null ? ln.descriptor : newDescriptor; ln = new LinkConstant(ln.type, className, elementName, descriptor); } } return ln; }