feat(jdk8): move files to new folder to avoid resources compiled.

This commit is contained in:
2025-09-07 15:25:52 +08:00
parent 3f0047bf6f
commit 8c35cfb1c0
17415 changed files with 217 additions and 213 deletions

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,174 @@
/*
* Copyright (c) 2000, 2007, Oracle and/or its affiliates. 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
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation. Oracle designates this
* particular file as subject to the "Classpath" exception as provided
* by Oracle in the LICENSE file that accompanied this code.
*
* This code is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
*
* You should have received a copy of the GNU General Public License version
* 2 along with this work; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
*
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
*/
package javax.management.openmbean;
// java import
//
import java.util.Collection;
// jmx import
//
/**
* The <tt>CompositeData</tt> interface specifies the behavior of a specific type of complex <i>open data</i> objects
* which represent <i>composite data</i> structures.
*
*
* @since 1.5
*/
public interface CompositeData {
/**
* Returns the <i>composite type </i> of this <i>composite data</i> instance.
*
* @return the type of this CompositeData.
*/
public CompositeType getCompositeType();
/**
* Returns the value of the item whose name is <tt>key</tt>.
*
* @param key the name of the item.
*
* @return the value associated with this key.
*
* @throws IllegalArgumentException if <tt>key</tt> is a null or empty String.
*
* @throws InvalidKeyException if <tt>key</tt> is not an existing item name for this <tt>CompositeData</tt> instance.
*/
public Object get(String key) ;
/**
* Returns an array of the values of the items whose names are specified by <tt>keys</tt>, in the same order as <tt>keys</tt>.
*
* @param keys the names of the items.
*
* @return the values corresponding to the keys.
*
* @throws IllegalArgumentException if an element in <tt>keys</tt> is a null or empty String.
*
* @throws InvalidKeyException if an element in <tt>keys</tt> is not an existing item name for this <tt>CompositeData</tt> instance.
*/
public Object[] getAll(String[] keys) ;
/**
* Returns <tt>true</tt> if and only if this <tt>CompositeData</tt> instance contains
* an item whose name is <tt>key</tt>.
* If <tt>key</tt> is a null or empty String, this method simply returns false.
*
* @param key the key to be tested.
*
* @return true if this <tt>CompositeData</tt> contains the key.
*/
public boolean containsKey(String key) ;
/**
* Returns <tt>true</tt> if and only if this <tt>CompositeData</tt> instance contains an item
* whose value is <tt>value</tt>.
*
* @param value the value to be tested.
*
* @return true if this <tt>CompositeData</tt> contains the value.
*/
public boolean containsValue(Object value) ;
/**
* Returns an unmodifiable Collection view of the item values contained in this <tt>CompositeData</tt> instance.
* The returned collection's iterator will return the values in the ascending lexicographic order of the corresponding
* item names.
*
* @return the values.
*/
public Collection<?> values() ;
/**
* Compares the specified <var>obj</var> parameter with this
* <code>CompositeData</code> instance for equality.
* <p>
* Returns <tt>true</tt> if and only if all of the following statements are true:
* <ul>
* <li><var>obj</var> is non null,</li>
* <li><var>obj</var> also implements the <code>CompositeData</code> interface,</li>
* <li>their composite types are equal</li>
* <li>their contents, i.e. (name, value) pairs are equal. If a value contained in
* the content is an array, the value comparison is done as if by calling
* the {@link java.util.Arrays#deepEquals(Object[], Object[]) deepEquals} method
* for arrays of object reference types or the appropriate overloading of
* {@code Arrays.equals(e1,e2)} for arrays of primitive types</li>
* </ul>
* <p>
* This ensures that this <tt>equals</tt> method works properly for
* <var>obj</var> parameters which are different implementations of the
* <code>CompositeData</code> interface, with the restrictions mentioned in the
* {@link java.util.Collection#equals(Object) equals}
* method of the <tt>java.util.Collection</tt> interface.
*
* @param obj the object to be compared for equality with this
* <code>CompositeData</code> instance.
* @return <code>true</code> if the specified object is equal to this
* <code>CompositeData</code> instance.
*/
public boolean equals(Object obj) ;
/**
* Returns the hash code value for this <code>CompositeData</code> instance.
* <p>
* The hash code of a <code>CompositeData</code> instance is the sum of the hash codes
* of all elements of information used in <code>equals</code> comparisons
* (ie: its <i>composite type</i> and all the item values).
* <p>
* This ensures that <code> t1.equals(t2) </code> implies that <code> t1.hashCode()==t2.hashCode() </code>
* for any two <code>CompositeData</code> instances <code>t1</code> and <code>t2</code>,
* as required by the general contract of the method
* {@link Object#hashCode() Object.hashCode()}.
* <p>
* Each item value's hash code is added to the returned hash code.
* If an item value is an array,
* its hash code is obtained as if by calling the
* {@link java.util.Arrays#deepHashCode(Object[]) deepHashCode} method
* for arrays of object reference types or the appropriate overloading
* of {@code Arrays.hashCode(e)} for arrays of primitive types.
*
* @return the hash code value for this <code>CompositeData</code> instance
*/
public int hashCode() ;
/**
* Returns a string representation of this <code>CompositeData</code> instance.
* <p>
* The string representation consists of the name of the implementing class,
* the string representation of the composite type of this instance, and the string representation of the contents
* (ie list the itemName=itemValue mappings).
*
* @return a string representation of this <code>CompositeData</code> instance
*/
public String toString() ;
}

View File

@@ -0,0 +1,245 @@
/*
* Copyright (c) 2005, 2013, Oracle and/or its affiliates. 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
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation. Oracle designates this
* particular file as subject to the "Classpath" exception as provided
* by Oracle in the LICENSE file that accompanied this code.
*
* This code is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
*
* You should have received a copy of the GNU General Public License version
* 2 along with this work; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
*
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
*/
package javax.management.openmbean;
import com.sun.jmx.mbeanserver.MXBeanLookup;
import com.sun.jmx.mbeanserver.MXBeanMapping;
import com.sun.jmx.mbeanserver.MXBeanMappingFactory;
import com.sun.jmx.mbeanserver.DefaultMXBeanMappingFactory;
import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method;
import java.lang.reflect.Proxy;
/**
<p>An {@link InvocationHandler} that forwards getter methods to a
{@link CompositeData}. If you have an interface that contains
only getter methods (such as {@code String getName()} or
{@code boolean isActive()}) then you can use this class in
conjunction with the {@link Proxy} class to produce an implementation
of the interface where each getter returns the value of the
corresponding item in a {@code CompositeData}.</p>
<p>For example, suppose you have an interface like this:
<blockquote>
<pre>
public interface NamedNumber {
public int getNumber();
public String getName();
}
</pre>
</blockquote>
and a {@code CompositeData} constructed like this:
<blockquote>
<pre>
CompositeData cd =
new {@link CompositeDataSupport}(
someCompositeType,
new String[] {"number", "name"},
new Object[] {<b>5</b>, "five"}
);
</pre>
</blockquote>
then you can construct an object implementing {@code NamedNumber}
and backed by the object {@code cd} like this:
<blockquote>
<pre>
InvocationHandler handler =
new CompositeDataInvocationHandler(cd);
NamedNumber nn = (NamedNumber)
Proxy.newProxyInstance(NamedNumber.class.getClassLoader(),
new Class[] {NamedNumber.class},
handler);
</pre>
</blockquote>
A call to {@code nn.getNumber()} will then return <b>5</b>.
<p>If the first letter of the property defined by a getter is a
capital, then this handler will look first for an item in the
{@code CompositeData} beginning with a capital, then, if that is
not found, for an item beginning with the corresponding lowercase
letter or code point. For a getter called {@code getNumber()}, the
handler will first look for an item called {@code Number}, then for
{@code number}. If the getter is called {@code getnumber()}, then
the item must be called {@code number}.</p>
<p>If the method given to {@link #invoke invoke} is the method
{@code boolean equals(Object)} inherited from {@code Object}, then
it will return true if and only if the argument is a {@code Proxy}
whose {@code InvocationHandler} is also a {@code
CompositeDataInvocationHandler} and whose backing {@code
CompositeData} is equal (not necessarily identical) to this
object's. If the method given to {@code invoke} is the method
{@code int hashCode()} inherited from {@code Object}, then it will
return a value that is consistent with this definition of {@code
equals}: if two objects are equal according to {@code equals}, then
they will have the same {@code hashCode}.</p>
@since 1.6
*/
public class CompositeDataInvocationHandler implements InvocationHandler {
/**
<p>Construct a handler backed by the given {@code
CompositeData}.</p>
@param compositeData the {@code CompositeData} that will supply
information to getters.
@throws IllegalArgumentException if {@code compositeData}
is null.
*/
public CompositeDataInvocationHandler(CompositeData compositeData) {
this(compositeData, null);
}
/**
<p>Construct a handler backed by the given {@code
CompositeData}.</p>
@param compositeData the {@code CompositeData} that will supply
information to getters.
@throws IllegalArgumentException if {@code compositeData}
is null.
*/
CompositeDataInvocationHandler(CompositeData compositeData,
MXBeanLookup lookup) {
if (compositeData == null)
throw new IllegalArgumentException("compositeData");
this.compositeData = compositeData;
this.lookup = lookup;
}
/**
Return the {@code CompositeData} that was supplied to the
constructor.
@return the {@code CompositeData} that this handler is backed
by. This is never null.
*/
public CompositeData getCompositeData() {
assert compositeData != null;
return compositeData;
}
public Object invoke(Object proxy, Method method, Object[] args)
throws Throwable {
final String methodName = method.getName();
// Handle the methods from java.lang.Object
if (method.getDeclaringClass() == Object.class) {
if (methodName.equals("toString") && args == null)
return "Proxy[" + compositeData + "]";
else if (methodName.equals("hashCode") && args == null)
return compositeData.hashCode() + 0x43444948;
else if (methodName.equals("equals") && args.length == 1
&& method.getParameterTypes()[0] == Object.class)
return equals(proxy, args[0]);
else {
/* Either someone is calling invoke by hand, or
it is a non-final method from Object overriden
by the generated Proxy. At the time of writing,
the only non-final methods in Object that are not
handled above are finalize and clone, and these
are not overridden in generated proxies. */
// this plain Method.invoke is called only if the declaring class
// is Object and so it's safe.
return method.invoke(this, args);
}
}
String propertyName = DefaultMXBeanMappingFactory.propertyName(method);
if (propertyName == null) {
throw new IllegalArgumentException("Method is not getter: " +
method.getName());
}
Object openValue;
if (compositeData.containsKey(propertyName))
openValue = compositeData.get(propertyName);
else {
String decap = DefaultMXBeanMappingFactory.decapitalize(propertyName);
if (compositeData.containsKey(decap))
openValue = compositeData.get(decap);
else {
final String msg =
"No CompositeData item " + propertyName +
(decap.equals(propertyName) ? "" : " or " + decap) +
" to match " + methodName;
throw new IllegalArgumentException(msg);
}
}
MXBeanMapping mapping =
MXBeanMappingFactory.DEFAULT.mappingForType(method.getGenericReturnType(),
MXBeanMappingFactory.DEFAULT);
return mapping.fromOpenValue(openValue);
}
/* This method is called when equals(Object) is
* called on our proxy and hence forwarded to us. For example, if we
* are a proxy for an interface like this:
* public interface GetString {
* public String string();
* }
* then we must compare equal to another CompositeDataInvocationHandler
* proxy for the same interface and where string() returns the same value.
*
* You might think that we should also compare equal to another
* object that implements GetString directly rather than using
* Proxy, provided that its string() returns the same result as
* ours, and in fact an earlier version of this class did that (by
* converting the other object into a CompositeData and comparing
* that with ours). But in fact that doesn't make a great deal of
* sense because there's absolutely no guarantee that the
* resulting equals would be reflexive (otherObject.equals(this)
* might be false even if this.equals(otherObject) is true), and,
* especially, there's no way we could generate a hashCode() that
* would be equal to otherObject.hashCode() when
* this.equals(otherObject), because we don't know how
* otherObject.hashCode() is computed.
*/
private boolean equals(Object proxy, Object other) {
if (other == null)
return false;
final Class<?> proxyClass = proxy.getClass();
final Class<?> otherClass = other.getClass();
if (proxyClass != otherClass)
return false;
InvocationHandler otherih = Proxy.getInvocationHandler(other);
if (!(otherih instanceof CompositeDataInvocationHandler))
return false;
CompositeDataInvocationHandler othercdih =
(CompositeDataInvocationHandler) otherih;
return compositeData.equals(othercdih.compositeData);
}
private final CompositeData compositeData;
private final MXBeanLookup lookup;
}

View File

@@ -0,0 +1,486 @@
/*
* Copyright (c) 2000, 2008, Oracle and/or its affiliates. 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
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation. Oracle designates this
* particular file as subject to the "Classpath" exception as provided
* by Oracle in the LICENSE file that accompanied this code.
*
* This code is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
*
* You should have received a copy of the GNU General Public License version
* 2 along with this work; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
*
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
*/
package javax.management.openmbean;
// java import
//
import java.io.Serializable;
import java.util.Arrays;
import java.util.Collection;
import java.util.Collections;
import java.util.LinkedHashMap;
import java.util.Map;
import java.util.Set;
import java.util.SortedMap;
import java.util.TreeMap;
// jmx import
import java.util.TreeSet;
//
/**
* The <tt>CompositeDataSupport</tt> class is the <i>open data</i> class which
* implements the <tt>CompositeData</tt> interface.
*
*
* @since 1.5
*/
public class CompositeDataSupport
implements CompositeData, Serializable {
/* Serial version */
static final long serialVersionUID = 8003518976613702244L;
/**
* @serial Internal representation of the mapping of item names to their
* respective values.
* A {@link SortedMap} is used for faster retrieval of elements.
*/
private final SortedMap<String, Object> contents;
/**
* @serial The <i>composite type </i> of this <i>composite data</i> instance.
*/
private final CompositeType compositeType;
/**
* <p>Constructs a <tt>CompositeDataSupport</tt> instance with the specified
* <tt>compositeType</tt>, whose item values
* are specified by <tt>itemValues[]</tt>, in the same order as in
* <tt>itemNames[]</tt>.
* As a <tt>CompositeType</tt> does not specify any order on its items,
* the <tt>itemNames[]</tt> parameter is used
* to specify the order in which the values are given in <tt>itemValues[]</tt>.
* The items contained in this <tt>CompositeDataSupport</tt> instance are
* internally stored in a <tt>TreeMap</tt>,
* thus sorted in ascending lexicographic order of their names, for faster
* retrieval of individual item values.</p>
*
* <p>The constructor checks that all the constraints listed below for each
* parameter are satisfied,
* and throws the appropriate exception if they are not.</p>
*
* @param compositeType the <i>composite type </i> of this <i>composite
* data</i> instance; must not be null.
*
* @param itemNames <tt>itemNames</tt> must list, in any order, all the
* item names defined in <tt>compositeType</tt>; the order in which the
* names are listed, is used to match values in <tt>itemValues[]</tt>; must
* not be null or empty.
*
* @param itemValues the values of the items, listed in the same order as
* their respective names in <tt>itemNames</tt>; each item value can be
* null, but if it is non-null it must be a valid value for the open type
* defined in <tt>compositeType</tt> for the corresponding item; must be of
* the same size as <tt>itemNames</tt>; must not be null or empty.
*
* @throws IllegalArgumentException <tt>compositeType</tt> is null, or
* <tt>itemNames[]</tt> or <tt>itemValues[]</tt> is null or empty, or one
* of the elements in <tt>itemNames[]</tt> is a null or empty string, or
* <tt>itemNames[]</tt> and <tt>itemValues[]</tt> are not of the same size.
*
* @throws OpenDataException <tt>itemNames[]</tt> or
* <tt>itemValues[]</tt>'s size differs from the number of items defined in
* <tt>compositeType</tt>, or one of the elements in <tt>itemNames[]</tt>
* does not exist as an item name defined in <tt>compositeType</tt>, or one
* of the elements in <tt>itemValues[]</tt> is not a valid value for the
* corresponding item as defined in <tt>compositeType</tt>.
*/
public CompositeDataSupport(
CompositeType compositeType, String[] itemNames, Object[] itemValues)
throws OpenDataException {
this(makeMap(itemNames, itemValues), compositeType);
}
private static SortedMap<String, Object> makeMap(
String[] itemNames, Object[] itemValues)
throws OpenDataException {
if (itemNames == null || itemValues == null)
throw new IllegalArgumentException("Null itemNames or itemValues");
if (itemNames.length == 0 || itemValues.length == 0)
throw new IllegalArgumentException("Empty itemNames or itemValues");
if (itemNames.length != itemValues.length) {
throw new IllegalArgumentException(
"Different lengths: itemNames[" + itemNames.length +
"], itemValues[" + itemValues.length + "]");
}
SortedMap<String, Object> map = new TreeMap<String, Object>();
for (int i = 0; i < itemNames.length; i++) {
String name = itemNames[i];
if (name == null || name.equals(""))
throw new IllegalArgumentException("Null or empty item name");
if (map.containsKey(name))
throw new OpenDataException("Duplicate item name " + name);
map.put(itemNames[i], itemValues[i]);
}
return map;
}
/**
* <p>
* Constructs a <tt>CompositeDataSupport</tt> instance with the specified <tt>compositeType</tt>, whose item names and corresponding values
* are given by the mappings in the map <tt>items</tt>.
* This constructor converts the keys to a string array and the values to an object array and calls
* <tt>CompositeDataSupport(javax.management.openmbean.CompositeType, java.lang.String[], java.lang.Object[])</tt>.
*
* @param compositeType the <i>composite type </i> of this <i>composite data</i> instance;
* must not be null.
* @param items the mappings of all the item names to their values;
* <tt>items</tt> must contain all the item names defined in <tt>compositeType</tt>;
* must not be null or empty.
*
* @throws IllegalArgumentException <tt>compositeType</tt> is null, or
* <tt>items</tt> is null or empty, or one of the keys in <tt>items</tt> is a null
* or empty string.
* @throws OpenDataException <tt>items</tt>' size differs from the
* number of items defined in <tt>compositeType</tt>, or one of the
* keys in <tt>items</tt> does not exist as an item name defined in
* <tt>compositeType</tt>, or one of the values in <tt>items</tt>
* is not a valid value for the corresponding item as defined in
* <tt>compositeType</tt>.
* @throws ArrayStoreException one or more keys in <tt>items</tt> is not of
* the class <tt>java.lang.String</tt>.
*/
public CompositeDataSupport(CompositeType compositeType,
Map<String,?> items)
throws OpenDataException {
this(makeMap(items), compositeType);
}
private static SortedMap<String, Object> makeMap(Map<String, ?> items) {
if (items == null || items.isEmpty())
throw new IllegalArgumentException("Null or empty items map");
SortedMap<String, Object> map = new TreeMap<String, Object>();
for (Object key : items.keySet()) {
if (key == null || key.equals(""))
throw new IllegalArgumentException("Null or empty item name");
if (!(key instanceof String)) {
throw new ArrayStoreException("Item name is not string: " + key);
// This can happen because of erasure. The particular
// exception is a historical artifact - an implementation
// detail that leaked into the API.
}
map.put((String) key, items.get(key));
}
return map;
}
private CompositeDataSupport(
SortedMap<String, Object> items, CompositeType compositeType)
throws OpenDataException {
// Check compositeType is not null
//
if (compositeType == null) {
throw new IllegalArgumentException("Argument compositeType cannot be null.");
}
// item names defined in compositeType:
Set<String> namesFromType = compositeType.keySet();
Set<String> namesFromItems = items.keySet();
// This is just a comparison, but we do it this way for a better
// exception message.
if (!namesFromType.equals(namesFromItems)) {
Set<String> extraFromType = new TreeSet<String>(namesFromType);
extraFromType.removeAll(namesFromItems);
Set<String> extraFromItems = new TreeSet<String>(namesFromItems);
extraFromItems.removeAll(namesFromType);
if (!extraFromType.isEmpty() || !extraFromItems.isEmpty()) {
throw new OpenDataException(
"Item names do not match CompositeType: " +
"names in items but not in CompositeType: " + extraFromItems +
"; names in CompositeType but not in items: " + extraFromType);
}
}
// Check each value, if not null, is of the open type defined for the
// corresponding item
for (String name : namesFromType) {
Object value = items.get(name);
if (value != null) {
OpenType<?> itemType = compositeType.getType(name);
if (!itemType.isValue(value)) {
throw new OpenDataException(
"Argument value of wrong type for item " + name +
": value " + value + ", type " + itemType);
}
}
}
// Initialize internal fields: compositeType and contents
//
this.compositeType = compositeType;
this.contents = items;
}
/**
* Returns the <i>composite type </i> of this <i>composite data</i> instance.
*/
public CompositeType getCompositeType() {
return compositeType;
}
/**
* Returns the value of the item whose name is <tt>key</tt>.
*
* @throws IllegalArgumentException if <tt>key</tt> is a null or empty String.
*
* @throws InvalidKeyException if <tt>key</tt> is not an existing item name for
* this <tt>CompositeData</tt> instance.
*/
public Object get(String key) {
if ( (key == null) || (key.trim().equals("")) ) {
throw new IllegalArgumentException("Argument key cannot be a null or empty String.");
}
if ( ! contents.containsKey(key.trim())) {
throw new InvalidKeyException("Argument key=\""+ key.trim() +"\" is not an existing item name for this CompositeData instance.");
}
return contents.get(key.trim());
}
/**
* Returns an array of the values of the items whose names are specified by
* <tt>keys</tt>, in the same order as <tt>keys</tt>.
*
* @throws IllegalArgumentException if an element in <tt>keys</tt> is a null
* or empty String.
*
* @throws InvalidKeyException if an element in <tt>keys</tt> is not an existing
* item name for this <tt>CompositeData</tt> instance.
*/
public Object[] getAll(String[] keys) {
if ( (keys == null) || (keys.length == 0) ) {
return new Object[0];
}
Object[] results = new Object[keys.length];
for (int i=0; i<keys.length; i++) {
results[i] = this.get(keys[i]);
}
return results;
}
/**
* Returns <tt>true</tt> if and only if this <tt>CompositeData</tt> instance contains
* an item whose name is <tt>key</tt>.
* If <tt>key</tt> is a null or empty String, this method simply returns false.
*/
public boolean containsKey(String key) {
if ( (key == null) || (key.trim().equals("")) ) {
return false;
}
return contents.containsKey(key);
}
/**
* Returns <tt>true</tt> if and only if this <tt>CompositeData</tt> instance
* contains an item
* whose value is <tt>value</tt>.
*/
public boolean containsValue(Object value) {
return contents.containsValue(value);
}
/**
* Returns an unmodifiable Collection view of the item values contained in this
* <tt>CompositeData</tt> instance.
* The returned collection's iterator will return the values in the ascending
* lexicographic order of the corresponding
* item names.
*/
public Collection<?> values() {
return Collections.unmodifiableCollection(contents.values());
}
/**
* Compares the specified <var>obj</var> parameter with this
* <code>CompositeDataSupport</code> instance for equality.
* <p>
* Returns <tt>true</tt> if and only if all of the following statements are true:
* <ul>
* <li><var>obj</var> is non null,</li>
* <li><var>obj</var> also implements the <code>CompositeData</code> interface,</li>
* <li>their composite types are equal</li>
* <li>their contents, i.e. (name, value) pairs are equal. If a value contained in
* the content is an array, the value comparison is done as if by calling
* the {@link java.util.Arrays#deepEquals(Object[], Object[]) deepEquals} method
* for arrays of object reference types or the appropriate overloading of
* {@code Arrays.equals(e1,e2)} for arrays of primitive types</li>
* </ul>
* <p>
* This ensures that this <tt>equals</tt> method works properly for
* <var>obj</var> parameters which are different implementations of the
* <code>CompositeData</code> interface, with the restrictions mentioned in the
* {@link java.util.Collection#equals(Object) equals}
* method of the <tt>java.util.Collection</tt> interface.
*
* @param obj the object to be compared for equality with this
* <code>CompositeDataSupport</code> instance.
* @return <code>true</code> if the specified object is equal to this
* <code>CompositeDataSupport</code> instance.
*/
@Override
public boolean equals(Object obj) {
if (this == obj) {
return true;
}
// if obj is not a CompositeData, return false
if (!(obj instanceof CompositeData)) {
return false;
}
CompositeData other = (CompositeData) obj;
// their compositeType should be equal
if (!this.getCompositeType().equals(other.getCompositeType()) ) {
return false;
}
if (contents.size() != other.values().size()) {
return false;
}
for (Map.Entry<String,Object> entry : contents.entrySet()) {
Object e1 = entry.getValue();
Object e2 = other.get(entry.getKey());
if (e1 == e2)
continue;
if (e1 == null)
return false;
boolean eq = e1.getClass().isArray() ?
Arrays.deepEquals(new Object[] {e1}, new Object[] {e2}) :
e1.equals(e2);
if (!eq)
return false;
}
// All tests for equality were successful
//
return true;
}
/**
* Returns the hash code value for this <code>CompositeDataSupport</code> instance.
* <p>
* The hash code of a <code>CompositeDataSupport</code> instance is the sum of the hash codes
* of all elements of information used in <code>equals</code> comparisons
* (ie: its <i>composite type</i> and all the item values).
* <p>
* This ensures that <code> t1.equals(t2) </code> implies that <code> t1.hashCode()==t2.hashCode() </code>
* for any two <code>CompositeDataSupport</code> instances <code>t1</code> and <code>t2</code>,
* as required by the general contract of the method
* {@link Object#hashCode() Object.hashCode()}.
* <p>
* Each item value's hash code is added to the returned hash code.
* If an item value is an array,
* its hash code is obtained as if by calling the
* {@link java.util.Arrays#deepHashCode(Object[]) deepHashCode} method
* for arrays of object reference types or the appropriate overloading
* of {@code Arrays.hashCode(e)} for arrays of primitive types.
*
* @return the hash code value for this <code>CompositeDataSupport</code> instance
*/
@Override
public int hashCode() {
int hashcode = compositeType.hashCode();
for (Object o : contents.values()) {
if (o instanceof Object[])
hashcode += Arrays.deepHashCode((Object[]) o);
else if (o instanceof byte[])
hashcode += Arrays.hashCode((byte[]) o);
else if (o instanceof short[])
hashcode += Arrays.hashCode((short[]) o);
else if (o instanceof int[])
hashcode += Arrays.hashCode((int[]) o);
else if (o instanceof long[])
hashcode += Arrays.hashCode((long[]) o);
else if (o instanceof char[])
hashcode += Arrays.hashCode((char[]) o);
else if (o instanceof float[])
hashcode += Arrays.hashCode((float[]) o);
else if (o instanceof double[])
hashcode += Arrays.hashCode((double[]) o);
else if (o instanceof boolean[])
hashcode += Arrays.hashCode((boolean[]) o);
else if (o != null)
hashcode += o.hashCode();
}
return hashcode;
}
/**
* Returns a string representation of this <code>CompositeDataSupport</code> instance.
* <p>
* The string representation consists of the name of this class (ie <code>javax.management.openmbean.CompositeDataSupport</code>),
* the string representation of the composite type of this instance, and the string representation of the contents
* (ie list the itemName=itemValue mappings).
*
* @return a string representation of this <code>CompositeDataSupport</code> instance
*/
@Override
public String toString() {
return new StringBuilder()
.append(this.getClass().getName())
.append("(compositeType=")
.append(compositeType.toString())
.append(",contents=")
.append(contentString())
.append(")")
.toString();
}
private String contentString() {
StringBuilder sb = new StringBuilder("{");
String sep = "";
for (Map.Entry<String, Object> entry : contents.entrySet()) {
sb.append(sep).append(entry.getKey()).append("=");
String s = Arrays.deepToString(new Object[] {entry.getValue()});
sb.append(s.substring(1, s.length() - 1));
sep = ", ";
}
sb.append("}");
return sb.toString();
}
}

View File

@@ -0,0 +1,128 @@
/*
* Copyright (c) 2005, 2006, Oracle and/or its affiliates. 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
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation. Oracle designates this
* particular file as subject to the "Classpath" exception as provided
* by Oracle in the LICENSE file that accompanied this code.
*
* This code is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
*
* You should have received a copy of the GNU General Public License version
* 2 along with this work; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
*
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
*/
package javax.management.openmbean;
/**
* <p>A Java class can implement this interface to indicate how it is
* to be converted into a {@code CompositeData} by the MXBean framework.</p>
*
* <p>A typical way to use this class is to add extra items to the
* {@code CompositeData} in addition to the ones that are declared in the
* {@code CompositeType} supplied by the MXBean framework. To do this,
* you must create another {@code CompositeType} that has all the same items,
* plus your extra items.</p>
*
* <p>For example, suppose you have a class {@code Measure} that consists of
* a String called {@code units} and a {@code value} that is either a
* {@code long} or a {@code double}. It might look like this:</p>
*
* <pre>
* public class Measure implements CompositeDataView {
* private String units;
* private Number value; // a Long or a Double
*
* public Measure(String units, Number value) {
* this.units = units;
* this.value = value;
* }
*
* public static Measure from(CompositeData cd) {
* return new Measure((String) cd.get("units"),
* (Number) cd.get("value"));
* }
*
* public String getUnits() {
* return units;
* }
*
* // Can't be called getValue(), because Number is not a valid type
* // in an MXBean, so the implied "value" property would be rejected.
* public Number _getValue() {
* return value;
* }
*
* public CompositeData toCompositeData(CompositeType ct) {
* try {
* {@code List<String> itemNames = new ArrayList<String>(ct.keySet());}
* {@code List<String> itemDescriptions = new ArrayList<String>();}
* {@code List<OpenType<?>> itemTypes = new ArrayList<OpenType<?>>();}
* for (String item : itemNames) {
* itemDescriptions.add(ct.getDescription(item));
* itemTypes.add(ct.getType(item));
* }
* itemNames.add("value");
* itemDescriptions.add("long or double value of the measure");
* itemTypes.add((value instanceof Long) ? SimpleType.LONG :
* SimpleType.DOUBLE);
* CompositeType xct =
* new CompositeType(ct.getTypeName(),
* ct.getDescription(),
* itemNames.toArray(new String[0]),
* itemDescriptions.toArray(new String[0]),
* itemTypes.toArray(new OpenType&lt;?&gt;[0]));
* CompositeData cd =
* new CompositeDataSupport(xct,
* new String[] {"units", "value"},
* new Object[] {units, value});
* assert ct.isValue(cd); // check we've done it right
* return cd;
* } catch (Exception e) {
* throw new RuntimeException(e);
* }
* }
* }
* </pre>
*
* <p>The {@code CompositeType} that will appear in the {@code openType} field
* of the {@link javax.management.Descriptor Descriptor} for an attribute or
* operation of this type will show only the {@code units} item, but the actual
* {@code CompositeData} that is generated will have both {@code units} and
* {@code value}.</p>
*
* @see javax.management.MXBean
*
* @since 1.6
*/
public interface CompositeDataView {
/**
* <p>Return a {@code CompositeData} corresponding to the values in
* this object. The returned value should usually be an instance of
* {@link CompositeDataSupport}, or a class that serializes as a
* {@code CompositeDataSupport} via a {@code writeReplace} method.
* Otherwise, a remote client that receives the object might not be
* able to reconstruct it.
*
* @param ct The expected {@code CompositeType} of the returned
* value. If the returned value is {@code cd}, then
* {@code cd.getCompositeType().equals(ct)} should be true.
* Typically this will be because {@code cd} is a
* {@link CompositeDataSupport} constructed with {@code ct} as its
* {@code CompositeType}.
*
* @return the {@code CompositeData}.
*/
public CompositeData toCompositeData(CompositeType ct);
}

View File

@@ -0,0 +1,478 @@
/*
* Copyright (c) 2000, 2013, Oracle and/or its affiliates. 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
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation. Oracle designates this
* particular file as subject to the "Classpath" exception as provided
* by Oracle in the LICENSE file that accompanied this code.
*
* This code is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
*
* You should have received a copy of the GNU General Public License version
* 2 along with this work; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
*
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
*/
package javax.management.openmbean;
// java import
//
import java.util.Set;
import java.util.TreeMap;
import java.util.Collections;
import java.util.Iterator;
// jmx import
//
/**
* The <code>CompositeType</code> class is the <i>open type</i> class
* whose instances describe the types of {@link CompositeData CompositeData} values.
*
*
* @since 1.5
*/
public class CompositeType extends OpenType<CompositeData> {
/* Serial version */
static final long serialVersionUID = -5366242454346948798L;
/**
* @serial Sorted mapping of the item names to their descriptions
*/
private TreeMap<String,String> nameToDescription;
/**
* @serial Sorted mapping of the item names to their open types
*/
private TreeMap<String,OpenType<?>> nameToType;
/* As this instance is immutable, following three values need only
* be calculated once. */
private transient Integer myHashCode = null;
private transient String myToString = null;
private transient Set<String> myNamesSet = null;
/* *** Constructor *** */
/**
* Constructs a <code>CompositeType</code> instance, checking for the validity of the given parameters.
* The validity constraints are described below for each parameter.
* <p>
* Note that the contents of the three array parameters
* <var>itemNames</var>, <var>itemDescriptions</var> and <var>itemTypes</var>
* are internally copied so that any subsequent modification of these arrays by the caller of this constructor
* has no impact on the constructed <code>CompositeType</code> instance.
* <p>
* The Java class name of composite data values this composite type represents
* (ie the class name returned by the {@link OpenType#getClassName() getClassName} method)
* is set to the string value returned by <code>CompositeData.class.getName()</code>.
* <p>
* @param typeName The name given to the composite type this instance represents; cannot be a null or empty string.
* <br>&nbsp;
* @param description The human readable description of the composite type this instance represents;
* cannot be a null or empty string.
* <br>&nbsp;
* @param itemNames The names of the items contained in the
* composite data values described by this <code>CompositeType</code> instance;
* cannot be null and should contain at least one element; no element can be a null or empty string.
* Note that the order in which the item names are given is not important to differentiate a
* <code>CompositeType</code> instance from another;
* the item names are internally stored sorted in ascending alphanumeric order.
* <br>&nbsp;
* @param itemDescriptions The descriptions, in the same order as <var>itemNames</var>, of the items contained in the
* composite data values described by this <code>CompositeType</code> instance;
* should be of the same size as <var>itemNames</var>;
* no element can be null or an empty string.
* <br>&nbsp;
* @param itemTypes The open type instances, in the same order as <var>itemNames</var>, describing the items contained
* in the composite data values described by this <code>CompositeType</code> instance;
* should be of the same size as <var>itemNames</var>;
* no element can be null.
* <br>&nbsp;
* @throws IllegalArgumentException If <var>typeName</var> or <var>description</var> is a null or empty string,
* or <var>itemNames</var> or <var>itemDescriptions</var> or <var>itemTypes</var> is null,
* or any element of <var>itemNames</var> or <var>itemDescriptions</var>
* is a null or empty string,
* or any element of <var>itemTypes</var> is null,
* or <var>itemNames</var> or <var>itemDescriptions</var> or <var>itemTypes</var>
* are not of the same size.
* <br>&nbsp;
* @throws OpenDataException If <var>itemNames</var> contains duplicate item names
* (case sensitive, but leading and trailing whitespaces removed).
*/
public CompositeType(String typeName,
String description,
String[] itemNames,
String[] itemDescriptions,
OpenType<?>[] itemTypes) throws OpenDataException {
// Check and construct state defined by parent
//
super(CompositeData.class.getName(), typeName, description, false);
// Check the 3 arrays are not null or empty (ie length==0) and that there is no null element or empty string in them
//
checkForNullElement(itemNames, "itemNames");
checkForNullElement(itemDescriptions, "itemDescriptions");
checkForNullElement(itemTypes, "itemTypes");
checkForEmptyString(itemNames, "itemNames");
checkForEmptyString(itemDescriptions, "itemDescriptions");
// Check the sizes of the 3 arrays are the same
//
if ( (itemNames.length != itemDescriptions.length) || (itemNames.length != itemTypes.length) ) {
throw new IllegalArgumentException("Array arguments itemNames[], itemDescriptions[] and itemTypes[] "+
"should be of same length (got "+ itemNames.length +", "+
itemDescriptions.length +" and "+ itemTypes.length +").");
}
// Initialize internal "names to descriptions" and "names to types" sorted maps,
// and, by doing so, check there are no duplicate item names
//
nameToDescription = new TreeMap<String,String>();
nameToType = new TreeMap<String,OpenType<?>>();
String key;
for (int i=0; i<itemNames.length; i++) {
key = itemNames[i].trim();
if (nameToDescription.containsKey(key)) {
throw new OpenDataException("Argument's element itemNames["+ i +"]=\""+ itemNames[i] +
"\" duplicates a previous item names.");
}
nameToDescription.put(key, itemDescriptions[i].trim());
nameToType.put(key, itemTypes[i]);
}
}
private static void checkForNullElement(Object[] arg, String argName) {
if ( (arg == null) || (arg.length == 0) ) {
throw new IllegalArgumentException("Argument "+ argName +"[] cannot be null or empty.");
}
for (int i=0; i<arg.length; i++) {
if (arg[i] == null) {
throw new IllegalArgumentException("Argument's element "+ argName +"["+ i +"] cannot be null.");
}
}
}
private static void checkForEmptyString(String[] arg, String argName) {
for (int i=0; i<arg.length; i++) {
if (arg[i].trim().equals("")) {
throw new IllegalArgumentException("Argument's element "+ argName +"["+ i +"] cannot be an empty string.");
}
}
}
/* *** Composite type specific information methods *** */
/**
* Returns <code>true</code> if this <code>CompositeType</code> instance defines an item
* whose name is <var>itemName</var>.
*
* @param itemName the name of the item.
*
* @return true if an item of this name is present.
*/
public boolean containsKey(String itemName) {
if (itemName == null) {
return false;
}
return nameToDescription.containsKey(itemName);
}
/**
* Returns the description of the item whose name is <var>itemName</var>,
* or <code>null</code> if this <code>CompositeType</code> instance does not define any item
* whose name is <var>itemName</var>.
*
* @param itemName the name of the item.
*
* @return the description.
*/
public String getDescription(String itemName) {
if (itemName == null) {
return null;
}
return nameToDescription.get(itemName);
}
/**
* Returns the <i>open type</i> of the item whose name is <var>itemName</var>,
* or <code>null</code> if this <code>CompositeType</code> instance does not define any item
* whose name is <var>itemName</var>.
*
* @param itemName the name of the time.
*
* @return the type.
*/
public OpenType<?> getType(String itemName) {
if (itemName == null) {
return null;
}
return (OpenType<?>) nameToType.get(itemName);
}
/**
* Returns an unmodifiable Set view of all the item names defined by this <code>CompositeType</code> instance.
* The set's iterator will return the item names in ascending order.
*
* @return a {@link Set} of {@link String}.
*/
public Set<String> keySet() {
// Initializes myNamesSet on first call
if (myNamesSet == null) {
myNamesSet = Collections.unmodifiableSet(nameToDescription.keySet());
}
return myNamesSet; // always return the same value
}
/**
* Tests whether <var>obj</var> is a value which could be
* described by this <code>CompositeType</code> instance.
*
* <p>If <var>obj</var> is null or is not an instance of
* <code>javax.management.openmbean.CompositeData</code>,
* <code>isValue</code> returns <code>false</code>.</p>
*
* <p>If <var>obj</var> is an instance of
* <code>javax.management.openmbean.CompositeData</code>, then let
* {@code ct} be its {@code CompositeType} as returned by {@link
* CompositeData#getCompositeType()}. The result is true if
* {@code this} is <em>assignable from</em> {@code ct}. This
* means that:</p>
*
* <ul>
* <li>{@link #getTypeName() this.getTypeName()} equals
* {@code ct.getTypeName()}, and
* <li>there are no item names present in {@code this} that are
* not also present in {@code ct}, and
* <li>for every item in {@code this}, its type is assignable from
* the type of the corresponding item in {@code ct}.
* </ul>
*
* <p>A {@code TabularType} is assignable from another {@code
* TabularType} if they have the same {@linkplain
* TabularType#getTypeName() typeName} and {@linkplain
* TabularType#getIndexNames() index name list}, and the
* {@linkplain TabularType#getRowType() row type} of the first is
* assignable from the row type of the second.
*
* <p>An {@code ArrayType} is assignable from another {@code
* ArrayType} if they have the same {@linkplain
* ArrayType#getDimension() dimension}; and both are {@linkplain
* ArrayType#isPrimitiveArray() primitive arrays} or neither is;
* and the {@linkplain ArrayType#getElementOpenType() element
* type} of the first is assignable from the element type of the
* second.
*
* <p>In every other case, an {@code OpenType} is assignable from
* another {@code OpenType} only if they are equal.</p>
*
* <p>These rules mean that extra items can be added to a {@code
* CompositeData} without making it invalid for a {@code CompositeType}
* that does not have those items.</p>
*
* @param obj the value whose open type is to be tested for compatibility
* with this <code>CompositeType</code> instance.
*
* @return <code>true</code> if <var>obj</var> is a value for this
* composite type, <code>false</code> otherwise.
*/
public boolean isValue(Object obj) {
// if obj is null or not CompositeData, return false
//
if (!(obj instanceof CompositeData)) {
return false;
}
// if obj is not a CompositeData, return false
//
CompositeData value = (CompositeData) obj;
// test value's CompositeType is assignable to this CompositeType instance
//
CompositeType valueType = value.getCompositeType();
return this.isAssignableFrom(valueType);
}
/**
* Tests whether values of the given type can be assigned to this
* open type. The result is true if the given type is also a
* CompositeType with the same name ({@link #getTypeName()}), and
* every item in this type is also present in the given type with
* the same name and assignable type. There can be additional
* items in the given type, which are ignored.
*
* @param ot the type to be tested.
*
* @return true if {@code ot} is assignable to this open type.
*/
@Override
boolean isAssignableFrom(OpenType<?> ot) {
if (!(ot instanceof CompositeType))
return false;
CompositeType ct = (CompositeType) ot;
if (!ct.getTypeName().equals(getTypeName()))
return false;
for (String key : keySet()) {
OpenType<?> otItemType = ct.getType(key);
OpenType<?> thisItemType = getType(key);
if (otItemType == null ||
!thisItemType.isAssignableFrom(otItemType))
return false;
}
return true;
}
/* *** Methods overriden from class Object *** */
/**
* Compares the specified <code>obj</code> parameter with this <code>CompositeType</code> instance for equality.
* <p>
* Two <code>CompositeType</code> instances are equal if and only if all of the following statements are true:
* <ul>
* <li>their type names are equal</li>
* <li>their items' names and types are equal</li>
* </ul>
* <br>&nbsp;
* @param obj the object to be compared for equality with this <code>CompositeType</code> instance;
* if <var>obj</var> is <code>null</code>, <code>equals</code> returns <code>false</code>.
*
* @return <code>true</code> if the specified object is equal to this <code>CompositeType</code> instance.
*/
public boolean equals(Object obj) {
// if obj is null, return false
//
if (obj == null) {
return false;
}
// if obj is not a CompositeType, return false
//
CompositeType other;
try {
other = (CompositeType) obj;
} catch (ClassCastException e) {
return false;
}
// Now, really test for equality between this CompositeType instance and the other
//
// their names should be equal
if ( ! this.getTypeName().equals(other.getTypeName()) ) {
return false;
}
// their items names and types should be equal
if ( ! this.nameToType.equals(other.nameToType) ) {
return false;
}
// All tests for equality were successfull
//
return true;
}
/**
* Returns the hash code value for this <code>CompositeType</code> instance.
* <p>
* The hash code of a <code>CompositeType</code> instance is the sum of the hash codes
* of all elements of information used in <code>equals</code> comparisons
* (ie: name, items names, items types).
* This ensures that <code> t1.equals(t2) </code> implies that <code> t1.hashCode()==t2.hashCode() </code>
* for any two <code>CompositeType</code> instances <code>t1</code> and <code>t2</code>,
* as required by the general contract of the method
* {@link Object#hashCode() Object.hashCode()}.
* <p>
* As <code>CompositeType</code> instances are immutable, the hash code for this instance is calculated once,
* on the first call to <code>hashCode</code>, and then the same value is returned for subsequent calls.
*
* @return the hash code value for this <code>CompositeType</code> instance
*/
public int hashCode() {
// Calculate the hash code value if it has not yet been done (ie 1st call to hashCode())
//
if (myHashCode == null) {
int value = 0;
value += this.getTypeName().hashCode();
for (String key : nameToDescription.keySet()) {
value += key.hashCode();
value += this.nameToType.get(key).hashCode();
}
myHashCode = Integer.valueOf(value);
}
// return always the same hash code for this instance (immutable)
//
return myHashCode.intValue();
}
/**
* Returns a string representation of this <code>CompositeType</code> instance.
* <p>
* The string representation consists of
* the name of this class (ie <code>javax.management.openmbean.CompositeType</code>), the type name for this instance,
* and the list of the items names and types string representation of this instance.
* <p>
* As <code>CompositeType</code> instances are immutable, the string representation for this instance is calculated once,
* on the first call to <code>toString</code>, and then the same value is returned for subsequent calls.
*
* @return a string representation of this <code>CompositeType</code> instance
*/
public String toString() {
// Calculate the string representation if it has not yet been done (ie 1st call to toString())
//
if (myToString == null) {
final StringBuilder result = new StringBuilder();
result.append(this.getClass().getName());
result.append("(name=");
result.append(getTypeName());
result.append(",items=(");
int i=0;
Iterator<String> k=nameToType.keySet().iterator();
String key;
while (k.hasNext()) {
key = k.next();
if (i > 0) result.append(",");
result.append("(itemName=");
result.append(key);
result.append(",itemType=");
result.append(nameToType.get(key).toString() +")");
i++;
}
result.append("))");
myToString = result.toString();
}
// return always the same string representation for this instance (immutable)
//
return myToString;
}
}

View File

@@ -0,0 +1,55 @@
/*
* Copyright (c) 2000, 2007, Oracle and/or its affiliates. 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
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation. Oracle designates this
* particular file as subject to the "Classpath" exception as provided
* by Oracle in the LICENSE file that accompanied this code.
*
* This code is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
*
* You should have received a copy of the GNU General Public License version
* 2 along with this work; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
*
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
*/
package javax.management.openmbean;
/**
* This runtime exception is thrown to indicate that a method parameter which was expected to be
* an item name of a <i>composite data</i> or a row index of a <i>tabular data</i> is not valid.
*
*
* @since 1.5
*/
public class InvalidKeyException extends IllegalArgumentException {
private static final long serialVersionUID = 4224269443946322062L;
/**
* An InvalidKeyException with no detail message.
*/
public InvalidKeyException() {
super();
}
/**
* An InvalidKeyException with a detail message.
*
* @param msg the detail message.
*/
public InvalidKeyException(String msg) {
super(msg);
}
}

View File

@@ -0,0 +1,53 @@
/*
* Copyright (c) 2000, 2007, Oracle and/or its affiliates. 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
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation. Oracle designates this
* particular file as subject to the "Classpath" exception as provided
* by Oracle in the LICENSE file that accompanied this code.
*
* This code is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
*
* You should have received a copy of the GNU General Public License version
* 2 along with this work; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
*
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
*/
package javax.management.openmbean;
/**
* This runtime exception is thrown to indicate that the <i>open type</i> of an <i>open data</i> value
* is not the one expected.
*
*
* @since 1.5
*/
public class InvalidOpenTypeException extends IllegalArgumentException {
private static final long serialVersionUID = -2837312755412327534L;
/** An InvalidOpenTypeException with no detail message. */
public InvalidOpenTypeException() {
super();
}
/**
* An InvalidOpenTypeException with a detail message.
*
* @param msg the detail message.
*/
public InvalidOpenTypeException(String msg) {
super(msg);
}
}

View File

@@ -0,0 +1,55 @@
/*
* Copyright (c) 2000, 2007, Oracle and/or its affiliates. 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
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation. Oracle designates this
* particular file as subject to the "Classpath" exception as provided
* by Oracle in the LICENSE file that accompanied this code.
*
* This code is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
*
* You should have received a copy of the GNU General Public License version
* 2 along with this work; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
*
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
*/
package javax.management.openmbean;
/**
* This runtime exception is thrown to indicate that the index of a row to be added to a <i>tabular data</i> instance
* is already used to refer to another row in this <i>tabular data</i> instance.
*
*
* @since 1.5
*/
public class KeyAlreadyExistsException extends IllegalArgumentException {
private static final long serialVersionUID = 1845183636745282866L;
/**
* A KeyAlreadyExistsException with no detail message.
*/
public KeyAlreadyExistsException() {
super();
}
/**
* A KeyAlreadyExistsException with a detail message.
*
* @param msg the detail message.
*/
public KeyAlreadyExistsException(String msg) {
super(msg);
}
}

View File

@@ -0,0 +1,59 @@
/*
* Copyright (c) 2000, 2007, Oracle and/or its affiliates. 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
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation. Oracle designates this
* particular file as subject to the "Classpath" exception as provided
* by Oracle in the LICENSE file that accompanied this code.
*
* This code is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
*
* You should have received a copy of the GNU General Public License version
* 2 along with this work; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
*
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
*/
package javax.management.openmbean;
// jmx import
//
import javax.management.JMException;
/**
* This checked exception is thrown when an <i>open type</i>, an <i>open data</i> or an <i>open MBean metadata info</i> instance
* could not be constructed because one or more validity constraints were not met.
*
*
* @since 1.5
*/
public class OpenDataException extends JMException {
private static final long serialVersionUID = 8346311255433349870L;
/**
* An OpenDataException with no detail message.
*/
public OpenDataException() {
super();
}
/**
* An OpenDataException with a detail message.
*
* @param msg the detail message.
*/
public OpenDataException(String msg) {
super(msg);
}
}

View File

@@ -0,0 +1,138 @@
/*
* Copyright (c) 2000, 2007, Oracle and/or its affiliates. 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
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation. Oracle designates this
* particular file as subject to the "Classpath" exception as provided
* by Oracle in the LICENSE file that accompanied this code.
*
* This code is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
*
* You should have received a copy of the GNU General Public License version
* 2 along with this work; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
*
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
*/
package javax.management.openmbean;
// java import
//
// jmx import
//
/**
* <p>Describes an attribute of an open MBean.</p>
*
* <p>This interface declares the same methods as the class {@link
* javax.management.MBeanAttributeInfo}. A class implementing this
* interface (typically {@link OpenMBeanAttributeInfoSupport}) should
* extend {@link javax.management.MBeanAttributeInfo}.</p>
*
*
* @since 1.5
*/
public interface OpenMBeanAttributeInfo extends OpenMBeanParameterInfo {
// Re-declares the methods that are in class MBeanAttributeInfo of JMX 1.0
// (these will be removed when MBeanAttributeInfo is made a parent interface of this interface)
/**
* Returns <tt>true</tt> if the attribute described by this <tt>OpenMBeanAttributeInfo</tt> instance is readable,
* <tt>false</tt> otherwise.
*
* @return true if the attribute is readable.
*/
public boolean isReadable() ;
/**
* Returns <tt>true</tt> if the attribute described by this <tt>OpenMBeanAttributeInfo</tt> instance is writable,
* <tt>false</tt> otherwise.
*
* @return true if the attribute is writable.
*/
public boolean isWritable() ;
/**
* Returns <tt>true</tt> if the attribute described by this <tt>OpenMBeanAttributeInfo</tt> instance
* is accessed through a <tt>is<i>XXX</i></tt> getter (applies only to <tt>boolean</tt> and <tt>Boolean</tt> values),
* <tt>false</tt> otherwise.
*
* @return true if the attribute is accessed through <tt>is<i>XXX</i></tt>.
*/
public boolean isIs() ;
// commodity methods
//
/**
* Compares the specified <var>obj</var> parameter with this <code>OpenMBeanAttributeInfo</code> instance for equality.
* <p>
* Returns <tt>true</tt> if and only if all of the following statements are true:
* <ul>
* <li><var>obj</var> is non null,</li>
* <li><var>obj</var> also implements the <code>OpenMBeanAttributeInfo</code> interface,</li>
* <li>their names are equal</li>
* <li>their open types are equal</li>
* <li>their access properties (isReadable, isWritable and isIs) are equal</li>
* <li>their default, min, max and legal values are equal.</li>
* </ul>
* This ensures that this <tt>equals</tt> method works properly for <var>obj</var> parameters which are
* different implementations of the <code>OpenMBeanAttributeInfo</code> interface.
* <br>&nbsp;
* @param obj the object to be compared for equality with this <code>OpenMBeanAttributeInfo</code> instance;
*
* @return <code>true</code> if the specified object is equal to this <code>OpenMBeanAttributeInfo</code> instance.
*/
public boolean equals(Object obj);
/**
* Returns the hash code value for this <code>OpenMBeanAttributeInfo</code> instance.
* <p>
* The hash code of an <code>OpenMBeanAttributeInfo</code> instance is the sum of the hash codes
* of all elements of information used in <code>equals</code> comparisons
* (ie: its name, its <i>open type</i>, and its default, min, max and legal values).
* <p>
* This ensures that <code> t1.equals(t2) </code> implies that <code> t1.hashCode()==t2.hashCode() </code>
* for any two <code>OpenMBeanAttributeInfo</code> instances <code>t1</code> and <code>t2</code>,
* as required by the general contract of the method
* {@link Object#hashCode() Object.hashCode()}.
* <p>
*
* @return the hash code value for this <code>OpenMBeanAttributeInfo</code> instance
*/
public int hashCode();
/**
* Returns a string representation of this <code>OpenMBeanAttributeInfo</code> instance.
* <p>
* The string representation consists of the name of this class (ie <code>javax.management.openmbean.OpenMBeanAttributeInfo</code>),
* the string representation of the name and open type of the described attribute,
* and the string representation of its default, min, max and legal values.
*
* @return a string representation of this <code>OpenMBeanAttributeInfo</code> instance
*/
public String toString();
// methods specific to open MBeans are inherited from
// OpenMBeanParameterInfo
//
}

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,137 @@
/*
* Copyright (c) 2000, 2007, Oracle and/or its affiliates. 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
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation. Oracle designates this
* particular file as subject to the "Classpath" exception as provided
* by Oracle in the LICENSE file that accompanied this code.
*
* This code is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
*
* You should have received a copy of the GNU General Public License version
* 2 along with this work; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
*
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
*/
package javax.management.openmbean;
// java import
//
// jmx import
//
import javax.management.MBeanParameterInfo;
/**
* <p>Describes a constructor of an Open MBean.</p>
*
* <p>This interface declares the same methods as the class {@link
* javax.management.MBeanConstructorInfo}. A class implementing this
* interface (typically {@link OpenMBeanConstructorInfoSupport})
* should extend {@link javax.management.MBeanConstructorInfo}.</p>
*
* <p>The {@link #getSignature()} method should return at runtime an
* array of instances of a subclass of {@link MBeanParameterInfo}
* which implements the {@link OpenMBeanParameterInfo} interface
* (typically {@link OpenMBeanParameterInfoSupport}).</p>
*
*
*
* @since 1.5
*/
public interface OpenMBeanConstructorInfo {
// Re-declares the methods that are in class MBeanConstructorInfo of JMX 1.0
// (methods will be removed when MBeanConstructorInfo is made a parent interface of this interface)
/**
* Returns a human readable description of the constructor
* described by this <tt>OpenMBeanConstructorInfo</tt> instance.
*
* @return the description.
*/
public String getDescription() ;
/**
* Returns the name of the constructor
* described by this <tt>OpenMBeanConstructorInfo</tt> instance.
*
* @return the name.
*/
public String getName() ;
/**
* Returns an array of <tt>OpenMBeanParameterInfo</tt> instances
* describing each parameter in the signature of the constructor
* described by this <tt>OpenMBeanConstructorInfo</tt> instance.
*
* @return the signature.
*/
public MBeanParameterInfo[] getSignature() ;
// commodity methods
//
/**
* Compares the specified <var>obj</var> parameter with this <code>OpenMBeanConstructorInfo</code> instance for equality.
* <p>
* Returns <tt>true</tt> if and only if all of the following statements are true:
* <ul>
* <li><var>obj</var> is non null,</li>
* <li><var>obj</var> also implements the <code>OpenMBeanConstructorInfo</code> interface,</li>
* <li>their names are equal</li>
* <li>their signatures are equal.</li>
* </ul>
* This ensures that this <tt>equals</tt> method works properly for <var>obj</var> parameters which are
* different implementations of the <code>OpenMBeanConstructorInfo</code> interface.
* <br>&nbsp;
* @param obj the object to be compared for equality with this <code>OpenMBeanConstructorInfo</code> instance;
*
* @return <code>true</code> if the specified object is equal to this <code>OpenMBeanConstructorInfo</code> instance.
*/
public boolean equals(Object obj);
/**
* Returns the hash code value for this <code>OpenMBeanConstructorInfo</code> instance.
* <p>
* The hash code of an <code>OpenMBeanConstructorInfo</code> instance is the sum of the hash codes
* of all elements of information used in <code>equals</code> comparisons
* (ie: its name and signature, where the signature hashCode is calculated by a call to
* <tt>java.util.Arrays.asList(this.getSignature).hashCode()</tt>).
* <p>
* This ensures that <code> t1.equals(t2) </code> implies that <code> t1.hashCode()==t2.hashCode() </code>
* for any two <code>OpenMBeanConstructorInfo</code> instances <code>t1</code> and <code>t2</code>,
* as required by the general contract of the method
* {@link Object#hashCode() Object.hashCode()}.
* <p>
*
* @return the hash code value for this <code>OpenMBeanConstructorInfo</code> instance
*/
public int hashCode();
/**
* Returns a string representation of this <code>OpenMBeanConstructorInfo</code> instance.
* <p>
* The string representation consists of the name of this class (ie <code>javax.management.openmbean.OpenMBeanConstructorInfo</code>),
* and the name and signature of the described constructor.
*
* @return a string representation of this <code>OpenMBeanConstructorInfo</code> instance
*/
public String toString();
}

View File

@@ -0,0 +1,305 @@
/*
* Copyright (c) 2000, 2008, Oracle and/or its affiliates. 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
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation. Oracle designates this
* particular file as subject to the "Classpath" exception as provided
* by Oracle in the LICENSE file that accompanied this code.
*
* This code is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
*
* You should have received a copy of the GNU General Public License version
* 2 along with this work; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
*
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
*/
package javax.management.openmbean;
// java import
//
import java.util.Arrays;
import javax.management.Descriptor;
import javax.management.MBeanConstructorInfo;
import javax.management.MBeanParameterInfo;
/**
* Describes a constructor of an Open MBean.
*
*
* @since 1.5
*/
public class OpenMBeanConstructorInfoSupport
extends MBeanConstructorInfo
implements OpenMBeanConstructorInfo {
/* Serial version */
static final long serialVersionUID = -4400441579007477003L;
// As this instance is immutable,
// these two values need only be calculated once.
private transient Integer myHashCode = null;
private transient String myToString = null;
/**
* <p>Constructs an {@code OpenMBeanConstructorInfoSupport}
* instance, which describes the constructor of a class of open
* MBeans with the specified {@code name}, {@code description} and
* {@code signature}.</p>
*
* <p>The {@code signature} array parameter is internally copied,
* so that subsequent changes to the array referenced by {@code
* signature} have no effect on this instance.</p>
*
* @param name cannot be a null or empty string.
*
* @param description cannot be a null or empty string.
*
* @param signature can be null or empty if there are no
* parameters to describe.
*
* @throws IllegalArgumentException if {@code name} or {@code
* description} are null or empty string.
*
* @throws ArrayStoreException If {@code signature} is not an
* array of instances of a subclass of {@code MBeanParameterInfo}.
*/
public OpenMBeanConstructorInfoSupport(String name,
String description,
OpenMBeanParameterInfo[] signature) {
this(name, description, signature, (Descriptor) null);
}
/**
* <p>Constructs an {@code OpenMBeanConstructorInfoSupport}
* instance, which describes the constructor of a class of open
* MBeans with the specified {@code name}, {@code description},
* {@code signature}, and {@code descriptor}.</p>
*
* <p>The {@code signature} array parameter is internally copied,
* so that subsequent changes to the array referenced by {@code
* signature} have no effect on this instance.</p>
*
* @param name cannot be a null or empty string.
*
* @param description cannot be a null or empty string.
*
* @param signature can be null or empty if there are no
* parameters to describe.
*
* @param descriptor The descriptor for the constructor. This may
* be null which is equivalent to an empty descriptor.
*
* @throws IllegalArgumentException if {@code name} or {@code
* description} are null or empty string.
*
* @throws ArrayStoreException If {@code signature} is not an
* array of instances of a subclass of {@code MBeanParameterInfo}.
*
* @since 1.6
*/
public OpenMBeanConstructorInfoSupport(String name,
String description,
OpenMBeanParameterInfo[] signature,
Descriptor descriptor) {
super(name,
description,
arrayCopyCast(signature), // may throw an ArrayStoreException
descriptor);
// check parameters that should not be null or empty
// (unfortunately it is not done in superclass :-( ! )
//
if (name == null || name.trim().equals("")) {
throw new IllegalArgumentException("Argument name cannot be " +
"null or empty");
}
if (description == null || description.trim().equals("")) {
throw new IllegalArgumentException("Argument description cannot " +
"be null or empty");
}
}
private static MBeanParameterInfo[]
arrayCopyCast(OpenMBeanParameterInfo[] src) {
if (src == null)
return null;
MBeanParameterInfo[] dst = new MBeanParameterInfo[src.length];
System.arraycopy(src, 0, dst, 0, src.length);
// may throw an ArrayStoreException
return dst;
}
/* *** Commodity methods from java.lang.Object *** */
/**
* <p>Compares the specified {@code obj} parameter with this
* {@code OpenMBeanConstructorInfoSupport} instance for
* equality.</p>
*
* <p>Returns {@code true} if and only if all of the following
* statements are true:
*
* <ul>
* <li>{@code obj} is non null,</li>
* <li>{@code obj} also implements the {@code
* OpenMBeanConstructorInfo} interface,</li>
* <li>their names are equal</li>
* <li>their signatures are equal.</li>
* </ul>
*
* This ensures that this {@code equals} method works properly for
* {@code obj} parameters which are different implementations of
* the {@code OpenMBeanConstructorInfo} interface.
*
* @param obj the object to be compared for equality with this
* {@code OpenMBeanConstructorInfoSupport} instance;
*
* @return {@code true} if the specified object is equal to this
* {@code OpenMBeanConstructorInfoSupport} instance.
*/
public boolean equals(Object obj) {
// if obj is null, return false
//
if (obj == null) {
return false;
}
// if obj is not a OpenMBeanConstructorInfo, return false
//
OpenMBeanConstructorInfo other;
try {
other = (OpenMBeanConstructorInfo) obj;
} catch (ClassCastException e) {
return false;
}
// Now, really test for equality between this
// OpenMBeanConstructorInfo implementation and the other:
//
// their Name should be equal
if ( ! this.getName().equals(other.getName()) ) {
return false;
}
// their Signatures should be equal
if ( ! Arrays.equals(this.getSignature(), other.getSignature()) ) {
return false;
}
// All tests for equality were successfull
//
return true;
}
/**
* <p>Returns the hash code value for this {@code
* OpenMBeanConstructorInfoSupport} instance.</p>
*
* <p>The hash code of an {@code OpenMBeanConstructorInfoSupport}
* instance is the sum of the hash codes of all elements of
* information used in {@code equals} comparisons (ie: its name
* and signature, where the signature hashCode is calculated by a
* call to {@code
* java.util.Arrays.asList(this.getSignature).hashCode()}).</p>
*
* <p>This ensures that {@code t1.equals(t2)} implies that {@code
* t1.hashCode()==t2.hashCode()} for any two {@code
* OpenMBeanConstructorInfoSupport} instances {@code t1} and
* {@code t2}, as required by the general contract of the method
* {@link Object#hashCode() Object.hashCode()}.</p>
*
* <p>However, note that another instance of a class implementing
* the {@code OpenMBeanConstructorInfo} interface may be equal to
* this {@code OpenMBeanConstructorInfoSupport} instance as
* defined by {@link #equals(java.lang.Object)}, but may have a
* different hash code if it is calculated differently.</p>
*
* <p>As {@code OpenMBeanConstructorInfoSupport} instances are
* immutable, the hash code for this instance is calculated once,
* on the first call to {@code hashCode}, and then the same value
* is returned for subsequent calls.</p>
*
* @return the hash code value for this {@code
* OpenMBeanConstructorInfoSupport} instance
*/
public int hashCode() {
// Calculate the hash code value if it has not yet been done
// (ie 1st call to hashCode())
//
if (myHashCode == null) {
int value = 0;
value += this.getName().hashCode();
value += Arrays.asList(this.getSignature()).hashCode();
myHashCode = Integer.valueOf(value);
}
// return always the same hash code for this instance (immutable)
//
return myHashCode.intValue();
}
/**
* <p>Returns a string representation of this {@code
* OpenMBeanConstructorInfoSupport} instance.</p>
*
* <p>The string representation consists of the name of this class
* (ie {@code
* javax.management.openmbean.OpenMBeanConstructorInfoSupport}),
* the name and signature of the described constructor and the
* string representation of its descriptor.</p>
*
* <p>As {@code OpenMBeanConstructorInfoSupport} instances are
* immutable, the string representation for this instance is
* calculated once, on the first call to {@code toString}, and
* then the same value is returned for subsequent calls.</p>
*
* @return a string representation of this {@code
* OpenMBeanConstructorInfoSupport} instance
*/
public String toString() {
// Calculate the string value if it has not yet been done (ie
// 1st call to toString())
//
if (myToString == null) {
myToString = new StringBuilder()
.append(this.getClass().getName())
.append("(name=")
.append(this.getName())
.append(",signature=")
.append(Arrays.asList(this.getSignature()).toString())
.append(",descriptor=")
.append(this.getDescriptor())
.append(")")
.toString();
}
// return always the same string representation for this
// instance (immutable)
//
return myToString;
}
}

View File

@@ -0,0 +1,188 @@
/*
* Copyright (c) 2000, 2007, Oracle and/or its affiliates. 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
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation. Oracle designates this
* particular file as subject to the "Classpath" exception as provided
* by Oracle in the LICENSE file that accompanied this code.
*
* This code is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
*
* You should have received a copy of the GNU General Public License version
* 2 along with this work; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
*
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
*/
package javax.management.openmbean;
// java import
//
// jmx import
//
import javax.management.MBeanAttributeInfo;
import javax.management.MBeanOperationInfo;
import javax.management.MBeanConstructorInfo;
import javax.management.MBeanNotificationInfo;
/**
* <p>Describes an Open MBean: an Open MBean is recognized as such if
* its {@link javax.management.DynamicMBean#getMBeanInfo()
* getMBeanInfo()} method returns an instance of a class which
* implements the {@link OpenMBeanInfo} interface, typically {@link
* OpenMBeanInfoSupport}.</p>
*
* <p>This interface declares the same methods as the class {@link
* javax.management.MBeanInfo}. A class implementing this interface
* (typically {@link OpenMBeanInfoSupport}) should extend {@link
* javax.management.MBeanInfo}.</p>
*
* <p>The {@link #getAttributes()}, {@link #getOperations()} and
* {@link #getConstructors()} methods of the implementing class should
* return at runtime an array of instances of a subclass of {@link
* MBeanAttributeInfo}, {@link MBeanOperationInfo} or {@link
* MBeanConstructorInfo} respectively which implement the {@link
* OpenMBeanAttributeInfo}, {@link OpenMBeanOperationInfo} or {@link
* OpenMBeanConstructorInfo} interface respectively.
*
*
* @since 1.5
*/
public interface OpenMBeanInfo {
// Re-declares the methods that are in class MBeanInfo of JMX 1.0
// (methods will be removed when MBeanInfo is made a parent interface of this interface)
/**
* Returns the fully qualified Java class name of the open MBean
* instances this <tt>OpenMBeanInfo</tt> describes.
*
* @return the class name.
*/
public String getClassName() ;
/**
* Returns a human readable description of the type of open MBean
* instances this <tt>OpenMBeanInfo</tt> describes.
*
* @return the description.
*/
public String getDescription() ;
/**
* Returns an array of <tt>OpenMBeanAttributeInfo</tt> instances
* describing each attribute in the open MBean described by this
* <tt>OpenMBeanInfo</tt> instance. Each instance in the returned
* array should actually be a subclass of
* <tt>MBeanAttributeInfo</tt> which implements the
* <tt>OpenMBeanAttributeInfo</tt> interface (typically {@link
* OpenMBeanAttributeInfoSupport}).
*
* @return the attribute array.
*/
public MBeanAttributeInfo[] getAttributes() ;
/**
* Returns an array of <tt>OpenMBeanOperationInfo</tt> instances
* describing each operation in the open MBean described by this
* <tt>OpenMBeanInfo</tt> instance. Each instance in the returned
* array should actually be a subclass of
* <tt>MBeanOperationInfo</tt> which implements the
* <tt>OpenMBeanOperationInfo</tt> interface (typically {@link
* OpenMBeanOperationInfoSupport}).
*
* @return the operation array.
*/
public MBeanOperationInfo[] getOperations() ;
/**
* Returns an array of <tt>OpenMBeanConstructorInfo</tt> instances
* describing each constructor in the open MBean described by this
* <tt>OpenMBeanInfo</tt> instance. Each instance in the returned
* array should actually be a subclass of
* <tt>MBeanConstructorInfo</tt> which implements the
* <tt>OpenMBeanConstructorInfo</tt> interface (typically {@link
* OpenMBeanConstructorInfoSupport}).
*
* @return the constructor array.
*/
public MBeanConstructorInfo[] getConstructors() ;
/**
* Returns an array of <tt>MBeanNotificationInfo</tt> instances
* describing each notification emitted by the open MBean
* described by this <tt>OpenMBeanInfo</tt> instance.
*
* @return the notification array.
*/
public MBeanNotificationInfo[] getNotifications() ;
// commodity methods
//
/**
* Compares the specified <var>obj</var> parameter with this <code>OpenMBeanInfo</code> instance for equality.
* <p>
* Returns <tt>true</tt> if and only if all of the following statements are true:
* <ul>
* <li><var>obj</var> is non null,</li>
* <li><var>obj</var> also implements the <code>OpenMBeanInfo</code> interface,</li>
* <li>their class names are equal</li>
* <li>their infos on attributes, constructors, operations and notifications are equal</li>
* </ul>
* This ensures that this <tt>equals</tt> method works properly for <var>obj</var> parameters which are
* different implementations of the <code>OpenMBeanInfo</code> interface.
* <br>&nbsp;
* @param obj the object to be compared for equality with this <code>OpenMBeanInfo</code> instance;
*
* @return <code>true</code> if the specified object is equal to this <code>OpenMBeanInfo</code> instance.
*/
public boolean equals(Object obj);
/**
* Returns the hash code value for this <code>OpenMBeanInfo</code> instance.
* <p>
* The hash code of an <code>OpenMBeanInfo</code> instance is the sum of the hash codes
* of all elements of information used in <code>equals</code> comparisons
* (ie: its class name, and its infos on attributes, constructors, operations and notifications,
* where the hashCode of each of these arrays is calculated by a call to
* <tt>new java.util.HashSet(java.util.Arrays.asList(this.getSignature)).hashCode()</tt>).
* <p>
* This ensures that <code> t1.equals(t2) </code> implies that <code> t1.hashCode()==t2.hashCode() </code>
* for any two <code>OpenMBeanInfo</code> instances <code>t1</code> and <code>t2</code>,
* as required by the general contract of the method
* {@link Object#hashCode() Object.hashCode()}.
* <p>
*
* @return the hash code value for this <code>OpenMBeanInfo</code> instance
*/
public int hashCode();
/**
* Returns a string representation of this <code>OpenMBeanInfo</code> instance.
* <p>
* The string representation consists of the name of this class (ie <code>javax.management.openmbean.OpenMBeanInfo</code>),
* the MBean class name,
* and the string representation of infos on attributes, constructors, operations and notifications of the described MBean.
*
* @return a string representation of this <code>OpenMBeanInfo</code> instance
*/
public String toString();
}

View File

@@ -0,0 +1,416 @@
/*
* Copyright (c) 2000, 2013, Oracle and/or its affiliates. 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
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation. Oracle designates this
* particular file as subject to the "Classpath" exception as provided
* by Oracle in the LICENSE file that accompanied this code.
*
* This code is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
*
* You should have received a copy of the GNU General Public License version
* 2 along with this work; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
*
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
*/
package javax.management.openmbean;
// java import
//
import java.util.Arrays;
import java.util.HashSet;
import java.util.Objects;
import javax.management.Descriptor;
import javax.management.MBeanAttributeInfo;
import javax.management.MBeanConstructorInfo;
import javax.management.MBeanInfo;
import javax.management.MBeanNotificationInfo;
import javax.management.MBeanOperationInfo;
/**
* The {@code OpenMBeanInfoSupport} class describes the management
* information of an <i>open MBean</i>: it is a subclass of {@link
* javax.management.MBeanInfo}, and it implements the {@link
* OpenMBeanInfo} interface. Note that an <i>open MBean</i> is
* recognized as such if its {@code getMBeanInfo()} method returns an
* instance of a class which implements the OpenMBeanInfo interface,
* typically {@code OpenMBeanInfoSupport}.
*
*
* @since 1.5
*/
public class OpenMBeanInfoSupport
extends MBeanInfo
implements OpenMBeanInfo {
/* Serial version */
static final long serialVersionUID = 4349395935420511492L;
// As this instance is immutable, these two values
// need only be calculated once.
private transient Integer myHashCode = null;
private transient String myToString = null;
/**
* <p>Constructs an {@code OpenMBeanInfoSupport} instance, which
* describes a class of open MBeans with the specified {@code
* className}, {@code description}, {@code openAttributes}, {@code
* openConstructors} , {@code openOperations} and {@code
* notifications}.</p>
*
* <p>The {@code openAttributes}, {@code openConstructors},
* {@code openOperations} and {@code notifications}
* array parameters are internally copied, so that subsequent changes
* to the arrays referenced by these parameters have no effect on this
* instance.</p>
*
* @param className The fully qualified Java class name of the
* open MBean described by this <CODE>OpenMBeanInfoSupport</CODE>
* instance.
*
* @param description A human readable description of the open
* MBean described by this <CODE>OpenMBeanInfoSupport</CODE>
* instance.
*
* @param openAttributes The list of exposed attributes of the
* described open MBean; Must be an array of instances of a
* subclass of {@code MBeanAttributeInfo}, typically {@code
* OpenMBeanAttributeInfoSupport}.
*
* @param openConstructors The list of exposed public constructors
* of the described open MBean; Must be an array of instances of a
* subclass of {@code MBeanConstructorInfo}, typically {@code
* OpenMBeanConstructorInfoSupport}.
*
* @param openOperations The list of exposed operations of the
* described open MBean. Must be an array of instances of a
* subclass of {@code MBeanOperationInfo}, typically {@code
* OpenMBeanOperationInfoSupport}.
*
* @param notifications The list of notifications emitted by the
* described open MBean.
*
* @throws ArrayStoreException If {@code openAttributes}, {@code
* openConstructors} or {@code openOperations} is not an array of
* instances of a subclass of {@code MBeanAttributeInfo}, {@code
* MBeanConstructorInfo} or {@code MBeanOperationInfo}
* respectively.
*/
public OpenMBeanInfoSupport(String className,
String description,
OpenMBeanAttributeInfo[] openAttributes,
OpenMBeanConstructorInfo[] openConstructors,
OpenMBeanOperationInfo[] openOperations,
MBeanNotificationInfo[] notifications) {
this(className, description,
openAttributes, openConstructors, openOperations, notifications,
(Descriptor) null);
}
/**
* <p>Constructs an {@code OpenMBeanInfoSupport} instance, which
* describes a class of open MBeans with the specified {@code
* className}, {@code description}, {@code openAttributes}, {@code
* openConstructors} , {@code openOperations}, {@code
* notifications}, and {@code descriptor}.</p>
*
* <p>The {@code openAttributes}, {@code openConstructors}, {@code
* openOperations} and {@code notifications} array parameters are
* internally copied, so that subsequent changes to the arrays
* referenced by these parameters have no effect on this
* instance.</p>
*
* @param className The fully qualified Java class name of the
* open MBean described by this <CODE>OpenMBeanInfoSupport</CODE>
* instance.
*
* @param description A human readable description of the open
* MBean described by this <CODE>OpenMBeanInfoSupport</CODE>
* instance.
*
* @param openAttributes The list of exposed attributes of the
* described open MBean; Must be an array of instances of a
* subclass of {@code MBeanAttributeInfo}, typically {@code
* OpenMBeanAttributeInfoSupport}.
*
* @param openConstructors The list of exposed public constructors
* of the described open MBean; Must be an array of instances of a
* subclass of {@code MBeanConstructorInfo}, typically {@code
* OpenMBeanConstructorInfoSupport}.
*
* @param openOperations The list of exposed operations of the
* described open MBean. Must be an array of instances of a
* subclass of {@code MBeanOperationInfo}, typically {@code
* OpenMBeanOperationInfoSupport}.
*
* @param notifications The list of notifications emitted by the
* described open MBean.
*
* @param descriptor The descriptor for the MBean. This may be null
* which is equivalent to an empty descriptor.
*
* @throws ArrayStoreException If {@code openAttributes}, {@code
* openConstructors} or {@code openOperations} is not an array of
* instances of a subclass of {@code MBeanAttributeInfo}, {@code
* MBeanConstructorInfo} or {@code MBeanOperationInfo}
* respectively.
*
* @since 1.6
*/
public OpenMBeanInfoSupport(String className,
String description,
OpenMBeanAttributeInfo[] openAttributes,
OpenMBeanConstructorInfo[] openConstructors,
OpenMBeanOperationInfo[] openOperations,
MBeanNotificationInfo[] notifications,
Descriptor descriptor) {
super(className,
description,
attributeArray(openAttributes),
constructorArray(openConstructors),
operationArray(openOperations),
(notifications == null) ? null : notifications.clone(),
descriptor);
}
private static MBeanAttributeInfo[]
attributeArray(OpenMBeanAttributeInfo[] src) {
if (src == null)
return null;
MBeanAttributeInfo[] dst = new MBeanAttributeInfo[src.length];
System.arraycopy(src, 0, dst, 0, src.length);
// may throw an ArrayStoreException
return dst;
}
private static MBeanConstructorInfo[]
constructorArray(OpenMBeanConstructorInfo[] src) {
if (src == null)
return null;
MBeanConstructorInfo[] dst = new MBeanConstructorInfo[src.length];
System.arraycopy(src, 0, dst, 0, src.length);
// may throw an ArrayStoreException
return dst;
}
private static MBeanOperationInfo[]
operationArray(OpenMBeanOperationInfo[] src) {
if (src == null)
return null;
MBeanOperationInfo[] dst = new MBeanOperationInfo[src.length];
System.arraycopy(src, 0, dst, 0, src.length);
return dst;
}
/* *** Commodity methods from java.lang.Object *** */
/**
* <p>Compares the specified {@code obj} parameter with this
* {@code OpenMBeanInfoSupport} instance for equality.</p>
*
* <p>Returns {@code true} if and only if all of the following
* statements are true:
*
* <ul>
* <li>{@code obj} is non null,</li>
* <li>{@code obj} also implements the {@code OpenMBeanInfo}
* interface,</li>
* <li>their class names are equal</li>
* <li>their infos on attributes, constructors, operations and
* notifications are equal</li>
* </ul>
*
* This ensures that this {@code equals} method works properly for
* {@code obj} parameters which are different implementations of
* the {@code OpenMBeanInfo} interface.
*
* @param obj the object to be compared for equality with this
* {@code OpenMBeanInfoSupport} instance;
*
* @return {@code true} if the specified object is equal to this
* {@code OpenMBeanInfoSupport} instance.
*/
public boolean equals(Object obj) {
// if obj is null, return false
//
if (obj == null) {
return false;
}
// if obj is not a OpenMBeanInfo, return false
//
OpenMBeanInfo other;
try {
other = (OpenMBeanInfo) obj;
} catch (ClassCastException e) {
return false;
}
// Now, really test for equality between this OpenMBeanInfo
// implementation and the other:
//
// their MBean className should be equal
if (!Objects.equals(this.getClassName(), other.getClassName())) {
return false;
}
// their infos on attributes should be equal (order not
// significant => equality between sets, not arrays or lists)
if (!sameArrayContents(this.getAttributes(), other.getAttributes()))
return false;
// their infos on constructors should be equal (order not
// significant => equality between sets, not arrays or lists)
if (!sameArrayContents(this.getConstructors(), other.getConstructors()))
return false;
// their infos on operations should be equal (order not
// significant => equality between sets, not arrays or lists)
if (!sameArrayContents(this.getOperations(), other.getOperations()))
return false;
// their infos on notifications should be equal (order not
// significant => equality between sets, not arrays or lists)
if (!sameArrayContents(this.getNotifications(), other.getNotifications()))
return false;
// All tests for equality were successful
//
return true;
}
private static <T> boolean sameArrayContents(T[] a1, T[] a2) {
return (new HashSet<T>(Arrays.asList(a1))
.equals(new HashSet<T>(Arrays.asList(a2))));
}
/**
* <p>Returns the hash code value for this {@code
* OpenMBeanInfoSupport} instance.</p>
*
* <p>The hash code of an {@code OpenMBeanInfoSupport} instance is
* the sum of the hash codes of all elements of information used
* in {@code equals} comparisons (ie: its class name, and its
* infos on attributes, constructors, operations and
* notifications, where the hashCode of each of these arrays is
* calculated by a call to {@code new
* java.util.HashSet(java.util.Arrays.asList(this.getSignature)).hashCode()}).</p>
*
* <p>This ensures that {@code t1.equals(t2)} implies that {@code
* t1.hashCode()==t2.hashCode()} for any two {@code
* OpenMBeanInfoSupport} instances {@code t1} and {@code t2}, as
* required by the general contract of the method {@link
* Object#hashCode() Object.hashCode()}.</p>
*
* <p>However, note that another instance of a class implementing
* the {@code OpenMBeanInfo} interface may be equal to this {@code
* OpenMBeanInfoSupport} instance as defined by {@link
* #equals(java.lang.Object)}, but may have a different hash code
* if it is calculated differently.</p>
*
* <p>As {@code OpenMBeanInfoSupport} instances are immutable, the
* hash code for this instance is calculated once, on the first
* call to {@code hashCode}, and then the same value is returned
* for subsequent calls.</p>
*
* @return the hash code value for this {@code
* OpenMBeanInfoSupport} instance
*/
public int hashCode() {
// Calculate the hash code value if it has not yet been done
// (ie 1st call to hashCode())
//
if (myHashCode == null) {
int value = 0;
if (this.getClassName() != null) {
value += this.getClassName().hashCode();
}
value += arraySetHash(this.getAttributes());
value += arraySetHash(this.getConstructors());
value += arraySetHash(this.getOperations());
value += arraySetHash(this.getNotifications());
myHashCode = Integer.valueOf(value);
}
// return always the same hash code for this instance (immutable)
//
return myHashCode.intValue();
}
private static <T> int arraySetHash(T[] a) {
return new HashSet<T>(Arrays.asList(a)).hashCode();
}
/**
* <p>Returns a string representation of this {@code
* OpenMBeanInfoSupport} instance.</p>
*
* <p>The string representation consists of the name of this class
* (ie {@code javax.management.openmbean.OpenMBeanInfoSupport}),
* the MBean class name, the string representation of infos on
* attributes, constructors, operations and notifications of the
* described MBean and the string representation of the descriptor.</p>
*
* <p>As {@code OpenMBeanInfoSupport} instances are immutable, the
* string representation for this instance is calculated once, on
* the first call to {@code toString}, and then the same value is
* returned for subsequent calls.</p>
*
* @return a string representation of this {@code
* OpenMBeanInfoSupport} instance
*/
public String toString() {
// Calculate the string value if it has not yet been done (ie
// 1st call to toString())
//
if (myToString == null) {
myToString = new StringBuilder()
.append(this.getClass().getName())
.append("(mbean_class_name=")
.append(this.getClassName())
.append(",attributes=")
.append(Arrays.asList(this.getAttributes()).toString())
.append(",constructors=")
.append(Arrays.asList(this.getConstructors()).toString())
.append(",operations=")
.append(Arrays.asList(this.getOperations()).toString())
.append(",notifications=")
.append(Arrays.asList(this.getNotifications()).toString())
.append(",descriptor=")
.append(this.getDescriptor())
.append(")")
.toString();
}
// return always the same string representation for this
// instance (immutable)
//
return myToString;
}
}

View File

@@ -0,0 +1,180 @@
/*
* Copyright (c) 2000, 2007, Oracle and/or its affiliates. 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
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation. Oracle designates this
* particular file as subject to the "Classpath" exception as provided
* by Oracle in the LICENSE file that accompanied this code.
*
* This code is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
*
* You should have received a copy of the GNU General Public License version
* 2 along with this work; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
*
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
*/
package javax.management.openmbean;
// java import
//
// jmx import
//
import javax.management.MBeanParameterInfo;
/**
* <p>Describes an operation of an Open MBean.</p>
*
* <p>This interface declares the same methods as the class {@link
* javax.management.MBeanOperationInfo}. A class implementing this
* interface (typically {@link OpenMBeanOperationInfoSupport}) should
* extend {@link javax.management.MBeanOperationInfo}.</p>
*
* <p>The {@link #getSignature()} method should return at runtime an
* array of instances of a subclass of {@link MBeanParameterInfo}
* which implements the {@link OpenMBeanParameterInfo} interface
* (typically {@link OpenMBeanParameterInfoSupport}).</p>
*
*
* @since 1.5
*/
public interface OpenMBeanOperationInfo {
// Re-declares fields and methods that are in class MBeanOperationInfo of JMX 1.0
// (fields and methods will be removed when MBeanOperationInfo is made a parent interface of this interface)
/**
* Returns a human readable description of the operation
* described by this <tt>OpenMBeanOperationInfo</tt> instance.
*
* @return the description.
*/
public String getDescription() ;
/**
* Returns the name of the operation
* described by this <tt>OpenMBeanOperationInfo</tt> instance.
*
* @return the name.
*/
public String getName() ;
/**
* Returns an array of <tt>OpenMBeanParameterInfo</tt> instances
* describing each parameter in the signature of the operation
* described by this <tt>OpenMBeanOperationInfo</tt> instance.
* Each instance in the returned array should actually be a
* subclass of <tt>MBeanParameterInfo</tt> which implements the
* <tt>OpenMBeanParameterInfo</tt> interface (typically {@link
* OpenMBeanParameterInfoSupport}).
*
* @return the signature.
*/
public MBeanParameterInfo[] getSignature() ;
/**
* Returns an <tt>int</tt> constant qualifying the impact of the
* operation described by this <tt>OpenMBeanOperationInfo</tt>
* instance.
*
* The returned constant is one of {@link
* javax.management.MBeanOperationInfo#INFO}, {@link
* javax.management.MBeanOperationInfo#ACTION}, {@link
* javax.management.MBeanOperationInfo#ACTION_INFO}, or {@link
* javax.management.MBeanOperationInfo#UNKNOWN}.
*
* @return the impact code.
*/
public int getImpact() ;
/**
* Returns the fully qualified Java class name of the values
* returned by the operation described by this
* <tt>OpenMBeanOperationInfo</tt> instance. This method should
* return the same value as a call to
* <tt>getReturnOpenType().getClassName()</tt>.
*
* @return the return type.
*/
public String getReturnType() ;
// Now declares methods that are specific to open MBeans
//
/**
* Returns the <i>open type</i> of the values returned by the
* operation described by this <tt>OpenMBeanOperationInfo</tt>
* instance.
*
* @return the return type.
*/
public OpenType<?> getReturnOpenType() ; // open MBean specific method
// commodity methods
//
/**
* Compares the specified <var>obj</var> parameter with this <code>OpenMBeanOperationInfo</code> instance for equality.
* <p>
* Returns <tt>true</tt> if and only if all of the following statements are true:
* <ul>
* <li><var>obj</var> is non null,</li>
* <li><var>obj</var> also implements the <code>OpenMBeanOperationInfo</code> interface,</li>
* <li>their names are equal</li>
* <li>their signatures are equal</li>
* <li>their return open types are equal</li>
* <li>their impacts are equal</li>
* </ul>
* This ensures that this <tt>equals</tt> method works properly for <var>obj</var> parameters which are
* different implementations of the <code>OpenMBeanOperationInfo</code> interface.
* <br>&nbsp;
* @param obj the object to be compared for equality with this <code>OpenMBeanOperationInfo</code> instance;
*
* @return <code>true</code> if the specified object is equal to this <code>OpenMBeanOperationInfo</code> instance.
*/
public boolean equals(Object obj);
/**
* Returns the hash code value for this <code>OpenMBeanOperationInfo</code> instance.
* <p>
* The hash code of an <code>OpenMBeanOperationInfo</code> instance is the sum of the hash codes
* of all elements of information used in <code>equals</code> comparisons
* (ie: its name, return open type, impact and signature, where the signature hashCode is calculated by a call to
* <tt>java.util.Arrays.asList(this.getSignature).hashCode()</tt>).
* <p>
* This ensures that <code> t1.equals(t2) </code> implies that <code> t1.hashCode()==t2.hashCode() </code>
* for any two <code>OpenMBeanOperationInfo</code> instances <code>t1</code> and <code>t2</code>,
* as required by the general contract of the method
* {@link Object#hashCode() Object.hashCode()}.
* <p>
*
* @return the hash code value for this <code>OpenMBeanOperationInfo</code> instance
*/
public int hashCode();
/**
* Returns a string representation of this <code>OpenMBeanOperationInfo</code> instance.
* <p>
* The string representation consists of the name of this class (ie <code>javax.management.openmbean.OpenMBeanOperationInfo</code>),
* and the name, signature, return open type and impact of the described operation.
*
* @return a string representation of this <code>OpenMBeanOperationInfo</code> instance
*/
public String toString();
}

View File

@@ -0,0 +1,427 @@
/*
* Copyright (c) 2000, 2008, Oracle and/or its affiliates. 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
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation. Oracle designates this
* particular file as subject to the "Classpath" exception as provided
* by Oracle in the LICENSE file that accompanied this code.
*
* This code is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
*
* You should have received a copy of the GNU General Public License version
* 2 along with this work; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
*
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
*/
package javax.management.openmbean;
// java import
//
import java.util.Arrays;
import javax.management.Descriptor;
import javax.management.ImmutableDescriptor;
import javax.management.MBeanOperationInfo;
import javax.management.MBeanParameterInfo;
/**
* Describes an operation of an Open MBean.
*
*
* @since 1.5
*/
public class OpenMBeanOperationInfoSupport
extends MBeanOperationInfo
implements OpenMBeanOperationInfo {
/* Serial version */
static final long serialVersionUID = 4996859732565369366L;
/**
* @serial The <i>open type</i> of the values returned by the operation
* described by this {@link OpenMBeanOperationInfo} instance
*
*/
private OpenType<?> returnOpenType;
// As this instance is immutable,
// these two values need only be calculated once.
private transient Integer myHashCode = null;
private transient String myToString = null;
/**
* <p>Constructs an {@code OpenMBeanOperationInfoSupport}
* instance, which describes the operation of a class of open
* MBeans, with the specified {@code name}, {@code description},
* {@code signature}, {@code returnOpenType} and {@code
* impact}.</p>
*
* <p>The {@code signature} array parameter is internally copied,
* so that subsequent changes to the array referenced by {@code
* signature} have no effect on this instance.</p>
*
* @param name cannot be a null or empty string.
*
* @param description cannot be a null or empty string.
*
* @param signature can be null or empty if there are no
* parameters to describe.
*
* @param returnOpenType cannot be null: use {@code
* SimpleType.VOID} for operations that return nothing.
*
* @param impact must be one of {@code ACTION}, {@code
* ACTION_INFO}, {@code INFO}, or {@code UNKNOWN}.
*
* @throws IllegalArgumentException if {@code name} or {@code
* description} are null or empty string, or {@code
* returnOpenType} is null, or {@code impact} is not one of {@code
* ACTION}, {@code ACTION_INFO}, {@code INFO}, or {@code UNKNOWN}.
*
* @throws ArrayStoreException If {@code signature} is not an
* array of instances of a subclass of {@code MBeanParameterInfo}.
*/
public OpenMBeanOperationInfoSupport(String name,
String description,
OpenMBeanParameterInfo[] signature,
OpenType<?> returnOpenType,
int impact) {
this(name, description, signature, returnOpenType, impact,
(Descriptor) null);
}
/**
* <p>Constructs an {@code OpenMBeanOperationInfoSupport}
* instance, which describes the operation of a class of open
* MBeans, with the specified {@code name}, {@code description},
* {@code signature}, {@code returnOpenType}, {@code
* impact}, and {@code descriptor}.</p>
*
* <p>The {@code signature} array parameter is internally copied,
* so that subsequent changes to the array referenced by {@code
* signature} have no effect on this instance.</p>
*
* @param name cannot be a null or empty string.
*
* @param description cannot be a null or empty string.
*
* @param signature can be null or empty if there are no
* parameters to describe.
*
* @param returnOpenType cannot be null: use {@code
* SimpleType.VOID} for operations that return nothing.
*
* @param impact must be one of {@code ACTION}, {@code
* ACTION_INFO}, {@code INFO}, or {@code UNKNOWN}.
*
* @param descriptor The descriptor for the operation. This may
* be null, which is equivalent to an empty descriptor.
*
* @throws IllegalArgumentException if {@code name} or {@code
* description} are null or empty string, or {@code
* returnOpenType} is null, or {@code impact} is not one of {@code
* ACTION}, {@code ACTION_INFO}, {@code INFO}, or {@code UNKNOWN}.
*
* @throws ArrayStoreException If {@code signature} is not an
* array of instances of a subclass of {@code MBeanParameterInfo}.
*
* @since 1.6
*/
public OpenMBeanOperationInfoSupport(String name,
String description,
OpenMBeanParameterInfo[] signature,
OpenType<?> returnOpenType,
int impact,
Descriptor descriptor) {
super(name,
description,
arrayCopyCast(signature),
// must prevent NPE here - we will throw IAE later on if
// returnOpenType is null
(returnOpenType == null) ? null : returnOpenType.getClassName(),
impact,
ImmutableDescriptor.union(descriptor,
// must prevent NPE here - we will throw IAE later on if
// returnOpenType is null
(returnOpenType==null) ? null :returnOpenType.getDescriptor()));
// check parameters that should not be null or empty
// (unfortunately it is not done in superclass :-( ! )
//
if (name == null || name.trim().equals("")) {
throw new IllegalArgumentException("Argument name cannot " +
"be null or empty");
}
if (description == null || description.trim().equals("")) {
throw new IllegalArgumentException("Argument description cannot " +
"be null or empty");
}
if (returnOpenType == null) {
throw new IllegalArgumentException("Argument returnOpenType " +
"cannot be null");
}
if (impact != ACTION && impact != ACTION_INFO && impact != INFO &&
impact != UNKNOWN) {
throw new IllegalArgumentException("Argument impact can only be " +
"one of ACTION, ACTION_INFO, " +
"INFO, or UNKNOWN: " + impact);
}
this.returnOpenType = returnOpenType;
}
// Converts an array of OpenMBeanParameterInfo objects extending
// MBeanParameterInfo into an array of MBeanParameterInfo.
//
private static MBeanParameterInfo[]
arrayCopyCast(OpenMBeanParameterInfo[] src) {
if (src == null)
return null;
MBeanParameterInfo[] dst = new MBeanParameterInfo[src.length];
System.arraycopy(src, 0, dst, 0, src.length);
// may throw an ArrayStoreException
return dst;
}
// Converts an array of MBeanParameterInfo objects implementing
// OpenMBeanParameterInfo into an array of OpenMBeanParameterInfo.
//
private static OpenMBeanParameterInfo[]
arrayCopyCast(MBeanParameterInfo[] src) {
if (src == null)
return null;
OpenMBeanParameterInfo[] dst = new OpenMBeanParameterInfo[src.length];
System.arraycopy(src, 0, dst, 0, src.length);
// may throw an ArrayStoreException
return dst;
}
// [JF]: should we add constructor with java.lang.reflect.Method
// method parameter ? would need to add consistency check between
// OpenType<?> returnOpenType and method.getReturnType().
/**
* Returns the <i>open type</i> of the values returned by the
* operation described by this {@code OpenMBeanOperationInfo}
* instance.
*/
public OpenType<?> getReturnOpenType() {
return returnOpenType;
}
/* *** Commodity methods from java.lang.Object *** */
/**
* <p>Compares the specified {@code obj} parameter with this
* {@code OpenMBeanOperationInfoSupport} instance for
* equality.</p>
*
* <p>Returns {@code true} if and only if all of the following
* statements are true:
*
* <ul>
* <li>{@code obj} is non null,</li>
* <li>{@code obj} also implements the {@code
* OpenMBeanOperationInfo} interface,</li>
* <li>their names are equal</li>
* <li>their signatures are equal</li>
* <li>their return open types are equal</li>
* <li>their impacts are equal</li>
* </ul>
*
* This ensures that this {@code equals} method works properly for
* {@code obj} parameters which are different implementations of
* the {@code OpenMBeanOperationInfo} interface.
*
* @param obj the object to be compared for equality with this
* {@code OpenMBeanOperationInfoSupport} instance;
*
* @return {@code true} if the specified object is equal to this
* {@code OpenMBeanOperationInfoSupport} instance.
*/
public boolean equals(Object obj) {
// if obj is null, return false
//
if (obj == null) {
return false;
}
// if obj is not a OpenMBeanOperationInfo, return false
//
OpenMBeanOperationInfo other;
try {
other = (OpenMBeanOperationInfo) obj;
} catch (ClassCastException e) {
return false;
}
// Now, really test for equality between this
// OpenMBeanOperationInfo implementation and the other:
//
// their Name should be equal
if ( ! this.getName().equals(other.getName()) ) {
return false;
}
// their Signatures should be equal
if ( ! Arrays.equals(this.getSignature(), other.getSignature()) ) {
return false;
}
// their return open types should be equal
if ( ! this.getReturnOpenType().equals(other.getReturnOpenType()) ) {
return false;
}
// their impacts should be equal
if ( this.getImpact() != other.getImpact() ) {
return false;
}
// All tests for equality were successfull
//
return true;
}
/**
* <p>Returns the hash code value for this {@code
* OpenMBeanOperationInfoSupport} instance.</p>
*
* <p>The hash code of an {@code OpenMBeanOperationInfoSupport}
* instance is the sum of the hash codes of all elements of
* information used in {@code equals} comparisons (ie: its name,
* return open type, impact and signature, where the signature
* hashCode is calculated by a call to {@code
* java.util.Arrays.asList(this.getSignature).hashCode()}).</p>
*
* <p>This ensures that {@code t1.equals(t2) } implies that {@code
* t1.hashCode()==t2.hashCode() } for any two {@code
* OpenMBeanOperationInfoSupport} instances {@code t1} and {@code
* t2}, as required by the general contract of the method {@link
* Object#hashCode() Object.hashCode()}.</p>
*
* <p>However, note that another instance of a class implementing
* the {@code OpenMBeanOperationInfo} interface may be equal to
* this {@code OpenMBeanOperationInfoSupport} instance as defined
* by {@link #equals(java.lang.Object)}, but may have a different
* hash code if it is calculated differently.</p>
*
* <p>As {@code OpenMBeanOperationInfoSupport} instances are
* immutable, the hash code for this instance is calculated once,
* on the first call to {@code hashCode}, and then the same value
* is returned for subsequent calls.</p>
*
* @return the hash code value for this {@code
* OpenMBeanOperationInfoSupport} instance
*/
public int hashCode() {
// Calculate the hash code value if it has not yet been done
// (ie 1st call to hashCode())
//
if (myHashCode == null) {
int value = 0;
value += this.getName().hashCode();
value += Arrays.asList(this.getSignature()).hashCode();
value += this.getReturnOpenType().hashCode();
value += this.getImpact();
myHashCode = Integer.valueOf(value);
}
// return always the same hash code for this instance (immutable)
//
return myHashCode.intValue();
}
/**
* <p>Returns a string representation of this {@code
* OpenMBeanOperationInfoSupport} instance.</p>
*
* <p>The string representation consists of the name of this class
* (ie {@code
* javax.management.openmbean.OpenMBeanOperationInfoSupport}), and
* the name, signature, return open type and impact of the
* described operation and the string representation of its descriptor.</p>
*
* <p>As {@code OpenMBeanOperationInfoSupport} instances are
* immutable, the string representation for this instance is
* calculated once, on the first call to {@code toString}, and
* then the same value is returned for subsequent calls.</p>
*
* @return a string representation of this {@code
* OpenMBeanOperationInfoSupport} instance
*/
public String toString() {
// Calculate the hash code value if it has not yet been done
// (ie 1st call to toString())
//
if (myToString == null) {
myToString = new StringBuilder()
.append(this.getClass().getName())
.append("(name=")
.append(this.getName())
.append(",signature=")
.append(Arrays.asList(this.getSignature()).toString())
.append(",return=")
.append(this.getReturnOpenType().toString())
.append(",impact=")
.append(this.getImpact())
.append(",descriptor=")
.append(this.getDescriptor())
.append(")")
.toString();
}
// return always the same string representation for this
// instance (immutable)
//
return myToString;
}
/**
* An object serialized in a version of the API before Descriptors were
* added to this class will have an empty or null Descriptor.
* For consistency with our
* behavior in this version, we must replace the object with one
* where the Descriptors reflect the same value of returned openType.
**/
private Object readResolve() {
if (getDescriptor().getFieldNames().length == 0) {
// This constructor will construct the expected default Descriptor.
//
return new OpenMBeanOperationInfoSupport(
name, description, arrayCopyCast(getSignature()),
returnOpenType, getImpact());
} else
return this;
}
}

View File

@@ -0,0 +1,212 @@
/*
* Copyright (c) 2000, 2007, Oracle and/or its affiliates. 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
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation. Oracle designates this
* particular file as subject to the "Classpath" exception as provided
* by Oracle in the LICENSE file that accompanied this code.
*
* This code is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
*
* You should have received a copy of the GNU General Public License version
* 2 along with this work; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
*
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
*/
package javax.management.openmbean;
// java import
//
import java.util.Set;
import java.lang.Comparable; // to be substituted for jdk1.1.x
// jmx import
//
/**
* <p>Describes a parameter used in one or more operations or
* constructors of an open MBean.</p>
*
* <p>This interface declares the same methods as the class {@link
* javax.management.MBeanParameterInfo}. A class implementing this
* interface (typically {@link OpenMBeanParameterInfoSupport}) should
* extend {@link javax.management.MBeanParameterInfo}.</p>
*
*
* @since 1.5
*/
public interface OpenMBeanParameterInfo {
// Re-declares methods that are in class MBeanParameterInfo of JMX 1.0
// (these will be removed when MBeanParameterInfo is made a parent interface of this interface)
/**
* Returns a human readable description of the parameter
* described by this <tt>OpenMBeanParameterInfo</tt> instance.
*
* @return the description.
*/
public String getDescription() ;
/**
* Returns the name of the parameter
* described by this <tt>OpenMBeanParameterInfo</tt> instance.
*
* @return the name.
*/
public String getName() ;
// Now declares methods that are specific to open MBeans
//
/**
* Returns the <i>open type</i> of the values of the parameter
* described by this <tt>OpenMBeanParameterInfo</tt> instance.
*
* @return the open type.
*/
public OpenType<?> getOpenType() ;
/**
* Returns the default value for this parameter, if it has one, or
* <tt>null</tt> otherwise.
*
* @return the default value.
*/
public Object getDefaultValue() ;
/**
* Returns the set of legal values for this parameter, if it has
* one, or <tt>null</tt> otherwise.
*
* @return the set of legal values.
*/
public Set<?> getLegalValues() ;
/**
* Returns the minimal value for this parameter, if it has one, or
* <tt>null</tt> otherwise.
*
* @return the minimum value.
*/
public Comparable<?> getMinValue() ;
/**
* Returns the maximal value for this parameter, if it has one, or
* <tt>null</tt> otherwise.
*
* @return the maximum value.
*/
public Comparable<?> getMaxValue() ;
/**
* Returns <tt>true</tt> if this parameter has a specified default
* value, or <tt>false</tt> otherwise.
*
* @return true if there is a default value.
*/
public boolean hasDefaultValue() ;
/**
* Returns <tt>true</tt> if this parameter has a specified set of
* legal values, or <tt>false</tt> otherwise.
*
* @return true if there is a set of legal values.
*/
public boolean hasLegalValues() ;
/**
* Returns <tt>true</tt> if this parameter has a specified minimal
* value, or <tt>false</tt> otherwise.
*
* @return true if there is a minimum value.
*/
public boolean hasMinValue() ;
/**
* Returns <tt>true</tt> if this parameter has a specified maximal
* value, or <tt>false</tt> otherwise.
*
* @return true if there is a maximum value.
*/
public boolean hasMaxValue() ;
/**
* Tests whether <var>obj</var> is a valid value for the parameter
* described by this <code>OpenMBeanParameterInfo</code> instance.
*
* @param obj the object to be tested.
*
* @return <code>true</code> if <var>obj</var> is a valid value
* for the parameter described by this
* <code>OpenMBeanParameterInfo</code> instance,
* <code>false</code> otherwise.
*/
public boolean isValue(Object obj) ;
/**
* Compares the specified <var>obj</var> parameter with this <code>OpenMBeanParameterInfo</code> instance for equality.
* <p>
* Returns <tt>true</tt> if and only if all of the following statements are true:
* <ul>
* <li><var>obj</var> is non null,</li>
* <li><var>obj</var> also implements the <code>OpenMBeanParameterInfo</code> interface,</li>
* <li>their names are equal</li>
* <li>their open types are equal</li>
* <li>their default, min, max and legal values are equal.</li>
* </ul>
* This ensures that this <tt>equals</tt> method works properly for <var>obj</var> parameters which are
* different implementations of the <code>OpenMBeanParameterInfo</code> interface.
* <br>&nbsp;
* @param obj the object to be compared for equality with this <code>OpenMBeanParameterInfo</code> instance;
*
* @return <code>true</code> if the specified object is equal to this <code>OpenMBeanParameterInfo</code> instance.
*/
public boolean equals(Object obj);
/**
* Returns the hash code value for this <code>OpenMBeanParameterInfo</code> instance.
* <p>
* The hash code of an <code>OpenMBeanParameterInfo</code> instance is the sum of the hash codes
* of all elements of information used in <code>equals</code> comparisons
* (ie: its name, its <i>open type</i>, and its default, min, max and legal values).
* <p>
* This ensures that <code> t1.equals(t2) </code> implies that <code> t1.hashCode()==t2.hashCode() </code>
* for any two <code>OpenMBeanParameterInfo</code> instances <code>t1</code> and <code>t2</code>,
* as required by the general contract of the method
* {@link Object#hashCode() Object.hashCode()}.
* <p>
*
* @return the hash code value for this <code>OpenMBeanParameterInfo</code> instance
*/
public int hashCode();
/**
* Returns a string representation of this <code>OpenMBeanParameterInfo</code> instance.
* <p>
* The string representation consists of the name of this class (ie <code>javax.management.openmbean.OpenMBeanParameterInfo</code>),
* the string representation of the name and open type of the described parameter,
* and the string representation of its default, min, max and legal values.
*
* @return a string representation of this <code>OpenMBeanParameterInfo</code> instance
*/
public String toString();
}

View File

@@ -0,0 +1,627 @@
/*
* Copyright (c) 2000, 2013, Oracle and/or its affiliates. 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
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation. Oracle designates this
* particular file as subject to the "Classpath" exception as provided
* by Oracle in the LICENSE file that accompanied this code.
*
* This code is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
*
* You should have received a copy of the GNU General Public License version
* 2 along with this work; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
*
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
*/
package javax.management.openmbean;
// java import
//
import java.util.Set;
import javax.management.Descriptor;
import javax.management.DescriptorRead; // for Javadoc
import javax.management.ImmutableDescriptor;
import javax.management.MBeanParameterInfo;
// OpenMBeanAttributeInfoSupport and this class are very similar
// but can't easily be refactored because there's no multiple inheritance.
// The best we can do for refactoring is to put a bunch of static methods
// in OpenMBeanAttributeInfoSupport and import them here.
import static javax.management.openmbean.OpenMBeanAttributeInfoSupport.*;
/**
* Describes a parameter used in one or more operations or
* constructors of an open MBean.
*
*
* @since 1.5
*/
public class OpenMBeanParameterInfoSupport
extends MBeanParameterInfo
implements OpenMBeanParameterInfo {
/* Serial version */
static final long serialVersionUID = -7235016873758443122L;
/**
* @serial The open mbean parameter's <i>open type</i>
*/
private OpenType<?> openType;
/**
* @serial The open mbean parameter's default value
*/
private Object defaultValue = null;
/**
* @serial The open mbean parameter's legal values. This {@link
* Set} is unmodifiable
*/
private Set<?> legalValues = null; // to be constructed unmodifiable
/**
* @serial The open mbean parameter's min value
*/
private Comparable<?> minValue = null;
/**
* @serial The open mbean parameter's max value
*/
private Comparable<?> maxValue = null;
// As this instance is immutable, these two values need only
// be calculated once.
private transient Integer myHashCode = null; // As this instance is immutable, these two values
private transient String myToString = null; // need only be calculated once.
/**
* Constructs an {@code OpenMBeanParameterInfoSupport} instance,
* which describes the parameter used in one or more operations or
* constructors of a class of open MBeans, with the specified
* {@code name}, {@code openType} and {@code description}.
*
* @param name cannot be a null or empty string.
*
* @param description cannot be a null or empty string.
*
* @param openType cannot be null.
*
* @throws IllegalArgumentException if {@code name} or {@code
* description} are null or empty string, or {@code openType} is
* null.
*/
public OpenMBeanParameterInfoSupport(String name,
String description,
OpenType<?> openType) {
this(name, description, openType, (Descriptor) null);
}
/**
* Constructs an {@code OpenMBeanParameterInfoSupport} instance,
* which describes the parameter used in one or more operations or
* constructors of a class of open MBeans, with the specified
* {@code name}, {@code openType}, {@code description},
* and {@code descriptor}.
*
* <p>The {@code descriptor} can contain entries that will define
* the values returned by certain methods of this class, as
* explained in the <a href="package-summary.html#constraints">
* package description</a>.
*
* @param name cannot be a null or empty string.
*
* @param description cannot be a null or empty string.
*
* @param openType cannot be null.
*
* @param descriptor The descriptor for the parameter. This may be null
* which is equivalent to an empty descriptor.
*
* @throws IllegalArgumentException if {@code name} or {@code
* description} are null or empty string, or {@code openType} is
* null, or the descriptor entries are invalid as described in the
* <a href="package-summary.html#constraints">package
* description</a>.
*
* @since 1.6
*/
public OpenMBeanParameterInfoSupport(String name,
String description,
OpenType<?> openType,
Descriptor descriptor) {
// Construct parent's state
//
super(name,
(openType==null) ? null : openType.getClassName(),
description,
ImmutableDescriptor.union(descriptor,(openType==null)?null:
openType.getDescriptor()));
// Initialize this instance's specific state
//
this.openType = openType;
descriptor = getDescriptor(); // replace null by empty
this.defaultValue = valueFrom(descriptor, "defaultValue", openType);
this.legalValues = valuesFrom(descriptor, "legalValues", openType);
this.minValue = comparableValueFrom(descriptor, "minValue", openType);
this.maxValue = comparableValueFrom(descriptor, "maxValue", openType);
try {
check(this);
} catch (OpenDataException e) {
throw new IllegalArgumentException(e.getMessage(), e);
}
}
/**
* Constructs an {@code OpenMBeanParameterInfoSupport} instance,
* which describes the parameter used in one or more operations or
* constructors of a class of open MBeans, with the specified
* {@code name}, {@code openType}, {@code description} and {@code
* defaultValue}.
*
* @param name cannot be a null or empty string.
*
* @param description cannot be a null or empty string.
*
* @param openType cannot be null.
*
* @param defaultValue must be a valid value for the {@code
* openType} specified for this parameter; default value not
* supported for {@code ArrayType} and {@code TabularType}; can be
* null, in which case it means that no default value is set.
*
* @param <T> allows the compiler to check that the {@code defaultValue},
* if non-null, has the correct Java type for the given {@code openType}.
*
* @throws IllegalArgumentException if {@code name} or {@code
* description} are null or empty string, or {@code openType} is
* null.
*
* @throws OpenDataException if {@code defaultValue} is not a
* valid value for the specified {@code openType}, or {@code
* defaultValue} is non null and {@code openType} is an {@code
* ArrayType} or a {@code TabularType}.
*/
public <T> OpenMBeanParameterInfoSupport(String name,
String description,
OpenType<T> openType,
T defaultValue)
throws OpenDataException {
this(name, description, openType, defaultValue, (T[]) null);
}
/**
* <p>Constructs an {@code OpenMBeanParameterInfoSupport} instance,
* which describes the parameter used in one or more operations or
* constructors of a class of open MBeans, with the specified
* {@code name}, {@code openType}, {@code description}, {@code
* defaultValue} and {@code legalValues}.</p>
*
* <p>The contents of {@code legalValues} are copied, so subsequent
* modifications of the array referenced by {@code legalValues}
* have no impact on this {@code OpenMBeanParameterInfoSupport}
* instance.</p>
*
* @param name cannot be a null or empty string.
*
* @param description cannot be a null or empty string.
*
* @param openType cannot be null.
*
* @param defaultValue must be a valid value for the {@code
* openType} specified for this parameter; default value not
* supported for {@code ArrayType} and {@code TabularType}; can be
* null, in which case it means that no default value is set.
*
* @param legalValues each contained value must be valid for the
* {@code openType} specified for this parameter; legal values not
* supported for {@code ArrayType} and {@code TabularType}; can be
* null or empty.
*
* @param <T> allows the compiler to check that the {@code
* defaultValue} and {@code legalValues}, if non-null, have the
* correct Java type for the given {@code openType}.
*
* @throws IllegalArgumentException if {@code name} or {@code
* description} are null or empty string, or {@code openType} is
* null.
*
* @throws OpenDataException if {@code defaultValue} is not a
* valid value for the specified {@code openType}, or one value in
* {@code legalValues} is not valid for the specified {@code
* openType}, or {@code defaultValue} is non null and {@code
* openType} is an {@code ArrayType} or a {@code TabularType}, or
* {@code legalValues} is non null and non empty and {@code
* openType} is an {@code ArrayType} or a {@code TabularType}, or
* {@code legalValues} is non null and non empty and {@code
* defaultValue} is not contained in {@code legalValues}.
*/
public <T> OpenMBeanParameterInfoSupport(String name,
String description,
OpenType<T> openType,
T defaultValue,
T[] legalValues)
throws OpenDataException {
this(name, description, openType,
defaultValue, legalValues, null, null);
}
/**
* Constructs an {@code OpenMBeanParameterInfoSupport} instance,
* which describes the parameter used in one or more operations or
* constructors of a class of open MBeans, with the specified
* {@code name}, {@code openType}, {@code description}, {@code
* defaultValue}, {@code minValue} and {@code maxValue}.
*
* It is possible to specify minimal and maximal values only for
* an open type whose values are {@code Comparable}.
*
* @param name cannot be a null or empty string.
*
* @param description cannot be a null or empty string.
*
* @param openType cannot be null.
*
* @param defaultValue must be a valid value for the {@code
* openType} specified for this parameter; default value not
* supported for {@code ArrayType} and {@code TabularType}; can be
* null, in which case it means that no default value is set.
*
* @param minValue must be valid for the {@code openType}
* specified for this parameter; can be null, in which case it
* means that no minimal value is set.
*
* @param maxValue must be valid for the {@code openType}
* specified for this parameter; can be null, in which case it
* means that no maximal value is set.
*
* @param <T> allows the compiler to check that the {@code
* defaultValue}, {@code minValue}, and {@code maxValue}, if
* non-null, have the correct Java type for the given {@code
* openType}.
*
* @throws IllegalArgumentException if {@code name} or {@code
* description} are null or empty string, or {@code openType} is
* null.
*
* @throws OpenDataException if {@code defaultValue}, {@code
* minValue} or {@code maxValue} is not a valid value for the
* specified {@code openType}, or {@code defaultValue} is non null
* and {@code openType} is an {@code ArrayType} or a {@code
* TabularType}, or both {@code minValue} and {@code maxValue} are
* non-null and {@code minValue.compareTo(maxValue) > 0} is {@code
* true}, or both {@code defaultValue} and {@code minValue} are
* non-null and {@code minValue.compareTo(defaultValue) > 0} is
* {@code true}, or both {@code defaultValue} and {@code maxValue}
* are non-null and {@code defaultValue.compareTo(maxValue) > 0}
* is {@code true}.
*/
public <T> OpenMBeanParameterInfoSupport(String name,
String description,
OpenType<T> openType,
T defaultValue,
Comparable<T> minValue,
Comparable<T> maxValue)
throws OpenDataException {
this(name, description, openType,
defaultValue, null, minValue, maxValue);
}
private <T> OpenMBeanParameterInfoSupport(String name,
String description,
OpenType<T> openType,
T defaultValue,
T[] legalValues,
Comparable<T> minValue,
Comparable<T> maxValue)
throws OpenDataException {
super(name,
(openType == null) ? null : openType.getClassName(),
description,
makeDescriptor(openType,
defaultValue, legalValues, minValue, maxValue));
this.openType = openType;
Descriptor d = getDescriptor();
this.defaultValue = defaultValue;
this.minValue = minValue;
this.maxValue = maxValue;
// We already converted the array into an unmodifiable Set
// in the descriptor.
this.legalValues = (Set<?>) d.getFieldValue("legalValues");
check(this);
}
/**
* An object serialized in a version of the API before Descriptors were
* added to this class will have an empty or null Descriptor.
* For consistency with our
* behavior in this version, we must replace the object with one
* where the Descriptors reflect the same values of openType, defaultValue,
* etc.
**/
private Object readResolve() {
if (getDescriptor().getFieldNames().length == 0) {
// This noise allows us to avoid "unchecked" warnings without
// having to suppress them explicitly.
OpenType<Object> xopenType = cast(openType);
Set<Object> xlegalValues = cast(legalValues);
Comparable<Object> xminValue = cast(minValue);
Comparable<Object> xmaxValue = cast(maxValue);
return new OpenMBeanParameterInfoSupport(
name, description, openType,
makeDescriptor(xopenType, defaultValue, xlegalValues,
xminValue, xmaxValue));
} else
return this;
}
/**
* Returns the open type for the values of the parameter described
* by this {@code OpenMBeanParameterInfoSupport} instance.
*/
public OpenType<?> getOpenType() {
return openType;
}
/**
* Returns the default value for the parameter described by this
* {@code OpenMBeanParameterInfoSupport} instance, if specified,
* or {@code null} otherwise.
*/
public Object getDefaultValue() {
// Special case for ArrayType and TabularType
// [JF] TODO: clone it so that it cannot be altered,
// [JF] TODO: if we decide to support defaultValue as an array itself.
// [JF] As of today (oct 2000) it is not supported so
// defaultValue is null for arrays. Nothing to do.
return defaultValue;
}
/**
* Returns an unmodifiable Set of legal values for the parameter
* described by this {@code OpenMBeanParameterInfoSupport}
* instance, if specified, or {@code null} otherwise.
*/
public Set<?> getLegalValues() {
// Special case for ArrayType and TabularType
// [JF] TODO: clone values so that they cannot be altered,
// [JF] TODO: if we decide to support LegalValues as an array itself.
// [JF] As of today (oct 2000) it is not supported so
// legalValues is null for arrays. Nothing to do.
// Returns our legalValues Set (set was constructed unmodifiable)
return (legalValues);
}
/**
* Returns the minimal value for the parameter described by this
* {@code OpenMBeanParameterInfoSupport} instance, if specified,
* or {@code null} otherwise.
*/
public Comparable<?> getMinValue() {
// Note: only comparable values have a minValue, so that's not
// the case of arrays and tabulars (always null).
return minValue;
}
/**
* Returns the maximal value for the parameter described by this
* {@code OpenMBeanParameterInfoSupport} instance, if specified,
* or {@code null} otherwise.
*/
public Comparable<?> getMaxValue() {
// Note: only comparable values have a maxValue, so that's not
// the case of arrays and tabulars (always null).
return maxValue;
}
/**
* Returns {@code true} if this {@code
* OpenMBeanParameterInfoSupport} instance specifies a non-null
* default value for the described parameter, {@code false}
* otherwise.
*/
public boolean hasDefaultValue() {
return (defaultValue != null);
}
/**
* Returns {@code true} if this {@code
* OpenMBeanParameterInfoSupport} instance specifies a non-null
* set of legal values for the described parameter, {@code false}
* otherwise.
*/
public boolean hasLegalValues() {
return (legalValues != null);
}
/**
* Returns {@code true} if this {@code
* OpenMBeanParameterInfoSupport} instance specifies a non-null
* minimal value for the described parameter, {@code false}
* otherwise.
*/
public boolean hasMinValue() {
return (minValue != null);
}
/**
* Returns {@code true} if this {@code
* OpenMBeanParameterInfoSupport} instance specifies a non-null
* maximal value for the described parameter, {@code false}
* otherwise.
*/
public boolean hasMaxValue() {
return (maxValue != null);
}
/**
* Tests whether {@code obj} is a valid value for the parameter
* described by this {@code OpenMBeanParameterInfo} instance.
*
* @param obj the object to be tested.
*
* @return {@code true} if {@code obj} is a valid value
* for the parameter described by this
* {@code OpenMBeanParameterInfo} instance,
* {@code false} otherwise.
*/
public boolean isValue(Object obj) {
return OpenMBeanAttributeInfoSupport.isValue(this, obj);
// compiler bug? should be able to omit class name here
// also below in toString and hashCode
}
/* *** Commodity methods from java.lang.Object *** */
/**
* <p>Compares the specified {@code obj} parameter with this {@code
* OpenMBeanParameterInfoSupport} instance for equality.</p>
*
* <p>Returns {@code true} if and only if all of the following
* statements are true:
*
* <ul>
* <li>{@code obj} is non null,</li>
* <li>{@code obj} also implements the {@code OpenMBeanParameterInfo}
* interface,</li>
* <li>their names are equal</li>
* <li>their open types are equal</li>
* <li>their default, min, max and legal values are equal.</li>
* </ul>
* This ensures that this {@code equals} method works properly for
* {@code obj} parameters which are different implementations of
* the {@code OpenMBeanParameterInfo} interface.
*
* <p>If {@code obj} also implements {@link DescriptorRead}, then its
* {@link DescriptorRead#getDescriptor() getDescriptor()} method must
* also return the same value as for this object.</p>
*
* @param obj the object to be compared for equality with this
* {@code OpenMBeanParameterInfoSupport} instance.
*
* @return {@code true} if the specified object is equal to this
* {@code OpenMBeanParameterInfoSupport} instance.
*/
public boolean equals(Object obj) {
if (!(obj instanceof OpenMBeanParameterInfo))
return false;
OpenMBeanParameterInfo other = (OpenMBeanParameterInfo) obj;
return equal(this, other);
}
/**
* <p>Returns the hash code value for this {@code
* OpenMBeanParameterInfoSupport} instance.</p>
*
* <p>The hash code of an {@code OpenMBeanParameterInfoSupport}
* instance is the sum of the hash codes of all elements of
* information used in {@code equals} comparisons (ie: its name,
* its <i>open type</i>, its default, min, max and legal
* values, and its Descriptor).
*
* <p>This ensures that {@code t1.equals(t2)} implies that {@code
* t1.hashCode()==t2.hashCode()} for any two {@code
* OpenMBeanParameterInfoSupport} instances {@code t1} and {@code
* t2}, as required by the general contract of the method {@link
* Object#hashCode() Object.hashCode()}.
*
* <p>However, note that another instance of a class implementing
* the {@code OpenMBeanParameterInfo} interface may be equal to
* this {@code OpenMBeanParameterInfoSupport} instance as defined
* by {@link #equals(java.lang.Object)}, but may have a different
* hash code if it is calculated differently.
*
* <p>As {@code OpenMBeanParameterInfoSupport} instances are
* immutable, the hash code for this instance is calculated once,
* on the first call to {@code hashCode}, and then the same value
* is returned for subsequent calls.
*
* @return the hash code value for this {@code
* OpenMBeanParameterInfoSupport} instance
*/
public int hashCode() {
// Calculate the hash code value if it has not yet been done
// (ie 1st call to hashCode())
//
if (myHashCode == null)
myHashCode = OpenMBeanAttributeInfoSupport.hashCode(this);
// return always the same hash code for this instance (immutable)
//
return myHashCode.intValue();
}
/**
* Returns a string representation of this
* {@code OpenMBeanParameterInfoSupport} instance.
* <p>
* The string representation consists of the name of this class (i.e.
* {@code javax.management.openmbean.OpenMBeanParameterInfoSupport}),
* the string representation of the name and open type of the described
* parameter, the string representation of its default, min, max and legal
* values and the string representation of its descriptor.
* <p>
* As {@code OpenMBeanParameterInfoSupport} instances are immutable,
* the string representation for this instance is calculated once,
* on the first call to {@code toString}, and then the same value
* is returned for subsequent calls.
*
* @return a string representation of this
* {@code OpenMBeanParameterInfoSupport} instance.
*/
public String toString() {
// Calculate the string value if it has not yet been done (ie
// 1st call to toString())
//
if (myToString == null)
myToString = OpenMBeanAttributeInfoSupport.toString(this);
// return always the same string representation for this
// instance (immutable)
//
return myToString;
}
}

View File

@@ -0,0 +1,418 @@
/*
* Copyright (c) 2000, 2008, Oracle and/or its affiliates. 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
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation. Oracle designates this
* particular file as subject to the "Classpath" exception as provided
* by Oracle in the LICENSE file that accompanied this code.
*
* This code is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
*
* You should have received a copy of the GNU General Public License version
* 2 along with this work; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
*
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
*/
package javax.management.openmbean;
import com.sun.jmx.mbeanserver.GetPropertyAction;
import java.io.IOException;
import java.io.InvalidObjectException;
import java.io.ObjectInputStream;
import java.io.Serializable;
import java.security.AccessController;
import java.security.PrivilegedAction;
import java.util.Arrays;
import java.util.Collections;
import java.util.List;
import javax.management.Descriptor;
import javax.management.ImmutableDescriptor;
/**
* The <code>OpenType</code> class is the parent abstract class of all classes which describe the actual <i>open type</i>
* of open data values.
* <p>
* An <i>open type</i> is defined by:
* <ul>
* <li>the fully qualified Java class name of the open data values this type describes;
* note that only a limited set of Java classes is allowed for open data values
* (see {@link #ALLOWED_CLASSNAMES_LIST ALLOWED_CLASSNAMES_LIST}),</li>
* <li>its name,</li>
* <li>its description.</li>
* </ul>
*
* @param <T> the Java type that instances described by this type must
* have. For example, {@link SimpleType#INTEGER} is a {@code
* SimpleType<Integer>} which is a subclass of {@code OpenType<Integer>},
* meaning that an attribute, parameter, or return value that is described
* as a {@code SimpleType.INTEGER} must have Java type
* {@link Integer}.
*
* @since 1.5
*/
public abstract class OpenType<T> implements Serializable {
/* Serial version */
static final long serialVersionUID = -9195195325186646468L;
/**
* List of the fully qualified names of the Java classes allowed for open
* data values. A multidimensional array of any one of these classes or
* their corresponding primitive types is also an allowed class for open
* data values.
*
<pre>ALLOWED_CLASSNAMES_LIST = {
"java.lang.Void",
"java.lang.Boolean",
"java.lang.Character",
"java.lang.Byte",
"java.lang.Short",
"java.lang.Integer",
"java.lang.Long",
"java.lang.Float",
"java.lang.Double",
"java.lang.String",
"java.math.BigDecimal",
"java.math.BigInteger",
"java.util.Date",
"javax.management.ObjectName",
CompositeData.class.getName(),
TabularData.class.getName() } ;
</pre>
*
*/
public static final List<String> ALLOWED_CLASSNAMES_LIST =
Collections.unmodifiableList(
Arrays.asList(
"java.lang.Void",
"java.lang.Boolean",
"java.lang.Character",
"java.lang.Byte",
"java.lang.Short",
"java.lang.Integer",
"java.lang.Long",
"java.lang.Float",
"java.lang.Double",
"java.lang.String",
"java.math.BigDecimal",
"java.math.BigInteger",
"java.util.Date",
"javax.management.ObjectName",
CompositeData.class.getName(), // better refer to these two class names like this, rather than hardcoding a string,
TabularData.class.getName()) ); // in case the package of these classes should change (who knows...)
/**
* @deprecated Use {@link #ALLOWED_CLASSNAMES_LIST ALLOWED_CLASSNAMES_LIST} instead.
*/
@Deprecated
public static final String[] ALLOWED_CLASSNAMES =
ALLOWED_CLASSNAMES_LIST.toArray(new String[0]);
/**
* @serial The fully qualified Java class name of open data values this
* type describes.
*/
private String className;
/**
* @serial The type description (should not be null or empty).
*/
private String description;
/**
* @serial The name given to this type (should not be null or empty).
*/
private String typeName;
/**
* Tells if this type describes an array (checked in constructor).
*/
private transient boolean isArray = false;
/**
* Cached Descriptor for this OpenType, constructed on demand.
*/
private transient Descriptor descriptor;
/* *** Constructor *** */
/**
* Constructs an <code>OpenType</code> instance (actually a subclass instance as <code>OpenType</code> is abstract),
* checking for the validity of the given parameters.
* The validity constraints are described below for each parameter.
* <br>&nbsp;
* @param className The fully qualified Java class name of the open data values this open type describes.
* The valid Java class names allowed for open data values are listed in
* {@link #ALLOWED_CLASSNAMES_LIST ALLOWED_CLASSNAMES_LIST}.
* A multidimensional array of any one of these classes
* or their corresponding primitive types is also an allowed class,
* in which case the class name follows the rules defined by the method
* {@link Class#getName() getName()} of <code>java.lang.Class</code>.
* For example, a 3-dimensional array of Strings has for class name
* &quot;<code>[[[Ljava.lang.String;</code>&quot; (without the quotes).
* <br>&nbsp;
* @param typeName The name given to the open type this instance represents; cannot be a null or empty string.
* <br>&nbsp;
* @param description The human readable description of the open type this instance represents;
* cannot be a null or empty string.
* <br>&nbsp;
* @throws IllegalArgumentException if <var>className</var>, <var>typeName</var> or <var>description</var>
* is a null or empty string
* <br>&nbsp;
* @throws OpenDataException if <var>className</var> is not one of the allowed Java class names for open data
*/
protected OpenType(String className,
String typeName,
String description) throws OpenDataException {
checkClassNameOverride();
this.typeName = valid("typeName", typeName);
this.description = valid("description", description);
this.className = validClassName(className);
this.isArray = (this.className != null && this.className.startsWith("["));
}
/* Package-private constructor for callers we trust to get it right. */
OpenType(String className, String typeName, String description,
boolean isArray) {
this.className = valid("className",className);
this.typeName = valid("typeName", typeName);
this.description = valid("description", description);
this.isArray = isArray;
}
private void checkClassNameOverride() throws SecurityException {
if (this.getClass().getClassLoader() == null)
return; // We trust bootstrap classes.
if (overridesGetClassName(this.getClass())) {
final GetPropertyAction getExtendOpenTypes =
new GetPropertyAction("jmx.extend.open.types");
if (AccessController.doPrivileged(getExtendOpenTypes) == null) {
throw new SecurityException("Cannot override getClassName() " +
"unless -Djmx.extend.open.types");
}
}
}
private static boolean overridesGetClassName(final Class<?> c) {
return AccessController.doPrivileged(new PrivilegedAction<Boolean>() {
public Boolean run() {
try {
return (c.getMethod("getClassName").getDeclaringClass() !=
OpenType.class);
} catch (Exception e) {
return true; // fail safe
}
}
});
}
private static String validClassName(String className) throws OpenDataException {
className = valid("className", className);
// Check if className describes an array class, and determines its elements' class name.
// (eg: a 3-dimensional array of Strings has for class name: "[[[Ljava.lang.String;")
//
int n = 0;
while (className.startsWith("[", n)) {
n++;
}
String eltClassName; // class name of array elements
boolean isPrimitiveArray = false;
if (n > 0) {
if (className.startsWith("L", n) && className.endsWith(";")) {
// removes the n leading '[' + the 'L' characters
// and the last ';' character
eltClassName = className.substring(n+1, className.length()-1);
} else if (n == className.length() - 1) {
// removes the n leading '[' characters
eltClassName = className.substring(n, className.length());
isPrimitiveArray = true;
} else {
throw new OpenDataException("Argument className=\"" + className +
"\" is not a valid class name");
}
} else {
// not an array
eltClassName = className;
}
// Check that eltClassName's value is one of the allowed basic data types for open data
//
boolean ok = false;
if (isPrimitiveArray) {
ok = ArrayType.isPrimitiveContentType(eltClassName);
} else {
ok = ALLOWED_CLASSNAMES_LIST.contains(eltClassName);
}
if ( ! ok ) {
throw new OpenDataException("Argument className=\""+ className +
"\" is not one of the allowed Java class names for open data.");
}
return className;
}
/* Return argValue.trim() provided argValue is neither null nor empty;
otherwise throw IllegalArgumentException. */
private static String valid(String argName, String argValue) {
if (argValue == null || (argValue = argValue.trim()).equals(""))
throw new IllegalArgumentException("Argument " + argName +
" cannot be null or empty");
return argValue;
}
/* Package-private access to a Descriptor containing this OpenType. */
synchronized Descriptor getDescriptor() {
if (descriptor == null) {
descriptor = new ImmutableDescriptor(new String[] {"openType"},
new Object[] {this});
}
return descriptor;
}
/* *** Open type information methods *** */
/**
* Returns the fully qualified Java class name of the open data values
* this open type describes.
* The only possible Java class names for open data values are listed in
* {@link #ALLOWED_CLASSNAMES_LIST ALLOWED_CLASSNAMES_LIST}.
* A multidimensional array of any one of these classes or their
* corresponding primitive types is also an allowed class,
* in which case the class name follows the rules defined by the method
* {@link Class#getName() getName()} of <code>java.lang.Class</code>.
* For example, a 3-dimensional array of Strings has for class name
* &quot;<code>[[[Ljava.lang.String;</code>&quot; (without the quotes),
* a 3-dimensional array of Integers has for class name
* &quot;<code>[[[Ljava.lang.Integer;</code>&quot; (without the quotes),
* and a 3-dimensional array of int has for class name
* &quot;<code>[[[I</code>&quot; (without the quotes)
*
* @return the class name.
*/
public String getClassName() {
return className;
}
// A version of getClassName() that can only be called from within this
// package and that cannot be overridden.
String safeGetClassName() {
return className;
}
/**
* Returns the name of this <code>OpenType</code> instance.
*
* @return the type name.
*/
public String getTypeName() {
return typeName;
}
/**
* Returns the text description of this <code>OpenType</code> instance.
*
* @return the description.
*/
public String getDescription() {
return description;
}
/**
* Returns <code>true</code> if the open data values this open
* type describes are arrays, <code>false</code> otherwise.
*
* @return true if this is an array type.
*/
public boolean isArray() {
return isArray;
}
/**
* Tests whether <var>obj</var> is a value for this open type.
*
* @param obj the object to be tested for validity.
*
* @return <code>true</code> if <var>obj</var> is a value for this
* open type, <code>false</code> otherwise.
*/
public abstract boolean isValue(Object obj) ;
/**
* Tests whether values of the given type can be assigned to this open type.
* The default implementation of this method returns true only if the
* types are equal.
*
* @param ot the type to be tested.
*
* @return true if {@code ot} is assignable to this open type.
*/
boolean isAssignableFrom(OpenType<?> ot) {
return this.equals(ot);
}
/* *** Methods overriden from class Object *** */
/**
* Compares the specified <code>obj</code> parameter with this
* open type instance for equality.
*
* @param obj the object to compare to.
*
* @return true if this object and <code>obj</code> are equal.
*/
public abstract boolean equals(Object obj) ;
public abstract int hashCode() ;
/**
* Returns a string representation of this open type instance.
*
* @return the string representation.
*/
public abstract String toString() ;
/**
* Deserializes an {@link OpenType} from an {@link java.io.ObjectInputStream}.
*/
private void readObject(ObjectInputStream in)
throws IOException, ClassNotFoundException {
checkClassNameOverride();
ObjectInputStream.GetField fields = in.readFields();
final String classNameField;
final String descriptionField;
final String typeNameField;
try {
classNameField =
validClassName((String) fields.get("className", null));
descriptionField =
valid("description", (String) fields.get("description", null));
typeNameField =
valid("typeName", (String) fields.get("typeName", null));
} catch (Exception e) {
IOException e2 = new InvalidObjectException(e.getMessage());
e2.initCause(e);
throw e2;
}
className = classNameField;
description = descriptionField;
typeName = typeNameField;
isArray = (className.startsWith("["));
}
}

View File

@@ -0,0 +1,320 @@
/*
* Copyright (c) 2000, 2013, Oracle and/or its affiliates. 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
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation. Oracle designates this
* particular file as subject to the "Classpath" exception as provided
* by Oracle in the LICENSE file that accompanied this code.
*
* This code is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
*
* You should have received a copy of the GNU General Public License version
* 2 along with this work; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
*
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
*/
package javax.management.openmbean;
// java import
//
import java.io.InvalidObjectException;
import java.io.ObjectStreamException;
import java.math.BigDecimal;
import java.math.BigInteger;
import java.util.Date;
import java.util.Map;
import java.util.HashMap;
// jmx import
//
import javax.management.ObjectName;
/**
* The <code>SimpleType</code> class is the <i>open type</i> class whose instances describe
* all <i>open data</i> values which are neither arrays,
* nor {@link CompositeData CompositeData} values,
* nor {@link TabularData TabularData} values.
* It predefines all its possible instances as static fields, and has no public constructor.
* <p>
* Given a <code>SimpleType</code> instance describing values whose Java class name is <i>className</i>,
* the internal fields corresponding to the name and description of this <code>SimpleType</code> instance
* are also set to <i>className</i>.
* In other words, its methods <code>getClassName</code>, <code>getTypeName</code> and <code>getDescription</code>
* all return the same string value <i>className</i>.
*
* @since 1.5
*/
public final class SimpleType<T> extends OpenType<T> {
/* Serial version */
static final long serialVersionUID = 2215577471957694503L;
// SimpleType instances.
// IF YOU ADD A SimpleType, YOU MUST UPDATE OpenType and typeArray
/**
* The <code>SimpleType</code> instance describing values whose
* Java class name is <code>java.lang.Void</code>.
*/
public static final SimpleType<Void> VOID =
new SimpleType<Void>(Void.class);
/**
* The <code>SimpleType</code> instance describing values whose
* Java class name is <code>java.lang.Boolean</code>.
*/
public static final SimpleType<Boolean> BOOLEAN =
new SimpleType<Boolean>(Boolean.class);
/**
* The <code>SimpleType</code> instance describing values whose
* Java class name is <code>java.lang.Character</code>.
*/
public static final SimpleType<Character> CHARACTER =
new SimpleType<Character>(Character.class);
/**
* The <code>SimpleType</code> instance describing values whose
* Java class name is <code>java.lang.Byte</code>.
*/
public static final SimpleType<Byte> BYTE =
new SimpleType<Byte>(Byte.class);
/**
* The <code>SimpleType</code> instance describing values whose
* Java class name is <code>java.lang.Short</code>.
*/
public static final SimpleType<Short> SHORT =
new SimpleType<Short>(Short.class);
/**
* The <code>SimpleType</code> instance describing values whose
* Java class name is <code>java.lang.Integer</code>.
*/
public static final SimpleType<Integer> INTEGER =
new SimpleType<Integer>(Integer.class);
/**
* The <code>SimpleType</code> instance describing values whose
* Java class name is <code>java.lang.Long</code>.
*/
public static final SimpleType<Long> LONG =
new SimpleType<Long>(Long.class);
/**
* The <code>SimpleType</code> instance describing values whose
* Java class name is <code>java.lang.Float</code>.
*/
public static final SimpleType<Float> FLOAT =
new SimpleType<Float>(Float.class);
/**
* The <code>SimpleType</code> instance describing values whose
* Java class name is <code>java.lang.Double</code>.
*/
public static final SimpleType<Double> DOUBLE =
new SimpleType<Double>(Double.class);
/**
* The <code>SimpleType</code> instance describing values whose
* Java class name is <code>java.lang.String</code>.
*/
public static final SimpleType<String> STRING =
new SimpleType<String>(String.class);
/**
* The <code>SimpleType</code> instance describing values whose
* Java class name is <code>java.math.BigDecimal</code>.
*/
public static final SimpleType<BigDecimal> BIGDECIMAL =
new SimpleType<BigDecimal>(BigDecimal.class);
/**
* The <code>SimpleType</code> instance describing values whose
* Java class name is <code>java.math.BigInteger</code>.
*/
public static final SimpleType<BigInteger> BIGINTEGER =
new SimpleType<BigInteger>(BigInteger.class);
/**
* The <code>SimpleType</code> instance describing values whose
* Java class name is <code>java.util.Date</code>.
*/
public static final SimpleType<Date> DATE =
new SimpleType<Date>(Date.class);
/**
* The <code>SimpleType</code> instance describing values whose
* Java class name is <code>javax.management.ObjectName</code>.
*/
public static final SimpleType<ObjectName> OBJECTNAME =
new SimpleType<ObjectName>(ObjectName.class);
private static final SimpleType<?>[] typeArray = {
VOID, BOOLEAN, CHARACTER, BYTE, SHORT, INTEGER, LONG, FLOAT,
DOUBLE, STRING, BIGDECIMAL, BIGINTEGER, DATE, OBJECTNAME,
};
private transient Integer myHashCode = null; // As this instance is immutable, these two values
private transient String myToString = null; // need only be calculated once.
/* *** Constructor *** */
private SimpleType(Class<T> valueClass) {
super(valueClass.getName(), valueClass.getName(), valueClass.getName(),
false);
}
/* *** SimpleType specific information methods *** */
/**
* Tests whether <var>obj</var> is a value for this
* <code>SimpleType</code> instance. <p> This method returns
* <code>true</code> if and only if <var>obj</var> is not null and
* <var>obj</var>'s class name is the same as the className field
* defined for this <code>SimpleType</code> instance (ie the class
* name returned by the {@link OpenType#getClassName()
* getClassName} method).
*
* @param obj the object to be tested.
*
* @return <code>true</code> if <var>obj</var> is a value for this
* <code>SimpleType</code> instance.
*/
public boolean isValue(Object obj) {
// if obj is null, return false
//
if (obj == null) {
return false;
}
// Test if obj's class name is the same as for this instance
//
return this.getClassName().equals(obj.getClass().getName());
}
/* *** Methods overriden from class Object *** */
/**
* Compares the specified <code>obj</code> parameter with this <code>SimpleType</code> instance for equality.
* <p>
* Two <code>SimpleType</code> instances are equal if and only if their
* {@link OpenType#getClassName() getClassName} methods return the same value.
*
* @param obj the object to be compared for equality with this <code>SimpleType</code> instance;
* if <var>obj</var> is <code>null</code> or is not an instance of the class <code>SimpleType</code>,
* <code>equals</code> returns <code>false</code>.
*
* @return <code>true</code> if the specified object is equal to this <code>SimpleType</code> instance.
*/
public boolean equals(Object obj) {
/* If it weren't for readReplace(), we could replace this method
with just:
return (this == obj);
*/
if (!(obj instanceof SimpleType<?>))
return false;
SimpleType<?> other = (SimpleType<?>) obj;
// Test if other's className field is the same as for this instance
//
return this.getClassName().equals(other.getClassName());
}
/**
* Returns the hash code value for this <code>SimpleType</code> instance.
* The hash code of a <code>SimpleType</code> instance is the the hash code of
* the string value returned by the {@link OpenType#getClassName() getClassName} method.
* <p>
* As <code>SimpleType</code> instances are immutable, the hash code for this instance is calculated once,
* on the first call to <code>hashCode</code>, and then the same value is returned for subsequent calls.
*
* @return the hash code value for this <code>SimpleType</code> instance
*/
public int hashCode() {
// Calculate the hash code value if it has not yet been done (ie 1st call to hashCode())
//
if (myHashCode == null) {
myHashCode = Integer.valueOf(this.getClassName().hashCode());
}
// return always the same hash code for this instance (immutable)
//
return myHashCode.intValue();
}
/**
* Returns a string representation of this <code>SimpleType</code> instance.
* <p>
* The string representation consists of
* the name of this class (ie <code>javax.management.openmbean.SimpleType</code>) and the type name
* for this instance (which is the java class name of the values this <code>SimpleType</code> instance represents).
* <p>
* As <code>SimpleType</code> instances are immutable, the string representation for this instance is calculated once,
* on the first call to <code>toString</code>, and then the same value is returned for subsequent calls.
*
* @return a string representation of this <code>SimpleType</code> instance
*/
public String toString() {
// Calculate the string representation if it has not yet been done (ie 1st call to toString())
//
if (myToString == null) {
myToString = this.getClass().getName()+ "(name="+ getTypeName() +")";
}
// return always the same string representation for this instance (immutable)
//
return myToString;
}
private static final Map<SimpleType<?>,SimpleType<?>> canonicalTypes =
new HashMap<SimpleType<?>,SimpleType<?>>();
static {
for (int i = 0; i < typeArray.length; i++) {
final SimpleType<?> type = typeArray[i];
canonicalTypes.put(type, type);
}
}
/**
* Replace an object read from an {@link
* java.io.ObjectInputStream} with the unique instance for that
* value.
*
* @return the replacement object.
*
* @exception ObjectStreamException if the read object cannot be
* resolved.
*/
public Object readResolve() throws ObjectStreamException {
final SimpleType<?> canonical = canonicalTypes.get(this);
if (canonical == null) {
// Should not happen
throw new InvalidObjectException("Invalid SimpleType: " + this);
}
return canonical;
}
}

View File

@@ -0,0 +1,304 @@
/*
* Copyright (c) 2000, 2007, Oracle and/or its affiliates. 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
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation. Oracle designates this
* particular file as subject to the "Classpath" exception as provided
* by Oracle in the LICENSE file that accompanied this code.
*
* This code is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
*
* You should have received a copy of the GNU General Public License version
* 2 along with this work; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
*
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
*/
package javax.management.openmbean;
// java import
//
import java.util.Set;
import java.util.Collection;
// jmx import
//
/**
* The <tt>TabularData</tt> interface specifies the behavior of a specific type of complex <i>open data</i> objects
* which represent <i>tabular data</i> structures.
*
* @since 1.5
*/
public interface TabularData /*extends Map*/ {
/* *** TabularData specific information methods *** */
/**
* Returns the <i>tabular type</i> describing this
* <tt>TabularData</tt> instance.
*
* @return the tabular type.
*/
public TabularType getTabularType();
/**
* Calculates the index that would be used in this <tt>TabularData</tt> instance to refer to the specified
* composite data <var>value</var> parameter if it were added to this instance.
* This method checks for the type validity of the specified <var>value</var>,
* but does not check if the calculated index is already used to refer to a value in this <tt>TabularData</tt> instance.
*
* @param value the composite data value whose index in this
* <tt>TabularData</tt> instance is to be calculated;
* must be of the same composite type as this instance's row type;
* must not be null.
*
* @return the index that the specified <var>value</var> would have in this <tt>TabularData</tt> instance.
*
* @throws NullPointerException if <var>value</var> is <tt>null</tt>
*
* @throws InvalidOpenTypeException if <var>value</var> does not conform to this <tt>TabularData</tt> instance's
* row type definition.
*/
public Object[] calculateIndex(CompositeData value) ;
/* *** Content information query methods *** */
/**
* Returns the number of <tt>CompositeData</tt> values (ie the
* number of rows) contained in this <tt>TabularData</tt>
* instance.
*
* @return the number of values contained.
*/
public int size() ;
/**
* Returns <tt>true</tt> if the number of <tt>CompositeData</tt>
* values (ie the number of rows) contained in this
* <tt>TabularData</tt> instance is zero.
*
* @return true if this <tt>TabularData</tt> is empty.
*/
public boolean isEmpty() ;
/**
* Returns <tt>true</tt> if and only if this <tt>TabularData</tt> instance contains a <tt>CompositeData</tt> value
* (ie a row) whose index is the specified <var>key</var>. If <var>key</var> is <tt>null</tt> or does not conform to
* this <tt>TabularData</tt> instance's <tt>TabularType</tt> definition, this method simply returns <tt>false</tt>.
*
* @param key the index value whose presence in this <tt>TabularData</tt> instance is to be tested.
*
* @return <tt>true</tt> if this <tt>TabularData</tt> indexes a row value with the specified key.
*/
public boolean containsKey(Object[] key) ;
/**
* Returns <tt>true</tt> if and only if this <tt>TabularData</tt> instance contains the specified
* <tt>CompositeData</tt> value. If <var>value</var> is <tt>null</tt> or does not conform to
* this <tt>TabularData</tt> instance's row type definition, this method simply returns <tt>false</tt>.
*
* @param value the row value whose presence in this <tt>TabularData</tt> instance is to be tested.
*
* @return <tt>true</tt> if this <tt>TabularData</tt> instance contains the specified row value.
*/
public boolean containsValue(CompositeData value) ;
/**
* Returns the <tt>CompositeData</tt> value whose index is
* <var>key</var>, or <tt>null</tt> if there is no value mapping
* to <var>key</var>, in this <tt>TabularData</tt> instance.
*
* @param key the key of the row to return.
*
* @return the value corresponding to <var>key</var>.
*
* @throws NullPointerException if the <var>key</var> is
* <tt>null</tt>
* @throws InvalidKeyException if the <var>key</var> does not
* conform to this <tt>TabularData</tt> instance's *
* <tt>TabularType</tt> definition
*/
public CompositeData get(Object[] key) ;
/* *** Content modification operations (one element at a time) *** */
/**
* Adds <var>value</var> to this <tt>TabularData</tt> instance.
* The composite type of <var>value</var> must be the same as this
* instance's row type (ie the composite type returned by
* <tt>this.getTabularType().{@link TabularType#getRowType
* getRowType()}</tt>), and there must not already be an existing
* value in this <tt>TabularData</tt> instance whose index is the
* same as the one calculated for the <var>value</var> to be
* added. The index for <var>value</var> is calculated according
* to this <tt>TabularData</tt> instance's <tt>TabularType</tt>
* definition (see <tt>TabularType.{@link
* TabularType#getIndexNames getIndexNames()}</tt>).
*
* @param value the composite data value to be added as a new row to this <tt>TabularData</tt> instance;
* must be of the same composite type as this instance's row type;
* must not be null.
*
* @throws NullPointerException if <var>value</var> is <tt>null</tt>
* @throws InvalidOpenTypeException if <var>value</var> does not conform to this <tt>TabularData</tt> instance's
* row type definition.
* @throws KeyAlreadyExistsException if the index for <var>value</var>, calculated according to
* this <tt>TabularData</tt> instance's <tt>TabularType</tt> definition
* already maps to an existing value in the underlying HashMap.
*/
public void put(CompositeData value) ;
/**
* Removes the <tt>CompositeData</tt> value whose index is <var>key</var> from this <tt>TabularData</tt> instance,
* and returns the removed value, or returns <tt>null</tt> if there is no value whose index is <var>key</var>.
*
* @param key the index of the value to get in this <tt>TabularData</tt> instance;
* must be valid with this <tt>TabularData</tt> instance's row type definition;
* must not be null.
*
* @return previous value associated with specified key, or <tt>null</tt>
* if there was no mapping for key.
*
* @throws NullPointerException if the <var>key</var> is <tt>null</tt>
* @throws InvalidKeyException if the <var>key</var> does not conform to this <tt>TabularData</tt> instance's
* <tt>TabularType</tt> definition
*/
public CompositeData remove(Object[] key) ;
/* *** Content modification bulk operations *** */
/**
* Add all the elements in <var>values</var> to this <tt>TabularData</tt> instance.
* If any element in <var>values</var> does not satisfy the constraints defined in {@link #put(CompositeData) <tt>put</tt>},
* or if any two elements in <var>values</var> have the same index calculated according to this <tt>TabularData</tt>
* instance's <tt>TabularType</tt> definition, then an exception describing the failure is thrown
* and no element of <var>values</var> is added, thus leaving this <tt>TabularData</tt> instance unchanged.
*
* @param values the array of composite data values to be added as new rows to this <tt>TabularData</tt> instance;
* if <var>values</var> is <tt>null</tt> or empty, this method returns without doing anything.
*
* @throws NullPointerException if an element of <var>values</var> is <tt>null</tt>
* @throws InvalidOpenTypeException if an element of <var>values</var> does not conform to
* this <tt>TabularData</tt> instance's row type definition
* @throws KeyAlreadyExistsException if the index for an element of <var>values</var>, calculated according to
* this <tt>TabularData</tt> instance's <tt>TabularType</tt> definition
* already maps to an existing value in this instance,
* or two elements of <var>values</var> have the same index.
*/
public void putAll(CompositeData[] values) ;
/**
* Removes all <tt>CompositeData</tt> values (ie rows) from this <tt>TabularData</tt> instance.
*/
public void clear();
/* *** Collection views of the keys and values *** */
/**
* Returns a set view of the keys (ie the index values) of the
* {@code CompositeData} values (ie the rows) contained in this
* {@code TabularData} instance. The returned {@code Set} is a
* {@code Set<List<?>>} but is declared as a {@code Set<?>} for
* compatibility reasons. The returned set can be used to iterate
* over the keys.
*
* @return a set view ({@code Set<List<?>>}) of the index values
* used in this {@code TabularData} instance.
*/
public Set<?> keySet();
/**
* Returns a collection view of the {@code CompositeData} values
* (ie the rows) contained in this {@code TabularData} instance.
* The returned {@code Collection} is a {@code Collection<CompositeData>}
* but is declared as a {@code Collection<?>} for compatibility reasons.
* The returned collection can be used to iterate over the values.
*
* @return a collection view ({@code Collection<CompositeData>})
* of the rows contained in this {@code TabularData} instance.
*/
public Collection<?> values();
/* *** Commodity methods from java.lang.Object *** */
/**
* Compares the specified <var>obj</var> parameter with this <code>TabularData</code> instance for equality.
* <p>
* Returns <tt>true</tt> if and only if all of the following statements are true:
* <ul>
* <li><var>obj</var> is non null,</li>
* <li><var>obj</var> also implements the <code>TabularData</code> interface,</li>
* <li>their row types are equal</li>
* <li>their contents (ie index to value mappings) are equal</li>
* </ul>
* This ensures that this <tt>equals</tt> method works properly for <var>obj</var> parameters which are
* different implementations of the <code>TabularData</code> interface.
* <br>&nbsp;
* @param obj the object to be compared for equality with this <code>TabularData</code> instance;
*
* @return <code>true</code> if the specified object is equal to this <code>TabularData</code> instance.
*/
public boolean equals(Object obj);
/**
* Returns the hash code value for this <code>TabularData</code> instance.
* <p>
* The hash code of a <code>TabularData</code> instance is the sum of the hash codes
* of all elements of information used in <code>equals</code> comparisons
* (ie: its <i>tabular type</i> and its content, where the content is defined as all the index to value mappings).
* <p>
* This ensures that <code> t1.equals(t2) </code> implies that <code> t1.hashCode()==t2.hashCode() </code>
* for any two <code>TabularDataSupport</code> instances <code>t1</code> and <code>t2</code>,
* as required by the general contract of the method
* {@link Object#hashCode() Object.hashCode()}.
*
* @return the hash code value for this <code>TabularDataSupport</code> instance
*/
public int hashCode();
/**
* Returns a string representation of this <code>TabularData</code> instance.
* <p>
* The string representation consists of the name of the implementing class,
* and the tabular type of this instance.
*
* @return a string representation of this <code>TabularData</code> instance
*/
public String toString();
}

View File

@@ -0,0 +1,919 @@
/*
* Copyright (c) 2000, 2018, Oracle and/or its affiliates. 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
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation. Oracle designates this
* particular file as subject to the "Classpath" exception as provided
* by Oracle in the LICENSE file that accompanied this code.
*
* This code is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
*
* You should have received a copy of the GNU General Public License version
* 2 along with this work; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
*
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
*/
package javax.management.openmbean;
// java import
//
import com.sun.jmx.mbeanserver.GetPropertyAction;
import com.sun.jmx.mbeanserver.Util;
import java.io.IOException;
import java.io.ObjectInputStream;
import java.io.Serializable;
import java.security.AccessController;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collection;
import java.util.Collections;
import java.util.HashMap;
import java.util.Iterator;
import java.util.LinkedHashMap;
import java.util.List;
import java.util.Map;
import java.util.Set;
import sun.misc.SharedSecrets;
// jmx import
//
/**
* The <tt>TabularDataSupport</tt> class is the <i>open data</i> class which implements the <tt>TabularData</tt>
* and the <tt>Map</tt> interfaces, and which is internally based on a hash map data structure.
*
* @since 1.5
*/
/* It would make much more sense to implement
Map<List<?>,CompositeData> here, but unfortunately we cannot for
compatibility reasons. If we did that, then we would have to
define e.g.
CompositeData remove(Object)
instead of
Object remove(Object).
That would mean that if any existing code subclassed
TabularDataSupport and overrode
Object remove(Object),
it would (a) no longer compile and (b) not actually override
CompositeData remove(Object)
in binaries compiled before the change.
*/
public class TabularDataSupport
implements TabularData, Map<Object,Object>,
Cloneable, Serializable {
/* Serial version */
static final long serialVersionUID = 5720150593236309827L;
/**
* @serial This tabular data instance's contents: a {@link HashMap}
*/
// field cannot be final because of clone method
private Map<Object,CompositeData> dataMap;
/**
* @serial This tabular data instance's tabular type
*/
private final TabularType tabularType;
/**
* The array of item names that define the index used for rows (convenience field)
*/
private transient String[] indexNamesArray;
/* *** Constructors *** */
/**
* Creates an empty <tt>TabularDataSupport</tt> instance whose open-type is <var>tabularType</var>,
* and whose underlying <tt>HashMap</tt> has a default initial capacity (101) and default load factor (0.75).
* <p>
* This constructor simply calls <tt>this(tabularType, 101, 0.75f);</tt>
*
* @param tabularType the <i>tabular type</i> describing this <tt>TabularData</tt> instance;
* cannot be null.
*
* @throws IllegalArgumentException if the tabular type is null.
*/
public TabularDataSupport(TabularType tabularType) {
this(tabularType, 16, 0.75f);
}
/**
* Creates an empty <tt>TabularDataSupport</tt> instance whose open-type is <var>tabularType</var>,
* and whose underlying <tt>HashMap</tt> has the specified initial capacity and load factor.
*
* @param tabularType the <i>tabular type</i> describing this <tt>TabularData</tt> instance;
* cannot be null.
*
* @param initialCapacity the initial capacity of the HashMap.
*
* @param loadFactor the load factor of the HashMap
*
* @throws IllegalArgumentException if the initial capacity is less than zero,
* or the load factor is nonpositive,
* or the tabular type is null.
*/
public TabularDataSupport(TabularType tabularType, int initialCapacity, float loadFactor) {
// Check tabularType is not null
//
if (tabularType == null) {
throw new IllegalArgumentException("Argument tabularType cannot be null.");
}
// Initialize this.tabularType (and indexNamesArray for convenience)
//
this.tabularType = tabularType;
List<String> tmpNames = tabularType.getIndexNames();
this.indexNamesArray = tmpNames.toArray(new String[tmpNames.size()]);
// Since LinkedHashMap was introduced in SE 1.4, it's conceivable even
// if very unlikely that we might be the server of a 1.3 client. In
// that case you'll need to set this property. See CR 6334663.
String useHashMapProp = AccessController.doPrivileged(
new GetPropertyAction("jmx.tabular.data.hash.map"));
boolean useHashMap = "true".equalsIgnoreCase(useHashMapProp);
// Construct the empty contents HashMap
//
this.dataMap = useHashMap ?
new HashMap<Object,CompositeData>(initialCapacity, loadFactor) :
new LinkedHashMap<Object, CompositeData>(initialCapacity, loadFactor);
}
/* *** TabularData specific information methods *** */
/**
* Returns the <i>tabular type</i> describing this <tt>TabularData</tt> instance.
*/
public TabularType getTabularType() {
return tabularType;
}
/**
* Calculates the index that would be used in this <tt>TabularData</tt> instance to refer to the specified
* composite data <var>value</var> parameter if it were added to this instance.
* This method checks for the type validity of the specified <var>value</var>,
* but does not check if the calculated index is already used to refer to a value in this <tt>TabularData</tt> instance.
*
* @param value the composite data value whose index in this
* <tt>TabularData</tt> instance is to be calculated;
* must be of the same composite type as this instance's row type;
* must not be null.
*
* @return the index that the specified <var>value</var> would have in this <tt>TabularData</tt> instance.
*
* @throws NullPointerException if <var>value</var> is <tt>null</tt>.
*
* @throws InvalidOpenTypeException if <var>value</var> does not conform to this <tt>TabularData</tt> instance's
* row type definition.
*/
public Object[] calculateIndex(CompositeData value) {
// Check value is valid
//
checkValueType(value);
// Return its calculated index
//
return internalCalculateIndex(value).toArray();
}
/* *** Content information query methods *** */
/**
* Returns <tt>true</tt> if and only if this <tt>TabularData</tt> instance contains a <tt>CompositeData</tt> value
* (ie a row) whose index is the specified <var>key</var>. If <var>key</var> cannot be cast to a one dimension array
* of Object instances, this method simply returns <tt>false</tt>; otherwise it returns the the result of the call to
* <tt>this.containsKey((Object[]) key)</tt>.
*
* @param key the index value whose presence in this <tt>TabularData</tt> instance is to be tested.
*
* @return <tt>true</tt> if this <tt>TabularData</tt> indexes a row value with the specified key.
*/
public boolean containsKey(Object key) {
// if key is not an array of Object instances, return false
//
Object[] k;
try {
k = (Object[]) key;
} catch (ClassCastException e) {
return false;
}
return this.containsKey(k);
}
/**
* Returns <tt>true</tt> if and only if this <tt>TabularData</tt> instance contains a <tt>CompositeData</tt> value
* (ie a row) whose index is the specified <var>key</var>. If <var>key</var> is <tt>null</tt> or does not conform to
* this <tt>TabularData</tt> instance's <tt>TabularType</tt> definition, this method simply returns <tt>false</tt>.
*
* @param key the index value whose presence in this <tt>TabularData</tt> instance is to be tested.
*
* @return <tt>true</tt> if this <tt>TabularData</tt> indexes a row value with the specified key.
*/
public boolean containsKey(Object[] key) {
return ( key == null ? false : dataMap.containsKey(Arrays.asList(key)));
}
/**
* Returns <tt>true</tt> if and only if this <tt>TabularData</tt> instance contains the specified
* <tt>CompositeData</tt> value. If <var>value</var> is <tt>null</tt> or does not conform to
* this <tt>TabularData</tt> instance's row type definition, this method simply returns <tt>false</tt>.
*
* @param value the row value whose presence in this <tt>TabularData</tt> instance is to be tested.
*
* @return <tt>true</tt> if this <tt>TabularData</tt> instance contains the specified row value.
*/
public boolean containsValue(CompositeData value) {
return dataMap.containsValue(value);
}
/**
* Returns <tt>true</tt> if and only if this <tt>TabularData</tt> instance contains the specified
* value.
*
* @param value the row value whose presence in this <tt>TabularData</tt> instance is to be tested.
*
* @return <tt>true</tt> if this <tt>TabularData</tt> instance contains the specified row value.
*/
public boolean containsValue(Object value) {
return dataMap.containsValue(value);
}
/**
* This method simply calls <tt>get((Object[]) key)</tt>.
*
* @throws NullPointerException if the <var>key</var> is <tt>null</tt>
* @throws ClassCastException if the <var>key</var> is not of the type <tt>Object[]</tt>
* @throws InvalidKeyException if the <var>key</var> does not conform to this <tt>TabularData</tt> instance's
* <tt>TabularType</tt> definition
*/
public Object get(Object key) {
return get((Object[]) key);
}
/**
* Returns the <tt>CompositeData</tt> value whose index is
* <var>key</var>, or <tt>null</tt> if there is no value mapping
* to <var>key</var>, in this <tt>TabularData</tt> instance.
*
* @param key the index of the value to get in this
* <tt>TabularData</tt> instance; * must be valid with this
* <tt>TabularData</tt> instance's row type definition; * must not
* be null.
*
* @return the value corresponding to <var>key</var>.
*
* @throws NullPointerException if the <var>key</var> is <tt>null</tt>
* @throws InvalidKeyException if the <var>key</var> does not conform to this <tt>TabularData</tt> instance's
* <tt>TabularType</tt> type definition.
*/
public CompositeData get(Object[] key) {
// Check key is not null and valid with tabularType
// (throws NullPointerException, InvalidKeyException)
//
checkKeyType(key);
// Return the mapping stored in the parent HashMap
//
return dataMap.get(Arrays.asList(key));
}
/* *** Content modification operations (one element at a time) *** */
/**
* This method simply calls <tt>put((CompositeData) value)</tt> and
* therefore ignores its <var>key</var> parameter which can be <tt>null</tt>.
*
* @param key an ignored parameter.
* @param value the {@link CompositeData} to put.
*
* @return the value which is put
*
* @throws NullPointerException if the <var>value</var> is <tt>null</tt>
* @throws ClassCastException if the <var>value</var> is not of
* the type <tt>CompositeData</tt>
* @throws InvalidOpenTypeException if the <var>value</var> does
* not conform to this <tt>TabularData</tt> instance's
* <tt>TabularType</tt> definition
* @throws KeyAlreadyExistsException if the key for the
* <var>value</var> parameter, calculated according to this
* <tt>TabularData</tt> instance's <tt>TabularType</tt> definition
* already maps to an existing value
*/
public Object put(Object key, Object value) {
internalPut((CompositeData) value);
return value; // should be return internalPut(...); (5090566)
}
public void put(CompositeData value) {
internalPut(value);
}
private CompositeData internalPut(CompositeData value) {
// Check value is not null, value's type is the same as this instance's row type,
// and calculate the value's index according to this instance's tabularType and
// check it is not already used for a mapping in the parent HashMap
//
List<?> index = checkValueAndIndex(value);
// store the (key, value) mapping in the dataMap HashMap
//
return dataMap.put(index, value);
}
/**
* This method simply calls <tt>remove((Object[]) key)</tt>.
*
* @param key an <tt>Object[]</tt> representing the key to remove.
*
* @return previous value associated with specified key, or <tt>null</tt>
* if there was no mapping for key.
*
* @throws NullPointerException if the <var>key</var> is <tt>null</tt>
* @throws ClassCastException if the <var>key</var> is not of the type <tt>Object[]</tt>
* @throws InvalidKeyException if the <var>key</var> does not conform to this <tt>TabularData</tt> instance's
* <tt>TabularType</tt> definition
*/
public Object remove(Object key) {
return remove((Object[]) key);
}
/**
* Removes the <tt>CompositeData</tt> value whose index is <var>key</var> from this <tt>TabularData</tt> instance,
* and returns the removed value, or returns <tt>null</tt> if there is no value whose index is <var>key</var>.
*
* @param key the index of the value to get in this <tt>TabularData</tt> instance;
* must be valid with this <tt>TabularData</tt> instance's row type definition;
* must not be null.
*
* @return previous value associated with specified key, or <tt>null</tt>
* if there was no mapping for key.
*
* @throws NullPointerException if the <var>key</var> is <tt>null</tt>
* @throws InvalidKeyException if the <var>key</var> does not conform to this <tt>TabularData</tt> instance's
* <tt>TabularType</tt> definition
*/
public CompositeData remove(Object[] key) {
// Check key is not null and valid with tabularType
// (throws NullPointerException, InvalidKeyException)
//
checkKeyType(key);
// Removes the (key, value) mapping in the parent HashMap
//
return dataMap.remove(Arrays.asList(key));
}
/* *** Content modification bulk operations *** */
/**
* Add all the values contained in the specified map <var>t</var>
* to this <tt>TabularData</tt> instance. This method converts
* the collection of values contained in this map into an array of
* <tt>CompositeData</tt> values, if possible, and then call the
* method <tt>putAll(CompositeData[])</tt>. Note that the keys
* used in the specified map <var>t</var> are ignored. This method
* allows, for example to add the content of another
* <tt>TabularData</tt> instance with the same row type (but
* possibly different index names) into this instance.
*
* @param t the map whose values are to be added as new rows to
* this <tt>TabularData</tt> instance; if <var>t</var> is
* <tt>null</tt> or empty, this method returns without doing
* anything.
*
* @throws NullPointerException if a value in <var>t</var> is
* <tt>null</tt>.
* @throws ClassCastException if a value in <var>t</var> is not an
* instance of <tt>CompositeData</tt>.
* @throws InvalidOpenTypeException if a value in <var>t</var>
* does not conform to this <tt>TabularData</tt> instance's row
* type definition.
* @throws KeyAlreadyExistsException if the index for a value in
* <var>t</var>, calculated according to this
* <tt>TabularData</tt> instance's <tt>TabularType</tt> definition
* already maps to an existing value in this instance, or two
* values in <var>t</var> have the same index.
*/
public void putAll(Map<?,?> t) {
// if t is null or empty, just return
//
if ( (t == null) || (t.size() == 0) ) {
return;
}
// Convert the values in t into an array of <tt>CompositeData</tt>
//
CompositeData[] values;
try {
values =
t.values().toArray(new CompositeData[t.size()]);
} catch (java.lang.ArrayStoreException e) {
throw new ClassCastException("Map argument t contains values which are not instances of <tt>CompositeData</tt>");
}
// Add the array of values
//
putAll(values);
}
/**
* Add all the elements in <var>values</var> to this
* <tt>TabularData</tt> instance. If any element in
* <var>values</var> does not satisfy the constraints defined in
* {@link #put(CompositeData) <tt>put</tt>}, or if any two
* elements in <var>values</var> have the same index calculated
* according to this <tt>TabularData</tt> instance's
* <tt>TabularType</tt> definition, then an exception describing
* the failure is thrown and no element of <var>values</var> is
* added, thus leaving this <tt>TabularData</tt> instance
* unchanged.
*
* @param values the array of composite data values to be added as
* new rows to this <tt>TabularData</tt> instance; if
* <var>values</var> is <tt>null</tt> or empty, this method
* returns without doing anything.
*
* @throws NullPointerException if an element of <var>values</var>
* is <tt>null</tt>
* @throws InvalidOpenTypeException if an element of
* <var>values</var> does not conform to this
* <tt>TabularData</tt> instance's row type definition (ie its
* <tt>TabularType</tt> definition)
* @throws KeyAlreadyExistsException if the index for an element
* of <var>values</var>, calculated according to this
* <tt>TabularData</tt> instance's <tt>TabularType</tt> definition
* already maps to an existing value in this instance, or two
* elements of <var>values</var> have the same index
*/
public void putAll(CompositeData[] values) {
// if values is null or empty, just return
//
if ( (values == null) || (values.length == 0) ) {
return;
}
// create the list of indexes corresponding to each value
List<List<?>> indexes =
new ArrayList<List<?>>(values.length + 1);
// Check all elements in values and build index list
//
List<?> index;
for (int i=0; i<values.length; i++) {
// check value and calculate index
index = checkValueAndIndex(values[i]);
// check index is different of those previously calculated
if (indexes.contains(index)) {
throw new KeyAlreadyExistsException("Argument elements values["+ i +"] and values["+ indexes.indexOf(index) +
"] have the same indexes, "+
"calculated according to this TabularData instance's tabularType.");
}
// add to index list
indexes.add(index);
}
// store all (index, value) mappings in the dataMap HashMap
//
for (int i=0; i<values.length; i++) {
dataMap.put(indexes.get(i), values[i]);
}
}
/**
* Removes all rows from this <code>TabularDataSupport</code> instance.
*/
public void clear() {
dataMap.clear();
}
/* *** Informational methods from java.util.Map *** */
/**
* Returns the number of rows in this <code>TabularDataSupport</code> instance.
*
* @return the number of rows in this <code>TabularDataSupport</code> instance.
*/
public int size() {
return dataMap.size();
}
/**
* Returns <tt>true</tt> if this <code>TabularDataSupport</code> instance contains no rows.
*
* @return <tt>true</tt> if this <code>TabularDataSupport</code> instance contains no rows.
*/
public boolean isEmpty() {
return (this.size() == 0);
}
/* *** Collection views from java.util.Map *** */
/**
* Returns a set view of the keys contained in the underlying map of this
* {@code TabularDataSupport} instance used to index the rows.
* Each key contained in this {@code Set} is an unmodifiable {@code List<?>}
* so the returned set view is a {@code Set<List<?>>} but is declared as a
* {@code Set<Object>} for compatibility reasons.
* The set is backed by the underlying map of this
* {@code TabularDataSupport} instance, so changes to the
* {@code TabularDataSupport} instance are reflected in the
* set, and vice-versa.
*
* The set supports element removal, which removes the corresponding
* row from this {@code TabularDataSupport} instance, via the
* {@link Iterator#remove}, {@link Set#remove}, {@link Set#removeAll},
* {@link Set#retainAll}, and {@link Set#clear} operations. It does
* not support the {@link Set#add} or {@link Set#addAll} operations.
*
* @return a set view ({@code Set<List<?>>}) of the keys used to index
* the rows of this {@code TabularDataSupport} instance.
*/
public Set<Object> keySet() {
return dataMap.keySet() ;
}
/**
* Returns a collection view of the rows contained in this
* {@code TabularDataSupport} instance. The returned {@code Collection}
* is a {@code Collection<CompositeData>} but is declared as a
* {@code Collection<Object>} for compatibility reasons.
* The returned collection can be used to iterate over the values.
* The collection is backed by the underlying map, so changes to the
* {@code TabularDataSupport} instance are reflected in the collection,
* and vice-versa.
*
* The collection supports element removal, which removes the corresponding
* index to row mapping from this {@code TabularDataSupport} instance, via
* the {@link Iterator#remove}, {@link Collection#remove},
* {@link Collection#removeAll}, {@link Collection#retainAll},
* and {@link Collection#clear} operations. It does not support
* the {@link Collection#add} or {@link Collection#addAll} operations.
*
* @return a collection view ({@code Collection<CompositeData>}) of
* the values contained in this {@code TabularDataSupport} instance.
*/
@SuppressWarnings("unchecked") // historical confusion about the return type
public Collection<Object> values() {
return Util.cast(dataMap.values());
}
/**
* Returns a collection view of the index to row mappings
* contained in this {@code TabularDataSupport} instance.
* Each element in the returned collection is
* a {@code Map.Entry<List<?>,CompositeData>} but
* is declared as a {@code Map.Entry<Object,Object>}
* for compatibility reasons. Each of the map entry
* keys is an unmodifiable {@code List<?>}.
* The collection is backed by the underlying map of this
* {@code TabularDataSupport} instance, so changes to the
* {@code TabularDataSupport} instance are reflected in
* the collection, and vice-versa.
* The collection supports element removal, which removes
* the corresponding mapping from the map, via the
* {@link Iterator#remove}, {@link Collection#remove},
* {@link Collection#removeAll}, {@link Collection#retainAll},
* and {@link Collection#clear} operations. It does not support
* the {@link Collection#add} or {@link Collection#addAll}
* operations.
* <p>
* <b>IMPORTANT NOTICE</b>: Do not use the {@code setValue} method of the
* {@code Map.Entry} elements contained in the returned collection view.
* Doing so would corrupt the index to row mappings contained in this
* {@code TabularDataSupport} instance.
*
* @return a collection view ({@code Set<Map.Entry<List<?>,CompositeData>>})
* of the mappings contained in this map.
* @see java.util.Map.Entry
*/
@SuppressWarnings("unchecked") // historical confusion about the return type
public Set<Map.Entry<Object,Object>> entrySet() {
return Util.cast(dataMap.entrySet());
}
/* *** Commodity methods from java.lang.Object *** */
/**
* Returns a clone of this <code>TabularDataSupport</code> instance:
* the clone is obtained by calling <tt>super.clone()</tt>, and then cloning the underlying map.
* Only a shallow clone of the underlying map is made, i.e. no cloning of the indexes and row values is made as they are immutable.
*/
/* We cannot use covariance here and return TabularDataSupport
because this would fail with existing code that subclassed
TabularDataSupport and overrode Object clone(). It would not
override the new clone(). */
public Object clone() {
try {
TabularDataSupport c = (TabularDataSupport) super.clone();
c.dataMap = new HashMap<Object,CompositeData>(c.dataMap);
return c;
}
catch (CloneNotSupportedException e) {
throw new InternalError(e.toString(), e);
}
}
/**
* Compares the specified <var>obj</var> parameter with this <code>TabularDataSupport</code> instance for equality.
* <p>
* Returns <tt>true</tt> if and only if all of the following statements are true:
* <ul>
* <li><var>obj</var> is non null,</li>
* <li><var>obj</var> also implements the <code>TabularData</code> interface,</li>
* <li>their tabular types are equal</li>
* <li>their contents (ie all CompositeData values) are equal.</li>
* </ul>
* This ensures that this <tt>equals</tt> method works properly for <var>obj</var> parameters which are
* different implementations of the <code>TabularData</code> interface.
* <br>&nbsp;
* @param obj the object to be compared for equality with this <code>TabularDataSupport</code> instance;
*
* @return <code>true</code> if the specified object is equal to this <code>TabularDataSupport</code> instance.
*/
public boolean equals(Object obj) {
// if obj is null, return false
//
if (obj == null) {
return false;
}
// if obj is not a TabularData, return false
//
TabularData other;
try {
other = (TabularData) obj;
} catch (ClassCastException e) {
return false;
}
// Now, really test for equality between this TabularData implementation and the other:
//
// their tabularType should be equal
if ( ! this.getTabularType().equals(other.getTabularType()) ) {
return false;
}
// their contents should be equal:
// . same size
// . values in this instance are in the other (we know there are no duplicate elements possible)
// (row values comparison is enough, because keys are calculated according to tabularType)
if (this.size() != other.size()) {
return false;
}
for (CompositeData value : dataMap.values()) {
if ( ! other.containsValue(value) ) {
return false;
}
}
// All tests for equality were successfull
//
return true;
}
/**
* Returns the hash code value for this <code>TabularDataSupport</code> instance.
* <p>
* The hash code of a <code>TabularDataSupport</code> instance is the sum of the hash codes
* of all elements of information used in <code>equals</code> comparisons
* (ie: its <i>tabular type</i> and its content, where the content is defined as all the CompositeData values).
* <p>
* This ensures that <code> t1.equals(t2) </code> implies that <code> t1.hashCode()==t2.hashCode() </code>
* for any two <code>TabularDataSupport</code> instances <code>t1</code> and <code>t2</code>,
* as required by the general contract of the method
* {@link Object#hashCode() Object.hashCode()}.
* <p>
* However, note that another instance of a class implementing the <code>TabularData</code> interface
* may be equal to this <code>TabularDataSupport</code> instance as defined by {@link #equals},
* but may have a different hash code if it is calculated differently.
*
* @return the hash code value for this <code>TabularDataSupport</code> instance
*/
public int hashCode() {
int result = 0;
result += this.tabularType.hashCode();
for (Object value : values())
result += value.hashCode();
return result;
}
/**
* Returns a string representation of this <code>TabularDataSupport</code> instance.
* <p>
* The string representation consists of the name of this class (ie <code>javax.management.openmbean.TabularDataSupport</code>),
* the string representation of the tabular type of this instance, and the string representation of the contents
* (ie list the key=value mappings as returned by a call to
* <tt>dataMap.</tt>{@link java.util.HashMap#toString() toString()}).
*
* @return a string representation of this <code>TabularDataSupport</code> instance
*/
public String toString() {
return new StringBuilder()
.append(this.getClass().getName())
.append("(tabularType=")
.append(tabularType.toString())
.append(",contents=")
.append(dataMap.toString())
.append(")")
.toString();
}
/* *** TabularDataSupport internal utility methods *** */
/**
* Returns the index for value, assuming value is valid for this <tt>TabularData</tt> instance
* (ie value is not null, and its composite type is equal to row type).
*
* The index is a List, and not an array, so that an index.equals(otherIndex) call will actually compare contents,
* not just the objects references as is done for an array object.
*
* The returned List is unmodifiable so that once a row has been put into the dataMap, its index cannot be modified,
* for example by a user that would attempt to modify an index contained in the Set returned by keySet().
*/
private List<?> internalCalculateIndex(CompositeData value) {
return Collections.unmodifiableList(Arrays.asList(value.getAll(this.indexNamesArray)));
}
/**
* Checks if the specified key is valid for this <tt>TabularData</tt> instance.
*
* @throws NullPointerException
* @throws InvalidOpenTypeException
*/
private void checkKeyType(Object[] key) {
// Check key is neither null nor empty
//
if ( (key == null) || (key.length == 0) ) {
throw new NullPointerException("Argument key cannot be null or empty.");
}
/* Now check key is valid with tabularType index and row type definitions: */
// key[] should have the size expected for an index
//
if (key.length != this.indexNamesArray.length) {
throw new InvalidKeyException("Argument key's length="+ key.length +
" is different from the number of item values, which is "+ indexNamesArray.length +
", specified for the indexing rows in this TabularData instance.");
}
// each element in key[] should be a value for its corresponding open type specified in rowType
//
OpenType<?> keyElementType;
for (int i=0; i<key.length; i++) {
keyElementType = tabularType.getRowType().getType(this.indexNamesArray[i]);
if ( (key[i] != null) && (! keyElementType.isValue(key[i])) ) {
throw new InvalidKeyException("Argument element key["+ i +"] is not a value for the open type expected for "+
"this element of the index, whose name is \""+ indexNamesArray[i] +
"\" and whose open type is "+ keyElementType);
}
}
}
/**
* Checks the specified value's type is valid for this <tt>TabularData</tt> instance
* (ie value is not null, and its composite type is equal to row type).
*
* @throws NullPointerException
* @throws InvalidOpenTypeException
*/
private void checkValueType(CompositeData value) {
// Check value is not null
//
if (value == null) {
throw new NullPointerException("Argument value cannot be null.");
}
// if value's type is not the same as this instance's row type, throw InvalidOpenTypeException
//
if (!tabularType.getRowType().isValue(value)) {
throw new InvalidOpenTypeException("Argument value's composite type ["+ value.getCompositeType() +
"] is not assignable to "+
"this TabularData instance's row type ["+ tabularType.getRowType() +"].");
}
}
/**
* Checks if the specified value can be put (ie added) in this <tt>TabularData</tt> instance
* (ie value is not null, its composite type is equal to row type, and its index is not already used),
* and returns the index calculated for this value.
*
* The index is a List, and not an array, so that an index.equals(otherIndex) call will actually compare contents,
* not just the objects references as is done for an array object.
*
* @throws NullPointerException
* @throws InvalidOpenTypeException
* @throws KeyAlreadyExistsException
*/
private List<?> checkValueAndIndex(CompositeData value) {
// Check value is valid
//
checkValueType(value);
// Calculate value's index according to this instance's tabularType
// and check it is not already used for a mapping in the parent HashMap
//
List<?> index = internalCalculateIndex(value);
if (dataMap.containsKey(index)) {
throw new KeyAlreadyExistsException("Argument value's index, calculated according to this TabularData "+
"instance's tabularType, already refers to a value in this table.");
}
// The check is OK, so return the index
//
return index;
}
/**
* Deserializes a {@link TabularDataSupport} from an {@link ObjectInputStream}.
*/
private void readObject(ObjectInputStream in)
throws IOException, ClassNotFoundException {
in.defaultReadObject();
List<String> tmpNames = tabularType.getIndexNames();
int size = tmpNames.size();
SharedSecrets.getJavaOISAccess().checkArray(in, String[].class, size);
indexNamesArray = tmpNames.toArray(new String[size]);
}
}

View File

@@ -0,0 +1,380 @@
/*
* Copyright (c) 2000, 2013, Oracle and/or its affiliates. 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
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation. Oracle designates this
* particular file as subject to the "Classpath" exception as provided
* by Oracle in the LICENSE file that accompanied this code.
*
* This code is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
*
* You should have received a copy of the GNU General Public License version
* 2 along with this work; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
*
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
*/
package javax.management.openmbean;
// java import
//
import java.util.ArrayList;
import java.util.Collections;
import java.util.Iterator;
import java.util.List;
// jmx import
//
/**
* The <code>TabularType</code> class is the <i> open type</i> class
* whose instances describe the types of {@link TabularData TabularData} values.
*
* @since 1.5
*/
public class TabularType extends OpenType<TabularData> {
/* Serial version */
static final long serialVersionUID = 6554071860220659261L;
/**
* @serial The composite type of rows
*/
private CompositeType rowType;
/**
* @serial The items used to index each row element, kept in the order the user gave
* This is an unmodifiable {@link ArrayList}
*/
private List<String> indexNames;
private transient Integer myHashCode = null; // As this instance is immutable, these two values
private transient String myToString = null; // need only be calculated once.
/* *** Constructor *** */
/**
* Constructs a <code>TabularType</code> instance, checking for the validity of the given parameters.
* The validity constraints are described below for each parameter.
* <p>
* The Java class name of tabular data values this tabular type represents
* (ie the class name returned by the {@link OpenType#getClassName() getClassName} method)
* is set to the string value returned by <code>TabularData.class.getName()</code>.
* <p>
* @param typeName The name given to the tabular type this instance represents; cannot be a null or empty string.
* <br>&nbsp;
* @param description The human readable description of the tabular type this instance represents;
* cannot be a null or empty string.
* <br>&nbsp;
* @param rowType The type of the row elements of tabular data values described by this tabular type instance;
* cannot be null.
* <br>&nbsp;
* @param indexNames The names of the items the values of which are used to uniquely index each row element in the
* tabular data values described by this tabular type instance;
* cannot be null or empty. Each element should be an item name defined in <var>rowType</var>
* (no null or empty string allowed).
* It is important to note that the <b>order</b> of the item names in <var>indexNames</var>
* is used by the methods {@link TabularData#get(java.lang.Object[]) get} and
* {@link TabularData#remove(java.lang.Object[]) remove} of class
* <code>TabularData</code> to match their array of values parameter to items.
* <br>&nbsp;
* @throws IllegalArgumentException if <var>rowType</var> is null,
* or <var>indexNames</var> is a null or empty array,
* or an element in <var>indexNames</var> is a null or empty string,
* or <var>typeName</var> or <var>description</var> is a null or empty string.
* <br>&nbsp;
* @throws OpenDataException if an element's value of <var>indexNames</var>
* is not an item name defined in <var>rowType</var>.
*/
public TabularType(String typeName,
String description,
CompositeType rowType,
String[] indexNames) throws OpenDataException {
// Check and initialize state defined by parent.
//
super(TabularData.class.getName(), typeName, description, false);
// Check rowType is not null
//
if (rowType == null) {
throw new IllegalArgumentException("Argument rowType cannot be null.");
}
// Check indexNames is neither null nor empty and does not contain any null element or empty string
//
checkForNullElement(indexNames, "indexNames");
checkForEmptyString(indexNames, "indexNames");
// Check all indexNames values are valid item names for rowType
//
for (int i=0; i<indexNames.length; i++) {
if ( ! rowType.containsKey(indexNames[i]) ) {
throw new OpenDataException("Argument's element value indexNames["+ i +"]=\""+ indexNames[i] +
"\" is not a valid item name for rowType.");
}
}
// initialize rowType
//
this.rowType = rowType;
// initialize indexNames (copy content so that subsequent
// modifs to the array referenced by the indexNames parameter
// have no impact)
//
List<String> tmpList = new ArrayList<String>(indexNames.length + 1);
for (int i=0; i<indexNames.length; i++) {
tmpList.add(indexNames[i]);
}
this.indexNames = Collections.unmodifiableList(tmpList);
}
/**
* Checks that Object[] arg is neither null nor empty (ie length==0)
* and that it does not contain any null element.
*/
private static void checkForNullElement(Object[] arg, String argName) {
if ( (arg == null) || (arg.length == 0) ) {
throw new IllegalArgumentException("Argument "+ argName +"[] cannot be null or empty.");
}
for (int i=0; i<arg.length; i++) {
if (arg[i] == null) {
throw new IllegalArgumentException("Argument's element "+ argName +"["+ i +"] cannot be null.");
}
}
}
/**
* Checks that String[] does not contain any empty (or blank characters only) string.
*/
private static void checkForEmptyString(String[] arg, String argName) {
for (int i=0; i<arg.length; i++) {
if (arg[i].trim().equals("")) {
throw new IllegalArgumentException("Argument's element "+ argName +"["+ i +"] cannot be an empty string.");
}
}
}
/* *** Tabular type specific information methods *** */
/**
* Returns the type of the row elements of tabular data values
* described by this <code>TabularType</code> instance.
*
* @return the type of each row.
*/
public CompositeType getRowType() {
return rowType;
}
/**
* <p>Returns, in the same order as was given to this instance's
* constructor, an unmodifiable List of the names of the items the
* values of which are used to uniquely index each row element of
* tabular data values described by this <code>TabularType</code>
* instance.</p>
*
* @return a List of String representing the names of the index
* items.
*
*/
public List<String> getIndexNames() {
return indexNames;
}
/**
* Tests whether <var>obj</var> is a value which could be
* described by this <code>TabularType</code> instance.
*
* <p>If <var>obj</var> is null or is not an instance of
* <code>javax.management.openmbean.TabularData</code>,
* <code>isValue</code> returns <code>false</code>.</p>
*
* <p>If <var>obj</var> is an instance of
* <code>javax.management.openmbean.TabularData</code>, say {@code
* td}, the result is true if this {@code TabularType} is
* <em>assignable from</em> {@link TabularData#getTabularType()
* td.getTabularType()}, as defined in {@link
* CompositeType#isValue CompositeType.isValue}.</p>
*
* @param obj the value whose open type is to be tested for
* compatibility with this <code>TabularType</code> instance.
*
* @return <code>true</code> if <var>obj</var> is a value for this
* tabular type, <code>false</code> otherwise.
*/
public boolean isValue(Object obj) {
// if obj is null or not a TabularData, return false
//
if (!(obj instanceof TabularData))
return false;
// if obj is not a TabularData, return false
//
TabularData value = (TabularData) obj;
TabularType valueType = value.getTabularType();
return isAssignableFrom(valueType);
}
@Override
boolean isAssignableFrom(OpenType<?> ot) {
if (!(ot instanceof TabularType))
return false;
TabularType tt = (TabularType) ot;
if (!getTypeName().equals(tt.getTypeName()) ||
!getIndexNames().equals(tt.getIndexNames()))
return false;
return getRowType().isAssignableFrom(tt.getRowType());
}
/* *** Methods overriden from class Object *** */
/**
* Compares the specified <code>obj</code> parameter with this <code>TabularType</code> instance for equality.
* <p>
* Two <code>TabularType</code> instances are equal if and only if all of the following statements are true:
* <ul>
* <li>their type names are equal</li>
* <li>their row types are equal</li>
* <li>they use the same index names, in the same order</li>
* </ul>
* <br>&nbsp;
* @param obj the object to be compared for equality with this <code>TabularType</code> instance;
* if <var>obj</var> is <code>null</code>, <code>equals</code> returns <code>false</code>.
*
* @return <code>true</code> if the specified object is equal to this <code>TabularType</code> instance.
*/
public boolean equals(Object obj) {
// if obj is null, return false
//
if (obj == null) {
return false;
}
// if obj is not a TabularType, return false
//
TabularType other;
try {
other = (TabularType) obj;
} catch (ClassCastException e) {
return false;
}
// Now, really test for equality between this TabularType instance and the other:
//
// their names should be equal
if ( ! this.getTypeName().equals(other.getTypeName()) ) {
return false;
}
// their row types should be equal
if ( ! this.rowType.equals(other.rowType) ) {
return false;
}
// their index names should be equal and in the same order (ensured by List.equals())
if ( ! this.indexNames.equals(other.indexNames) ) {
return false;
}
// All tests for equality were successfull
//
return true;
}
/**
* Returns the hash code value for this <code>TabularType</code> instance.
* <p>
* The hash code of a <code>TabularType</code> instance is the sum of the hash codes
* of all elements of information used in <code>equals</code> comparisons
* (ie: name, row type, index names).
* This ensures that <code> t1.equals(t2) </code> implies that <code> t1.hashCode()==t2.hashCode() </code>
* for any two <code>TabularType</code> instances <code>t1</code> and <code>t2</code>,
* as required by the general contract of the method
* {@link Object#hashCode() Object.hashCode()}.
* <p>
* As <code>TabularType</code> instances are immutable, the hash code for this instance is calculated once,
* on the first call to <code>hashCode</code>, and then the same value is returned for subsequent calls.
*
* @return the hash code value for this <code>TabularType</code> instance
*/
public int hashCode() {
// Calculate the hash code value if it has not yet been done (ie 1st call to hashCode())
//
if (myHashCode == null) {
int value = 0;
value += this.getTypeName().hashCode();
value += this.rowType.hashCode();
for (String index : indexNames)
value += index.hashCode();
myHashCode = Integer.valueOf(value);
}
// return always the same hash code for this instance (immutable)
//
return myHashCode.intValue();
}
/**
* Returns a string representation of this <code>TabularType</code> instance.
* <p>
* The string representation consists of the name of this class (ie <code>javax.management.openmbean.TabularType</code>),
* the type name for this instance, the row type string representation of this instance,
* and the index names of this instance.
* <p>
* As <code>TabularType</code> instances are immutable, the string representation for this instance is calculated once,
* on the first call to <code>toString</code>, and then the same value is returned for subsequent calls.
*
* @return a string representation of this <code>TabularType</code> instance
*/
public String toString() {
// Calculate the string representation if it has not yet been done (ie 1st call to toString())
//
if (myToString == null) {
final StringBuilder result = new StringBuilder()
.append(this.getClass().getName())
.append("(name=")
.append(getTypeName())
.append(",rowType=")
.append(rowType.toString())
.append(",indexNames=(");
String sep = "";
for (String index : indexNames) {
result.append(sep).append(index);
sep = ",";
}
result.append("))");
myToString = result.toString();
}
// return always the same string representation for this instance (immutable)
//
return myToString;
}
}