summaryrefslogtreecommitdiff
path: root/src/proguard/classfile/editor/InterfaceSorter.java
diff options
context:
space:
mode:
Diffstat (limited to 'src/proguard/classfile/editor/InterfaceSorter.java')
-rw-r--r--src/proguard/classfile/editor/InterfaceSorter.java119
1 files changed, 102 insertions, 17 deletions
diff --git a/src/proguard/classfile/editor/InterfaceSorter.java b/src/proguard/classfile/editor/InterfaceSorter.java
index 6521369..0d1f28c 100644
--- a/src/proguard/classfile/editor/InterfaceSorter.java
+++ b/src/proguard/classfile/editor/InterfaceSorter.java
@@ -2,7 +2,7 @@
* ProGuard -- shrinking, optimization, obfuscation, and preverification
* of Java bytecode.
*
- * Copyright (c) 2002-2009 Eric Lafortune (eric@graphics.cornell.edu)
+ * Copyright (c) 2002-2013 Eric Lafortune (eric@graphics.cornell.edu)
*
* This program is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License as published by the Free
@@ -21,10 +21,14 @@
package proguard.classfile.editor;
import proguard.classfile.*;
-import proguard.classfile.util.SimplifiedVisitor;
+import proguard.classfile.attribute.*;
+import proguard.classfile.attribute.visitor.AttributeVisitor;
+import proguard.classfile.constant.*;
+import proguard.classfile.constant.visitor.ConstantVisitor;
+import proguard.classfile.util.*;
import proguard.classfile.visitor.ClassVisitor;
-import java.util.Arrays;
+import java.util.*;
/**
* This ClassVisitor sorts the interfaces of the program classes that it visits.
@@ -33,7 +37,8 @@ import java.util.Arrays;
*/
public class InterfaceSorter
extends SimplifiedVisitor
-implements ClassVisitor
+implements ClassVisitor,
+ AttributeVisitor
{
// Implementations for ClassVisitor.
@@ -42,26 +47,106 @@ implements ClassVisitor
int[] interfaces = programClass.u2interfaces;
int interfacesCount = programClass.u2interfacesCount;
- // Sort the interfaces.
- Arrays.sort(interfaces, 0, interfacesCount);
+ if (interfacesCount > 1)
+ {
+ // Sort the interfaces.
+ Arrays.sort(interfaces, 0, interfacesCount);
+
+ // Remove any duplicate entries.
+ int newInterfacesCount = 0;
+ int previousInterfaceIndex = 0;
+ for (int index = 0; index < interfacesCount; index++)
+ {
+ int interfaceIndex = interfaces[index];
+
+ // Isn't this a duplicate of the previous interface?
+ if (interfaceIndex != previousInterfaceIndex)
+ {
+ interfaces[newInterfacesCount++] = interfaceIndex;
+
+ // Remember the interface.
+ previousInterfaceIndex = interfaceIndex;
+ }
+ }
+
+ programClass.u2interfacesCount = newInterfacesCount;
+
+ // Update the signature, if any
+ programClass.attributesAccept(this);
+ }
+ }
+
+
+ // Implementations for AttributeVisitor.
+
+ public void visitAnyAttribute(Clazz clazz, Attribute attribute) {}
+
+
+ public void visitSignatureAttribute(Clazz clazz, SignatureAttribute signatureAttribute)
+ {
+ // Process the generic definitions, superclass, and implemented
+ // interfaces.
+ String signature = clazz.getString(signatureAttribute.u2signatureIndex);
+
+ // Count the signature types.
+ InternalTypeEnumeration internalTypeEnumeration =
+ new InternalTypeEnumeration(signature);
- // Remove any duplicate entries.
- int newInterfacesCount = 0;
- int previousInterfaceIndex = 0;
- for (int index = 0; index < interfacesCount; index++)
+ int count = 0;
+ int interfacesCount = -1;
+ while (internalTypeEnumeration.hasMoreTypes())
{
- int interfaceIndex = interfaces[index];
+ String internalType = internalTypeEnumeration.nextType();
- // Isn't this a duplicate of the previous interface?
- if (interfaceIndex != previousInterfaceIndex)
+ count++;
+
+ if (ClassUtil.isInternalClassType(internalType))
{
- interfaces[newInterfacesCount++] = interfaceIndex;
+ interfacesCount++;
+ }
+ }
+
+ // Put the signature types in an array.
+ internalTypeEnumeration =
+ new InternalTypeEnumeration(signature);
+
+ String[] internalTypes = new String[count];
+
+ for (int index = 0; index < count; index++)
+ {
+ String internalType = internalTypeEnumeration.nextType();
+
+ internalTypes[index] = internalType;
+ }
- // Remember the interface.
- previousInterfaceIndex = interfaceIndex;
+ // Sort the interface types in the array.
+ Arrays.sort(internalTypes, count - interfacesCount, count);
+
+ // Recompose the signature types in a string.
+ StringBuffer newSignatureBuffer = new StringBuffer();
+
+ for (int index = 0; index < count; index++)
+ {
+ // Is this not an interface type, or an interface type that isn't
+ // a duplicate of the previous interface type?
+ if (index < count - interfacesCount ||
+ !internalTypes[index].equals(internalTypes[index-1]))
+ {
+ newSignatureBuffer.append(internalTypes[index]);
}
}
- programClass.u2interfacesCount = newInterfacesCount;
+ String newSignature = newSignatureBuffer.toString();
+
+ // Did the signature change?
+ if (!newSignature.equals(signature))
+ {
+ // Update the signature.
+ ((Utf8Constant)((ProgramClass)clazz).constantPool[signatureAttribute.u2signatureIndex]).setString(newSignatureBuffer.toString());
+
+ // Clear the referenced classes.
+ // TODO: Properly update the referenced classes.
+ signatureAttribute.referencedClasses = null;
+ }
}
}