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]