| 
					
				 | 
			
			
				@@ -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) { 
			 |