Author: olegk
Date: Mon Mar 14 12:23:16 2005
New Revision: 157457

URL: http://svn.apache.org/viewcvs?view=rev&rev=157457
Log:
PR #33988 (Cookie.java hashCode method violates contract)

Changelog:

All classes implementing Object#hashCode & Object#equals methods have been 
reviewed regarding their hashCode/equals contract compliance

Contributed by Oleg Kalnichevski
Reviewed by Michael Becke

Added:
    
jakarta/commons/proper/httpclient/trunk/src/java/org/apache/commons/httpclient/util/LangUtils.java
   (with props)
Modified:
    
jakarta/commons/proper/httpclient/trunk/src/java/org/apache/commons/httpclient/Cookie.java
    
jakarta/commons/proper/httpclient/trunk/src/java/org/apache/commons/httpclient/HostConfiguration.java
    
jakarta/commons/proper/httpclient/trunk/src/java/org/apache/commons/httpclient/HttpHost.java
    
jakarta/commons/proper/httpclient/trunk/src/java/org/apache/commons/httpclient/NameValuePair.java
    
jakarta/commons/proper/httpclient/trunk/src/java/org/apache/commons/httpclient/auth/AuthScope.java
    
jakarta/commons/proper/httpclient/trunk/src/java/org/apache/commons/httpclient/protocol/Protocol.java
    
jakarta/commons/proper/httpclient/trunk/src/test/org/apache/commons/httpclient/TestNVP.java

Modified: 
jakarta/commons/proper/httpclient/trunk/src/java/org/apache/commons/httpclient/Cookie.java
URL: 
http://svn.apache.org/viewcvs/jakarta/commons/proper/httpclient/trunk/src/java/org/apache/commons/httpclient/Cookie.java?view=diff&r1=157456&r2=157457
==============================================================================
--- 
jakarta/commons/proper/httpclient/trunk/src/java/org/apache/commons/httpclient/Cookie.java
 (original)
+++ 
jakarta/commons/proper/httpclient/trunk/src/java/org/apache/commons/httpclient/Cookie.java
 Mon Mar 14 12:23:16 2005
@@ -37,6 +37,7 @@
 
 import org.apache.commons.httpclient.cookie.CookiePolicy;
 import org.apache.commons.httpclient.cookie.CookieSpec;
+import org.apache.commons.httpclient.util.LangUtils;
 import org.apache.commons.logging.Log;
 import org.apache.commons.logging.LogFactory;
 
@@ -400,9 +401,11 @@
      * @return A hash code
      */
     public int hashCode() {
-        return super.hashCode()
-            ^ (null == cookiePath ? 0 : cookiePath.hashCode())
-            ^ (null == cookieDomain ? 0 : cookieDomain.hashCode());
+        int hash = LangUtils.HASH_SEED;
+        hash = LangUtils.hashCode(hash, this.getName());
+        hash = LangUtils.hashCode(hash, this.cookieDomain);
+        hash = LangUtils.hashCode(hash, this.cookiePath);
+        return hash;
     }
 
 
@@ -412,20 +415,13 @@
      * @return true if the two objects are equal.
      */
     public boolean equals(Object obj) {
-        LOG.trace("enter Cookie.equals(Object)");
-        
-        if ((obj != null) && (obj instanceof Cookie)) {
+        if (obj == null) return false;
+        if (this == obj) return true;
+        if (obj instanceof Cookie) {
             Cookie that = (Cookie) obj;
-            return 
-                (null == this.getName() 
-                    ? null == that.getName() 
-                    : this.getName().equals(that.getName())) 
-                && (null == this.getPath() 
-                    ? null == that.getPath() 
-                    : this.getPath().equals(that.getPath())) 
-                && (null == this.getDomain() 
-                    ? null == that.getDomain() 
-                    : this.getDomain().equals(that.getDomain()));
+            return LangUtils.equals(this.getName(), that.getName())
+                  && LangUtils.equals(this.cookieDomain, that.cookieDomain)
+                  && LangUtils.equals(this.cookiePath, that.cookiePath);
         } else {
             return false;
         }

Modified: 
jakarta/commons/proper/httpclient/trunk/src/java/org/apache/commons/httpclient/HostConfiguration.java
URL: 
http://svn.apache.org/viewcvs/jakarta/commons/proper/httpclient/trunk/src/java/org/apache/commons/httpclient/HostConfiguration.java?view=diff&r1=157456&r2=157457
==============================================================================
--- 
jakarta/commons/proper/httpclient/trunk/src/java/org/apache/commons/httpclient/HostConfiguration.java
 (original)
+++ 
jakarta/commons/proper/httpclient/trunk/src/java/org/apache/commons/httpclient/HostConfiguration.java
 Mon Mar 14 12:23:16 2005
@@ -31,6 +31,7 @@
 
 import org.apache.commons.httpclient.params.HostParams;
 import org.apache.commons.httpclient.protocol.Protocol;
+import org.apache.commons.httpclient.util.LangUtils;
 
 import java.net.InetAddress;
 
@@ -533,13 +534,10 @@
      * @see java.lang.Object#hashCode()
      */
     public int hashCode() {
-        if (host != null) {
-            return host.hashCode();
-        } else if (proxyHost != null) {
-            return proxyHost.hashCode();   
-        } else {
-            return super.hashCode();
-        }
+        int hash = LangUtils.HASH_SEED;
+        hash = LangUtils.hashCode(hash, this.host);
+        hash = LangUtils.hashCode(hash, this.proxyHost);
+        return hash;
     }
 
 }

Modified: 
jakarta/commons/proper/httpclient/trunk/src/java/org/apache/commons/httpclient/HttpHost.java
URL: 
http://svn.apache.org/viewcvs/jakarta/commons/proper/httpclient/trunk/src/java/org/apache/commons/httpclient/HttpHost.java?view=diff&r1=157456&r2=157457
==============================================================================
--- 
jakarta/commons/proper/httpclient/trunk/src/java/org/apache/commons/httpclient/HttpHost.java
 (original)
+++ 
jakarta/commons/proper/httpclient/trunk/src/java/org/apache/commons/httpclient/HttpHost.java
 Mon Mar 14 12:23:16 2005
@@ -30,6 +30,7 @@
 package org.apache.commons.httpclient;
 
 import org.apache.commons.httpclient.protocol.Protocol;
+import org.apache.commons.httpclient.util.LangUtils;
 
 /**
  * Holds all of the variables needed to describe an HTTP connection to a host. 
This includes 
@@ -209,10 +210,11 @@
      * @see java.lang.Object#hashCode()
      */
     public int hashCode() {
-        return 
-            this.hostname.hashCode() + 
-                       this.port + 
-            this.protocol.hashCode();
+        int hash = LangUtils.HASH_SEED;
+        hash = LangUtils.hashCode(hash, this.hostname);
+        hash = LangUtils.hashCode(hash, this.port);
+        hash = LangUtils.hashCode(hash, this.protocol);
+        return hash;
     }
 
 }

Modified: 
jakarta/commons/proper/httpclient/trunk/src/java/org/apache/commons/httpclient/NameValuePair.java
URL: 
http://svn.apache.org/viewcvs/jakarta/commons/proper/httpclient/trunk/src/java/org/apache/commons/httpclient/NameValuePair.java?view=diff&r1=157456&r2=157457
==============================================================================
--- 
jakarta/commons/proper/httpclient/trunk/src/java/org/apache/commons/httpclient/NameValuePair.java
 (original)
+++ 
jakarta/commons/proper/httpclient/trunk/src/java/org/apache/commons/httpclient/NameValuePair.java
 Mon Mar 14 12:23:16 2005
@@ -31,6 +31,8 @@
 
 import java.io.Serializable;
 
+import org.apache.commons.httpclient.util.LangUtils;
+
 /**
  * <p>A simple class encapsulating a name/value pair.</p>
  * 
@@ -128,46 +130,22 @@
         return ("name=" + name + ", " + "value=" + value);
     }
 
-    /**
-     * Test if the given <i>object</i> is equal to me. <tt>NameValuePair</tt>s
-     * are equals if both their <tt>name</tt> and <tt>value</tt> fields are 
equal.
-     * If <tt>object</tt> is <tt>null</tt> this method returns <tt>false</tt>.
-     *
-     * @param object the [EMAIL PROTECTED] Object} to compare to or 
<tt>null</tt>
-     * @return true if the objects are equal.
-     */
-    public boolean equals(Object object) {
+    public boolean equals(final Object object) {
         if (object == null) return false;
         if (this == object) return true;
-        if (!(object instanceof NameValuePair)) return false;
-        
-        NameValuePair pair = (NameValuePair) object;
-        return ((null == name ? null == pair.name : name.equals(pair.name))
-              && (null == value ? null == pair.value : 
value.equals(pair.value)));
+        if (object instanceof NameValuePair) {
+            NameValuePair that = (NameValuePair) object;
+            return LangUtils.equals(this.name, that.name)
+                  && LangUtils.equals(this.value, that.value);
+        } else {
+            return false;
+        }
     }
 
-    /**
-     * hashCode. Returns a hash code for this object such that if <tt>[EMAIL 
PROTECTED]
-     * #equals equals}(b)</tt> then <tt>a.hashCode() == b.hashCode()</tt>.
-     * @return The hash code.
-     */
     public int hashCode() {
-        return (this.getClass().hashCode() 
-            ^ (null == name ? 0 : name.hashCode()) 
-            ^ (null == value ? 0 : value.hashCode()));
-    }
-
-    /*
-    public Object clone() {
-        try {
-            NameValuePair that = (NameValuePair)(super.clone());
-            that.setName(this.getName());
-            that.setValue(this.getValue());
-            return that;
-        } catch(CloneNotSupportedException e) {
-            // this should never happen
-            throw new RuntimeException("Panic. super.clone not supported in 
NameValuePair.");
-        }
+        int hash = LangUtils.HASH_SEED;
+        hash = LangUtils.hashCode(hash, this.name);
+        hash = LangUtils.hashCode(hash, this.value);
+        return hash;
     }
-    */
 }

Modified: 
jakarta/commons/proper/httpclient/trunk/src/java/org/apache/commons/httpclient/auth/AuthScope.java
URL: 
http://svn.apache.org/viewcvs/jakarta/commons/proper/httpclient/trunk/src/java/org/apache/commons/httpclient/auth/AuthScope.java?view=diff&r1=157456&r2=157457
==============================================================================
--- 
jakarta/commons/proper/httpclient/trunk/src/java/org/apache/commons/httpclient/auth/AuthScope.java
 (original)
+++ 
jakarta/commons/proper/httpclient/trunk/src/java/org/apache/commons/httpclient/auth/AuthScope.java
 Mon Mar 14 12:23:16 2005
@@ -29,6 +29,8 @@
 
 package org.apache.commons.httpclient.auth;
 
+import org.apache.commons.httpclient.util.LangUtils;
+
 /** 
  * The class represents an authentication scope consisting of a host name,
  * a port number, a realm name and an authentication scheme name which 
@@ -316,9 +318,11 @@
      * @see java.lang.Object#hashCode()
      */
     public int hashCode() {
-        return ((this.host != null) ? this.host.toLowerCase().hashCode() : 0) 
+ 
-               ((this.port >= 0) ? this.port : -1) +
-               ((this.realm != null) ? this.realm.hashCode() : 0) +
-               ((this.scheme != null) ? this.scheme.toLowerCase().hashCode() : 
0);
+        int hash = LangUtils.HASH_SEED;
+        hash = LangUtils.hashCode(hash, this.host);
+        hash = LangUtils.hashCode(hash, this.port);
+        hash = LangUtils.hashCode(hash, this.realm);
+        hash = LangUtils.hashCode(hash, this.scheme);
+        return hash;
     }
 }

Modified: 
jakarta/commons/proper/httpclient/trunk/src/java/org/apache/commons/httpclient/protocol/Protocol.java
URL: 
http://svn.apache.org/viewcvs/jakarta/commons/proper/httpclient/trunk/src/java/org/apache/commons/httpclient/protocol/Protocol.java?view=diff&r1=157456&r2=157457
==============================================================================
--- 
jakarta/commons/proper/httpclient/trunk/src/java/org/apache/commons/httpclient/protocol/Protocol.java
 (original)
+++ 
jakarta/commons/proper/httpclient/trunk/src/java/org/apache/commons/httpclient/protocol/Protocol.java
 Mon Mar 14 12:23:16 2005
@@ -32,6 +32,8 @@
 import java.util.HashMap;
 import java.util.Map;
 
+import org.apache.commons.httpclient.util.LangUtils;
+
 /**
  * A class to encapsulate the specifics of a protocol.  This class class also
  * provides the ability to customize the set and characteristics of the
@@ -283,6 +285,11 @@
      * @return The hash code.
      */
     public int hashCode() {
-        return scheme.hashCode();
+        int hash = LangUtils.HASH_SEED;
+        hash = LangUtils.hashCode(hash, this.defaultPort);
+        hash = LangUtils.hashCode(hash, this.scheme.toLowerCase());
+        hash = LangUtils.hashCode(hash, this.secure);
+        hash = LangUtils.hashCode(hash, this.socketFactory);
+        return hash;
     }
 }

Added: 
jakarta/commons/proper/httpclient/trunk/src/java/org/apache/commons/httpclient/util/LangUtils.java
URL: 
http://svn.apache.org/viewcvs/jakarta/commons/proper/httpclient/trunk/src/java/org/apache/commons/httpclient/util/LangUtils.java?view=auto&rev=157457
==============================================================================
--- 
jakarta/commons/proper/httpclient/trunk/src/java/org/apache/commons/httpclient/util/LangUtils.java
 (added)
+++ 
jakarta/commons/proper/httpclient/trunk/src/java/org/apache/commons/httpclient/util/LangUtils.java
 Mon Mar 14 12:23:16 2005
@@ -0,0 +1,65 @@
+/*
+ * $HeadURL$
+ * $Revision$
+ * $Date$
+ *
+ * ====================================================================
+ *
+ *  Copyright 1999-2004 The Apache Software Foundation
+ *
+ *  Licensed 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.
+ *  See the License for the specific language governing permissions and
+ *  limitations under the License.
+ * ====================================================================
+ *
+ * This software consists of voluntary contributions made by many
+ * individuals on behalf of the Apache Software Foundation.  For more
+ * information on the Apache Software Foundation, please see
+ * <http://www.apache.org/>.
+ *
+ */
+
+package org.apache.commons.httpclient.util;
+
+/**
+ * A set of utility methods to help produce consistent Object#equals(Object) 
and
+ * Object#hashCode methods.
+ *  
+ * @author <a href="mailto:oleg at ural.ru">Oleg Kalnichevski</a>
+ * 
+ * @since 3.0
+ */
+public class LangUtils {
+    
+    public static int HASH_SEED = 17;
+    public static int HASH_OFFSET = 37;
+    
+    private LangUtils() {
+        super();
+    }
+
+    public static int hashCode(final int seed, final int hashcode) {
+        return seed * HASH_OFFSET + hashcode;
+    }
+
+    public static int hashCode(final int seed, final Object obj) {
+        return hashCode(seed, obj != null ? obj.hashCode() : 0);
+    }
+    
+    public static int hashCode(final int seed, final boolean b) {
+        return hashCode(seed, b ? 1 : 0);
+    }
+    
+    public static boolean equals(final Object obj1, final Object obj2) {
+        return obj1 == null ? obj2 == null : obj1.equals(obj2);
+    }
+
+}

Propchange: 
jakarta/commons/proper/httpclient/trunk/src/java/org/apache/commons/httpclient/util/LangUtils.java
------------------------------------------------------------------------------
    svn:eol-style = native

Propchange: 
jakarta/commons/proper/httpclient/trunk/src/java/org/apache/commons/httpclient/util/LangUtils.java
------------------------------------------------------------------------------
    svn:keywords = Date Author Id Revision HeadURL

Propchange: 
jakarta/commons/proper/httpclient/trunk/src/java/org/apache/commons/httpclient/util/LangUtils.java
------------------------------------------------------------------------------
    svn:mime-type = text/plain

Modified: 
jakarta/commons/proper/httpclient/trunk/src/test/org/apache/commons/httpclient/TestNVP.java
URL: 
http://svn.apache.org/viewcvs/jakarta/commons/proper/httpclient/trunk/src/test/org/apache/commons/httpclient/TestNVP.java?view=diff&r1=157456&r2=157457
==============================================================================
--- 
jakarta/commons/proper/httpclient/trunk/src/test/org/apache/commons/httpclient/TestNVP.java
 (original)
+++ 
jakarta/commons/proper/httpclient/trunk/src/test/org/apache/commons/httpclient/TestNVP.java
 Mon Mar 14 12:23:16 2005
@@ -24,8 +24,6 @@
  * information on the Apache Software Foundation, please see
  * <http://www.apache.org/>.
  *
- * [Additional notices, if required by prior licensing conditions]
- *
  */
 
 package org.apache.commons.httpclient;
@@ -86,44 +84,24 @@
         assertEquals("value",pair.getValue());
     }
 
-    public void testEqualsAndHashCode() {
-        NameValuePair pair1 = makePair();
-        NameValuePair pair2 = makePair();
-
-        assertEquals(pair1,pair1);
-        assertEquals(pair1.hashCode(),pair1.hashCode());
-        assertEquals(pair2,pair2);
-        assertEquals(pair2.hashCode(),pair2.hashCode());
-        assertEquals(pair1,pair2);
-        assertEquals(pair1.hashCode(),pair2.hashCode());
-        assertEquals(pair2,pair1);
-
-        pair1.setName("name");
-        pair1.setValue("value");
-
-        assertEquals(pair1,pair1);
-        assertEquals(pair1.hashCode(),pair1.hashCode());
-        assertTrue(!pair1.equals(pair2));
-        assertTrue(!pair2.equals(pair1));
-
-        pair2.setName("name");
-
-        assertEquals(pair1,pair1);
-        assertEquals(pair1.hashCode(),pair1.hashCode());
-        assertEquals(pair2,pair2);
-        assertEquals(pair2.hashCode(),pair2.hashCode());
-        assertTrue(!pair1.equals(pair2));
-        assertTrue(!pair2.equals(pair1));
-
-
-        pair2.setValue("value");
-
-        assertEquals(pair1,pair1);
-        assertEquals(pair1.hashCode(),pair1.hashCode());
-        assertEquals(pair2,pair2);
-        assertEquals(pair2.hashCode(),pair2.hashCode());
-        assertEquals(pair1,pair2);
-        assertEquals(pair1.hashCode(),pair2.hashCode());
-        assertEquals(pair2,pair1);
+    public void testHashCode() {
+        NameValuePair param1 = new NameValuePair("name1", "value1");
+        NameValuePair param2 = new NameValuePair("name2", "value2");
+        NameValuePair param3 = new NameValuePair("name1", "value1");
+        assertTrue(param1.hashCode() != param2.hashCode());
+        assertTrue(param1.hashCode() == param3.hashCode());
+    }
+    
+    public void testEquals() {
+        NameValuePair param1 = new NameValuePair("name1", "value1");
+        NameValuePair param2 = new NameValuePair("name2", "value2");
+        NameValuePair param3 = new NameValuePair("name1", "value1");
+        assertFalse(param1.equals(param2));
+        assertFalse(param1.equals(null));
+        assertFalse(param1.equals("name1 = value1"));
+        assertTrue(param1.equals(param1));
+        assertTrue(param2.equals(param2));
+        assertTrue(param1.equals(param3));
     }
+    
 }



---------------------------------------------------------------------
To unsubscribe, e-mail: [EMAIL PROTECTED]
For additional commands, e-mail: [EMAIL PROTECTED]

Reply via email to