|
@@ -32,6 +32,8 @@ package com.google.protobuf.nano;
|
|
|
|
|
|
import java.lang.reflect.Array;
|
|
|
import java.lang.reflect.Field;
|
|
|
+import java.lang.reflect.InvocationTargetException;
|
|
|
+import java.lang.reflect.Method;
|
|
|
import java.lang.reflect.Modifier;
|
|
|
|
|
|
/**
|
|
@@ -65,6 +67,8 @@ public final class MessageNanoPrinter {
|
|
|
print(null, message, new StringBuffer(), buf);
|
|
|
} catch (IllegalAccessException e) {
|
|
|
return "Error printing proto: " + e.getMessage();
|
|
|
+ } catch (InvocationTargetException e) {
|
|
|
+ return "Error printing proto: " + e.getMessage();
|
|
|
}
|
|
|
return buf.toString();
|
|
|
}
|
|
@@ -81,7 +85,8 @@ public final class MessageNanoPrinter {
|
|
|
* @param buf the output buffer.
|
|
|
*/
|
|
|
private static void print(String identifier, Object object,
|
|
|
- StringBuffer indentBuf, StringBuffer buf) throws IllegalAccessException {
|
|
|
+ StringBuffer indentBuf, StringBuffer buf) throws IllegalAccessException,
|
|
|
+ InvocationTargetException {
|
|
|
if (object == null) {
|
|
|
// This can happen if...
|
|
|
// - we're about to print a message, String, or byte[], but it not present;
|
|
@@ -94,35 +99,71 @@ public final class MessageNanoPrinter {
|
|
|
buf.append(indentBuf).append(deCamelCaseify(identifier)).append(" <\n");
|
|
|
indentBuf.append(INDENT);
|
|
|
}
|
|
|
+ Class<?> clazz = object.getClass();
|
|
|
|
|
|
- for (Field field : object.getClass().getFields()) {
|
|
|
- // Proto fields are public, non-static variables that do not begin or end with '_'
|
|
|
+ // Proto fields follow one of two formats:
|
|
|
+ //
|
|
|
+ // 1) Public, non-static variables that do not begin or end with '_'
|
|
|
+ // Find and print these using declared public fields
|
|
|
+ for (Field field : clazz.getFields()) {
|
|
|
int modifiers = field.getModifiers();
|
|
|
String fieldName = field.getName();
|
|
|
- if ((modifiers & Modifier.PUBLIC) != Modifier.PUBLIC
|
|
|
- || (modifiers & Modifier.STATIC) == Modifier.STATIC
|
|
|
- || fieldName.startsWith("_") || fieldName.endsWith("_")) {
|
|
|
- continue;
|
|
|
- }
|
|
|
|
|
|
- Class<?> fieldType = field.getType();
|
|
|
- Object value = field.get(object);
|
|
|
+ if ((modifiers & Modifier.PUBLIC) == Modifier.PUBLIC
|
|
|
+ && (modifiers & Modifier.STATIC) != Modifier.STATIC
|
|
|
+ && !fieldName.startsWith("_")
|
|
|
+ && !fieldName.endsWith("_")) {
|
|
|
+ Class<?> fieldType = field.getType();
|
|
|
+ Object value = field.get(object);
|
|
|
|
|
|
- if (fieldType.isArray()) {
|
|
|
- Class<?> arrayType = fieldType.getComponentType();
|
|
|
+ if (fieldType.isArray()) {
|
|
|
+ Class<?> arrayType = fieldType.getComponentType();
|
|
|
|
|
|
- // bytes is special since it's not repeated, but is represented by an array
|
|
|
- if (arrayType == byte.class) {
|
|
|
- print(fieldName, value, indentBuf, buf);
|
|
|
- } else {
|
|
|
- int len = value == null ? 0 : Array.getLength(value);
|
|
|
- for (int i = 0; i < len; i++) {
|
|
|
- Object elem = Array.get(value, i);
|
|
|
- print(fieldName, elem, indentBuf, buf);
|
|
|
+ // bytes is special since it's not repeated, but is represented by an array
|
|
|
+ if (arrayType == byte.class) {
|
|
|
+ print(fieldName, value, indentBuf, buf);
|
|
|
+ } else {
|
|
|
+ int len = value == null ? 0 : Array.getLength(value);
|
|
|
+ for (int i = 0; i < len; i++) {
|
|
|
+ Object elem = Array.get(value, i);
|
|
|
+ print(fieldName, elem, indentBuf, buf);
|
|
|
+ }
|
|
|
}
|
|
|
+ } else {
|
|
|
+ print(fieldName, value, indentBuf, buf);
|
|
|
}
|
|
|
- } else {
|
|
|
- print(fieldName, value, indentBuf, buf);
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ // 2) Fields that are accessed via getter methods (when accessors
|
|
|
+ // mode is turned on)
|
|
|
+ // Find and print these using getter methods.
|
|
|
+ for (Method method : clazz.getMethods()) {
|
|
|
+ String name = method.getName();
|
|
|
+ // Check for the setter accessor method since getters and hazzers both have
|
|
|
+ // non-proto-field name collisions (hashCode() and getSerializedSize())
|
|
|
+ if (name.startsWith("set")) {
|
|
|
+ String subfieldName = name.substring(3);
|
|
|
+
|
|
|
+ Method hazzer = null;
|
|
|
+ try {
|
|
|
+ hazzer = clazz.getMethod("has" + subfieldName);
|
|
|
+ } catch (NoSuchMethodException e) {
|
|
|
+ continue;
|
|
|
+ }
|
|
|
+ // If hazzer does't exist or returns false, no need to continue
|
|
|
+ if (!(Boolean) hazzer.invoke(object)) {
|
|
|
+ continue;
|
|
|
+ }
|
|
|
+
|
|
|
+ Method getter = null;
|
|
|
+ try {
|
|
|
+ getter = clazz.getMethod("get" + subfieldName);
|
|
|
+ } catch (NoSuchMethodException e) {
|
|
|
+ continue;
|
|
|
+ }
|
|
|
+
|
|
|
+ print(subfieldName, getter.invoke(object), indentBuf, buf);
|
|
|
}
|
|
|
}
|
|
|
if (identifier != null) {
|