Author: ceki Date: Thu Jun 5 22:53:19 2008 New Revision: 1049 Added: slf4j/trunk/slf4j-api/src/test/java/org/slf4j/Differentiator.java Modified: slf4j/trunk/slf4j-api/src/main/java/org/slf4j/IMarkerFactory.java slf4j/trunk/slf4j-api/src/main/java/org/slf4j/Marker.java slf4j/trunk/slf4j-api/src/main/java/org/slf4j/MarkerFactory.java slf4j/trunk/slf4j-api/src/main/java/org/slf4j/helpers/BasicMarker.java slf4j/trunk/slf4j-api/src/main/java/org/slf4j/helpers/BasicMarkerFactory.java slf4j/trunk/slf4j-api/src/test/java/org/slf4j/BasicMarkerTest.java slf4j/trunk/slf4j-site/src/site/pages/compatibility.html slf4j/trunk/slf4j-site/src/site/pages/news.html
Log: - fixed bug 74, an endless recursion problem in Marker.contains method also added getDetachedMarker method to IMarkerFactory and MarkerFactory classes updated compatibility.html, news.html accordingly Modified: slf4j/trunk/slf4j-api/src/main/java/org/slf4j/IMarkerFactory.java ============================================================================== --- slf4j/trunk/slf4j-api/src/main/java/org/slf4j/IMarkerFactory.java (original) +++ slf4j/trunk/slf4j-api/src/main/java/org/slf4j/IMarkerFactory.java Thu Jun 5 22:53:19 2008 @@ -69,4 +69,13 @@ * @return whether the marker could be detached or not */ boolean detachMarker(String name); + + + /** + * Create a marker which is detached (even at birth) from this IMarkerFactory. + * + * @return a dangling marker + * @since 1.5.1 + */ + Marker getDetachedMarker(String name); } Modified: slf4j/trunk/slf4j-api/src/main/java/org/slf4j/Marker.java ============================================================================== --- slf4j/trunk/slf4j-api/src/main/java/org/slf4j/Marker.java (original) +++ slf4j/trunk/slf4j-api/src/main/java/org/slf4j/Marker.java Thu Jun 5 22:53:19 2008 @@ -1,5 +1,5 @@ /* - * Copyright (c) 2004-2007 QOS.ch + * Copyright (c) 2004-2008 QOS.ch * All rights reserved. * * Permission is hereby granted, free of charge, to any person obtaining @@ -28,85 +28,108 @@ import java.util.Iterator; /** - * Markers are named objects used to enrich log statements. Conforming - * logging system Implementations of SLF4J determine how information - * conveyed by markers are used, if at all. In particular, many - * conforming logging systems ignore marker data. + * Markers are named objects used to enrich log statements. Conforming logging + * system Implementations of SLF4J determine how information conveyed by markers + * are used, if at all. In particular, many conforming logging systems ignore + * marker data. + * + * <p> + * Markers can contain child markers, which in turn can contain children of + * their own. * - * <p>Markers can contain child markers, which in turn can contain children - * of their own. - * * @author Ceki Gülcü */ public interface Marker extends Serializable { - + /** * This constant represents any marker, including a null marker. */ - public static final String ANY_MARKER = "*"; - + public final String ANY_MARKER = "*"; + /** * This constant represents any non-null marker. */ - public static final String ANY_NON_NULL_MARKER = "+"; - - + public final String ANY_NON_NULL_MARKER = "+"; + /** * Get the name of this Marker. + * * @return name of marker - */ + */ public String getName(); /** * Add a child Marker to this Marker. - * @param child a child marker + * + * @param child + * a child marker */ public void add(Marker child); - + /** * Remove a child Marker. - * @param child the child Marker to remove + * + * @param child + * the child Marker to remove * @return true if child could be found and removed, false otherwise. */ public boolean remove(Marker child); - + /** * Does this marker have children? + * * @return true if this marker has children, false otherwise. */ public boolean hasChildren(); - + /** - * Returns an Iterator which can be used to iterate over the - * children of this marker. An empty iterator is returned when this - * marker has no children. + * Returns an Iterator which can be used to iterate over the children of this + * marker. An empty iterator is returned when this marker has no children. * * @return Iterator over the children of this marker */ public Iterator iterator(); - + /** - * Does this marker contain the 'other' marker? Marker A is defined to - * contain marker B, if A == B or if B is a child of A. + * Does this marker contain the 'other' marker? Marker A is defined to contain + * marker B, if A == B or if B is a child of A. * - * @param other The marker to test for inclusion. - * @throws IllegalArgumentException if 'other' is null + * @param other + * The marker to test for inclusion. + * @throws IllegalArgumentException + * if 'other' is null * @return Whether this marker contains the other marker. */ public boolean contains(Marker other); - - /** - * Does this marker contain the marker named 'name'? + * Does this marker contain the marker named 'name'? * * If 'name' is null the returned value is always false. * - * @param other The marker to test for inclusion. + * @param other + * The marker to test for inclusion. * @return Whether this marker contains the other marker. */ public boolean contains(String name); - -// void makeImmutable(); -// public boolean isImmutable(); + + /** + * Markers are considered equal if they have the same name. + * + * @param o + * @return true, if this.name equals o.name + * + * @since 1.5.1 + */ + public boolean equals(Object o); + + /** + * Compute the hash code based on the name of this marker. + * Note that markers are considered equal if they have the same name. + * + * @return the computed hashCode + * @since 1.5.1 + */ + public int hashCode(); + } Modified: slf4j/trunk/slf4j-api/src/main/java/org/slf4j/MarkerFactory.java ============================================================================== --- slf4j/trunk/slf4j-api/src/main/java/org/slf4j/MarkerFactory.java (original) +++ slf4j/trunk/slf4j-api/src/main/java/org/slf4j/MarkerFactory.java Thu Jun 5 22:53:19 2008 @@ -69,6 +69,16 @@ } /** + * Create a marker which is detached (even at birth) from the MarkerFactory. + * + * @return a dangling marker + * @since 1.5.1 + */ + public static Marker getDetachedMarker(String name) { + return markerFactory.getDetachedMarker(name); + } + + /** * Return the [EMAIL PROTECTED] IMarkerFactory}instance in use. * * <p>The IMarkerFactory instance is usually bound with this class at Modified: slf4j/trunk/slf4j-api/src/main/java/org/slf4j/helpers/BasicMarker.java ============================================================================== --- slf4j/trunk/slf4j-api/src/main/java/org/slf4j/helpers/BasicMarker.java (original) +++ slf4j/trunk/slf4j-api/src/main/java/org/slf4j/helpers/BasicMarker.java Thu Jun 5 22:53:19 2008 @@ -1,5 +1,5 @@ /* - * Copyright (c) 2004-2007 QOS.ch + * Copyright (c) 2004-2008 QOS.ch * All rights reserved. * * Permission is hereby granted, free of charge, to any person obtaining @@ -49,10 +49,13 @@ private static final long serialVersionUID = 1803952589649545191L; - final String name; - List children; + private final String name; + private List children; BasicMarker(String name) { + if (name == null) { + throw new IllegalArgumentException("A merker name cannot be null"); + } this.name = name; } @@ -60,21 +63,25 @@ return name; } - public synchronized void add(Marker child) { - if (child == null) { - throw new NullPointerException( - "Null children cannot be added to a Marker."); - } - if (children == null) { - children = new Vector(); + public synchronized void add(Marker markerToAddAsChild) { + if (markerToAddAsChild == null) { + throw new IllegalArgumentException( + "A null value cannot be added to a Marker as child."); } // no point in adding the child multiple times - if (children.contains(child)) { + if (this.contains(markerToAddAsChild)) { + return; + + } else if (markerToAddAsChild.contains(this)) { // avoid recursion + // a potential child should not its future parent as a child return; } else { - // add the child - children.add(child); + // let's add the child + if (children == null) { + children = new Vector(); + } + children.add(markerToAddAsChild); } } @@ -155,12 +162,27 @@ private static String CLOSE = " ]"; private static String SEP = ", "; - public String toString() { + public boolean equals(Object obj) { + if (this == obj) + return true; + if (obj == null) + return false; + if (!(obj instanceof Marker)) + return false; + + final Marker other = (Marker) obj; + return name.equals(other.getName()); + } + + public int hashCode() { + return name.hashCode(); + } + + public String toString() { if (!this.hasChildren()) { return this.getName(); } - Iterator it = this.iterator(); Marker child; StringBuffer sb = new StringBuffer(this.getName()); Modified: slf4j/trunk/slf4j-api/src/main/java/org/slf4j/helpers/BasicMarkerFactory.java ============================================================================== --- slf4j/trunk/slf4j-api/src/main/java/org/slf4j/helpers/BasicMarkerFactory.java (original) +++ slf4j/trunk/slf4j-api/src/main/java/org/slf4j/helpers/BasicMarkerFactory.java Thu Jun 5 22:53:19 2008 @@ -88,5 +88,12 @@ } return (markerMap.remove(name) != null); } + + + public Marker getDetachedMarker(String name) { + return new BasicMarker(name); + } + + } Modified: slf4j/trunk/slf4j-api/src/test/java/org/slf4j/BasicMarkerTest.java ============================================================================== --- slf4j/trunk/slf4j-api/src/test/java/org/slf4j/BasicMarkerTest.java (original) +++ slf4j/trunk/slf4j-api/src/test/java/org/slf4j/BasicMarkerTest.java Thu Jun 5 22:53:19 2008 @@ -1,35 +1,27 @@ /* - * Copyright (c) 2004-2005 SLF4J.ORG - * Copyright (c) 2004-2005 QOS.ch - * + * Copyright (c) 2004-2008 QOS.ch * All rights reserved. - * - * Permission is hereby granted, free of charge, to any person obtaining - * a copy of this software and associated documentation files (the + * + * Permission is hereby granted, free of charge, to any person obtaining + * a copy of this software and associated documentation files (the * "Software"), to deal in the Software without restriction, including * without limitation the rights to use, copy, modify, merge, publish, - * distribute, and/or sell copies of the Software, and to permit persons - * to whom the Software is furnished to do so, provided that the above - * copyright notice(s) and this permission notice appear in all copies of - * the Software and that both the above copyright notice(s) and this - * permission notice appear in supporting documentation. - * + * distribute, sublicense, and/or sell copies of the Software, and to + * permit persons to whom the Software is furnished to do so, subject to + * the following conditions: + * + * The above copyright notice and this permission notice shall be + * included in all copies or substantial portions of the Software. + * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF - * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT - * OF THIRD PARTY RIGHTS. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR - * HOLDERS INCLUDED IN THIS NOTICE BE LIABLE FOR ANY CLAIM, OR ANY - * SPECIAL INDIRECT OR CONSEQUENTIAL DAMAGES, OR ANY DAMAGES WHATSOEVER - * RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF - * CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN - * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. - * - * Except as contained in this notice, the name of a copyright holder - * shall not be used in advertising or otherwise to promote the sale, use - * or other dealings in this Software without prior written authorization - * of the copyright holder. - * + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND + * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE + * LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION + * OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION + * WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ + package org.slf4j; import java.util.Iterator; @@ -52,7 +44,8 @@ static final String MULTI_COMP_STR = "MULTI_COMP"; static final String PARENT_MARKER_STR = "PARENT_MARKER"; static final String CHILD_MARKER_STR = "CHILD_MARKER"; - + static final String NOT_CONTAINED_MARKER_STR = "NOT_CONTAINED"; + final IMarkerFactory factory; final Marker blue; final Marker red; @@ -60,6 +53,8 @@ final Marker comp; final Marker multiComp; + short diff = Differentiator.getDiffentiator(); + public BasicMarkerTest() { factory = new BasicMarkerFactory(); @@ -119,7 +114,7 @@ for (int i = 0; i < 10; i++) { parent.add(child); } - + // check that the child was added once and only once Iterator iterator = parent.iterator(); assertTrue(iterator.hasNext()); @@ -147,4 +142,37 @@ assertFalse(parent.remove(child)); } + public void testSelfRecursion() { + final String diffPrefix = "NEW_"+diff; + final String PARENT_NAME = diffPrefix + PARENT_MARKER_STR; + final String NOT_CONTAINED_NAME = diffPrefix + NOT_CONTAINED_MARKER_STR; + Marker parent = factory.getMarker(PARENT_NAME); + Marker notContained = factory.getMarker(NOT_CONTAINED_NAME); + parent.add(parent); + assertTrue(parent.contains(parent)); + assertTrue(parent.contains(PARENT_NAME)); + assertFalse(parent.contains(notContained)); + assertFalse(parent.contains(NOT_CONTAINED_MARKER_STR)); + } + + public void testIndirectRecursion() { + final String diffPrefix = "NEW_"+diff; + final String PARENT_NAME=diffPrefix+PARENT_MARKER_STR; + final String CHILD_NAME=diffPrefix+CHILD_MARKER_STR; + final String NOT_CONTAINED_NAME=diffPrefix+NOT_CONTAINED_MARKER_STR; + + Marker parent = factory.getMarker(PARENT_NAME); + Marker child = factory.getMarker(CHILD_NAME); + Marker notContained = factory.getMarker(NOT_CONTAINED_NAME); + + parent.add(child); + child.add(parent); + assertTrue(parent.contains(parent)); + assertTrue(parent.contains(child)); + assertTrue(parent.contains(PARENT_NAME)); + assertTrue(parent.contains(CHILD_NAME)); + assertFalse(parent.contains(notContained)); + assertFalse(parent.contains(NOT_CONTAINED_MARKER_STR)); + } + } Added: slf4j/trunk/slf4j-api/src/test/java/org/slf4j/Differentiator.java ============================================================================== --- (empty file) +++ slf4j/trunk/slf4j-api/src/test/java/org/slf4j/Differentiator.java Thu Jun 5 22:53:19 2008 @@ -0,0 +1,37 @@ +/* + * Copyright (c) 2004-2008 QOS.ch + * All rights reserved. + * + * Permission is hereby granted, free of charge, to any person obtaining + * a copy of this software and associated documentation files (the + * "Software"), to deal in the Software without restriction, including + * without limitation the rights to use, copy, modify, merge, publish, + * distribute, sublicense, and/or sell copies of the Software, and to + * permit persons to whom the Software is furnished to do so, subject to + * the following conditions: + * + * The above copyright notice and this permission notice shall be + * included in all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, + * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND + * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE + * LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION + * OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION + * WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + */ + + +package org.slf4j; + +import java.util.Random; + +public class Differentiator { + + static Random random = new Random(System.currentTimeMillis()); + + static public short getDiffentiator() { + return (short) random.nextInt(Short.MAX_VALUE); + } +} Modified: slf4j/trunk/slf4j-site/src/site/pages/compatibility.html ============================================================================== --- slf4j/trunk/slf4j-site/src/site/pages/compatibility.html (original) +++ slf4j/trunk/slf4j-site/src/site/pages/compatibility.html Thu Jun 5 22:53:19 2008 @@ -66,8 +66,35 @@ <td>org.slf4j.spi.MDCAdapter</td> <td>public void setContextMap(java.util.Map)</td> </tr> - </table> + <tr> + <td>Error</td> + <td>Method 'getDetachedMarker(String)' has been added to an + interface + </td> + <td>org.slf4j.IMarkerFactory</td> + <td>public org.slf4j.Marker getDetachedMarker(java.lang.String)</td> + </tr> + + <tr class="alt"> + <td>Info</td> + <td>Method 'equals(Object)' has been added to an + interface + </td> + <td>org.slf4j.Marker</td> + <td>public boolean equals(java.lang.Object)</td> + </tr> + + <tr> + <td>info</td> + <td>Method 'hashCode()' has been added to an + interface + </td> + <td>org.slf4j.Marker</td> + <td>public int hashCode()</td> + </tr> + + </table> <p>The addition of the <code>getCopyOfContextMap()</code> method in the <code>MDCAdapter</code> class should only impact users who have @@ -88,6 +115,18 @@ <p>Similar reasoning applies to the <code>setContextMap(Map)</code> method.</p> + <p>The addition of <code>getDetachedMarker(String)</code> method in + the <code>org.slf4j.IMarkerFactory</code> should not impact users as + the only (known) implementation of this interface ships with SLF4J + itself. + </p> + + <p>The <code>equals()</code> and <code>hashCode()</code> methods + were added to the <code>org.slf4j.Marker</code> interface for + documentation purposes. Given that all objects implicitly implement + these methods, their addition should theoretically not break + existing code. </p> + <h3>Other modules</h3> Modified: slf4j/trunk/slf4j-site/src/site/pages/news.html ============================================================================== --- slf4j/trunk/slf4j-site/src/site/pages/news.html (original) +++ slf4j/trunk/slf4j-site/src/site/pages/news.html Thu Jun 5 22:53:19 2008 @@ -44,6 +44,10 @@ href="http://bugzilla.slf4j.org/show_bug.cgi?id=85">bug 85</a> as reported by Niklas Gustavsson. </p> + + <p>The <em>slf4j-jcl</em> binding now depends on commons-logging + version 1.1.1 instead of the older 1.0.4</p> + <p>Added a java.util.logging to SLF4J bridge as requested in <a href="http://bugzilla.slf4j.org/show_bug.cgi?id=38">bug 38</a> by @@ -76,11 +80,19 @@ Anton Tagunov. </p> + <p>Fixed <a href="http://bugzilla.slf4j.org/show_bug.cgi?id=74">bug + 74</a>, an endless recursion problem in Marker.contains method, + reported by Michael Newcomb. Also added he + <code>getDetachedMarker</code> method to <code>IMarkerFactor</code> + and <code>MarkerFactory</code> classes which was indirectly + requested in bug 74. + </p> + <p>Added the methods <code>getLevel()</code> and <code>getEffectiveLevel()</code> to the <code>Category</code> class - in log4j-over-slf4j. This addition was requested in <a - href="http://bugzilla.slf4j.org/show_bug.cgi?id=74">bug 74</a> by - Michael Newcomb. + in log4j-over-slf4j. + +This addition was requested indirectly in </p> <p>The <a href="migrator.html">SLF4J Migrator</a> _______________________________________________ dev mailing list dev@slf4j.org http://www.slf4j.org/mailman/listinfo/dev