You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@commons.apache.org by mb...@apache.org on 2010/02/04 22:46:22 UTC

svn commit: r906673 - /commons/proper/lang/trunk/src/main/java/org/apache/commons/lang3/builder/ToStringStyle.java

Author: mbenson
Date: Thu Feb  4 21:46:22 2010
New Revision: 906673

URL: http://svn.apache.org/viewvc?rev=906673&view=rev
Log:
[LANG-586] clear ThreadLocal recursion registry (compatibly with existing tests, first pass)

Modified:
    commons/proper/lang/trunk/src/main/java/org/apache/commons/lang3/builder/ToStringStyle.java

Modified: commons/proper/lang/trunk/src/main/java/org/apache/commons/lang3/builder/ToStringStyle.java
URL: http://svn.apache.org/viewvc/commons/proper/lang/trunk/src/main/java/org/apache/commons/lang3/builder/ToStringStyle.java?rev=906673&r1=906672&r2=906673&view=diff
==============================================================================
--- commons/proper/lang/trunk/src/main/java/org/apache/commons/lang3/builder/ToStringStyle.java (original)
+++ commons/proper/lang/trunk/src/main/java/org/apache/commons/lang3/builder/ToStringStyle.java Thu Feb  4 21:46:22 2010
@@ -5,9 +5,9 @@
  * The ASF licenses this file to You under the Apache License, Version 2.0
  * (the "License"); you may not use this file except in compliance with
  * the License.  You may obtain a copy of the License at
- * 
+ *
  *      http://www.apache.org/licenses/LICENSE-2.0
- * 
+ *
  * Unless required by applicable law or agreed to in writing, software
  * distributed under the License is distributed on an "AS IS" BASIS,
  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
@@ -19,9 +19,10 @@
 import java.io.Serializable;
 import java.lang.reflect.Array;
 import java.util.Collection;
-import java.util.HashSet;
+import java.util.Collections;
 import java.util.Map;
 import java.util.Set;
+import java.util.WeakHashMap;
 
 import org.apache.commons.lang3.ClassUtils;
 import org.apache.commons.lang3.ObjectUtils;
@@ -46,7 +47,7 @@
  * <p>For example, the detail version of the array based methods will
  * output the whole array, whereas the summary method will just output
  * the array length.</p>
- * 
+ *
  * <p>If you want to format the output of certain objects, such as dates, you
  * must create a subclass and override a method.
  * <pre>
@@ -73,17 +74,17 @@
     /**
      * The default toString style. Using the Using the <code>Person</code>
      * example from {@link ToStringBuilder}, the output would look like this:
-     * 
+     *
      * <pre>
      * Person@182f0db[name=John Doe,age=33,smoker=false]
      * </pre>
      */
     public static final ToStringStyle DEFAULT_STYLE = new DefaultToStringStyle();
-    
+
     /**
      * The multi line toString style. Using the Using the <code>Person</code>
      * example from {@link ToStringBuilder}, the output would look like this:
-     * 
+     *
      * <pre>
      * Person@182f0db[
      *   name=John Doe
@@ -93,26 +94,26 @@
      * </pre>
      */
     public static final ToStringStyle MULTI_LINE_STYLE = new MultiLineToStringStyle();
-    
+
     /**
      * The no field names toString style. Using the Using the
      * <code>Person</code> example from {@link ToStringBuilder}, the output
      * would look like this:
-     * 
+     *
      * <pre>
      * Person@182f0db[John Doe,33,false]
      * </pre>
      */
     public static final ToStringStyle NO_FIELD_NAMES_STYLE = new NoFieldNameToStringStyle();
-    
+
     /**
      * The short prefix toString style. Using the <code>Person</code> example
      * from {@link ToStringBuilder}, the output would look like this:
-     * 
+     *
      * <pre>
      * Person[name=John Doe,age=33,smoker=false]
      * </pre>
-     * 
+     *
      * @since 2.1
      */
     public static final ToStringStyle SHORT_PREFIX_STYLE = new ShortPrefixToStringStyle();
@@ -120,38 +121,32 @@
     /**
      * The simple toString style. Using the Using the <code>Person</code>
      * example from {@link ToStringBuilder}, the output would look like this:
-     * 
+     *
      * <pre>
      * John Doe,33,false
      * </pre>
      */
     public static final ToStringStyle SIMPLE_STYLE = new SimpleToStringStyle();
-    
+
     /**
      * <p>
      * A registry of objects used by <code>reflectionToString</code> methods
      * to detect cyclical object references and avoid infinite loops.
      * </p>
      */
-    private static final ThreadLocal<Set<Object>> registry = new ThreadLocal<Set<Object>>() {
-        @Override
-        protected Set<Object> initialValue() {
-            // The HashSet implementation is not synchronized,
-            // which is just what we need here.
-            return new HashSet<Object>();
-        }
-    };
+    private static final ThreadLocal<WeakHashMap<Object, Object>> REGISTRY = new ThreadLocal<WeakHashMap<Object,Object>>();
 
     /**
      * <p>
      * Returns the registry of objects being traversed by the <code>reflectionToString</code>
      * methods in the current thread.
      * </p>
-     * 
+     *
      * @return Set the registry of objects being traversed
      */
     static Set<Object> getRegistry() {
-        return registry.get();
+        WeakHashMap<Object, Object> m = REGISTRY.get();
+        return m == null ? Collections.<Object> emptySet() : m.keySet();
     }
 
     /**
@@ -159,7 +154,7 @@
      * Returns <code>true</code> if the registry contains the given object.
      * Used by the reflection methods to avoid infinite loops.
      * </p>
-     * 
+     *
      * @param value
      *                  The object to lookup in the registry.
      * @return boolean <code>true</code> if the registry contains the given
@@ -174,13 +169,21 @@
      * Registers the given object. Used by the reflection methods to avoid
      * infinite loops.
      * </p>
-     * 
+     *
      * @param value
      *                  The object to register.
      */
     static void register(Object value) {
         if (value != null) {
-            getRegistry().add(value);
+            WeakHashMap<Object, Object> m;
+            synchronized (ToStringStyle.class) {
+                m = REGISTRY.get();
+                if (m == null) {
+                    m = new WeakHashMap<Object, Object>();
+                    REGISTRY.set(m);
+                }
+            }
+            m.put(value, null);
         }
     }
 
@@ -188,33 +191,44 @@
      * <p>
      * Unregisters the given object.
      * </p>
-     * 
+     *
      * <p>
      * Used by the reflection methods to avoid infinite loops.
      * </p>
-     * 
+     *
      * @param value
      *                  The object to unregister.
      */
     static void unregister(Object value) {
-        getRegistry().remove(value);
+        if (value != null) {
+            WeakHashMap<Object, Object> m;
+            synchronized (ToStringStyle.class) {
+                m = REGISTRY.get();
+                if (m != null) {
+                    m.remove(value);
+                    if (m.isEmpty()) {
+                        REGISTRY.remove();
+                    }
+                }
+            }
+        }
     }
 
     /**
      * Whether to use the field names, the default is <code>true</code>.
      */
     private boolean useFieldNames = true;
-    
+
     /**
      * Whether to use the class name, the default is <code>true</code>.
      */
     private boolean useClassName = true;
-    
+
     /**
      * Whether to use short class names, the default is <code>false</code>.
      */
     private boolean useShortClassName = false;
-    
+
     /**
      * Whether to use the identity hash code, the default is <code>true</code>.
      */
@@ -224,78 +238,78 @@
      * The content start <code>'['</code>.
      */
     private String contentStart = "[";
-    
+
     /**
      * The content end <code>']'</code>.
      */
     private String contentEnd = "]";
-    
+
     /**
      * The field name value separator <code>'='</code>.
      */
     private String fieldNameValueSeparator = "=";
-    
+
     /**
      * Whether the field separator should be added before any other fields.
      */
     private boolean fieldSeparatorAtStart = false;
-    
+
     /**
      * Whether the field separator should be added after any other fields.
      */
     private boolean fieldSeparatorAtEnd = false;
-    
+
     /**
      * The field separator <code>','</code>.
      */
     private String fieldSeparator = ",";
-    
+
     /**
      * The array start <code>'{'</code>.
      */
     private String arrayStart = "{";
-    
+
     /**
      * The array separator <code>','</code>.
      */
     private String arraySeparator = ",";
-    
+
     /**
      * The detail for array content.
      */
     private boolean arrayContentDetail = true;
-    
+
     /**
      * The array end <code>'}'</code>.
      */
     private String arrayEnd = "}";
-    
+
     /**
      * The value to use when fullDetail is <code>null</code>,
      * the default value is <code>true</code>.
      */
     private boolean defaultFullDetail = true;
-    
+
     /**
      * The <code>null</code> text <code>'&lt;null&gt;'</code>.
      */
     private String nullText = "<null>";
-    
+
     /**
      * The summary size text start <code>'<size'</code>.
      */
     private String sizeStartText = "<size=";
-    
+
     /**
      * The summary size text start <code>'&gt;'</code>.
      */
     private String sizeEndText = ">";
-    
+
     /**
      * The summary object text start <code>'&lt;'</code>.
      */
     private String summaryObjectStartText = "<";
-    
+
     /**
      * The summary object text start <code>'&gt;'</code>.
      */
@@ -315,9 +329,9 @@
     /**
      * <p>Append to the <code>toString</code> the superclass toString.</p>
      * <p>NOTE: It assumes that the toString has been created from the same ToStringStyle. </p>
-     * 
+     *
      * <p>A <code>null</code> <code>superToString</code> is ignored.</p>
-     * 
+     *
      * @param buffer  the <code>StringBuffer</code> to populate
      * @param superToString  the <code>super.toString()</code>
      * @since 2.0
@@ -329,9 +343,9 @@
     /**
      * <p>Append to the <code>toString</code> another toString.</p>
      * <p>NOTE: It assumes that the toString has been created from the same ToStringStyle. </p>
-     * 
+     *
      * <p>A <code>null</code> <code>toString</code> is ignored.</p>
-     * 
+     *
      * @param buffer  the <code>StringBuffer</code> to populate
      * @param toString  the additional <code>toString</code>
      * @since 2.0
@@ -353,7 +367,7 @@
 
     /**
      * <p>Append to the <code>toString</code> the start of data indicator.</p>
-     * 
+     *
      * @param buffer  the <code>StringBuffer</code> to populate
      * @param object  the <code>Object</code> to build a <code>toString</code> for
      */
@@ -370,7 +384,7 @@
 
     /**
      * <p>Append to the <code>toString</code> the end of data indicator.</p>
-     * 
+     *
      * @param buffer  the <code>StringBuffer</code> to populate
      * @param object  the <code>Object</code> to build a
      *  <code>toString</code> for.
@@ -385,7 +399,7 @@
 
     /**
      * <p>Remove the last field separator from the buffer.</p>
-     * 
+     *
      * @param buffer  the <code>StringBuffer</code> to populate
      * @since 2.0
      */
@@ -456,7 +470,7 @@
             && !(value instanceof Number || value instanceof Boolean || value instanceof Character)) {
            appendCyclicObject(buffer, fieldName, value);
            return;
-        }   
+        }
 
         register(value);
 
@@ -467,77 +481,77 @@
                 } else {
                     appendSummarySize(buffer, fieldName, ((Collection<?>) value).size());
                 }
-    
+
             } else if (value instanceof Map<?, ?>) {
                 if (detail) {
                     appendDetail(buffer, fieldName, (Map<?, ?>) value);
                 } else {
                     appendSummarySize(buffer, fieldName, ((Map<?, ?>) value).size());
                 }
-    
+
             } else if (value instanceof long[]) {
                 if (detail) {
                     appendDetail(buffer, fieldName, (long[]) value);
                 } else {
                     appendSummary(buffer, fieldName, (long[]) value);
                 }
-    
+
             } else if (value instanceof int[]) {
                 if (detail) {
                     appendDetail(buffer, fieldName, (int[]) value);
                 } else {
                     appendSummary(buffer, fieldName, (int[]) value);
                 }
-    
+
             } else if (value instanceof short[]) {
                 if (detail) {
                     appendDetail(buffer, fieldName, (short[]) value);
                 } else {
                     appendSummary(buffer, fieldName, (short[]) value);
                 }
-    
+
             } else if (value instanceof byte[]) {
                 if (detail) {
                     appendDetail(buffer, fieldName, (byte[]) value);
                 } else {
                     appendSummary(buffer, fieldName, (byte[]) value);
                 }
-    
+
             } else if (value instanceof char[]) {
                 if (detail) {
                     appendDetail(buffer, fieldName, (char[]) value);
                 } else {
                     appendSummary(buffer, fieldName, (char[]) value);
                 }
-    
+
             } else if (value instanceof double[]) {
                 if (detail) {
                     appendDetail(buffer, fieldName, (double[]) value);
                 } else {
                     appendSummary(buffer, fieldName, (double[]) value);
                 }
-    
+
             } else if (value instanceof float[]) {
                 if (detail) {
                     appendDetail(buffer, fieldName, (float[]) value);
                 } else {
                     appendSummary(buffer, fieldName, (float[]) value);
                 }
-    
+
             } else if (value instanceof boolean[]) {
                 if (detail) {
                     appendDetail(buffer, fieldName, (boolean[]) value);
                 } else {
                     appendSummary(buffer, fieldName, (boolean[]) value);
                 }
-    
+
             } else if (value.getClass().isArray()) {
                 if (detail) {
                     appendDetail(buffer, fieldName, (Object[]) value);
                 } else {
                     appendSummary(buffer, fieldName, (Object[]) value);
                 }
-    
+
             } else {
                     if (detail) {
                         appendDetail(buffer, fieldName, value);
@@ -549,17 +563,17 @@
             unregister(value);
         }
     }
-    
+
     /**
      * <p>Append to the <code>toString</code> an <code>Object</code>
      * value that has been detected to participate in a cycle. This
      * implementation will print the standard string value of the value.</p>
-     * 
+     *
      * @param buffer  the <code>StringBuffer</code> to populate
      * @param fieldName  the field name, typically not used as already appended
      * @param value  the value to add to the <code>toString</code>,
      *  not <code>null</code>
-     *  
+     *
      * @since 2.2
      */
     protected void appendCyclicObject(StringBuffer buffer, String fieldName, Object value) {
@@ -1428,7 +1442,7 @@
 
     /**
      * <p>Append to the <code>toString</code> the class name.</p>
-     * 
+     *
      * @param buffer  the <code>StringBuffer</code> to populate
      * @param object  the <code>Object</code> whose name to output
      */
@@ -1445,7 +1459,7 @@
 
     /**
      * <p>Append the {@link System#identityHashCode(java.lang.Object)}.</p>
-     * 
+     *
      * @param buffer  the <code>StringBuffer</code> to populate
      * @param object  the <code>Object</code> whose id to output
      */
@@ -1459,7 +1473,7 @@
 
     /**
      * <p>Append to the <code>toString</code> the content start.</p>
-     * 
+     *
      * @param buffer  the <code>StringBuffer</code> to populate
      */
     protected void appendContentStart(StringBuffer buffer) {
@@ -1468,7 +1482,7 @@
 
     /**
      * <p>Append to the <code>toString</code> the content end.</p>
-     * 
+     *
      * @param buffer  the <code>StringBuffer</code> to populate
      */
     protected void appendContentEnd(StringBuffer buffer) {
@@ -1479,7 +1493,7 @@
      * <p>Append to the <code>toString</code> an indicator for <code>null</code>.</p>
      *
      * <p>The default indicator is <code>'&lt;null&gt;'</code>.</p>
-     * 
+     *
      * @param buffer  the <code>StringBuffer</code> to populate
      * @param fieldName  the field name, typically not used as already appended
      */
@@ -1489,7 +1503,7 @@
 
     /**
      * <p>Append to the <code>toString</code> the field separator.</p>
-     * 
+     *
      * @param buffer  the <code>StringBuffer</code> to populate
      */
     protected void appendFieldSeparator(StringBuffer buffer) {
@@ -1498,7 +1512,7 @@
 
     /**
      * <p>Append to the <code>toString</code> the field start.</p>
-     * 
+     *
      * @param buffer  the <code>StringBuffer</code> to populate
      * @param fieldName  the field name
      */
@@ -1511,7 +1525,7 @@
 
     /**
      * <p>Append to the <code>toString<code> the field end.</p>
-     * 
+     *
      * @param buffer  the <code>StringBuffer</code> to populate
      * @param fieldName  the field name, typically not used as already appended
      */
@@ -1550,7 +1564,7 @@
      * <code>null</code> indicating that it doesn't care about
      * the detail level. In this case the default detail level is
      * used.</p>
-     * 
+     *
      * @param fullDetailRequest  the detail level requested
      * @return whether full detail is to be shown
      */
@@ -1886,9 +1900,9 @@
     //---------------------------------------------------------------------
 
     /**
-     * <p>Gets whether the field separator should be added at the start 
+     * <p>Gets whether the field separator should be added at the start
      * of each buffer.</p>
-     * 
+     *
      * @return the fieldSeparatorAtStart flag
      * @since 2.0
      */
@@ -1897,9 +1911,9 @@
     }
 
     /**
-     * <p>Sets whether the field separator should be added at the start 
+     * <p>Sets whether the field separator should be added at the start
      * of each buffer.</p>
-     * 
+     *
      * @param fieldSeparatorAtStart  the fieldSeparatorAtStart flag
      * @since 2.0
      */
@@ -1910,9 +1924,9 @@
     //---------------------------------------------------------------------
 
     /**
-     * <p>Gets whether the field separator should be added at the end 
+     * <p>Gets whether the field separator should be added at the end
      * of each buffer.</p>
-     * 
+     *
      * @return fieldSeparatorAtEnd flag
      * @since 2.0
      */
@@ -1921,9 +1935,9 @@
     }
 
     /**
-     * <p>Sets whether the field separator should be added at the end 
+     * <p>Sets whether the field separator should be added at the end
      * of each buffer.</p>
-     * 
+     *
      * @param fieldSeparatorAtEnd  the fieldSeparatorAtEnd flag
      * @since 2.0
      */
@@ -2097,7 +2111,7 @@
 
         /**
          * Required for serialization support.
-         * 
+         *
          * @see java.io.Serializable
          */
         private static final long serialVersionUID = 1L;
@@ -2157,7 +2171,7 @@
     }
 
     //----------------------------------------------------------------------------
-    
+
     /**
      * <p><code>ToStringStyle</code> that prints out the short
      * class name and no identity hashcode.</p>



Re: svn commit: r906673 - /commons/proper/lang/trunk/src/main/java/org/apache/commons/lang3/builder/ToStringStyle.java

Posted by Niall Pemberton <ni...@gmail.com>.
On Fri, Feb 5, 2010 at 3:30 PM, Matt Benson <gu...@gmail.com> wrote:
> Sorry, guys.  I found the offending setting and disabled it.  -Matt

Thanks :)

Niall


> On Feb 4, 2010, at 10:32 PM, Henri Yandell wrote:
>
>> +1 :)
>>
>> On Thu, Feb 4, 2010 at 4:17 PM, Niall Pemberton
>> <ni...@gmail.com> wrote:
>>>
>>> Matt,
>>>
>>> Can you stop mixing up style/format changes with real functional
>>> changes - it makes it harder to follow along when you change a few
>>> lines and theres 10 pages in the commit email, I guess this is
>>> probably an IDE setting to remove trailing spaces. Can you either
>>> change your IDE or if you do want to change the format then do it as a
>>> separate commit before you make any functional changes.
>>>
>>> Thanks
>>>
>>> Niall
>>>
>>> On Thu, Feb 4, 2010 at 9:46 PM,  <mb...@apache.org> wrote:
>>>>
>>>> Author: mbenson
>>>> Date: Thu Feb  4 21:46:22 2010
>>>> New Revision: 906673
>>>>
>>>> URL: http://svn.apache.org/viewvc?rev=906673&view=rev
>>>> Log:
>>>> [LANG-586] clear ThreadLocal recursion registry (compatibly with
>>>> existing tests, first pass)
>>>>
>>>> Modified:
>>>>
>>>> commons/proper/lang/trunk/src/main/java/org/apache/commons/lang3/builder/ToStringStyle.java
>>>>
>>>> Modified:
>>>> commons/proper/lang/trunk/src/main/java/org/apache/commons/lang3/builder/ToStringStyle.java
>>>> URL:
>>>> http://svn.apache.org/viewvc/commons/proper/lang/trunk/src/main/java/org/apache/commons/lang3/builder/ToStringStyle.java?rev=906673&r1=906672&r2=906673&view=diff
>>>>
>>>> ==============================================================================
>>>> ---
>>>> commons/proper/lang/trunk/src/main/java/org/apache/commons/lang3/builder/ToStringStyle.java
>>>> (original)
>>>> +++
>>>> commons/proper/lang/trunk/src/main/java/org/apache/commons/lang3/builder/ToStringStyle.java
>>>> Thu Feb  4 21:46:22 2010
>>>> @@ -5,9 +5,9 @@
>>>>  * The ASF licenses this file to You under the Apache License, Version
>>>> 2.0
>>>>  * (the "License"); you may not use this file except in compliance with
>>>>  * the License.  You may obtain a copy of the License at
>>>> - *
>>>> + *
>>>>  *      http://www.apache.org/licenses/LICENSE-2.0
>>>> - *
>>>> + *
>>>>  * Unless required by applicable law or agreed to in writing, software
>>>>  * distributed under the License is distributed on an "AS IS" BASIS,
>>>>  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
>>>> implied.
>>>> @@ -19,9 +19,10 @@
>>>>  import java.io.Serializable;
>>>>  import java.lang.reflect.Array;
>>>>  import java.util.Collection;
>>>> -import java.util.HashSet;
>>>> +import java.util.Collections;
>>>>  import java.util.Map;
>>>>  import java.util.Set;
>>>> +import java.util.WeakHashMap;
>>>>
>>>>  import org.apache.commons.lang3.ClassUtils;
>>>>  import org.apache.commons.lang3.ObjectUtils;
>>>> @@ -46,7 +47,7 @@
>>>>  * <p>For example, the detail version of the array based methods will
>>>>  * output the whole array, whereas the summary method will just output
>>>>  * the array length.</p>
>>>> - *
>>>> + *
>>>>  * <p>If you want to format the output of certain objects, such as
>>>> dates, you
>>>>  * must create a subclass and override a method.
>>>>  * <pre>
>>>> @@ -73,17 +74,17 @@
>>>>    /**
>>>>     * The default toString style. Using the Using the
>>>> <code>Person</code>
>>>>     * example from {@link ToStringBuilder}, the output would look like
>>>> this:
>>>> -     *
>>>> +     *
>>>>     * <pre>
>>>>     * Person@182f0db[name=John Doe,age=33,smoker=false]
>>>>     * </pre>
>>>>     */
>>>>    public static final ToStringStyle DEFAULT_STYLE = new
>>>> DefaultToStringStyle();
>>>> -
>>>> +
>>>>    /**
>>>>     * The multi line toString style. Using the Using the
>>>> <code>Person</code>
>>>>     * example from {@link ToStringBuilder}, the output would look like
>>>> this:
>>>> -     *
>>>> +     *
>>>>     * <pre>
>>>>     * Person@182f0db[
>>>>     *   name=John Doe
>>>> @@ -93,26 +94,26 @@
>>>>     * </pre>
>>>>     */
>>>>    public static final ToStringStyle MULTI_LINE_STYLE = new
>>>> MultiLineToStringStyle();
>>>> -
>>>> +
>>>>    /**
>>>>     * The no field names toString style. Using the Using the
>>>>     * <code>Person</code> example from {@link ToStringBuilder}, the
>>>> output
>>>>     * would look like this:
>>>> -     *
>>>> +     *
>>>>     * <pre>
>>>>     * Person@182f0db[John Doe,33,false]
>>>>     * </pre>
>>>>     */
>>>>    public static final ToStringStyle NO_FIELD_NAMES_STYLE = new
>>>> NoFieldNameToStringStyle();
>>>> -
>>>> +
>>>>    /**
>>>>     * The short prefix toString style. Using the <code>Person</code>
>>>> example
>>>>     * from {@link ToStringBuilder}, the output would look like this:
>>>> -     *
>>>> +     *
>>>>     * <pre>
>>>>     * Person[name=John Doe,age=33,smoker=false]
>>>>     * </pre>
>>>> -     *
>>>> +     *
>>>>     * @since 2.1
>>>>     */
>>>>    public static final ToStringStyle SHORT_PREFIX_STYLE = new
>>>> ShortPrefixToStringStyle();
>>>> @@ -120,38 +121,32 @@
>>>>    /**
>>>>     * The simple toString style. Using the Using the <code>Person</code>
>>>>     * example from {@link ToStringBuilder}, the output would look like
>>>> this:
>>>> -     *
>>>> +     *
>>>>     * <pre>
>>>>     * John Doe,33,false
>>>>     * </pre>
>>>>     */
>>>>    public static final ToStringStyle SIMPLE_STYLE = new
>>>> SimpleToStringStyle();
>>>> -
>>>> +
>>>>    /**
>>>>     * <p>
>>>>     * A registry of objects used by <code>reflectionToString</code>
>>>> methods
>>>>     * to detect cyclical object references and avoid infinite loops.
>>>>     * </p>
>>>>     */
>>>> -    private static final ThreadLocal<Set<Object>> registry = new
>>>> ThreadLocal<Set<Object>>() {
>>>> -        @Override
>>>> -        protected Set<Object> initialValue() {
>>>> -            // The HashSet implementation is not synchronized,
>>>> -            // which is just what we need here.
>>>> -            return new HashSet<Object>();
>>>> -        }
>>>> -    };
>>>> +    private static final ThreadLocal<WeakHashMap<Object, Object>>
>>>> REGISTRY = new ThreadLocal<WeakHashMap<Object,Object>>();
>>>>
>>>>    /**
>>>>     * <p>
>>>>     * Returns the registry of objects being traversed by the
>>>> <code>reflectionToString</code>
>>>>     * methods in the current thread.
>>>>     * </p>
>>>> -     *
>>>> +     *
>>>>     * @return Set the registry of objects being traversed
>>>>     */
>>>>    static Set<Object> getRegistry() {
>>>> -        return registry.get();
>>>> +        WeakHashMap<Object, Object> m = REGISTRY.get();
>>>> +        return m == null ? Collections.<Object> emptySet() :
>>>> m.keySet();
>>>>    }
>>>>
>>>>    /**
>>>> @@ -159,7 +154,7 @@
>>>>     * Returns <code>true</code> if the registry contains the given
>>>> object.
>>>>     * Used by the reflection methods to avoid infinite loops.
>>>>     * </p>
>>>> -     *
>>>> +     *
>>>>     * @param value
>>>>     *                  The object to lookup in the registry.
>>>>     * @return boolean <code>true</code> if the registry contains the
>>>> given
>>>> @@ -174,13 +169,21 @@
>>>>     * Registers the given object. Used by the reflection methods to
>>>> avoid
>>>>     * infinite loops.
>>>>     * </p>
>>>> -     *
>>>> +     *
>>>>     * @param value
>>>>     *                  The object to register.
>>>>     */
>>>>    static void register(Object value) {
>>>>        if (value != null) {
>>>> -            getRegistry().add(value);
>>>> +            WeakHashMap<Object, Object> m;
>>>> +            synchronized (ToStringStyle.class) {
>>>> +                m = REGISTRY.get();
>>>> +                if (m == null) {
>>>> +                    m = new WeakHashMap<Object, Object>();
>>>> +                    REGISTRY.set(m);
>>>> +                }
>>>> +            }
>>>> +            m.put(value, null);
>>>>        }
>>>>    }
>>>>
>>>> @@ -188,33 +191,44 @@
>>>>     * <p>
>>>>     * Unregisters the given object.
>>>>     * </p>
>>>> -     *
>>>> +     *
>>>>     * <p>
>>>>     * Used by the reflection methods to avoid infinite loops.
>>>>     * </p>
>>>> -     *
>>>> +     *
>>>>     * @param value
>>>>     *                  The object to unregister.
>>>>     */
>>>>    static void unregister(Object value) {
>>>> -        getRegistry().remove(value);
>>>> +        if (value != null) {
>>>> +            WeakHashMap<Object, Object> m;
>>>> +            synchronized (ToStringStyle.class) {
>>>> +                m = REGISTRY.get();
>>>> +                if (m != null) {
>>>> +                    m.remove(value);
>>>> +                    if (m.isEmpty()) {
>>>> +                        REGISTRY.remove();
>>>> +                    }
>>>> +                }
>>>> +            }
>>>> +        }
>>>>    }
>>>>
>>>>    /**
>>>>     * Whether to use the field names, the default is <code>true</code>.
>>>>     */
>>>>    private boolean useFieldNames = true;
>>>> -
>>>> +
>>>>    /**
>>>>     * Whether to use the class name, the default is <code>true</code>.
>>>>     */
>>>>    private boolean useClassName = true;
>>>> -
>>>> +
>>>>    /**
>>>>     * Whether to use short class names, the default is
>>>> <code>false</code>.
>>>>     */
>>>>    private boolean useShortClassName = false;
>>>> -
>>>> +
>>>>    /**
>>>>     * Whether to use the identity hash code, the default is
>>>> <code>true</code>.
>>>>     */
>>>> @@ -224,78 +238,78 @@
>>>>     * The content start <code>'['</code>.
>>>>     */
>>>>    private String contentStart = "[";
>>>> -
>>>> +
>>>>    /**
>>>>     * The content end <code>']'</code>.
>>>>     */
>>>>    private String contentEnd = "]";
>>>> -
>>>> +
>>>>    /**
>>>>     * The field name value separator <code>'='</code>.
>>>>     */
>>>>    private String fieldNameValueSeparator = "=";
>>>> -
>>>> +
>>>>    /**
>>>>     * Whether the field separator should be added before any other
>>>> fields.
>>>>     */
>>>>    private boolean fieldSeparatorAtStart = false;
>>>> -
>>>> +
>>>>    /**
>>>>     * Whether the field separator should be added after any other
>>>> fields.
>>>>     */
>>>>    private boolean fieldSeparatorAtEnd = false;
>>>> -
>>>> +
>>>>    /**
>>>>     * The field separator <code>','</code>.
>>>>     */
>>>>    private String fieldSeparator = ",";
>>>> -
>>>> +
>>>>    /**
>>>>     * The array start <code>'{'</code>.
>>>>     */
>>>>    private String arrayStart = "{";
>>>> -
>>>> +
>>>>    /**
>>>>     * The array separator <code>','</code>.
>>>>     */
>>>>    private String arraySeparator = ",";
>>>> -
>>>> +
>>>>    /**
>>>>     * The detail for array content.
>>>>     */
>>>>    private boolean arrayContentDetail = true;
>>>> -
>>>> +
>>>>    /**
>>>>     * The array end <code>'}'</code>.
>>>>     */
>>>>    private String arrayEnd = "}";
>>>> -
>>>> +
>>>>    /**
>>>>     * The value to use when fullDetail is <code>null</code>,
>>>>     * the default value is <code>true</code>.
>>>>     */
>>>>    private boolean defaultFullDetail = true;
>>>> -
>>>> +
>>>>    /**
>>>>     * The <code>null</code> text <code>'&lt;null&gt;'</code>.
>>>>     */
>>>>    private String nullText = "<null>";
>>>> -
>>>> +
>>>>    /**
>>>>     * The summary size text start <code>'<size'</code>.
>>>>     */
>>>>    private String sizeStartText = "<size=";
>>>> -
>>>> +
>>>>    /**
>>>>     * The summary size text start <code>'&gt;'</code>.
>>>>     */
>>>>    private String sizeEndText = ">";
>>>> -
>>>> +
>>>>    /**
>>>>     * The summary object text start <code>'&lt;'</code>.
>>>>     */
>>>>    private String summaryObjectStartText = "<";
>>>> -
>>>> +
>>>>    /**
>>>>     * The summary object text start <code>'&gt;'</code>.
>>>>     */
>>>> @@ -315,9 +329,9 @@
>>>>    /**
>>>>     * <p>Append to the <code>toString</code> the superclass
>>>> toString.</p>
>>>>     * <p>NOTE: It assumes that the toString has been created from the
>>>> same ToStringStyle. </p>
>>>> -     *
>>>> +     *
>>>>     * <p>A <code>null</code> <code>superToString</code> is ignored.</p>
>>>> -     *
>>>> +     *
>>>>     * @param buffer  the <code>StringBuffer</code> to populate
>>>>     * @param superToString  the <code>super.toString()</code>
>>>>     * @since 2.0
>>>> @@ -329,9 +343,9 @@
>>>>    /**
>>>>     * <p>Append to the <code>toString</code> another toString.</p>
>>>>     * <p>NOTE: It assumes that the toString has been created from the
>>>> same ToStringStyle. </p>
>>>> -     *
>>>> +     *
>>>>     * <p>A <code>null</code> <code>toString</code> is ignored.</p>
>>>> -     *
>>>> +     *
>>>>     * @param buffer  the <code>StringBuffer</code> to populate
>>>>     * @param toString  the additional <code>toString</code>
>>>>     * @since 2.0
>>>> @@ -353,7 +367,7 @@
>>>>
>>>>    /**
>>>>     * <p>Append to the <code>toString</code> the start of data
>>>> indicator.</p>
>>>> -     *
>>>> +     *
>>>>     * @param buffer  the <code>StringBuffer</code> to populate
>>>>     * @param object  the <code>Object</code> to build a
>>>> <code>toString</code> for
>>>>     */
>>>> @@ -370,7 +384,7 @@
>>>>
>>>>    /**
>>>>     * <p>Append to the <code>toString</code> the end of data
>>>> indicator.</p>
>>>> -     *
>>>> +     *
>>>>     * @param buffer  the <code>StringBuffer</code> to populate
>>>>     * @param object  the <code>Object</code> to build a
>>>>     *  <code>toString</code> for.
>>>> @@ -385,7 +399,7 @@
>>>>
>>>>    /**
>>>>     * <p>Remove the last field separator from the buffer.</p>
>>>> -     *
>>>> +     *
>>>>     * @param buffer  the <code>StringBuffer</code> to populate
>>>>     * @since 2.0
>>>>     */
>>>> @@ -456,7 +470,7 @@
>>>>            && !(value instanceof Number || value instanceof Boolean ||
>>>> value instanceof Character)) {
>>>>           appendCyclicObject(buffer, fieldName, value);
>>>>           return;
>>>> -        }
>>>> +        }
>>>>
>>>>        register(value);
>>>>
>>>> @@ -467,77 +481,77 @@
>>>>                } else {
>>>>                    appendSummarySize(buffer, fieldName, ((Collection<?>)
>>>> value).size());
>>>>                }
>>>> -
>>>> +
>>>>            } else if (value instanceof Map<?, ?>) {
>>>>                if (detail) {
>>>>                    appendDetail(buffer, fieldName, (Map<?, ?>) value);
>>>>                } else {
>>>>                    appendSummarySize(buffer, fieldName, ((Map<?, ?>)
>>>> value).size());
>>>>                }
>>>> -
>>>> +
>>>>            } else if (value instanceof long[]) {
>>>>                if (detail) {
>>>>                    appendDetail(buffer, fieldName, (long[]) value);
>>>>                } else {
>>>>                    appendSummary(buffer, fieldName, (long[]) value);
>>>>                }
>>>> -
>>>> +
>>>>            } else if (value instanceof int[]) {
>>>>                if (detail) {
>>>>                    appendDetail(buffer, fieldName, (int[]) value);
>>>>                } else {
>>>>                    appendSummary(buffer, fieldName, (int[]) value);
>>>>                }
>>>> -
>>>> +
>>>>            } else if (value instanceof short[]) {
>>>>                if (detail) {
>>>>                    appendDetail(buffer, fieldName, (short[]) value);
>>>>                } else {
>>>>                    appendSummary(buffer, fieldName, (short[]) value);
>>>>                }
>>>> -
>>>> +
>>>>            } else if (value instanceof byte[]) {
>>>>                if (detail) {
>>>>                    appendDetail(buffer, fieldName, (byte[]) value);
>>>>                } else {
>>>>                    appendSummary(buffer, fieldName, (byte[]) value);
>>>>                }
>>>> -
>>>> +
>>>>            } else if (value instanceof char[]) {
>>>>                if (detail) {
>>>>                    appendDetail(buffer, fieldName, (char[]) value);
>>>>                } else {
>>>>                    appendSummary(buffer, fieldName, (char[]) value);
>>>>                }
>>>> -
>>>> +
>>>>            } else if (value instanceof double[]) {
>>>>                if (detail) {
>>>>                    appendDetail(buffer, fieldName, (double[]) value);
>>>>                } else {
>>>>                    appendSummary(buffer, fieldName, (double[]) value);
>>>>                }
>>>> -
>>>> +
>>>>            } else if (value instanceof float[]) {
>>>>                if (detail) {
>>>>                    appendDetail(buffer, fieldName, (float[]) value);
>>>>                } else {
>>>>                    appendSummary(buffer, fieldName, (float[]) value);
>>>>                }
>>>> -
>>>> +
>>>>            } else if (value instanceof boolean[]) {
>>>>                if (detail) {
>>>>                    appendDetail(buffer, fieldName, (boolean[]) value);
>>>>                } else {
>>>>                    appendSummary(buffer, fieldName, (boolean[]) value);
>>>>                }
>>>> -
>>>> +
>>>>            } else if (value.getClass().isArray()) {
>>>>                if (detail) {
>>>>                    appendDetail(buffer, fieldName, (Object[]) value);
>>>>                } else {
>>>>                    appendSummary(buffer, fieldName, (Object[]) value);
>>>>                }
>>>> -
>>>> +
>>>>            } else {
>>>>                    if (detail) {
>>>>                        appendDetail(buffer, fieldName, value);
>>>> @@ -549,17 +563,17 @@
>>>>            unregister(value);
>>>>        }
>>>>    }
>>>> -
>>>> +
>>>>    /**
>>>>     * <p>Append to the <code>toString</code> an <code>Object</code>
>>>>     * value that has been detected to participate in a cycle. This
>>>>     * implementation will print the standard string value of the
>>>> value.</p>
>>>> -     *
>>>> +     *
>>>>     * @param buffer  the <code>StringBuffer</code> to populate
>>>>     * @param fieldName  the field name, typically not used as already
>>>> appended
>>>>     * @param value  the value to add to the <code>toString</code>,
>>>>     *  not <code>null</code>
>>>> -     *
>>>> +     *
>>>>     * @since 2.2
>>>>     */
>>>>    protected void appendCyclicObject(StringBuffer buffer, String
>>>> fieldName, Object value) {
>>>> @@ -1428,7 +1442,7 @@
>>>>
>>>>    /**
>>>>     * <p>Append to the <code>toString</code> the class name.</p>
>>>> -     *
>>>> +     *
>>>>     * @param buffer  the <code>StringBuffer</code> to populate
>>>>     * @param object  the <code>Object</code> whose name to output
>>>>     */
>>>> @@ -1445,7 +1459,7 @@
>>>>
>>>>    /**
>>>>     * <p>Append the {@link
>>>> System#identityHashCode(java.lang.Object)}.</p>
>>>> -     *
>>>> +     *
>>>>     * @param buffer  the <code>StringBuffer</code> to populate
>>>>     * @param object  the <code>Object</code> whose id to output
>>>>     */
>>>> @@ -1459,7 +1473,7 @@
>>>>
>>>>    /**
>>>>     * <p>Append to the <code>toString</code> the content start.</p>
>>>> -     *
>>>> +     *
>>>>     * @param buffer  the <code>StringBuffer</code> to populate
>>>>     */
>>>>    protected void appendContentStart(StringBuffer buffer) {
>>>> @@ -1468,7 +1482,7 @@
>>>>
>>>>    /**
>>>>     * <p>Append to the <code>toString</code> the content end.</p>
>>>> -     *
>>>> +     *
>>>>     * @param buffer  the <code>StringBuffer</code> to populate
>>>>     */
>>>>    protected void appendContentEnd(StringBuffer buffer) {
>>>> @@ -1479,7 +1493,7 @@
>>>>     * <p>Append to the <code>toString</code> an indicator for
>>>> <code>null</code>.</p>
>>>>     *
>>>>     * <p>The default indicator is <code>'&lt;null&gt;'</code>.</p>
>>>> -     *
>>>> +     *
>>>>     * @param buffer  the <code>StringBuffer</code> to populate
>>>>     * @param fieldName  the field name, typically not used as already
>>>> appended
>>>>     */
>>>> @@ -1489,7 +1503,7 @@
>>>>
>>>>    /**
>>>>     * <p>Append to the <code>toString</code> the field separator.</p>
>>>> -     *
>>>> +     *
>>>>     * @param buffer  the <code>StringBuffer</code> to populate
>>>>     */
>>>>    protected void appendFieldSeparator(StringBuffer buffer) {
>>>> @@ -1498,7 +1512,7 @@
>>>>
>>>>    /**
>>>>     * <p>Append to the <code>toString</code> the field start.</p>
>>>> -     *
>>>> +     *
>>>>     * @param buffer  the <code>StringBuffer</code> to populate
>>>>     * @param fieldName  the field name
>>>>     */
>>>> @@ -1511,7 +1525,7 @@
>>>>
>>>>    /**
>>>>     * <p>Append to the <code>toString<code> the field end.</p>
>>>> -     *
>>>> +     *
>>>>     * @param buffer  the <code>StringBuffer</code> to populate
>>>>     * @param fieldName  the field name, typically not used as already
>>>> appended
>>>>     */
>>>> @@ -1550,7 +1564,7 @@
>>>>     * <code>null</code> indicating that it doesn't care about
>>>>     * the detail level. In this case the default detail level is
>>>>     * used.</p>
>>>> -     *
>>>> +     *
>>>>     * @param fullDetailRequest  the detail level requested
>>>>     * @return whether full detail is to be shown
>>>>     */
>>>> @@ -1886,9 +1900,9 @@
>>>>
>>>>  //---------------------------------------------------------------------
>>>>
>>>>    /**
>>>> -     * <p>Gets whether the field separator should be added at the start
>>>> +     * <p>Gets whether the field separator should be added at the start
>>>>     * of each buffer.</p>
>>>> -     *
>>>> +     *
>>>>     * @return the fieldSeparatorAtStart flag
>>>>     * @since 2.0
>>>>     */
>>>> @@ -1897,9 +1911,9 @@
>>>>    }
>>>>
>>>>    /**
>>>> -     * <p>Sets whether the field separator should be added at the start
>>>> +     * <p>Sets whether the field separator should be added at the start
>>>>     * of each buffer.</p>
>>>> -     *
>>>> +     *
>>>>     * @param fieldSeparatorAtStart  the fieldSeparatorAtStart flag
>>>>     * @since 2.0
>>>>     */
>>>> @@ -1910,9 +1924,9 @@
>>>>
>>>>  //---------------------------------------------------------------------
>>>>
>>>>    /**
>>>> -     * <p>Gets whether the field separator should be added at the end
>>>> +     * <p>Gets whether the field separator should be added at the end
>>>>     * of each buffer.</p>
>>>> -     *
>>>> +     *
>>>>     * @return fieldSeparatorAtEnd flag
>>>>     * @since 2.0
>>>>     */
>>>> @@ -1921,9 +1935,9 @@
>>>>    }
>>>>
>>>>    /**
>>>> -     * <p>Sets whether the field separator should be added at the end
>>>> +     * <p>Sets whether the field separator should be added at the end
>>>>     * of each buffer.</p>
>>>> -     *
>>>> +     *
>>>>     * @param fieldSeparatorAtEnd  the fieldSeparatorAtEnd flag
>>>>     * @since 2.0
>>>>     */
>>>> @@ -2097,7 +2111,7 @@
>>>>
>>>>        /**
>>>>         * Required for serialization support.
>>>> -         *
>>>> +         *
>>>>         * @see java.io.Serializable
>>>>         */
>>>>        private static final long serialVersionUID = 1L;
>>>> @@ -2157,7 +2171,7 @@
>>>>    }
>>>>
>>>>
>>>>  //----------------------------------------------------------------------------
>>>> -
>>>> +
>>>>    /**
>>>>     * <p><code>ToStringStyle</code> that prints out the short
>>>>     * class name and no identity hashcode.</p>
>>>>
>>>>
>>>>
>>>
>>> ---------------------------------------------------------------------
>>> To unsubscribe, e-mail: dev-unsubscribe@commons.apache.org
>>> For additional commands, e-mail: dev-help@commons.apache.org
>>>
>>>
>>
>> ---------------------------------------------------------------------
>> To unsubscribe, e-mail: dev-unsubscribe@commons.apache.org
>> For additional commands, e-mail: dev-help@commons.apache.org
>>
>
>
> ---------------------------------------------------------------------
> To unsubscribe, e-mail: dev-unsubscribe@commons.apache.org
> For additional commands, e-mail: dev-help@commons.apache.org
>
>

---------------------------------------------------------------------
To unsubscribe, e-mail: dev-unsubscribe@commons.apache.org
For additional commands, e-mail: dev-help@commons.apache.org


Re: svn commit: r906673 - /commons/proper/lang/trunk/src/main/java/org/apache/commons/lang3/builder/ToStringStyle.java

Posted by Matt Benson <gu...@gmail.com>.
Sorry, guys.  I found the offending setting and disabled it.  -Matt

On Feb 4, 2010, at 10:32 PM, Henri Yandell wrote:

> +1 :)
>
> On Thu, Feb 4, 2010 at 4:17 PM, Niall Pemberton
> <ni...@gmail.com> wrote:
>> Matt,
>>
>> Can you stop mixing up style/format changes with real functional
>> changes - it makes it harder to follow along when you change a few
>> lines and theres 10 pages in the commit email, I guess this is
>> probably an IDE setting to remove trailing spaces. Can you either
>> change your IDE or if you do want to change the format then do it  
>> as a
>> separate commit before you make any functional changes.
>>
>> Thanks
>>
>> Niall
>>
>> On Thu, Feb 4, 2010 at 9:46 PM,  <mb...@apache.org> wrote:
>>> Author: mbenson
>>> Date: Thu Feb  4 21:46:22 2010
>>> New Revision: 906673
>>>
>>> URL: http://svn.apache.org/viewvc?rev=906673&view=rev
>>> Log:
>>> [LANG-586] clear ThreadLocal recursion registry (compatibly with  
>>> existing tests, first pass)
>>>
>>> Modified:
>>>    commons/proper/lang/trunk/src/main/java/org/apache/commons/ 
>>> lang3/builder/ToStringStyle.java
>>>
>>> Modified: commons/proper/lang/trunk/src/main/java/org/apache/ 
>>> commons/lang3/builder/ToStringStyle.java
>>> URL: http://svn.apache.org/viewvc/commons/proper/lang/trunk/src/ 
>>> main/java/org/apache/commons/lang3/builder/ToStringStyle.java? 
>>> rev=906673&r1=906672&r2=906673&view=diff
>>> ==================================================================== 
>>> ==========
>>> --- commons/proper/lang/trunk/src/main/java/org/apache/commons/ 
>>> lang3/builder/ToStringStyle.java (original)
>>> +++ commons/proper/lang/trunk/src/main/java/org/apache/commons/ 
>>> lang3/builder/ToStringStyle.java Thu Feb  4 21:46:22 2010
>>> @@ -5,9 +5,9 @@
>>>  * The ASF licenses this file to You under the Apache License,  
>>> Version 2.0
>>>  * (the "License"); you may not use this file except in  
>>> compliance with
>>>  * the License.  You may obtain a copy of the License at
>>> - *
>>> + *
>>>  *      http://www.apache.org/licenses/LICENSE-2.0
>>> - *
>>> + *
>>>  * Unless required by applicable law or agreed to in writing,  
>>> software
>>>  * distributed under the License is distributed on an "AS IS" BASIS,
>>>  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express  
>>> or implied.
>>> @@ -19,9 +19,10 @@
>>>  import java.io.Serializable;
>>>  import java.lang.reflect.Array;
>>>  import java.util.Collection;
>>> -import java.util.HashSet;
>>> +import java.util.Collections;
>>>  import java.util.Map;
>>>  import java.util.Set;
>>> +import java.util.WeakHashMap;
>>>
>>>  import org.apache.commons.lang3.ClassUtils;
>>>  import org.apache.commons.lang3.ObjectUtils;
>>> @@ -46,7 +47,7 @@
>>>  * <p>For example, the detail version of the array based methods  
>>> will
>>>  * output the whole array, whereas the summary method will just  
>>> output
>>>  * the array length.</p>
>>> - *
>>> + *
>>>  * <p>If you want to format the output of certain objects, such  
>>> as dates, you
>>>  * must create a subclass and override a method.
>>>  * <pre>
>>> @@ -73,17 +74,17 @@
>>>     /**
>>>      * The default toString style. Using the Using the  
>>> <code>Person</code>
>>>      * example from {@link ToStringBuilder}, the output would  
>>> look like this:
>>> -     *
>>> +     *
>>>      * <pre>
>>>      * Person@182f0db[name=John Doe,age=33,smoker=false]
>>>      * </pre>
>>>      */
>>>     public static final ToStringStyle DEFAULT_STYLE = new  
>>> DefaultToStringStyle();
>>> -
>>> +
>>>     /**
>>>      * The multi line toString style. Using the Using the  
>>> <code>Person</code>
>>>      * example from {@link ToStringBuilder}, the output would  
>>> look like this:
>>> -     *
>>> +     *
>>>      * <pre>
>>>      * Person@182f0db[
>>>      *   name=John Doe
>>> @@ -93,26 +94,26 @@
>>>      * </pre>
>>>      */
>>>     public static final ToStringStyle MULTI_LINE_STYLE = new  
>>> MultiLineToStringStyle();
>>> -
>>> +
>>>     /**
>>>      * The no field names toString style. Using the Using the
>>>      * <code>Person</code> example from {@link ToStringBuilder},  
>>> the output
>>>      * would look like this:
>>> -     *
>>> +     *
>>>      * <pre>
>>>      * Person@182f0db[John Doe,33,false]
>>>      * </pre>
>>>      */
>>>     public static final ToStringStyle NO_FIELD_NAMES_STYLE = new  
>>> NoFieldNameToStringStyle();
>>> -
>>> +
>>>     /**
>>>      * The short prefix toString style. Using the <code>Person</ 
>>> code> example
>>>      * from {@link ToStringBuilder}, the output would look like  
>>> this:
>>> -     *
>>> +     *
>>>      * <pre>
>>>      * Person[name=John Doe,age=33,smoker=false]
>>>      * </pre>
>>> -     *
>>> +     *
>>>      * @since 2.1
>>>      */
>>>     public static final ToStringStyle SHORT_PREFIX_STYLE = new  
>>> ShortPrefixToStringStyle();
>>> @@ -120,38 +121,32 @@
>>>     /**
>>>      * The simple toString style. Using the Using the  
>>> <code>Person</code>
>>>      * example from {@link ToStringBuilder}, the output would  
>>> look like this:
>>> -     *
>>> +     *
>>>      * <pre>
>>>      * John Doe,33,false
>>>      * </pre>
>>>      */
>>>     public static final ToStringStyle SIMPLE_STYLE = new  
>>> SimpleToStringStyle();
>>> -
>>> +
>>>     /**
>>>      * <p>
>>>      * A registry of objects used by <code>reflectionToString</ 
>>> code> methods
>>>      * to detect cyclical object references and avoid infinite  
>>> loops.
>>>      * </p>
>>>      */
>>> -    private static final ThreadLocal<Set<Object>> registry = new  
>>> ThreadLocal<Set<Object>>() {
>>> -        @Override
>>> -        protected Set<Object> initialValue() {
>>> -            // The HashSet implementation is not synchronized,
>>> -            // which is just what we need here.
>>> -            return new HashSet<Object>();
>>> -        }
>>> -    };
>>> +    private static final ThreadLocal<WeakHashMap<Object,  
>>> Object>> REGISTRY = new ThreadLocal<WeakHashMap<Object,Object>>();
>>>
>>>     /**
>>>      * <p>
>>>      * Returns the registry of objects being traversed by the  
>>> <code>reflectionToString</code>
>>>      * methods in the current thread.
>>>      * </p>
>>> -     *
>>> +     *
>>>      * @return Set the registry of objects being traversed
>>>      */
>>>     static Set<Object> getRegistry() {
>>> -        return registry.get();
>>> +        WeakHashMap<Object, Object> m = REGISTRY.get();
>>> +        return m == null ? Collections.<Object> emptySet() :  
>>> m.keySet();
>>>     }
>>>
>>>     /**
>>> @@ -159,7 +154,7 @@
>>>      * Returns <code>true</code> if the registry contains the  
>>> given object.
>>>      * Used by the reflection methods to avoid infinite loops.
>>>      * </p>
>>> -     *
>>> +     *
>>>      * @param value
>>>      *                  The object to lookup in the registry.
>>>      * @return boolean <code>true</code> if the registry contains  
>>> the given
>>> @@ -174,13 +169,21 @@
>>>      * Registers the given object. Used by the reflection methods  
>>> to avoid
>>>      * infinite loops.
>>>      * </p>
>>> -     *
>>> +     *
>>>      * @param value
>>>      *                  The object to register.
>>>      */
>>>     static void register(Object value) {
>>>         if (value != null) {
>>> -            getRegistry().add(value);
>>> +            WeakHashMap<Object, Object> m;
>>> +            synchronized (ToStringStyle.class) {
>>> +                m = REGISTRY.get();
>>> +                if (m == null) {
>>> +                    m = new WeakHashMap<Object, Object>();
>>> +                    REGISTRY.set(m);
>>> +                }
>>> +            }
>>> +            m.put(value, null);
>>>         }
>>>     }
>>>
>>> @@ -188,33 +191,44 @@
>>>      * <p>
>>>      * Unregisters the given object.
>>>      * </p>
>>> -     *
>>> +     *
>>>      * <p>
>>>      * Used by the reflection methods to avoid infinite loops.
>>>      * </p>
>>> -     *
>>> +     *
>>>      * @param value
>>>      *                  The object to unregister.
>>>      */
>>>     static void unregister(Object value) {
>>> -        getRegistry().remove(value);
>>> +        if (value != null) {
>>> +            WeakHashMap<Object, Object> m;
>>> +            synchronized (ToStringStyle.class) {
>>> +                m = REGISTRY.get();
>>> +                if (m != null) {
>>> +                    m.remove(value);
>>> +                    if (m.isEmpty()) {
>>> +                        REGISTRY.remove();
>>> +                    }
>>> +                }
>>> +            }
>>> +        }
>>>     }
>>>
>>>     /**
>>>      * Whether to use the field names, the default is <code>true</ 
>>> code>.
>>>      */
>>>     private boolean useFieldNames = true;
>>> -
>>> +
>>>     /**
>>>      * Whether to use the class name, the default is <code>true</ 
>>> code>.
>>>      */
>>>     private boolean useClassName = true;
>>> -
>>> +
>>>     /**
>>>      * Whether to use short class names, the default is  
>>> <code>false</code>.
>>>      */
>>>     private boolean useShortClassName = false;
>>> -
>>> +
>>>     /**
>>>      * Whether to use the identity hash code, the default is  
>>> <code>true</code>.
>>>      */
>>> @@ -224,78 +238,78 @@
>>>      * The content start <code>'['</code>.
>>>      */
>>>     private String contentStart = "[";
>>> -
>>> +
>>>     /**
>>>      * The content end <code>']'</code>.
>>>      */
>>>     private String contentEnd = "]";
>>> -
>>> +
>>>     /**
>>>      * The field name value separator <code>'='</code>.
>>>      */
>>>     private String fieldNameValueSeparator = "=";
>>> -
>>> +
>>>     /**
>>>      * Whether the field separator should be added before any  
>>> other fields.
>>>      */
>>>     private boolean fieldSeparatorAtStart = false;
>>> -
>>> +
>>>     /**
>>>      * Whether the field separator should be added after any  
>>> other fields.
>>>      */
>>>     private boolean fieldSeparatorAtEnd = false;
>>> -
>>> +
>>>     /**
>>>      * The field separator <code>','</code>.
>>>      */
>>>     private String fieldSeparator = ",";
>>> -
>>> +
>>>     /**
>>>      * The array start <code>'{'</code>.
>>>      */
>>>     private String arrayStart = "{";
>>> -
>>> +
>>>     /**
>>>      * The array separator <code>','</code>.
>>>      */
>>>     private String arraySeparator = ",";
>>> -
>>> +
>>>     /**
>>>      * The detail for array content.
>>>      */
>>>     private boolean arrayContentDetail = true;
>>> -
>>> +
>>>     /**
>>>      * The array end <code>'}'</code>.
>>>      */
>>>     private String arrayEnd = "}";
>>> -
>>> +
>>>     /**
>>>      * The value to use when fullDetail is <code>null</code>,
>>>      * the default value is <code>true</code>.
>>>      */
>>>     private boolean defaultFullDetail = true;
>>> -
>>> +
>>>     /**
>>>      * The <code>null</code> text <code>'&lt;null&gt;'</code>.
>>>      */
>>>     private String nullText = "<null>";
>>> -
>>> +
>>>     /**
>>>      * The summary size text start <code>'<size'</code>.
>>>      */
>>>     private String sizeStartText = "<size=";
>>> -
>>> +
>>>     /**
>>>      * The summary size text start <code>'&gt;'</code>.
>>>      */
>>>     private String sizeEndText = ">";
>>> -
>>> +
>>>     /**
>>>      * The summary object text start <code>'&lt;'</code>.
>>>      */
>>>     private String summaryObjectStartText = "<";
>>> -
>>> +
>>>     /**
>>>      * The summary object text start <code>'&gt;'</code>.
>>>      */
>>> @@ -315,9 +329,9 @@
>>>     /**
>>>      * <p>Append to the <code>toString</code> the superclass  
>>> toString.</p>
>>>      * <p>NOTE: It assumes that the toString has been created  
>>> from the same ToStringStyle. </p>
>>> -     *
>>> +     *
>>>      * <p>A <code>null</code> <code>superToString</code> is  
>>> ignored.</p>
>>> -     *
>>> +     *
>>>      * @param buffer  the <code>StringBuffer</code> to populate
>>>      * @param superToString  the <code>super.toString()</code>
>>>      * @since 2.0
>>> @@ -329,9 +343,9 @@
>>>     /**
>>>      * <p>Append to the <code>toString</code> another toString.</p>
>>>      * <p>NOTE: It assumes that the toString has been created  
>>> from the same ToStringStyle. </p>
>>> -     *
>>> +     *
>>>      * <p>A <code>null</code> <code>toString</code> is ignored.</p>
>>> -     *
>>> +     *
>>>      * @param buffer  the <code>StringBuffer</code> to populate
>>>      * @param toString  the additional <code>toString</code>
>>>      * @since 2.0
>>> @@ -353,7 +367,7 @@
>>>
>>>     /**
>>>      * <p>Append to the <code>toString</code> the start of data  
>>> indicator.</p>
>>> -     *
>>> +     *
>>>      * @param buffer  the <code>StringBuffer</code> to populate
>>>      * @param object  the <code>Object</code> to build a  
>>> <code>toString</code> for
>>>      */
>>> @@ -370,7 +384,7 @@
>>>
>>>     /**
>>>      * <p>Append to the <code>toString</code> the end of data  
>>> indicator.</p>
>>> -     *
>>> +     *
>>>      * @param buffer  the <code>StringBuffer</code> to populate
>>>      * @param object  the <code>Object</code> to build a
>>>      *  <code>toString</code> for.
>>> @@ -385,7 +399,7 @@
>>>
>>>     /**
>>>      * <p>Remove the last field separator from the buffer.</p>
>>> -     *
>>> +     *
>>>      * @param buffer  the <code>StringBuffer</code> to populate
>>>      * @since 2.0
>>>      */
>>> @@ -456,7 +470,7 @@
>>>             && !(value instanceof Number || value instanceof  
>>> Boolean || value instanceof Character)) {
>>>            appendCyclicObject(buffer, fieldName, value);
>>>            return;
>>> -        }
>>> +        }
>>>
>>>         register(value);
>>>
>>> @@ -467,77 +481,77 @@
>>>                 } else {
>>>                     appendSummarySize(buffer, fieldName,  
>>> ((Collection<?>) value).size());
>>>                 }
>>> -
>>> +
>>>             } else if (value instanceof Map<?, ?>) {
>>>                 if (detail) {
>>>                     appendDetail(buffer, fieldName, (Map<?, ?>)  
>>> value);
>>>                 } else {
>>>                     appendSummarySize(buffer, fieldName,  
>>> ((Map<?, ?>) value).size());
>>>                 }
>>> -
>>> +
>>>             } else if (value instanceof long[]) {
>>>                 if (detail) {
>>>                     appendDetail(buffer, fieldName, (long[]) value);
>>>                 } else {
>>>                     appendSummary(buffer, fieldName, (long[])  
>>> value);
>>>                 }
>>> -
>>> +
>>>             } else if (value instanceof int[]) {
>>>                 if (detail) {
>>>                     appendDetail(buffer, fieldName, (int[]) value);
>>>                 } else {
>>>                     appendSummary(buffer, fieldName, (int[]) value);
>>>                 }
>>> -
>>> +
>>>             } else if (value instanceof short[]) {
>>>                 if (detail) {
>>>                     appendDetail(buffer, fieldName, (short[])  
>>> value);
>>>                 } else {
>>>                     appendSummary(buffer, fieldName, (short[])  
>>> value);
>>>                 }
>>> -
>>> +
>>>             } else if (value instanceof byte[]) {
>>>                 if (detail) {
>>>                     appendDetail(buffer, fieldName, (byte[]) value);
>>>                 } else {
>>>                     appendSummary(buffer, fieldName, (byte[])  
>>> value);
>>>                 }
>>> -
>>> +
>>>             } else if (value instanceof char[]) {
>>>                 if (detail) {
>>>                     appendDetail(buffer, fieldName, (char[]) value);
>>>                 } else {
>>>                     appendSummary(buffer, fieldName, (char[])  
>>> value);
>>>                 }
>>> -
>>> +
>>>             } else if (value instanceof double[]) {
>>>                 if (detail) {
>>>                     appendDetail(buffer, fieldName, (double[])  
>>> value);
>>>                 } else {
>>>                     appendSummary(buffer, fieldName, (double[])  
>>> value);
>>>                 }
>>> -
>>> +
>>>             } else if (value instanceof float[]) {
>>>                 if (detail) {
>>>                     appendDetail(buffer, fieldName, (float[])  
>>> value);
>>>                 } else {
>>>                     appendSummary(buffer, fieldName, (float[])  
>>> value);
>>>                 }
>>> -
>>> +
>>>             } else if (value instanceof boolean[]) {
>>>                 if (detail) {
>>>                     appendDetail(buffer, fieldName, (boolean[])  
>>> value);
>>>                 } else {
>>>                     appendSummary(buffer, fieldName, (boolean[])  
>>> value);
>>>                 }
>>> -
>>> +
>>>             } else if (value.getClass().isArray()) {
>>>                 if (detail) {
>>>                     appendDetail(buffer, fieldName, (Object[])  
>>> value);
>>>                 } else {
>>>                     appendSummary(buffer, fieldName, (Object[])  
>>> value);
>>>                 }
>>> -
>>> +
>>>             } else {
>>>                     if (detail) {
>>>                         appendDetail(buffer, fieldName, value);
>>> @@ -549,17 +563,17 @@
>>>             unregister(value);
>>>         }
>>>     }
>>> -
>>> +
>>>     /**
>>>      * <p>Append to the <code>toString</code> an <code>Object</code>
>>>      * value that has been detected to participate in a cycle. This
>>>      * implementation will print the standard string value of the  
>>> value.</p>
>>> -     *
>>> +     *
>>>      * @param buffer  the <code>StringBuffer</code> to populate
>>>      * @param fieldName  the field name, typically not used as  
>>> already appended
>>>      * @param value  the value to add to the <code>toString</code>,
>>>      *  not <code>null</code>
>>> -     *
>>> +     *
>>>      * @since 2.2
>>>      */
>>>     protected void appendCyclicObject(StringBuffer buffer, String  
>>> fieldName, Object value) {
>>> @@ -1428,7 +1442,7 @@
>>>
>>>     /**
>>>      * <p>Append to the <code>toString</code> the class name.</p>
>>> -     *
>>> +     *
>>>      * @param buffer  the <code>StringBuffer</code> to populate
>>>      * @param object  the <code>Object</code> whose name to output
>>>      */
>>> @@ -1445,7 +1459,7 @@
>>>
>>>     /**
>>>      * <p>Append the {@link System#identityHashCode 
>>> (java.lang.Object)}.</p>
>>> -     *
>>> +     *
>>>      * @param buffer  the <code>StringBuffer</code> to populate
>>>      * @param object  the <code>Object</code> whose id to output
>>>      */
>>> @@ -1459,7 +1473,7 @@
>>>
>>>     /**
>>>      * <p>Append to the <code>toString</code> the content start.</p>
>>> -     *
>>> +     *
>>>      * @param buffer  the <code>StringBuffer</code> to populate
>>>      */
>>>     protected void appendContentStart(StringBuffer buffer) {
>>> @@ -1468,7 +1482,7 @@
>>>
>>>     /**
>>>      * <p>Append to the <code>toString</code> the content end.</p>
>>> -     *
>>> +     *
>>>      * @param buffer  the <code>StringBuffer</code> to populate
>>>      */
>>>     protected void appendContentEnd(StringBuffer buffer) {
>>> @@ -1479,7 +1493,7 @@
>>>      * <p>Append to the <code>toString</code> an indicator for  
>>> <code>null</code>.</p>
>>>      *
>>>      * <p>The default indicator is <code>'&lt;null&gt;'</code>.</p>
>>> -     *
>>> +     *
>>>      * @param buffer  the <code>StringBuffer</code> to populate
>>>      * @param fieldName  the field name, typically not used as  
>>> already appended
>>>      */
>>> @@ -1489,7 +1503,7 @@
>>>
>>>     /**
>>>      * <p>Append to the <code>toString</code> the field  
>>> separator.</p>
>>> -     *
>>> +     *
>>>      * @param buffer  the <code>StringBuffer</code> to populate
>>>      */
>>>     protected void appendFieldSeparator(StringBuffer buffer) {
>>> @@ -1498,7 +1512,7 @@
>>>
>>>     /**
>>>      * <p>Append to the <code>toString</code> the field start.</p>
>>> -     *
>>> +     *
>>>      * @param buffer  the <code>StringBuffer</code> to populate
>>>      * @param fieldName  the field name
>>>      */
>>> @@ -1511,7 +1525,7 @@
>>>
>>>     /**
>>>      * <p>Append to the <code>toString<code> the field end.</p>
>>> -     *
>>> +     *
>>>      * @param buffer  the <code>StringBuffer</code> to populate
>>>      * @param fieldName  the field name, typically not used as  
>>> already appended
>>>      */
>>> @@ -1550,7 +1564,7 @@
>>>      * <code>null</code> indicating that it doesn't care about
>>>      * the detail level. In this case the default detail level is
>>>      * used.</p>
>>> -     *
>>> +     *
>>>      * @param fullDetailRequest  the detail level requested
>>>      * @return whether full detail is to be shown
>>>      */
>>> @@ -1886,9 +1900,9 @@
>>>     //-------------------------------------------------------------- 
>>> -------
>>>
>>>     /**
>>> -     * <p>Gets whether the field separator should be added at  
>>> the start
>>> +     * <p>Gets whether the field separator should be added at  
>>> the start
>>>      * of each buffer.</p>
>>> -     *
>>> +     *
>>>      * @return the fieldSeparatorAtStart flag
>>>      * @since 2.0
>>>      */
>>> @@ -1897,9 +1911,9 @@
>>>     }
>>>
>>>     /**
>>> -     * <p>Sets whether the field separator should be added at  
>>> the start
>>> +     * <p>Sets whether the field separator should be added at  
>>> the start
>>>      * of each buffer.</p>
>>> -     *
>>> +     *
>>>      * @param fieldSeparatorAtStart  the fieldSeparatorAtStart flag
>>>      * @since 2.0
>>>      */
>>> @@ -1910,9 +1924,9 @@
>>>     //-------------------------------------------------------------- 
>>> -------
>>>
>>>     /**
>>> -     * <p>Gets whether the field separator should be added at  
>>> the end
>>> +     * <p>Gets whether the field separator should be added at  
>>> the end
>>>      * of each buffer.</p>
>>> -     *
>>> +     *
>>>      * @return fieldSeparatorAtEnd flag
>>>      * @since 2.0
>>>      */
>>> @@ -1921,9 +1935,9 @@
>>>     }
>>>
>>>     /**
>>> -     * <p>Sets whether the field separator should be added at  
>>> the end
>>> +     * <p>Sets whether the field separator should be added at  
>>> the end
>>>      * of each buffer.</p>
>>> -     *
>>> +     *
>>>      * @param fieldSeparatorAtEnd  the fieldSeparatorAtEnd flag
>>>      * @since 2.0
>>>      */
>>> @@ -2097,7 +2111,7 @@
>>>
>>>         /**
>>>          * Required for serialization support.
>>> -         *
>>> +         *
>>>          * @see java.io.Serializable
>>>          */
>>>         private static final long serialVersionUID = 1L;
>>> @@ -2157,7 +2171,7 @@
>>>     }
>>>
>>>     //-------------------------------------------------------------- 
>>> --------------
>>> -
>>> +
>>>     /**
>>>      * <p><code>ToStringStyle</code> that prints out the short
>>>      * class name and no identity hashcode.</p>
>>>
>>>
>>>
>>
>> ---------------------------------------------------------------------
>> To unsubscribe, e-mail: dev-unsubscribe@commons.apache.org
>> For additional commands, e-mail: dev-help@commons.apache.org
>>
>>
>
> ---------------------------------------------------------------------
> To unsubscribe, e-mail: dev-unsubscribe@commons.apache.org
> For additional commands, e-mail: dev-help@commons.apache.org
>


---------------------------------------------------------------------
To unsubscribe, e-mail: dev-unsubscribe@commons.apache.org
For additional commands, e-mail: dev-help@commons.apache.org


Re: svn commit: r906673 - /commons/proper/lang/trunk/src/main/java/org/apache/commons/lang3/builder/ToStringStyle.java

Posted by Henri Yandell <fl...@gmail.com>.
+1 :)

On Thu, Feb 4, 2010 at 4:17 PM, Niall Pemberton
<ni...@gmail.com> wrote:
> Matt,
>
> Can you stop mixing up style/format changes with real functional
> changes - it makes it harder to follow along when you change a few
> lines and theres 10 pages in the commit email, I guess this is
> probably an IDE setting to remove trailing spaces. Can you either
> change your IDE or if you do want to change the format then do it as a
> separate commit before you make any functional changes.
>
> Thanks
>
> Niall
>
> On Thu, Feb 4, 2010 at 9:46 PM,  <mb...@apache.org> wrote:
>> Author: mbenson
>> Date: Thu Feb  4 21:46:22 2010
>> New Revision: 906673
>>
>> URL: http://svn.apache.org/viewvc?rev=906673&view=rev
>> Log:
>> [LANG-586] clear ThreadLocal recursion registry (compatibly with existing tests, first pass)
>>
>> Modified:
>>    commons/proper/lang/trunk/src/main/java/org/apache/commons/lang3/builder/ToStringStyle.java
>>
>> Modified: commons/proper/lang/trunk/src/main/java/org/apache/commons/lang3/builder/ToStringStyle.java
>> URL: http://svn.apache.org/viewvc/commons/proper/lang/trunk/src/main/java/org/apache/commons/lang3/builder/ToStringStyle.java?rev=906673&r1=906672&r2=906673&view=diff
>> ==============================================================================
>> --- commons/proper/lang/trunk/src/main/java/org/apache/commons/lang3/builder/ToStringStyle.java (original)
>> +++ commons/proper/lang/trunk/src/main/java/org/apache/commons/lang3/builder/ToStringStyle.java Thu Feb  4 21:46:22 2010
>> @@ -5,9 +5,9 @@
>>  * The ASF licenses this file to You under the Apache License, Version 2.0
>>  * (the "License"); you may not use this file except in compliance with
>>  * the License.  You may obtain a copy of the License at
>> - *
>> + *
>>  *      http://www.apache.org/licenses/LICENSE-2.0
>> - *
>> + *
>>  * Unless required by applicable law or agreed to in writing, software
>>  * distributed under the License is distributed on an "AS IS" BASIS,
>>  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
>> @@ -19,9 +19,10 @@
>>  import java.io.Serializable;
>>  import java.lang.reflect.Array;
>>  import java.util.Collection;
>> -import java.util.HashSet;
>> +import java.util.Collections;
>>  import java.util.Map;
>>  import java.util.Set;
>> +import java.util.WeakHashMap;
>>
>>  import org.apache.commons.lang3.ClassUtils;
>>  import org.apache.commons.lang3.ObjectUtils;
>> @@ -46,7 +47,7 @@
>>  * <p>For example, the detail version of the array based methods will
>>  * output the whole array, whereas the summary method will just output
>>  * the array length.</p>
>> - *
>> + *
>>  * <p>If you want to format the output of certain objects, such as dates, you
>>  * must create a subclass and override a method.
>>  * <pre>
>> @@ -73,17 +74,17 @@
>>     /**
>>      * The default toString style. Using the Using the <code>Person</code>
>>      * example from {@link ToStringBuilder}, the output would look like this:
>> -     *
>> +     *
>>      * <pre>
>>      * Person@182f0db[name=John Doe,age=33,smoker=false]
>>      * </pre>
>>      */
>>     public static final ToStringStyle DEFAULT_STYLE = new DefaultToStringStyle();
>> -
>> +
>>     /**
>>      * The multi line toString style. Using the Using the <code>Person</code>
>>      * example from {@link ToStringBuilder}, the output would look like this:
>> -     *
>> +     *
>>      * <pre>
>>      * Person@182f0db[
>>      *   name=John Doe
>> @@ -93,26 +94,26 @@
>>      * </pre>
>>      */
>>     public static final ToStringStyle MULTI_LINE_STYLE = new MultiLineToStringStyle();
>> -
>> +
>>     /**
>>      * The no field names toString style. Using the Using the
>>      * <code>Person</code> example from {@link ToStringBuilder}, the output
>>      * would look like this:
>> -     *
>> +     *
>>      * <pre>
>>      * Person@182f0db[John Doe,33,false]
>>      * </pre>
>>      */
>>     public static final ToStringStyle NO_FIELD_NAMES_STYLE = new NoFieldNameToStringStyle();
>> -
>> +
>>     /**
>>      * The short prefix toString style. Using the <code>Person</code> example
>>      * from {@link ToStringBuilder}, the output would look like this:
>> -     *
>> +     *
>>      * <pre>
>>      * Person[name=John Doe,age=33,smoker=false]
>>      * </pre>
>> -     *
>> +     *
>>      * @since 2.1
>>      */
>>     public static final ToStringStyle SHORT_PREFIX_STYLE = new ShortPrefixToStringStyle();
>> @@ -120,38 +121,32 @@
>>     /**
>>      * The simple toString style. Using the Using the <code>Person</code>
>>      * example from {@link ToStringBuilder}, the output would look like this:
>> -     *
>> +     *
>>      * <pre>
>>      * John Doe,33,false
>>      * </pre>
>>      */
>>     public static final ToStringStyle SIMPLE_STYLE = new SimpleToStringStyle();
>> -
>> +
>>     /**
>>      * <p>
>>      * A registry of objects used by <code>reflectionToString</code> methods
>>      * to detect cyclical object references and avoid infinite loops.
>>      * </p>
>>      */
>> -    private static final ThreadLocal<Set<Object>> registry = new ThreadLocal<Set<Object>>() {
>> -        @Override
>> -        protected Set<Object> initialValue() {
>> -            // The HashSet implementation is not synchronized,
>> -            // which is just what we need here.
>> -            return new HashSet<Object>();
>> -        }
>> -    };
>> +    private static final ThreadLocal<WeakHashMap<Object, Object>> REGISTRY = new ThreadLocal<WeakHashMap<Object,Object>>();
>>
>>     /**
>>      * <p>
>>      * Returns the registry of objects being traversed by the <code>reflectionToString</code>
>>      * methods in the current thread.
>>      * </p>
>> -     *
>> +     *
>>      * @return Set the registry of objects being traversed
>>      */
>>     static Set<Object> getRegistry() {
>> -        return registry.get();
>> +        WeakHashMap<Object, Object> m = REGISTRY.get();
>> +        return m == null ? Collections.<Object> emptySet() : m.keySet();
>>     }
>>
>>     /**
>> @@ -159,7 +154,7 @@
>>      * Returns <code>true</code> if the registry contains the given object.
>>      * Used by the reflection methods to avoid infinite loops.
>>      * </p>
>> -     *
>> +     *
>>      * @param value
>>      *                  The object to lookup in the registry.
>>      * @return boolean <code>true</code> if the registry contains the given
>> @@ -174,13 +169,21 @@
>>      * Registers the given object. Used by the reflection methods to avoid
>>      * infinite loops.
>>      * </p>
>> -     *
>> +     *
>>      * @param value
>>      *                  The object to register.
>>      */
>>     static void register(Object value) {
>>         if (value != null) {
>> -            getRegistry().add(value);
>> +            WeakHashMap<Object, Object> m;
>> +            synchronized (ToStringStyle.class) {
>> +                m = REGISTRY.get();
>> +                if (m == null) {
>> +                    m = new WeakHashMap<Object, Object>();
>> +                    REGISTRY.set(m);
>> +                }
>> +            }
>> +            m.put(value, null);
>>         }
>>     }
>>
>> @@ -188,33 +191,44 @@
>>      * <p>
>>      * Unregisters the given object.
>>      * </p>
>> -     *
>> +     *
>>      * <p>
>>      * Used by the reflection methods to avoid infinite loops.
>>      * </p>
>> -     *
>> +     *
>>      * @param value
>>      *                  The object to unregister.
>>      */
>>     static void unregister(Object value) {
>> -        getRegistry().remove(value);
>> +        if (value != null) {
>> +            WeakHashMap<Object, Object> m;
>> +            synchronized (ToStringStyle.class) {
>> +                m = REGISTRY.get();
>> +                if (m != null) {
>> +                    m.remove(value);
>> +                    if (m.isEmpty()) {
>> +                        REGISTRY.remove();
>> +                    }
>> +                }
>> +            }
>> +        }
>>     }
>>
>>     /**
>>      * Whether to use the field names, the default is <code>true</code>.
>>      */
>>     private boolean useFieldNames = true;
>> -
>> +
>>     /**
>>      * Whether to use the class name, the default is <code>true</code>.
>>      */
>>     private boolean useClassName = true;
>> -
>> +
>>     /**
>>      * Whether to use short class names, the default is <code>false</code>.
>>      */
>>     private boolean useShortClassName = false;
>> -
>> +
>>     /**
>>      * Whether to use the identity hash code, the default is <code>true</code>.
>>      */
>> @@ -224,78 +238,78 @@
>>      * The content start <code>'['</code>.
>>      */
>>     private String contentStart = "[";
>> -
>> +
>>     /**
>>      * The content end <code>']'</code>.
>>      */
>>     private String contentEnd = "]";
>> -
>> +
>>     /**
>>      * The field name value separator <code>'='</code>.
>>      */
>>     private String fieldNameValueSeparator = "=";
>> -
>> +
>>     /**
>>      * Whether the field separator should be added before any other fields.
>>      */
>>     private boolean fieldSeparatorAtStart = false;
>> -
>> +
>>     /**
>>      * Whether the field separator should be added after any other fields.
>>      */
>>     private boolean fieldSeparatorAtEnd = false;
>> -
>> +
>>     /**
>>      * The field separator <code>','</code>.
>>      */
>>     private String fieldSeparator = ",";
>> -
>> +
>>     /**
>>      * The array start <code>'{'</code>.
>>      */
>>     private String arrayStart = "{";
>> -
>> +
>>     /**
>>      * The array separator <code>','</code>.
>>      */
>>     private String arraySeparator = ",";
>> -
>> +
>>     /**
>>      * The detail for array content.
>>      */
>>     private boolean arrayContentDetail = true;
>> -
>> +
>>     /**
>>      * The array end <code>'}'</code>.
>>      */
>>     private String arrayEnd = "}";
>> -
>> +
>>     /**
>>      * The value to use when fullDetail is <code>null</code>,
>>      * the default value is <code>true</code>.
>>      */
>>     private boolean defaultFullDetail = true;
>> -
>> +
>>     /**
>>      * The <code>null</code> text <code>'&lt;null&gt;'</code>.
>>      */
>>     private String nullText = "<null>";
>> -
>> +
>>     /**
>>      * The summary size text start <code>'<size'</code>.
>>      */
>>     private String sizeStartText = "<size=";
>> -
>> +
>>     /**
>>      * The summary size text start <code>'&gt;'</code>.
>>      */
>>     private String sizeEndText = ">";
>> -
>> +
>>     /**
>>      * The summary object text start <code>'&lt;'</code>.
>>      */
>>     private String summaryObjectStartText = "<";
>> -
>> +
>>     /**
>>      * The summary object text start <code>'&gt;'</code>.
>>      */
>> @@ -315,9 +329,9 @@
>>     /**
>>      * <p>Append to the <code>toString</code> the superclass toString.</p>
>>      * <p>NOTE: It assumes that the toString has been created from the same ToStringStyle. </p>
>> -     *
>> +     *
>>      * <p>A <code>null</code> <code>superToString</code> is ignored.</p>
>> -     *
>> +     *
>>      * @param buffer  the <code>StringBuffer</code> to populate
>>      * @param superToString  the <code>super.toString()</code>
>>      * @since 2.0
>> @@ -329,9 +343,9 @@
>>     /**
>>      * <p>Append to the <code>toString</code> another toString.</p>
>>      * <p>NOTE: It assumes that the toString has been created from the same ToStringStyle. </p>
>> -     *
>> +     *
>>      * <p>A <code>null</code> <code>toString</code> is ignored.</p>
>> -     *
>> +     *
>>      * @param buffer  the <code>StringBuffer</code> to populate
>>      * @param toString  the additional <code>toString</code>
>>      * @since 2.0
>> @@ -353,7 +367,7 @@
>>
>>     /**
>>      * <p>Append to the <code>toString</code> the start of data indicator.</p>
>> -     *
>> +     *
>>      * @param buffer  the <code>StringBuffer</code> to populate
>>      * @param object  the <code>Object</code> to build a <code>toString</code> for
>>      */
>> @@ -370,7 +384,7 @@
>>
>>     /**
>>      * <p>Append to the <code>toString</code> the end of data indicator.</p>
>> -     *
>> +     *
>>      * @param buffer  the <code>StringBuffer</code> to populate
>>      * @param object  the <code>Object</code> to build a
>>      *  <code>toString</code> for.
>> @@ -385,7 +399,7 @@
>>
>>     /**
>>      * <p>Remove the last field separator from the buffer.</p>
>> -     *
>> +     *
>>      * @param buffer  the <code>StringBuffer</code> to populate
>>      * @since 2.0
>>      */
>> @@ -456,7 +470,7 @@
>>             && !(value instanceof Number || value instanceof Boolean || value instanceof Character)) {
>>            appendCyclicObject(buffer, fieldName, value);
>>            return;
>> -        }
>> +        }
>>
>>         register(value);
>>
>> @@ -467,77 +481,77 @@
>>                 } else {
>>                     appendSummarySize(buffer, fieldName, ((Collection<?>) value).size());
>>                 }
>> -
>> +
>>             } else if (value instanceof Map<?, ?>) {
>>                 if (detail) {
>>                     appendDetail(buffer, fieldName, (Map<?, ?>) value);
>>                 } else {
>>                     appendSummarySize(buffer, fieldName, ((Map<?, ?>) value).size());
>>                 }
>> -
>> +
>>             } else if (value instanceof long[]) {
>>                 if (detail) {
>>                     appendDetail(buffer, fieldName, (long[]) value);
>>                 } else {
>>                     appendSummary(buffer, fieldName, (long[]) value);
>>                 }
>> -
>> +
>>             } else if (value instanceof int[]) {
>>                 if (detail) {
>>                     appendDetail(buffer, fieldName, (int[]) value);
>>                 } else {
>>                     appendSummary(buffer, fieldName, (int[]) value);
>>                 }
>> -
>> +
>>             } else if (value instanceof short[]) {
>>                 if (detail) {
>>                     appendDetail(buffer, fieldName, (short[]) value);
>>                 } else {
>>                     appendSummary(buffer, fieldName, (short[]) value);
>>                 }
>> -
>> +
>>             } else if (value instanceof byte[]) {
>>                 if (detail) {
>>                     appendDetail(buffer, fieldName, (byte[]) value);
>>                 } else {
>>                     appendSummary(buffer, fieldName, (byte[]) value);
>>                 }
>> -
>> +
>>             } else if (value instanceof char[]) {
>>                 if (detail) {
>>                     appendDetail(buffer, fieldName, (char[]) value);
>>                 } else {
>>                     appendSummary(buffer, fieldName, (char[]) value);
>>                 }
>> -
>> +
>>             } else if (value instanceof double[]) {
>>                 if (detail) {
>>                     appendDetail(buffer, fieldName, (double[]) value);
>>                 } else {
>>                     appendSummary(buffer, fieldName, (double[]) value);
>>                 }
>> -
>> +
>>             } else if (value instanceof float[]) {
>>                 if (detail) {
>>                     appendDetail(buffer, fieldName, (float[]) value);
>>                 } else {
>>                     appendSummary(buffer, fieldName, (float[]) value);
>>                 }
>> -
>> +
>>             } else if (value instanceof boolean[]) {
>>                 if (detail) {
>>                     appendDetail(buffer, fieldName, (boolean[]) value);
>>                 } else {
>>                     appendSummary(buffer, fieldName, (boolean[]) value);
>>                 }
>> -
>> +
>>             } else if (value.getClass().isArray()) {
>>                 if (detail) {
>>                     appendDetail(buffer, fieldName, (Object[]) value);
>>                 } else {
>>                     appendSummary(buffer, fieldName, (Object[]) value);
>>                 }
>> -
>> +
>>             } else {
>>                     if (detail) {
>>                         appendDetail(buffer, fieldName, value);
>> @@ -549,17 +563,17 @@
>>             unregister(value);
>>         }
>>     }
>> -
>> +
>>     /**
>>      * <p>Append to the <code>toString</code> an <code>Object</code>
>>      * value that has been detected to participate in a cycle. This
>>      * implementation will print the standard string value of the value.</p>
>> -     *
>> +     *
>>      * @param buffer  the <code>StringBuffer</code> to populate
>>      * @param fieldName  the field name, typically not used as already appended
>>      * @param value  the value to add to the <code>toString</code>,
>>      *  not <code>null</code>
>> -     *
>> +     *
>>      * @since 2.2
>>      */
>>     protected void appendCyclicObject(StringBuffer buffer, String fieldName, Object value) {
>> @@ -1428,7 +1442,7 @@
>>
>>     /**
>>      * <p>Append to the <code>toString</code> the class name.</p>
>> -     *
>> +     *
>>      * @param buffer  the <code>StringBuffer</code> to populate
>>      * @param object  the <code>Object</code> whose name to output
>>      */
>> @@ -1445,7 +1459,7 @@
>>
>>     /**
>>      * <p>Append the {@link System#identityHashCode(java.lang.Object)}.</p>
>> -     *
>> +     *
>>      * @param buffer  the <code>StringBuffer</code> to populate
>>      * @param object  the <code>Object</code> whose id to output
>>      */
>> @@ -1459,7 +1473,7 @@
>>
>>     /**
>>      * <p>Append to the <code>toString</code> the content start.</p>
>> -     *
>> +     *
>>      * @param buffer  the <code>StringBuffer</code> to populate
>>      */
>>     protected void appendContentStart(StringBuffer buffer) {
>> @@ -1468,7 +1482,7 @@
>>
>>     /**
>>      * <p>Append to the <code>toString</code> the content end.</p>
>> -     *
>> +     *
>>      * @param buffer  the <code>StringBuffer</code> to populate
>>      */
>>     protected void appendContentEnd(StringBuffer buffer) {
>> @@ -1479,7 +1493,7 @@
>>      * <p>Append to the <code>toString</code> an indicator for <code>null</code>.</p>
>>      *
>>      * <p>The default indicator is <code>'&lt;null&gt;'</code>.</p>
>> -     *
>> +     *
>>      * @param buffer  the <code>StringBuffer</code> to populate
>>      * @param fieldName  the field name, typically not used as already appended
>>      */
>> @@ -1489,7 +1503,7 @@
>>
>>     /**
>>      * <p>Append to the <code>toString</code> the field separator.</p>
>> -     *
>> +     *
>>      * @param buffer  the <code>StringBuffer</code> to populate
>>      */
>>     protected void appendFieldSeparator(StringBuffer buffer) {
>> @@ -1498,7 +1512,7 @@
>>
>>     /**
>>      * <p>Append to the <code>toString</code> the field start.</p>
>> -     *
>> +     *
>>      * @param buffer  the <code>StringBuffer</code> to populate
>>      * @param fieldName  the field name
>>      */
>> @@ -1511,7 +1525,7 @@
>>
>>     /**
>>      * <p>Append to the <code>toString<code> the field end.</p>
>> -     *
>> +     *
>>      * @param buffer  the <code>StringBuffer</code> to populate
>>      * @param fieldName  the field name, typically not used as already appended
>>      */
>> @@ -1550,7 +1564,7 @@
>>      * <code>null</code> indicating that it doesn't care about
>>      * the detail level. In this case the default detail level is
>>      * used.</p>
>> -     *
>> +     *
>>      * @param fullDetailRequest  the detail level requested
>>      * @return whether full detail is to be shown
>>      */
>> @@ -1886,9 +1900,9 @@
>>     //---------------------------------------------------------------------
>>
>>     /**
>> -     * <p>Gets whether the field separator should be added at the start
>> +     * <p>Gets whether the field separator should be added at the start
>>      * of each buffer.</p>
>> -     *
>> +     *
>>      * @return the fieldSeparatorAtStart flag
>>      * @since 2.0
>>      */
>> @@ -1897,9 +1911,9 @@
>>     }
>>
>>     /**
>> -     * <p>Sets whether the field separator should be added at the start
>> +     * <p>Sets whether the field separator should be added at the start
>>      * of each buffer.</p>
>> -     *
>> +     *
>>      * @param fieldSeparatorAtStart  the fieldSeparatorAtStart flag
>>      * @since 2.0
>>      */
>> @@ -1910,9 +1924,9 @@
>>     //---------------------------------------------------------------------
>>
>>     /**
>> -     * <p>Gets whether the field separator should be added at the end
>> +     * <p>Gets whether the field separator should be added at the end
>>      * of each buffer.</p>
>> -     *
>> +     *
>>      * @return fieldSeparatorAtEnd flag
>>      * @since 2.0
>>      */
>> @@ -1921,9 +1935,9 @@
>>     }
>>
>>     /**
>> -     * <p>Sets whether the field separator should be added at the end
>> +     * <p>Sets whether the field separator should be added at the end
>>      * of each buffer.</p>
>> -     *
>> +     *
>>      * @param fieldSeparatorAtEnd  the fieldSeparatorAtEnd flag
>>      * @since 2.0
>>      */
>> @@ -2097,7 +2111,7 @@
>>
>>         /**
>>          * Required for serialization support.
>> -         *
>> +         *
>>          * @see java.io.Serializable
>>          */
>>         private static final long serialVersionUID = 1L;
>> @@ -2157,7 +2171,7 @@
>>     }
>>
>>     //----------------------------------------------------------------------------
>> -
>> +
>>     /**
>>      * <p><code>ToStringStyle</code> that prints out the short
>>      * class name and no identity hashcode.</p>
>>
>>
>>
>
> ---------------------------------------------------------------------
> To unsubscribe, e-mail: dev-unsubscribe@commons.apache.org
> For additional commands, e-mail: dev-help@commons.apache.org
>
>

---------------------------------------------------------------------
To unsubscribe, e-mail: dev-unsubscribe@commons.apache.org
For additional commands, e-mail: dev-help@commons.apache.org


Re: svn commit: r906673 - /commons/proper/lang/trunk/src/main/java/org/apache/commons/lang3/builder/ToStringStyle.java

Posted by Niall Pemberton <ni...@gmail.com>.
Matt,

Can you stop mixing up style/format changes with real functional
changes - it makes it harder to follow along when you change a few
lines and theres 10 pages in the commit email, I guess this is
probably an IDE setting to remove trailing spaces. Can you either
change your IDE or if you do want to change the format then do it as a
separate commit before you make any functional changes.

Thanks

Niall

On Thu, Feb 4, 2010 at 9:46 PM,  <mb...@apache.org> wrote:
> Author: mbenson
> Date: Thu Feb  4 21:46:22 2010
> New Revision: 906673
>
> URL: http://svn.apache.org/viewvc?rev=906673&view=rev
> Log:
> [LANG-586] clear ThreadLocal recursion registry (compatibly with existing tests, first pass)
>
> Modified:
>    commons/proper/lang/trunk/src/main/java/org/apache/commons/lang3/builder/ToStringStyle.java
>
> Modified: commons/proper/lang/trunk/src/main/java/org/apache/commons/lang3/builder/ToStringStyle.java
> URL: http://svn.apache.org/viewvc/commons/proper/lang/trunk/src/main/java/org/apache/commons/lang3/builder/ToStringStyle.java?rev=906673&r1=906672&r2=906673&view=diff
> ==============================================================================
> --- commons/proper/lang/trunk/src/main/java/org/apache/commons/lang3/builder/ToStringStyle.java (original)
> +++ commons/proper/lang/trunk/src/main/java/org/apache/commons/lang3/builder/ToStringStyle.java Thu Feb  4 21:46:22 2010
> @@ -5,9 +5,9 @@
>  * The ASF licenses this file to You under the Apache License, Version 2.0
>  * (the "License"); you may not use this file except in compliance with
>  * the License.  You may obtain a copy of the License at
> - *
> + *
>  *      http://www.apache.org/licenses/LICENSE-2.0
> - *
> + *
>  * Unless required by applicable law or agreed to in writing, software
>  * distributed under the License is distributed on an "AS IS" BASIS,
>  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
> @@ -19,9 +19,10 @@
>  import java.io.Serializable;
>  import java.lang.reflect.Array;
>  import java.util.Collection;
> -import java.util.HashSet;
> +import java.util.Collections;
>  import java.util.Map;
>  import java.util.Set;
> +import java.util.WeakHashMap;
>
>  import org.apache.commons.lang3.ClassUtils;
>  import org.apache.commons.lang3.ObjectUtils;
> @@ -46,7 +47,7 @@
>  * <p>For example, the detail version of the array based methods will
>  * output the whole array, whereas the summary method will just output
>  * the array length.</p>
> - *
> + *
>  * <p>If you want to format the output of certain objects, such as dates, you
>  * must create a subclass and override a method.
>  * <pre>
> @@ -73,17 +74,17 @@
>     /**
>      * The default toString style. Using the Using the <code>Person</code>
>      * example from {@link ToStringBuilder}, the output would look like this:
> -     *
> +     *
>      * <pre>
>      * Person@182f0db[name=John Doe,age=33,smoker=false]
>      * </pre>
>      */
>     public static final ToStringStyle DEFAULT_STYLE = new DefaultToStringStyle();
> -
> +
>     /**
>      * The multi line toString style. Using the Using the <code>Person</code>
>      * example from {@link ToStringBuilder}, the output would look like this:
> -     *
> +     *
>      * <pre>
>      * Person@182f0db[
>      *   name=John Doe
> @@ -93,26 +94,26 @@
>      * </pre>
>      */
>     public static final ToStringStyle MULTI_LINE_STYLE = new MultiLineToStringStyle();
> -
> +
>     /**
>      * The no field names toString style. Using the Using the
>      * <code>Person</code> example from {@link ToStringBuilder}, the output
>      * would look like this:
> -     *
> +     *
>      * <pre>
>      * Person@182f0db[John Doe,33,false]
>      * </pre>
>      */
>     public static final ToStringStyle NO_FIELD_NAMES_STYLE = new NoFieldNameToStringStyle();
> -
> +
>     /**
>      * The short prefix toString style. Using the <code>Person</code> example
>      * from {@link ToStringBuilder}, the output would look like this:
> -     *
> +     *
>      * <pre>
>      * Person[name=John Doe,age=33,smoker=false]
>      * </pre>
> -     *
> +     *
>      * @since 2.1
>      */
>     public static final ToStringStyle SHORT_PREFIX_STYLE = new ShortPrefixToStringStyle();
> @@ -120,38 +121,32 @@
>     /**
>      * The simple toString style. Using the Using the <code>Person</code>
>      * example from {@link ToStringBuilder}, the output would look like this:
> -     *
> +     *
>      * <pre>
>      * John Doe,33,false
>      * </pre>
>      */
>     public static final ToStringStyle SIMPLE_STYLE = new SimpleToStringStyle();
> -
> +
>     /**
>      * <p>
>      * A registry of objects used by <code>reflectionToString</code> methods
>      * to detect cyclical object references and avoid infinite loops.
>      * </p>
>      */
> -    private static final ThreadLocal<Set<Object>> registry = new ThreadLocal<Set<Object>>() {
> -        @Override
> -        protected Set<Object> initialValue() {
> -            // The HashSet implementation is not synchronized,
> -            // which is just what we need here.
> -            return new HashSet<Object>();
> -        }
> -    };
> +    private static final ThreadLocal<WeakHashMap<Object, Object>> REGISTRY = new ThreadLocal<WeakHashMap<Object,Object>>();
>
>     /**
>      * <p>
>      * Returns the registry of objects being traversed by the <code>reflectionToString</code>
>      * methods in the current thread.
>      * </p>
> -     *
> +     *
>      * @return Set the registry of objects being traversed
>      */
>     static Set<Object> getRegistry() {
> -        return registry.get();
> +        WeakHashMap<Object, Object> m = REGISTRY.get();
> +        return m == null ? Collections.<Object> emptySet() : m.keySet();
>     }
>
>     /**
> @@ -159,7 +154,7 @@
>      * Returns <code>true</code> if the registry contains the given object.
>      * Used by the reflection methods to avoid infinite loops.
>      * </p>
> -     *
> +     *
>      * @param value
>      *                  The object to lookup in the registry.
>      * @return boolean <code>true</code> if the registry contains the given
> @@ -174,13 +169,21 @@
>      * Registers the given object. Used by the reflection methods to avoid
>      * infinite loops.
>      * </p>
> -     *
> +     *
>      * @param value
>      *                  The object to register.
>      */
>     static void register(Object value) {
>         if (value != null) {
> -            getRegistry().add(value);
> +            WeakHashMap<Object, Object> m;
> +            synchronized (ToStringStyle.class) {
> +                m = REGISTRY.get();
> +                if (m == null) {
> +                    m = new WeakHashMap<Object, Object>();
> +                    REGISTRY.set(m);
> +                }
> +            }
> +            m.put(value, null);
>         }
>     }
>
> @@ -188,33 +191,44 @@
>      * <p>
>      * Unregisters the given object.
>      * </p>
> -     *
> +     *
>      * <p>
>      * Used by the reflection methods to avoid infinite loops.
>      * </p>
> -     *
> +     *
>      * @param value
>      *                  The object to unregister.
>      */
>     static void unregister(Object value) {
> -        getRegistry().remove(value);
> +        if (value != null) {
> +            WeakHashMap<Object, Object> m;
> +            synchronized (ToStringStyle.class) {
> +                m = REGISTRY.get();
> +                if (m != null) {
> +                    m.remove(value);
> +                    if (m.isEmpty()) {
> +                        REGISTRY.remove();
> +                    }
> +                }
> +            }
> +        }
>     }
>
>     /**
>      * Whether to use the field names, the default is <code>true</code>.
>      */
>     private boolean useFieldNames = true;
> -
> +
>     /**
>      * Whether to use the class name, the default is <code>true</code>.
>      */
>     private boolean useClassName = true;
> -
> +
>     /**
>      * Whether to use short class names, the default is <code>false</code>.
>      */
>     private boolean useShortClassName = false;
> -
> +
>     /**
>      * Whether to use the identity hash code, the default is <code>true</code>.
>      */
> @@ -224,78 +238,78 @@
>      * The content start <code>'['</code>.
>      */
>     private String contentStart = "[";
> -
> +
>     /**
>      * The content end <code>']'</code>.
>      */
>     private String contentEnd = "]";
> -
> +
>     /**
>      * The field name value separator <code>'='</code>.
>      */
>     private String fieldNameValueSeparator = "=";
> -
> +
>     /**
>      * Whether the field separator should be added before any other fields.
>      */
>     private boolean fieldSeparatorAtStart = false;
> -
> +
>     /**
>      * Whether the field separator should be added after any other fields.
>      */
>     private boolean fieldSeparatorAtEnd = false;
> -
> +
>     /**
>      * The field separator <code>','</code>.
>      */
>     private String fieldSeparator = ",";
> -
> +
>     /**
>      * The array start <code>'{'</code>.
>      */
>     private String arrayStart = "{";
> -
> +
>     /**
>      * The array separator <code>','</code>.
>      */
>     private String arraySeparator = ",";
> -
> +
>     /**
>      * The detail for array content.
>      */
>     private boolean arrayContentDetail = true;
> -
> +
>     /**
>      * The array end <code>'}'</code>.
>      */
>     private String arrayEnd = "}";
> -
> +
>     /**
>      * The value to use when fullDetail is <code>null</code>,
>      * the default value is <code>true</code>.
>      */
>     private boolean defaultFullDetail = true;
> -
> +
>     /**
>      * The <code>null</code> text <code>'&lt;null&gt;'</code>.
>      */
>     private String nullText = "<null>";
> -
> +
>     /**
>      * The summary size text start <code>'<size'</code>.
>      */
>     private String sizeStartText = "<size=";
> -
> +
>     /**
>      * The summary size text start <code>'&gt;'</code>.
>      */
>     private String sizeEndText = ">";
> -
> +
>     /**
>      * The summary object text start <code>'&lt;'</code>.
>      */
>     private String summaryObjectStartText = "<";
> -
> +
>     /**
>      * The summary object text start <code>'&gt;'</code>.
>      */
> @@ -315,9 +329,9 @@
>     /**
>      * <p>Append to the <code>toString</code> the superclass toString.</p>
>      * <p>NOTE: It assumes that the toString has been created from the same ToStringStyle. </p>
> -     *
> +     *
>      * <p>A <code>null</code> <code>superToString</code> is ignored.</p>
> -     *
> +     *
>      * @param buffer  the <code>StringBuffer</code> to populate
>      * @param superToString  the <code>super.toString()</code>
>      * @since 2.0
> @@ -329,9 +343,9 @@
>     /**
>      * <p>Append to the <code>toString</code> another toString.</p>
>      * <p>NOTE: It assumes that the toString has been created from the same ToStringStyle. </p>
> -     *
> +     *
>      * <p>A <code>null</code> <code>toString</code> is ignored.</p>
> -     *
> +     *
>      * @param buffer  the <code>StringBuffer</code> to populate
>      * @param toString  the additional <code>toString</code>
>      * @since 2.0
> @@ -353,7 +367,7 @@
>
>     /**
>      * <p>Append to the <code>toString</code> the start of data indicator.</p>
> -     *
> +     *
>      * @param buffer  the <code>StringBuffer</code> to populate
>      * @param object  the <code>Object</code> to build a <code>toString</code> for
>      */
> @@ -370,7 +384,7 @@
>
>     /**
>      * <p>Append to the <code>toString</code> the end of data indicator.</p>
> -     *
> +     *
>      * @param buffer  the <code>StringBuffer</code> to populate
>      * @param object  the <code>Object</code> to build a
>      *  <code>toString</code> for.
> @@ -385,7 +399,7 @@
>
>     /**
>      * <p>Remove the last field separator from the buffer.</p>
> -     *
> +     *
>      * @param buffer  the <code>StringBuffer</code> to populate
>      * @since 2.0
>      */
> @@ -456,7 +470,7 @@
>             && !(value instanceof Number || value instanceof Boolean || value instanceof Character)) {
>            appendCyclicObject(buffer, fieldName, value);
>            return;
> -        }
> +        }
>
>         register(value);
>
> @@ -467,77 +481,77 @@
>                 } else {
>                     appendSummarySize(buffer, fieldName, ((Collection<?>) value).size());
>                 }
> -
> +
>             } else if (value instanceof Map<?, ?>) {
>                 if (detail) {
>                     appendDetail(buffer, fieldName, (Map<?, ?>) value);
>                 } else {
>                     appendSummarySize(buffer, fieldName, ((Map<?, ?>) value).size());
>                 }
> -
> +
>             } else if (value instanceof long[]) {
>                 if (detail) {
>                     appendDetail(buffer, fieldName, (long[]) value);
>                 } else {
>                     appendSummary(buffer, fieldName, (long[]) value);
>                 }
> -
> +
>             } else if (value instanceof int[]) {
>                 if (detail) {
>                     appendDetail(buffer, fieldName, (int[]) value);
>                 } else {
>                     appendSummary(buffer, fieldName, (int[]) value);
>                 }
> -
> +
>             } else if (value instanceof short[]) {
>                 if (detail) {
>                     appendDetail(buffer, fieldName, (short[]) value);
>                 } else {
>                     appendSummary(buffer, fieldName, (short[]) value);
>                 }
> -
> +
>             } else if (value instanceof byte[]) {
>                 if (detail) {
>                     appendDetail(buffer, fieldName, (byte[]) value);
>                 } else {
>                     appendSummary(buffer, fieldName, (byte[]) value);
>                 }
> -
> +
>             } else if (value instanceof char[]) {
>                 if (detail) {
>                     appendDetail(buffer, fieldName, (char[]) value);
>                 } else {
>                     appendSummary(buffer, fieldName, (char[]) value);
>                 }
> -
> +
>             } else if (value instanceof double[]) {
>                 if (detail) {
>                     appendDetail(buffer, fieldName, (double[]) value);
>                 } else {
>                     appendSummary(buffer, fieldName, (double[]) value);
>                 }
> -
> +
>             } else if (value instanceof float[]) {
>                 if (detail) {
>                     appendDetail(buffer, fieldName, (float[]) value);
>                 } else {
>                     appendSummary(buffer, fieldName, (float[]) value);
>                 }
> -
> +
>             } else if (value instanceof boolean[]) {
>                 if (detail) {
>                     appendDetail(buffer, fieldName, (boolean[]) value);
>                 } else {
>                     appendSummary(buffer, fieldName, (boolean[]) value);
>                 }
> -
> +
>             } else if (value.getClass().isArray()) {
>                 if (detail) {
>                     appendDetail(buffer, fieldName, (Object[]) value);
>                 } else {
>                     appendSummary(buffer, fieldName, (Object[]) value);
>                 }
> -
> +
>             } else {
>                     if (detail) {
>                         appendDetail(buffer, fieldName, value);
> @@ -549,17 +563,17 @@
>             unregister(value);
>         }
>     }
> -
> +
>     /**
>      * <p>Append to the <code>toString</code> an <code>Object</code>
>      * value that has been detected to participate in a cycle. This
>      * implementation will print the standard string value of the value.</p>
> -     *
> +     *
>      * @param buffer  the <code>StringBuffer</code> to populate
>      * @param fieldName  the field name, typically not used as already appended
>      * @param value  the value to add to the <code>toString</code>,
>      *  not <code>null</code>
> -     *
> +     *
>      * @since 2.2
>      */
>     protected void appendCyclicObject(StringBuffer buffer, String fieldName, Object value) {
> @@ -1428,7 +1442,7 @@
>
>     /**
>      * <p>Append to the <code>toString</code> the class name.</p>
> -     *
> +     *
>      * @param buffer  the <code>StringBuffer</code> to populate
>      * @param object  the <code>Object</code> whose name to output
>      */
> @@ -1445,7 +1459,7 @@
>
>     /**
>      * <p>Append the {@link System#identityHashCode(java.lang.Object)}.</p>
> -     *
> +     *
>      * @param buffer  the <code>StringBuffer</code> to populate
>      * @param object  the <code>Object</code> whose id to output
>      */
> @@ -1459,7 +1473,7 @@
>
>     /**
>      * <p>Append to the <code>toString</code> the content start.</p>
> -     *
> +     *
>      * @param buffer  the <code>StringBuffer</code> to populate
>      */
>     protected void appendContentStart(StringBuffer buffer) {
> @@ -1468,7 +1482,7 @@
>
>     /**
>      * <p>Append to the <code>toString</code> the content end.</p>
> -     *
> +     *
>      * @param buffer  the <code>StringBuffer</code> to populate
>      */
>     protected void appendContentEnd(StringBuffer buffer) {
> @@ -1479,7 +1493,7 @@
>      * <p>Append to the <code>toString</code> an indicator for <code>null</code>.</p>
>      *
>      * <p>The default indicator is <code>'&lt;null&gt;'</code>.</p>
> -     *
> +     *
>      * @param buffer  the <code>StringBuffer</code> to populate
>      * @param fieldName  the field name, typically not used as already appended
>      */
> @@ -1489,7 +1503,7 @@
>
>     /**
>      * <p>Append to the <code>toString</code> the field separator.</p>
> -     *
> +     *
>      * @param buffer  the <code>StringBuffer</code> to populate
>      */
>     protected void appendFieldSeparator(StringBuffer buffer) {
> @@ -1498,7 +1512,7 @@
>
>     /**
>      * <p>Append to the <code>toString</code> the field start.</p>
> -     *
> +     *
>      * @param buffer  the <code>StringBuffer</code> to populate
>      * @param fieldName  the field name
>      */
> @@ -1511,7 +1525,7 @@
>
>     /**
>      * <p>Append to the <code>toString<code> the field end.</p>
> -     *
> +     *
>      * @param buffer  the <code>StringBuffer</code> to populate
>      * @param fieldName  the field name, typically not used as already appended
>      */
> @@ -1550,7 +1564,7 @@
>      * <code>null</code> indicating that it doesn't care about
>      * the detail level. In this case the default detail level is
>      * used.</p>
> -     *
> +     *
>      * @param fullDetailRequest  the detail level requested
>      * @return whether full detail is to be shown
>      */
> @@ -1886,9 +1900,9 @@
>     //---------------------------------------------------------------------
>
>     /**
> -     * <p>Gets whether the field separator should be added at the start
> +     * <p>Gets whether the field separator should be added at the start
>      * of each buffer.</p>
> -     *
> +     *
>      * @return the fieldSeparatorAtStart flag
>      * @since 2.0
>      */
> @@ -1897,9 +1911,9 @@
>     }
>
>     /**
> -     * <p>Sets whether the field separator should be added at the start
> +     * <p>Sets whether the field separator should be added at the start
>      * of each buffer.</p>
> -     *
> +     *
>      * @param fieldSeparatorAtStart  the fieldSeparatorAtStart flag
>      * @since 2.0
>      */
> @@ -1910,9 +1924,9 @@
>     //---------------------------------------------------------------------
>
>     /**
> -     * <p>Gets whether the field separator should be added at the end
> +     * <p>Gets whether the field separator should be added at the end
>      * of each buffer.</p>
> -     *
> +     *
>      * @return fieldSeparatorAtEnd flag
>      * @since 2.0
>      */
> @@ -1921,9 +1935,9 @@
>     }
>
>     /**
> -     * <p>Sets whether the field separator should be added at the end
> +     * <p>Sets whether the field separator should be added at the end
>      * of each buffer.</p>
> -     *
> +     *
>      * @param fieldSeparatorAtEnd  the fieldSeparatorAtEnd flag
>      * @since 2.0
>      */
> @@ -2097,7 +2111,7 @@
>
>         /**
>          * Required for serialization support.
> -         *
> +         *
>          * @see java.io.Serializable
>          */
>         private static final long serialVersionUID = 1L;
> @@ -2157,7 +2171,7 @@
>     }
>
>     //----------------------------------------------------------------------------
> -
> +
>     /**
>      * <p><code>ToStringStyle</code> that prints out the short
>      * class name and no identity hashcode.</p>
>
>
>

---------------------------------------------------------------------
To unsubscribe, e-mail: dev-unsubscribe@commons.apache.org
For additional commands, e-mail: dev-help@commons.apache.org