Archiviert
13
0

Allow the structure modifier to read final fields.

Dieser Commit ist enthalten in:
Kristian S. Stangeland 2012-11-11 01:22:17 +01:00
Ursprung addc62457a
Commit 76d27017de
2 geänderte Dateien mit 32 neuen und 12 gelöschten Zeilen

Datei anzeigen

@ -152,6 +152,18 @@ public class StructureModifier<TField> {
} }
} }
/**
* Determine whether or not a field is read-only (final).
* @param fieldIndex - index of the field.
* @return TRUE if the field by the given index is read-only, FALSE otherwise.
*/
public boolean isReadOnly(int fieldIndex) {
if (fieldIndex < 0 || fieldIndex >= data.size())
new IllegalArgumentException("Index parameter is not within [0 - " + data.size() + ")");
return Modifier.isFinal(data.get(fieldIndex).getModifiers());
}
/** /**
* Writes the value of a field given its index. * Writes the value of a field given its index.
* @param fieldIndex - index of the field. * @param fieldIndex - index of the field.
@ -424,9 +436,10 @@ public class StructureModifier<TField> {
for (Field field : fields) { for (Field field : fields) {
Class<?> type = field.getType(); Class<?> type = field.getType();
int modifier = field.getModifiers();
// First, ignore primitive fields // First, ignore primitive fields and final fields
if (!type.isPrimitive()) { if (!type.isPrimitive() && !Modifier.isFinal(modifier)) {
// Next, see if we actually can generate a default value // Next, see if we actually can generate a default value
if (generator.getDefault(type) != null) { if (generator.getDefault(type) != null) {
// If so, require it // If so, require it
@ -449,9 +462,9 @@ public class StructureModifier<TField> {
for (Field field : FuzzyReflection.fromClass(type, true).getFields()) { for (Field field : FuzzyReflection.fromClass(type, true).getFields()) {
int mod = field.getModifiers(); int mod = field.getModifiers();
// Ignore static, final and "abstract packet" fields // Ignore static and "abstract packet" fields
if (!Modifier.isFinal(mod) && !Modifier.isStatic(mod) && ( if (!Modifier.isStatic(mod) &&
superclassExclude == null || !field.getDeclaringClass().equals(superclassExclude) (superclassExclude == null || !field.getDeclaringClass().equals(superclassExclude)
)) { )) {
result.add(field); result.add(field);

Datei anzeigen

@ -272,6 +272,10 @@ public final class StructureCompiler {
return Modifier.isPublic(field.getModifiers()); return Modifier.isPublic(field.getModifiers());
} }
private boolean isNonFinal(Field field) {
return !Modifier.isFinal(field.getModifiers());
}
private void createFields(ClassWriter cw, String targetSignature) { private void createFields(ClassWriter cw, String targetSignature) {
FieldVisitor typedField = cw.visitField(Opcodes.ACC_PRIVATE, "typedTarget", targetSignature, null, null); FieldVisitor typedField = cw.visitField(Opcodes.ACC_PRIVATE, "typedTarget", targetSignature, null, null);
typedField.visitEnd(); typedField.visitEnd();
@ -305,7 +309,8 @@ public final class StructureCompiler {
for (int i = 0; i < fields.size(); i++) { for (int i = 0; i < fields.size(); i++) {
Class<?> outputType = fields.get(i).getType(); Field field = fields.get(i);
Class<?> outputType = field.getType();
Class<?> inputType = Primitives.wrap(outputType); Class<?> inputType = Primitives.wrap(outputType);
String typeDescriptor = Type.getDescriptor(outputType); String typeDescriptor = Type.getDescriptor(outputType);
String inputPath = inputType.getName().replace('.', '/'); String inputPath = inputType.getName().replace('.', '/');
@ -318,8 +323,8 @@ public final class StructureCompiler {
else else
mv.visitFrame(Opcodes.F_SAME, 0, null, 0, null); mv.visitFrame(Opcodes.F_SAME, 0, null, 0, null);
// Only write to public fields // Only write to public non-final fields
if (isPublic(fields.get(i))) { if (isPublic(field) && isNonFinal(field)) {
mv.visitVarInsn(Opcodes.ALOAD, 3); mv.visitVarInsn(Opcodes.ALOAD, 3);
mv.visitVarInsn(Opcodes.ALOAD, 2); mv.visitVarInsn(Opcodes.ALOAD, 2);
@ -328,7 +333,7 @@ public final class StructureCompiler {
else else
boxingHelper.unbox(Type.getType(outputType)); boxingHelper.unbox(Type.getType(outputType));
mv.visitFieldInsn(Opcodes.PUTFIELD, targetName, fields.get(i).getName(), typeDescriptor); mv.visitFieldInsn(Opcodes.PUTFIELD, targetName, field.getName(), typeDescriptor);
} else { } else {
// Use reflection. We don't have a choice, unfortunately. // Use reflection. We don't have a choice, unfortunately.
@ -386,7 +391,9 @@ public final class StructureCompiler {
mv.visitTableSwitchInsn(0, fields.size() - 1, errorLabel, labels); mv.visitTableSwitchInsn(0, fields.size() - 1, errorLabel, labels);
for (int i = 0; i < fields.size(); i++) { for (int i = 0; i < fields.size(); i++) {
Class<?> outputType = fields.get(i).getType();
Field field = fields.get(i);
Class<?> outputType = field.getType();
String typeDescriptor = Type.getDescriptor(outputType); String typeDescriptor = Type.getDescriptor(outputType);
mv.visitLabel(labels[i]); mv.visitLabel(labels[i]);
@ -398,9 +405,9 @@ public final class StructureCompiler {
mv.visitFrame(Opcodes.F_SAME, 0, null, 0, null); mv.visitFrame(Opcodes.F_SAME, 0, null, 0, null);
// Note that byte code cannot access non-public fields // Note that byte code cannot access non-public fields
if (isPublic(fields.get(i))) { if (isPublic(field)) {
mv.visitVarInsn(Opcodes.ALOAD, 2); mv.visitVarInsn(Opcodes.ALOAD, 2);
mv.visitFieldInsn(Opcodes.GETFIELD, targetName, fields.get(i).getName(), typeDescriptor); mv.visitFieldInsn(Opcodes.GETFIELD, targetName, field.getName(), typeDescriptor);
boxingHelper.box(Type.getType(outputType)); boxingHelper.box(Type.getType(outputType));
} else { } else {