String annotation reading/writing
This commit is contained in:
41
src/main/java/net/runelite/deob/attributes/Annotations.java
Normal file
41
src/main/java/net/runelite/deob/attributes/Annotations.java
Normal file
@@ -0,0 +1,41 @@
|
||||
package net.runelite.deob.attributes;
|
||||
|
||||
import java.io.DataInputStream;
|
||||
import java.io.DataOutputStream;
|
||||
import java.io.IOException;
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
import net.runelite.deob.attributes.annotation.Annotation;
|
||||
|
||||
public class Annotations extends Attribute
|
||||
{
|
||||
private final List<Annotation> annotations = new ArrayList<>();
|
||||
|
||||
public Annotations(Attributes attributes)
|
||||
{
|
||||
super(attributes, AttributeType.RUNTIMEVISIBLEANNOTATIONS);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void loadAttribute(DataInputStream is) throws IOException
|
||||
{
|
||||
int num_annotations = is.readUnsignedShort();
|
||||
for (int i = 0; i < num_annotations; ++i)
|
||||
{
|
||||
Annotation a = new Annotation(this);
|
||||
a.load(is);
|
||||
annotations.add(a);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void writeAttr(DataOutputStream out) throws IOException
|
||||
{
|
||||
out.writeShort(annotations.size());
|
||||
for (Annotation a : annotations)
|
||||
{
|
||||
a.write(out);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
@@ -5,6 +5,7 @@ public enum AttributeType
|
||||
CONSTANT_VALUE("ConstantValue", ConstantValue.class),
|
||||
CODE("Code", Code.class),
|
||||
EXCEPTIONS("Exceptions", Exceptions.class),
|
||||
RUNTIMEVISIBLEANNOTATIONS("RuntimeVisibleAnnotations", Annotations.class),
|
||||
UNKNOWN(null, Unknown.class);
|
||||
|
||||
private String name;
|
||||
|
||||
@@ -0,0 +1,55 @@
|
||||
package net.runelite.deob.attributes.annotation;
|
||||
|
||||
import java.io.DataInputStream;
|
||||
import java.io.DataOutputStream;
|
||||
import java.io.IOException;
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
import net.runelite.deob.ConstantPool;
|
||||
import net.runelite.deob.attributes.Annotations;
|
||||
import net.runelite.deob.signature.Type;
|
||||
|
||||
public class Annotation
|
||||
{
|
||||
private final Annotations annotations;
|
||||
private Type type;
|
||||
private List<Element> elements = new ArrayList<>();
|
||||
|
||||
public Annotation(Annotations annotations)
|
||||
{
|
||||
this.annotations = annotations;
|
||||
}
|
||||
|
||||
public Annotations getAnnotations()
|
||||
{
|
||||
return annotations;
|
||||
}
|
||||
|
||||
public void load(DataInputStream is) throws IOException
|
||||
{
|
||||
ConstantPool pool = annotations.getAttributes().getClassFile().getPool();
|
||||
|
||||
int typeIndex = is.readUnsignedShort();
|
||||
type = new Type(pool.getUTF8(typeIndex));
|
||||
|
||||
int pairs = is.readUnsignedShort();
|
||||
for (int i = 0; i < pairs; ++i)
|
||||
{
|
||||
Element e = new Element(this);
|
||||
e.load(is);
|
||||
elements.add(e);
|
||||
}
|
||||
}
|
||||
|
||||
public void write(DataOutputStream out) throws IOException
|
||||
{
|
||||
ConstantPool pool = annotations.getAttributes().getClassFile().getPool();
|
||||
|
||||
out.writeShort(pool.makeUTF8(type.toString()));
|
||||
out.writeShort(elements.size());
|
||||
for (Element e : elements)
|
||||
{
|
||||
e.write(out);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,45 @@
|
||||
package net.runelite.deob.attributes.annotation;
|
||||
|
||||
import java.io.DataInputStream;
|
||||
import java.io.DataOutputStream;
|
||||
import java.io.IOException;
|
||||
import net.runelite.deob.ConstantPool;
|
||||
import net.runelite.deob.signature.Type;
|
||||
|
||||
public class Element
|
||||
{
|
||||
private final Annotation annotation;
|
||||
private Type type;
|
||||
private String value;
|
||||
|
||||
public Element(Annotation annotation)
|
||||
{
|
||||
this.annotation = annotation;
|
||||
}
|
||||
|
||||
public void load(DataInputStream is) throws IOException
|
||||
{
|
||||
ConstantPool pool = annotation.getAnnotations().getAttributes().getClassFile().getPool();
|
||||
|
||||
int typeIndex = is.readShort();
|
||||
type = new Type(pool.getUTF8(typeIndex));
|
||||
|
||||
byte type = is.readByte();
|
||||
|
||||
if (type != 's')
|
||||
throw new RuntimeException("can't parse non string annotation element");
|
||||
|
||||
int index = is.readShort(); // pool index to String
|
||||
|
||||
value = pool.getUTF8(index);
|
||||
}
|
||||
|
||||
public void write(DataOutputStream out) throws IOException
|
||||
{
|
||||
ConstantPool pool = annotation.getAnnotations().getAttributes().getClassFile().getPool();
|
||||
|
||||
out.writeShort(pool.makeUTF8(type.toString()));
|
||||
out.write('s');
|
||||
out.writeShort(pool.makeUTF8(value));
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,35 @@
|
||||
package net.runelite.deob.annotations;
|
||||
|
||||
import java.io.ByteArrayInputStream;
|
||||
import java.io.ByteArrayOutputStream;
|
||||
import java.io.DataInputStream;
|
||||
import java.io.DataOutputStream;
|
||||
import java.io.InputStream;
|
||||
import net.runelite.deob.ClassFile;
|
||||
import net.runelite.deob.ClassGroup;
|
||||
import org.junit.Assert;
|
||||
import org.junit.Test;
|
||||
|
||||
public class AnnotationTest
|
||||
{
|
||||
@Test
|
||||
public void testAnnotation() throws Exception
|
||||
{
|
||||
InputStream in = this.getClass().getClassLoader().getResourceAsStream("net/runelite/deob/annotations/TestClass.class");
|
||||
Assert.assertNotNull(in);
|
||||
|
||||
ClassGroup group = new ClassGroup();
|
||||
|
||||
ClassFile cf = new ClassFile(group, new DataInputStream(in));
|
||||
group.addClass(cf);
|
||||
|
||||
ByteArrayOutputStream bout = new ByteArrayOutputStream();
|
||||
DataOutputStream out = new DataOutputStream(bout);
|
||||
cf.write(out); // write it out
|
||||
|
||||
// parse it again
|
||||
cf = new ClassFile(group, new DataInputStream(new ByteArrayInputStream(bout.toByteArray())));
|
||||
|
||||
System.out.println(cf);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,10 @@
|
||||
package net.runelite.deob.annotations;
|
||||
|
||||
import java.lang.annotation.Retention;
|
||||
import java.lang.annotation.RetentionPolicy;
|
||||
|
||||
@Retention(RetentionPolicy.RUNTIME)
|
||||
public @interface MyAnnotation
|
||||
{
|
||||
String value();
|
||||
}
|
||||
10
src/test/java/net/runelite/deob/annotations/TestClass.java
Normal file
10
src/test/java/net/runelite/deob/annotations/TestClass.java
Normal file
@@ -0,0 +1,10 @@
|
||||
package net.runelite.deob.annotations;
|
||||
|
||||
public class TestClass
|
||||
{
|
||||
@MyAnnotation("field1")
|
||||
public int field1;
|
||||
|
||||
@MyAnnotation("method1")
|
||||
public void method1() { }
|
||||
}
|
||||
Reference in New Issue
Block a user