Allow the structure modifier to read final fields.
Dieser Commit ist enthalten in:
Ursprung
addc62457a
Commit
76d27017de
@ -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);
|
||||||
|
@ -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 {
|
||||||
|
In neuem Issue referenzieren
Einen Benutzer sperren