changeset 443:8c667d55b79e

6402254: Revisit ModelMBean DescriptorSupport implementation of equals and hashCode. Reviewed-by: emcmanus
author dfuchs
date Tue, 29 Jul 2008 19:21:59 +0200
parents f2547e64dc3c
children 498c2de672c1
files src/share/classes/com/sun/jmx/mbeanserver/Util.java src/share/classes/javax/management/ImmutableDescriptor.java src/share/classes/javax/management/modelmbean/DescriptorSupport.java
diffstat 3 files changed, 51 insertions(+), 22 deletions(-) [+]
line wrap: on
line diff
--- a/src/share/classes/com/sun/jmx/mbeanserver/Util.java	Mon Jul 28 12:37:52 2008 -0700
+++ b/src/share/classes/com/sun/jmx/mbeanserver/Util.java	Tue Jul 29 19:21:59 2008 +0200
@@ -26,6 +26,7 @@
 package com.sun.jmx.mbeanserver;
 
 import java.util.ArrayList;
+import java.util.Arrays;
 import java.util.Collection;
 import java.util.Collections;
 import java.util.Comparator;
@@ -113,4 +114,32 @@
     public static <T> T cast(Object x) {
         return (T) x;
     }
+
+    /**
+     * Computes a descriptor hashcode from its names and values.
+     * @param names  the sorted array of descriptor names.
+     * @param values the array of descriptor values.
+     * @return a hash code value, as described in {@link #hashCode(Descriptor)}
+     */
+    public static int hashCode(String[] names, Object[] values) {
+        int hash = 0;
+        for (int i = 0; i < names.length; i++) {
+            Object v = values[i];
+            int h;
+            if (v == null) {
+                h = 0;
+            } else if (v instanceof Object[]) {
+                h = Arrays.deepHashCode((Object[]) v);
+            } else if (v.getClass().isArray()) {
+                h = Arrays.deepHashCode(new Object[]{v}) - 31;
+            // hashcode of a list containing just v is
+            // v.hashCode() + 31, see List.hashCode()
+            } else {
+                h = v.hashCode();
+            }
+            hash += names[i].toLowerCase().hashCode() ^ h;
+        }
+        return hash;
+    }
+
 }
--- a/src/share/classes/javax/management/ImmutableDescriptor.java	Mon Jul 28 12:37:52 2008 -0700
+++ b/src/share/classes/javax/management/ImmutableDescriptor.java	Tue Jul 29 19:21:59 2008 +0200
@@ -1,5 +1,5 @@
 /*
- * Copyright 2004-2006 Sun Microsystems, Inc.  All Rights Reserved.
+ * Copyright 2004-2008 Sun Microsystems, Inc.  All Rights Reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
@@ -25,6 +25,7 @@
 
 package javax.management;
 
+import com.sun.jmx.mbeanserver.Util;
 import java.io.InvalidObjectException;
 import java.lang.reflect.Array;
 import java.util.Arrays;
@@ -362,6 +363,7 @@
      */
     // Note: this Javadoc is copied from javax.management.Descriptor
     //       due to 6369229.
+    @Override
     public boolean equals(Object o) {
         if (o == this)
             return true;
@@ -410,29 +412,15 @@
      */
     // Note: this Javadoc is copied from javax.management.Descriptor
     //       due to 6369229.
+    @Override
     public int hashCode() {
         if (hashCode == -1) {
-            int hash = 0;
-            for (int i = 0; i < names.length; i++) {
-                Object v = values[i];
-                int h;
-                if (v == null)
-                    h = 0;
-                else if (v instanceof Object[])
-                    h = Arrays.deepHashCode((Object[]) v);
-                else if (v.getClass().isArray()) {
-                    h = Arrays.deepHashCode(new Object[] {v}) - 31;
-                    // hashcode of a list containing just v is
-                    // v.hashCode() + 31, see List.hashCode()
-                } else
-                    h = v.hashCode();
-                hash += names[i].toLowerCase().hashCode() ^ h;
-            }
-            hashCode = hash;
+            hashCode = Util.hashCode(names, values);
         }
         return hashCode;
     }
 
+    @Override
     public String toString() {
         StringBuilder sb = new StringBuilder("{");
         for (int i = 0; i < names.length; i++) {
@@ -479,6 +467,7 @@
      * If the descriptor construction fails for any reason, this exception will
      * be thrown.
      */
+    @Override
     public Descriptor clone() {
         return this;
     }
--- a/src/share/classes/javax/management/modelmbean/DescriptorSupport.java	Mon Jul 28 12:37:52 2008 -0700
+++ b/src/share/classes/javax/management/modelmbean/DescriptorSupport.java	Tue Jul 29 19:21:59 2008 +0200
@@ -33,6 +33,7 @@
 import static com.sun.jmx.defaults.JmxProperties.MODELMBEAN_LOGGER;
 import static com.sun.jmx.mbeanserver.Util.cast;
 import com.sun.jmx.mbeanserver.GetPropertyAction;
+import com.sun.jmx.mbeanserver.Util;
 
 import java.io.IOException;
 import java.io.ObjectInputStream;
@@ -774,6 +775,7 @@
      * fails for any reason, this exception will be thrown.
      */
 
+    @Override
     public synchronized Object clone() throws RuntimeOperationsException {
         if (MODELMBEAN_LOGGER.isLoggable(Level.FINEST)) {
             MODELMBEAN_LOGGER.logp(Level.FINEST,
@@ -814,13 +816,16 @@
      * otherwise.
      *
      */
-    // XXXX TODO: This is not very efficient!
     // Note: this Javadoc is copied from javax.management.Descriptor
     //       due to 6369229.
+    @Override
     public synchronized boolean equals(Object o) {
         if (o == this)
             return true;
-
+        if (! (o instanceof Descriptor))
+            return false;
+        if (o instanceof ImmutableDescriptor)
+            return o.equals(this);
         return new ImmutableDescriptor(descriptorMap).equals(o);
     }
 
@@ -844,11 +849,16 @@
      * @return A hash code value for this object.
      *
      */
-    // XXXX TODO: This is not very efficient!
     // Note: this Javadoc is copied from javax.management.Descriptor
     //       due to 6369229.
+    @Override
     public synchronized int hashCode() {
-        return new ImmutableDescriptor(descriptorMap).hashCode();
+        final int size = descriptorMap.size();
+        // descriptorMap is sorted with a comparator that ignores cases.
+        //
+        return Util.hashCode(
+                descriptorMap.keySet().toArray(new String[size]),
+                descriptorMap.values().toArray(new Object[size]));
     }
 
     /**
@@ -1278,6 +1288,7 @@
      * field Names or field Values.  If the descriptor string fails
      * for any reason, this exception will be thrown.
      */
+    @Override
     public synchronized String toString() {
         if (MODELMBEAN_LOGGER.isLoggable(Level.FINEST)) {
             MODELMBEAN_LOGGER.logp(Level.FINEST,