Save This Page
Home » openjdk-7 » javax » management » openmbean » [javadoc | source]
    1   /*
    2    * Copyright 2000-2007 Sun Microsystems, Inc.  All Rights Reserved.
    3    * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
    4    *
    5    * This code is free software; you can redistribute it and/or modify it
    6    * under the terms of the GNU General Public License version 2 only, as
    7    * published by the Free Software Foundation.  Sun designates this
    8    * particular file as subject to the "Classpath" exception as provided
    9    * by Sun in the LICENSE file that accompanied this code.
   10    *
   11    * This code is distributed in the hope that it will be useful, but WITHOUT
   12    * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
   13    * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
   14    * version 2 for more details (a copy is included in the LICENSE file that
   15    * accompanied this code).
   16    *
   17    * You should have received a copy of the GNU General Public License version
   18    * 2 along with this work; if not, write to the Free Software Foundation,
   19    * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
   20    *
   21    * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
   22    * CA 95054 USA or visit www.sun.com if you need additional information or
   23    * have any questions.
   24    */
   25   
   26   package javax.management.openmbean;
   27   
   28   import com.sun.jmx.mbeanserver.GetPropertyAction;
   29   import java.io.IOException;
   30   import java.io.InvalidObjectException;
   31   import java.io.ObjectInputStream;
   32   import java.io.Serializable;
   33   import java.security.AccessController;
   34   import java.security.PrivilegedAction;
   35   import java.util.Arrays;
   36   import java.util.Collections;
   37   import java.util.List;
   38   import javax.management.Descriptor;
   39   import javax.management.ImmutableDescriptor;
   40   
   41   /**
   42    * The <code>OpenType</code> class is the parent abstract class of all classes which describe the actual <i>open type</i>
   43    * of open data values.
   44    * <p>
   45    * An <i>open type</i> is defined by:
   46    * <ul>
   47    *  <li>the fully qualified Java class name of the open data values this type describes;
   48    *      note that only a limited set of Java classes is allowed for open data values
   49    *      (see {@link #ALLOWED_CLASSNAMES_LIST ALLOWED_CLASSNAMES_LIST}),</li>
   50    *  <li>its name,</li>
   51    *  <li>its description.</li>
   52    * </ul>
   53    *
   54    * @param <T> the Java type that instances described by this type must
   55    * have.  For example, {@link SimpleType#INTEGER} is a {@code
   56    * SimpleType<Integer>} which is a subclass of {@code OpenType<Integer>},
   57    * meaning that an attribute, parameter, or return value that is described
   58    * as a {@code SimpleType.INTEGER} must have Java type
   59    * {@link Integer}.
   60    *
   61    * @since 1.5
   62    */
   63   public abstract class OpenType<T> implements Serializable {
   64   
   65       /* Serial version */
   66       static final long serialVersionUID = -9195195325186646468L;
   67   
   68   
   69       /**
   70        * List of the fully qualified names of the Java classes allowed for open
   71        * data values. A multidimensional array of any one of these classes or
   72        * their corresponding primitive types is also an allowed class for open
   73        * data values.
   74        *
   75          <pre>ALLOWED_CLASSNAMES_LIST = {
   76           "java.lang.Void",
   77           "java.lang.Boolean",
   78           "java.lang.Character",
   79           "java.lang.Byte",
   80           "java.lang.Short",
   81           "java.lang.Integer",
   82           "java.lang.Long",
   83           "java.lang.Float",
   84           "java.lang.Double",
   85           "java.lang.String",
   86           "java.math.BigDecimal",
   87           "java.math.BigInteger",
   88           "java.util.Date",
   89           "javax.management.ObjectName",
   90           CompositeData.class.getName(),
   91           TabularData.class.getName() } ;
   92          </pre>
   93        *
   94        */
   95       public static final List<String> ALLOWED_CLASSNAMES_LIST =
   96         Collections.unmodifiableList(
   97           Arrays.asList(
   98             "java.lang.Void",
   99             "java.lang.Boolean",
  100             "java.lang.Character",
  101             "java.lang.Byte",
  102             "java.lang.Short",
  103             "java.lang.Integer",
  104             "java.lang.Long",
  105             "java.lang.Float",
  106             "java.lang.Double",
  107             "java.lang.String",
  108             "java.math.BigDecimal",
  109             "java.math.BigInteger",
  110             "java.util.Date",
  111             "javax.management.ObjectName",
  112             CompositeData.class.getName(),        // better refer to these two class names like this, rather than hardcoding a string,
  113             TabularData.class.getName()) );       // in case the package of these classes should change (who knows...)
  114   
  115   
  116       /**
  117        * @deprecated Use {@link #ALLOWED_CLASSNAMES_LIST ALLOWED_CLASSNAMES_LIST} instead.
  118        */
  119       @Deprecated
  120       public static final String[] ALLOWED_CLASSNAMES =
  121           ALLOWED_CLASSNAMES_LIST.toArray(new String[0]);
  122   
  123   
  124       /**
  125        * @serial The fully qualified Java class name of open data values this
  126        *         type describes.
  127        */
  128       private String className;
  129   
  130       /**
  131        * @serial The type description (should not be null or empty).
  132        */
  133       private String description;
  134   
  135       /**
  136        * @serial The name given to this type (should not be null or empty).
  137        */
  138       private String typeName;
  139   
  140       /**
  141        * Tells if this type describes an array (checked in constructor).
  142        */
  143       private transient boolean isArray = false;
  144   
  145       /**
  146        * Cached Descriptor for this OpenType, constructed on demand.
  147        */
  148       private transient Descriptor descriptor;
  149   
  150       /* *** Constructor *** */
  151   
  152       /**
  153        * Constructs an <code>OpenType</code> instance (actually a subclass instance as <code>OpenType</code> is abstract),
  154        * checking for the validity of the given parameters.
  155        * The validity constraints are described below for each parameter.
  156        * <br>&nbsp;
  157        * @param  className  The fully qualified Java class name of the open data values this open type describes.
  158        *                    The valid Java class names allowed for open data values are listed in
  159        *                    {@link #ALLOWED_CLASSNAMES_LIST ALLOWED_CLASSNAMES_LIST}.
  160        *                    A multidimensional array of any one of these classes
  161        *                    or their corresponding primitive types is also an allowed class,
  162        *                    in which case the class name follows the rules defined by the method
  163        *                    {@link Class#getName() getName()} of <code>java.lang.Class</code>.
  164        *                    For example, a 3-dimensional array of Strings has for class name
  165        *                    &quot;<code>[[[Ljava.lang.String;</code>&quot; (without the quotes).
  166        * <br>&nbsp;
  167        * @param  typeName  The name given to the open type this instance represents; cannot be a null or empty string.
  168        * <br>&nbsp;
  169        * @param  description  The human readable description of the open type this instance represents;
  170        *                      cannot be a null or empty string.
  171        * <br>&nbsp;
  172        * @throws IllegalArgumentException  if <var>className</var>, <var>typeName</var> or <var>description</var>
  173        *                                   is a null or empty string
  174        * <br>&nbsp;
  175        * @throws OpenDataException  if <var>className</var> is not one of the allowed Java class names for open data
  176        */
  177       protected OpenType(String  className,
  178                          String  typeName,
  179                          String  description) throws OpenDataException {
  180           checkClassNameOverride();
  181           this.typeName = valid("typeName", typeName);
  182           this.description = valid("description", description);
  183           this.className = validClassName(className);
  184           this.isArray = (this.className != null && this.className.startsWith("["));
  185       }
  186   
  187       /* Package-private constructor for callers we trust to get it right. */
  188       OpenType(String className, String typeName, String description,
  189                boolean isArray) {
  190           this.className   = valid("className",className);
  191           this.typeName    = valid("typeName", typeName);
  192           this.description = valid("description", description);
  193           this.isArray     = isArray;
  194       }
  195   
  196       private void checkClassNameOverride() throws SecurityException {
  197           if (this.getClass().getClassLoader() == null)
  198               return;  // We trust bootstrap classes.
  199           if (overridesGetClassName(this.getClass())) {
  200               final GetPropertyAction getExtendOpenTypes =
  201                   new GetPropertyAction("jmx.extend.open.types");
  202               if (AccessController.doPrivileged(getExtendOpenTypes) == null) {
  203                   throw new SecurityException("Cannot override getClassName() " +
  204                           "unless -Djmx.extend.open.types");
  205               }
  206           }
  207       }
  208   
  209       private static boolean overridesGetClassName(final Class<? extends OpenType> c) {
  210           return AccessController.doPrivileged(new PrivilegedAction<Boolean>() {
  211               public Boolean run() {
  212                   try {
  213                       return (c.getMethod("getClassName").getDeclaringClass() !=
  214                               OpenType.class);
  215                   } catch (Exception e) {
  216                       return true;  // fail safe
  217                   }
  218               }
  219           });
  220       }
  221   
  222       private static String validClassName(String className) throws OpenDataException {
  223           className   = valid("className", className);
  224   
  225           // Check if className describes an array class, and determines its elements' class name.
  226           // (eg: a 3-dimensional array of Strings has for class name: "[[[Ljava.lang.String;")
  227           //
  228           int n = 0;
  229           while (className.startsWith("[", n)) {
  230               n++;
  231           }
  232           String eltClassName; // class name of array elements
  233           boolean isPrimitiveArray = false;
  234           if (n > 0) {
  235               if (className.startsWith("L", n) && className.endsWith(";")) {
  236                   // removes the n leading '[' + the 'L' characters
  237                   // and the last ';' character
  238                   eltClassName = className.substring(n+1, className.length()-1);
  239               } else if (n == className.length() - 1) {
  240                   // removes the n leading '[' characters
  241                   eltClassName = className.substring(n, className.length());
  242                   isPrimitiveArray = true;
  243               } else {
  244                   throw new OpenDataException("Argument className=\"" + className +
  245                           "\" is not a valid class name");
  246               }
  247           } else {
  248               // not an array
  249               eltClassName = className;
  250           }
  251   
  252           // Check that eltClassName's value is one of the allowed basic data types for open data
  253           //
  254           boolean ok = false;
  255           if (isPrimitiveArray) {
  256               ok = ArrayType.isPrimitiveContentType(eltClassName);
  257           } else {
  258               ok = ALLOWED_CLASSNAMES_LIST.contains(eltClassName);
  259           }
  260           if ( ! ok ) {
  261               throw new OpenDataException("Argument className=\""+ className +
  262                                           "\" is not one of the allowed Java class names for open data.");
  263           }
  264   
  265           return className;
  266       }
  267   
  268       /* Return argValue.trim() provided argValue is neither null nor empty;
  269          otherwise throw IllegalArgumentException.  */
  270       private static String valid(String argName, String argValue) {
  271           if (argValue == null || (argValue = argValue.trim()).equals(""))
  272               throw new IllegalArgumentException("Argument " + argName +
  273                                                  " cannot be null or empty");
  274           return argValue;
  275       }
  276   
  277       /* Package-private access to a Descriptor containing this OpenType. */
  278       synchronized Descriptor getDescriptor() {
  279           if (descriptor == null) {
  280               descriptor = new ImmutableDescriptor(new String[] {"openType"},
  281                                                    new Object[] {this});
  282           }
  283           return descriptor;
  284       }
  285   
  286       /* *** Open type information methods *** */
  287   
  288       /**
  289        * Returns the fully qualified Java class name of the open data values
  290        * this open type describes.
  291        * The only possible Java class names for open data values are listed in
  292        * {@link #ALLOWED_CLASSNAMES_LIST ALLOWED_CLASSNAMES_LIST}.
  293        * A multidimensional array of any one of these classes or their
  294        * corresponding primitive types is also an allowed class,
  295        * in which case the class name follows the rules defined by the method
  296        * {@link Class#getName() getName()} of <code>java.lang.Class</code>.
  297        * For example, a 3-dimensional array of Strings has for class name
  298        * &quot;<code>[[[Ljava.lang.String;</code>&quot; (without the quotes),
  299        * a 3-dimensional array of Integers has for class name
  300        * &quot;<code>[[[Ljava.lang.Integer;</code>&quot; (without the quotes),
  301        * and a 3-dimensional array of int has for class name
  302        * &quot;<code>[[[I</code>&quot; (without the quotes)
  303        *
  304        * @return the class name.
  305        */
  306       public String getClassName() {
  307   
  308           return className;
  309       }
  310   
  311       /**
  312        * Returns the name of this <code>OpenType</code> instance.
  313        *
  314        * @return the type name.
  315        */
  316       public String getTypeName() {
  317   
  318           return typeName;
  319       }
  320   
  321       /**
  322        * Returns the text description of this <code>OpenType</code> instance.
  323        *
  324        * @return the description.
  325        */
  326       public String getDescription() {
  327   
  328           return description;
  329       }
  330   
  331       /**
  332        * Returns <code>true</code> if the open data values this open
  333        * type describes are arrays, <code>false</code> otherwise.
  334        *
  335        * @return true if this is an array type.
  336        */
  337       public boolean isArray() {
  338   
  339           return isArray;
  340       }
  341   
  342       /**
  343        * Tests whether <var>obj</var> is a value for this open type.
  344        *
  345        * @param obj the object to be tested for validity.
  346        *
  347        * @return <code>true</code> if <var>obj</var> is a value for this
  348        * open type, <code>false</code> otherwise.
  349        */
  350       public abstract boolean isValue(Object obj) ;
  351   
  352       /**
  353        * Tests whether values of the given type can be assigned to this open type.
  354        * The default implementation of this method returns true only if the
  355        * types are equal.
  356        *
  357        * @param ot the type to be tested.
  358        *
  359        * @return true if {@code ot} is assignable to this open type.
  360        */
  361       boolean isAssignableFrom(OpenType<?> ot) {
  362           return this.equals(ot);
  363       }
  364   
  365       /* *** Methods overriden from class Object *** */
  366   
  367       /**
  368        * Compares the specified <code>obj</code> parameter with this
  369        * open type instance for equality.
  370        *
  371        * @param obj the object to compare to.
  372        *
  373        * @return true if this object and <code>obj</code> are equal.
  374        */
  375       public abstract boolean equals(Object obj) ;
  376   
  377       public abstract int hashCode() ;
  378   
  379       /**
  380        * Returns a string representation of this open type instance.
  381        *
  382        * @return the string representation.
  383        */
  384       public abstract String toString() ;
  385   
  386       /**
  387        * Deserializes an {@link OpenType} from an {@link java.io.ObjectInputStream}.
  388        */
  389       private void readObject(ObjectInputStream in)
  390               throws IOException, ClassNotFoundException {
  391           checkClassNameOverride();
  392           ObjectInputStream.GetField fields = in.readFields();
  393           final String classNameField;
  394           final String descriptionField;
  395           final String typeNameField;
  396           try {
  397               classNameField =
  398                   validClassName((String) fields.get("className", null));
  399               descriptionField =
  400                   valid("description", (String) fields.get("description", null));
  401               typeNameField =
  402                   valid("typeName", (String) fields.get("typeName", null));
  403           } catch (Exception e) {
  404               IOException e2 = new InvalidObjectException(e.getMessage());
  405               e2.initCause(e);
  406               throw e2;
  407           }
  408           className = classNameField;
  409           description = descriptionField;
  410           typeName = typeNameField;
  411           isArray = (className.startsWith("["));
  412       }
  413   }

Save This Page
Home » openjdk-7 » javax » management » openmbean » [javadoc | source]