Skip to content
127 changes: 58 additions & 69 deletions JavaAsm/AttributeNode.cs
Original file line number Diff line number Diff line change
Expand Up @@ -6,10 +6,8 @@
using JavaAsm.Helpers;
using JavaAsm.IO;

namespace JavaAsm
{
public static class PredefinedAttributeNames
{
namespace JavaAsm {
public static class PredefinedAttributeNames {
public const string AnnotationDefault = "AnnotationDefault";
public const string BootstrapMethods = "BootstrapMethods";
public const string Code = "Code";
Expand All @@ -35,50 +33,48 @@ public static class PredefinedAttributeNames
public const string Synthetic = "Synthetic";
}

public class AttributeNode
{
public class AttributeNode {
private static readonly Dictionary<(string Name, AttributeScope Scope), ICustomAttributeFactory<CustomAttribute>> predefinedAttributes
= new Dictionary<(string Name, AttributeScope Scope), ICustomAttributeFactory<CustomAttribute>>
{
{ (PredefinedAttributeNames.Code, AttributeScope.Method), new CodeAttributeFactory() },
{ (PredefinedAttributeNames.ConstantValue, AttributeScope.Field), new ConstantValueAttributeFactory() },
{ (PredefinedAttributeNames.SourceDebugExtension, AttributeScope.Class), new SourceDebugExtensionFactory() },
{ (PredefinedAttributeNames.SourceFile, AttributeScope.Class), new SourceFileAttributeFactory() },
{ (PredefinedAttributeNames.Exceptions, AttributeScope.Method), new ExceptionsAttributeFactory() },
{ (PredefinedAttributeNames.EnclosingMethod, AttributeScope.Class), new EnclosingMethodAttributeFactory() },
{ (PredefinedAttributeNames.Synthetic, AttributeScope.Class), new SyntheticAttributeFactory() },
{ (PredefinedAttributeNames.Synthetic, AttributeScope.Method), new SyntheticAttributeFactory() },
{ (PredefinedAttributeNames.Synthetic, AttributeScope.Field), new SyntheticAttributeFactory() },
{ (PredefinedAttributeNames.Signature, AttributeScope.Class), new SignatureAttributeFactory() },
{ (PredefinedAttributeNames.Signature, AttributeScope.Method), new SignatureAttributeFactory() },
{ (PredefinedAttributeNames.Signature, AttributeScope.Field), new SignatureAttributeFactory() },
{ (PredefinedAttributeNames.LineNumberTable, AttributeScope.Code), new LineNumberTableAttributeFactory() },
{ (PredefinedAttributeNames.Deprecated, AttributeScope.Class), new DeprecatedAttributeFactory() },
{ (PredefinedAttributeNames.Deprecated, AttributeScope.Method), new DeprecatedAttributeFactory() },
{ (PredefinedAttributeNames.Deprecated, AttributeScope.Field), new DeprecatedAttributeFactory() },
{ (PredefinedAttributeNames.MethodParameters, AttributeScope.Method), new MethodParametersAttributeFactory() },
{ (PredefinedAttributeNames.LocalVariableTable, AttributeScope.Code), new LocalVariableTableAttributeFactory() },
{ (PredefinedAttributeNames.LocalVariableTypeTable, AttributeScope.Code), new LocalVariableTypeTableAttributeFactory() },
{ (PredefinedAttributeNames.InnerClasses, AttributeScope.Class), new InnerClassesAttributeFactory() },
{ (PredefinedAttributeNames.RuntimeInvisibleAnnotations, AttributeScope.Class), new RuntimeInvisibleAnnotationsAttributeFactory() },
{ (PredefinedAttributeNames.RuntimeInvisibleAnnotations, AttributeScope.Method), new RuntimeInvisibleAnnotationsAttributeFactory() },
{ (PredefinedAttributeNames.RuntimeInvisibleAnnotations, AttributeScope.Field), new RuntimeInvisibleAnnotationsAttributeFactory() },
{ (PredefinedAttributeNames.RuntimeVisibleAnnotations, AttributeScope.Class), new RuntimeVisibleAnnotationsAttributeFactory() },
{ (PredefinedAttributeNames.RuntimeVisibleAnnotations, AttributeScope.Method), new RuntimeVisibleAnnotationsAttributeFactory() },
{ (PredefinedAttributeNames.RuntimeVisibleAnnotations, AttributeScope.Field), new RuntimeVisibleAnnotationsAttributeFactory() },
{ (PredefinedAttributeNames.RuntimeInvisibleParameterAnnotations, AttributeScope.Method), new RuntimeInvisibleParameterAnnotationsAttributeFactory() },
{ (PredefinedAttributeNames.RuntimeVisibleParameterAnnotations, AttributeScope.Method), new RuntimeVisibleParameterAnnotationsAttributeFactory() },
{ (PredefinedAttributeNames.RuntimeInvisibleTypeAnnotations, AttributeScope.Class), new RuntimeInvisibleTypeAnnotationsAttributeFactory() },
{ (PredefinedAttributeNames.RuntimeInvisibleTypeAnnotations, AttributeScope.Method), new RuntimeInvisibleTypeAnnotationsAttributeFactory() },
{ (PredefinedAttributeNames.RuntimeInvisibleTypeAnnotations, AttributeScope.Field), new RuntimeInvisibleTypeAnnotationsAttributeFactory() },
{ (PredefinedAttributeNames.RuntimeInvisibleTypeAnnotations, AttributeScope.Code), new RuntimeInvisibleTypeAnnotationsAttributeFactory() },
{ (PredefinedAttributeNames.RuntimeVisibleTypeAnnotations, AttributeScope.Class), new RuntimeVisibleTypeAnnotationsAttributeFactory() },
{ (PredefinedAttributeNames.RuntimeVisibleTypeAnnotations, AttributeScope.Method), new RuntimeVisibleTypeAnnotationsAttributeFactory() },
{ (PredefinedAttributeNames.RuntimeVisibleTypeAnnotations, AttributeScope.Field), new RuntimeVisibleTypeAnnotationsAttributeFactory() },
{ (PredefinedAttributeNames.RuntimeVisibleTypeAnnotations, AttributeScope.Code), new RuntimeVisibleTypeAnnotationsAttributeFactory() },
{ (PredefinedAttributeNames.AnnotationDefault, AttributeScope.Method), new AnnotationDefaultAttributeFactory() },
{ (PredefinedAttributeNames.BootstrapMethods, AttributeScope.Class), new BootstrapMethodsAttributeFactory() },
{ (PredefinedAttributeNames.StackMapTable, AttributeScope.Code), new StackMapTableAttributeFactory() }
= new Dictionary<(string Name, AttributeScope Scope), ICustomAttributeFactory<CustomAttribute>> {
{(PredefinedAttributeNames.Code, AttributeScope.Method), new CodeAttributeFactory()},
{(PredefinedAttributeNames.ConstantValue, AttributeScope.Field), new ConstantValueAttributeFactory()},
{(PredefinedAttributeNames.SourceDebugExtension, AttributeScope.Class), new SourceDebugExtensionFactory()},
{(PredefinedAttributeNames.SourceFile, AttributeScope.Class), new SourceFileAttributeFactory()},
{(PredefinedAttributeNames.Exceptions, AttributeScope.Method), new ExceptionsAttributeFactory()},
{(PredefinedAttributeNames.EnclosingMethod, AttributeScope.Class), new EnclosingMethodAttributeFactory()},
{(PredefinedAttributeNames.Synthetic, AttributeScope.Class), new SyntheticAttributeFactory()},
{(PredefinedAttributeNames.Synthetic, AttributeScope.Method), new SyntheticAttributeFactory()},
{(PredefinedAttributeNames.Synthetic, AttributeScope.Field), new SyntheticAttributeFactory()},
{(PredefinedAttributeNames.Signature, AttributeScope.Class), new SignatureAttributeFactory()},
{(PredefinedAttributeNames.Signature, AttributeScope.Method), new SignatureAttributeFactory()},
{(PredefinedAttributeNames.Signature, AttributeScope.Field), new SignatureAttributeFactory()},
{(PredefinedAttributeNames.LineNumberTable, AttributeScope.Code), new LineNumberTableAttributeFactory()},
{(PredefinedAttributeNames.Deprecated, AttributeScope.Class), new DeprecatedAttributeFactory()},
{(PredefinedAttributeNames.Deprecated, AttributeScope.Method), new DeprecatedAttributeFactory()},
{(PredefinedAttributeNames.Deprecated, AttributeScope.Field), new DeprecatedAttributeFactory()},
{(PredefinedAttributeNames.MethodParameters, AttributeScope.Method), new MethodParametersAttributeFactory()},
{(PredefinedAttributeNames.LocalVariableTable, AttributeScope.Code), new LocalVariableTableAttributeFactory()},
{(PredefinedAttributeNames.LocalVariableTypeTable, AttributeScope.Code), new LocalVariableTypeTableAttributeFactory()},
{(PredefinedAttributeNames.InnerClasses, AttributeScope.Class), new InnerClassesAttributeFactory()},
{(PredefinedAttributeNames.RuntimeInvisibleAnnotations, AttributeScope.Class), new RuntimeInvisibleAnnotationsAttributeFactory()},
{(PredefinedAttributeNames.RuntimeInvisibleAnnotations, AttributeScope.Method), new RuntimeInvisibleAnnotationsAttributeFactory()},
{(PredefinedAttributeNames.RuntimeInvisibleAnnotations, AttributeScope.Field), new RuntimeInvisibleAnnotationsAttributeFactory()},
{(PredefinedAttributeNames.RuntimeVisibleAnnotations, AttributeScope.Class), new RuntimeVisibleAnnotationsAttributeFactory()},
{(PredefinedAttributeNames.RuntimeVisibleAnnotations, AttributeScope.Method), new RuntimeVisibleAnnotationsAttributeFactory()},
{(PredefinedAttributeNames.RuntimeVisibleAnnotations, AttributeScope.Field), new RuntimeVisibleAnnotationsAttributeFactory()},
{(PredefinedAttributeNames.RuntimeInvisibleParameterAnnotations, AttributeScope.Method), new RuntimeInvisibleParameterAnnotationsAttributeFactory()},
{(PredefinedAttributeNames.RuntimeVisibleParameterAnnotations, AttributeScope.Method), new RuntimeVisibleParameterAnnotationsAttributeFactory()},
{(PredefinedAttributeNames.RuntimeInvisibleTypeAnnotations, AttributeScope.Class), new RuntimeInvisibleTypeAnnotationsAttributeFactory()},
{(PredefinedAttributeNames.RuntimeInvisibleTypeAnnotations, AttributeScope.Method), new RuntimeInvisibleTypeAnnotationsAttributeFactory()},
{(PredefinedAttributeNames.RuntimeInvisibleTypeAnnotations, AttributeScope.Field), new RuntimeInvisibleTypeAnnotationsAttributeFactory()},
{(PredefinedAttributeNames.RuntimeInvisibleTypeAnnotations, AttributeScope.Code), new RuntimeInvisibleTypeAnnotationsAttributeFactory()},
{(PredefinedAttributeNames.RuntimeVisibleTypeAnnotations, AttributeScope.Class), new RuntimeVisibleTypeAnnotationsAttributeFactory()},
{(PredefinedAttributeNames.RuntimeVisibleTypeAnnotations, AttributeScope.Method), new RuntimeVisibleTypeAnnotationsAttributeFactory()},
{(PredefinedAttributeNames.RuntimeVisibleTypeAnnotations, AttributeScope.Field), new RuntimeVisibleTypeAnnotationsAttributeFactory()},
{(PredefinedAttributeNames.RuntimeVisibleTypeAnnotations, AttributeScope.Code), new RuntimeVisibleTypeAnnotationsAttributeFactory()},
{(PredefinedAttributeNames.AnnotationDefault, AttributeScope.Method), new AnnotationDefaultAttributeFactory()},
{(PredefinedAttributeNames.BootstrapMethods, AttributeScope.Class), new BootstrapMethodsAttributeFactory()},
{(PredefinedAttributeNames.StackMapTable, AttributeScope.Code), new StackMapTableAttributeFactory()}
};

public string Name { get; set; }
Expand All @@ -87,41 +83,34 @@ public class AttributeNode

public CustomAttribute ParsedAttribute { get; set; }

internal void Parse(Stream stream, AttributeScope scope, ClassReaderState readerState)
{
var dataLength = Binary.BigEndian.ReadUInt32(stream);
var data = stream.ReadBytes(dataLength);
internal void Parse(Stream stream, AttributeScope scope, ClassReaderState readerState) {
uint dataLength = Binary.BigEndian.ReadUInt32(stream);
byte[] data = stream.ReadBytes(dataLength);

try
{
if (!predefinedAttributes.ContainsKey((Name, scope)))
throw new ArgumentException($"Attribute {Name} in {scope} not found");
var readWriteCounter = new ReadWriteCountStream(new MemoryStream(data));
ParsedAttribute = predefinedAttributes[(Name, scope)].Parse(readWriteCounter, dataLength, readerState, scope);
try {
if (!predefinedAttributes.ContainsKey((this.Name, scope)))
throw new ArgumentException($"Attribute {this.Name} in {scope} not found");
ReadWriteCountStream readWriteCounter = new ReadWriteCountStream(new MemoryStream(data));
this.ParsedAttribute = predefinedAttributes[(this.Name, scope)].Parse(readWriteCounter, dataLength, readerState, scope);
if (readWriteCounter.ReadBytes != dataLength)
throw new ArgumentOutOfRangeException(nameof(dataLength),
$"Wrong data length of attribute {Name} in {scope}: Given {dataLength}, Read: {readWriteCounter.ReadBytes}");
}
catch
{
Data = data;
$"Wrong data length of attribute {this.Name} in {scope}: Given {dataLength}, Read: {readWriteCounter.ReadBytes}");
}
catch {
this.Data = data;
}

}
}

public abstract class CustomAttribute
{
public abstract class CustomAttribute {
internal abstract byte[] Save(ClassWriterState writerState, AttributeScope scope);
}

internal interface ICustomAttributeFactory<out T> where T : CustomAttribute
{
internal interface ICustomAttributeFactory<out T> where T : CustomAttribute {
T Parse(Stream attributeDataStream, uint attributeDataLength, ClassReaderState readerState, AttributeScope scope);
}

internal enum AttributeScope
{
internal enum AttributeScope {
Class,
Method,
Field,
Expand Down
34 changes: 7 additions & 27 deletions JavaAsm/ClassAccessModifiers.cs
Original file line number Diff line number Diff line change
@@ -1,11 +1,9 @@
using System;
using System.Linq;

namespace JavaAsm
{
namespace JavaAsm {
[Flags]
public enum ClassAccessModifiers : ushort
{
public enum ClassAccessModifiers : ushort {
Public = 0x0001,
Protected = 0x0004,
Private = 0x0002,
Expand All @@ -21,8 +19,7 @@ public enum ClassAccessModifiers : ushort
}

[Flags]
public enum MethodAccessModifiers : ushort
{
public enum MethodAccessModifiers : ushort {
Public = 0x0001,
Protected = 0x0004,
Private = 0x0002,
Expand All @@ -38,8 +35,7 @@ public enum MethodAccessModifiers : ushort
}

[Flags]
public enum FieldAccessModifiers : ushort
{
public enum FieldAccessModifiers : ushort {
Public = 0x0001,
Protected = 0x0004,
Private = 0x0002,
Expand All @@ -51,26 +47,10 @@ public enum FieldAccessModifiers : ushort
}

public static class AccessModifiersExtensions {
public static string ToString(ClassAccessModifiers accessModifiers) => string.Join(" ", Enum.GetValues(typeof(ClassAccessModifiers)).OfType<ClassAccessModifiers>().Where(x => accessModifiers.HasFlag(x)).Select(x => x.ToString().ToLower()));

public static string ToString(ClassAccessModifiers accessModifiers)
{
return string.Join(' ',
Enum.GetValues(typeof(ClassAccessModifiers)).OfType<ClassAccessModifiers>().Where(x => accessModifiers.HasFlag(x))
.Select(x => x.ToString().ToLower()));
}
public static string ToString(MethodAccessModifiers accessModifiers) => string.Join(" ", Enum.GetValues(typeof(MethodAccessModifiers)).OfType<MethodAccessModifiers>().Where(x => accessModifiers.HasFlag(x)).Select(x => x.ToString().ToLower()));

public static string ToString(MethodAccessModifiers accessModifiers)
{
return string.Join(' ',
Enum.GetValues(typeof(MethodAccessModifiers)).OfType<MethodAccessModifiers>().Where(x => accessModifiers.HasFlag(x))
.Select(x => x.ToString().ToLower()));
}

public static string ToString(FieldAccessModifiers accessModifiers)
{
return string.Join(' ',
Enum.GetValues(typeof(FieldAccessModifiers)).OfType<FieldAccessModifiers>().Where(x => accessModifiers.HasFlag(x))
.Select(x => x.ToString().ToLower()));
}
public static string ToString(FieldAccessModifiers accessModifiers) => string.Join(" ", Enum.GetValues(typeof(FieldAccessModifiers)).OfType<FieldAccessModifiers>().Where(x => accessModifiers.HasFlag(x)).Select(x => x.ToString().ToLower()));
}
}
58 changes: 38 additions & 20 deletions JavaAsm/ClassName.cs
Original file line number Diff line number Diff line change
@@ -1,36 +1,54 @@
using System;
using System.Windows.Input;

namespace JavaAsm
{
public class ClassName
{
namespace JavaAsm {
/// <summary>
/// The name of a class, where the separator for packages and the class name is the / char (e.g java/lang/String)
/// </summary>
public class ClassName {
public string Name { get; }

public ClassName(string name)
{
Name = name ?? throw new ArgumentNullException(nameof(name));
public ClassName(string name) {
this.Name = name ?? throw new ArgumentNullException(nameof(name));
}

public override string ToString()
{
return Name.Replace("/", ".");
public static bool TryParse(string value, out ClassName name) {
if (string.IsNullOrEmpty(value)) {
name = null;
return false;
}

// convert type descriptor to class name
if (value[0] == 'L' && value[value.Length - 1] == ';') {
value = value.Substring(1, value.Length - 2);
}

name = new ClassName(value.Replace('.', '/'));
return true;
}

public override string ToString() {
return this.Name.Replace('/', '.');
}

private bool Equals(ClassName other)
{
return Name == other.Name;
private bool Equals(ClassName other) {
return this.Name == other.Name;
}

public override bool Equals(object obj)
{
if (obj is null) return false;
if (ReferenceEquals(this, obj)) return true;
public override bool Equals(object obj) {
if (obj is null)
return false;
if (ReferenceEquals(this, obj))
return true;
return obj.GetType() == GetType() && Equals((ClassName) obj);
}

public override int GetHashCode()
{
return Name.GetHashCode();
public override int GetHashCode() {
return this.Name.GetHashCode();
}

public ClassName Copy() {
return new ClassName(this.Name);
}
}
}
Loading