1 /*
   2  * Copyright (c) 2000, 2008, Oracle and/or its affiliates. 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.  Oracle designates this
   8  * particular file as subject to the "Classpath" exception as provided
   9  * by Oracle 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 Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
  22  * or visit www.oracle.com if you need additional information or have any
  23  * questions.
  24  */
  25 
  26 package javax.management.relation;
  27 
  28 import static com.sun.jmx.mbeanserver.Util.cast;
  29 import com.sun.jmx.mbeanserver.GetPropertyAction;
  30 
  31 import java.io.IOException;
  32 import java.io.ObjectInputStream;
  33 import java.io.ObjectOutputStream;
  34 import java.io.ObjectStreamField;
  35 import java.io.Serializable;
  36 
  37 import java.security.AccessController;
  38 
  39 import java.util.ArrayList;
  40 import java.util.Iterator;
  41 import java.util.List;
  42 
  43 import javax.management.ObjectName;
  44 
  45 /**
  46  * Represents a role: includes a role name and referenced MBeans (via their
  47  * ObjectNames). The role value is always represented as an ArrayList
  48  * collection (of ObjectNames) to homogenize the access.
  49  *
  50  * <p>The <b>serialVersionUID</b> of this class is <code>-279985518429862552L</code>.
  51  *
  52  * @since 1.5
  53  */
  54 @SuppressWarnings("serial")  // serialVersionUID not constant
  55 public class Role implements Serializable {
  56 
  57     // Serialization compatibility stuff:
  58     // Two serial forms are supported in this class. The selected form depends
  59     // on system property "jmx.serial.form":
  60     //  - "1.0" for JMX 1.0
  61     //  - any other value for JMX 1.1 and higher
  62     //
  63     // Serial version for old serial form
  64     private static final long oldSerialVersionUID = -1959486389343113026L;
  65     //
  66     // Serial version for new serial form
  67     private static final long newSerialVersionUID = -279985518429862552L;
  68     //
  69     // Serializable fields in old serial form
  70     private static final ObjectStreamField[] oldSerialPersistentFields =
  71     {
  72       new ObjectStreamField("myName", String.class),
  73       new ObjectStreamField("myObjNameList", ArrayList.class)
  74     };
  75     //
  76     // Serializable fields in new serial form
  77     private static final ObjectStreamField[] newSerialPersistentFields =
  78     {
  79       new ObjectStreamField("name", String.class),
  80       new ObjectStreamField("objectNameList", List.class)
  81     };
  82     //
  83     // Actual serial version and serial form
  84     private static final long serialVersionUID;
  85     /**
  86      * @serialField name String Role name
  87      * @serialField objectNameList List {@link List} of {@link ObjectName}s of referenced MBeans
  88      */
  89     private static final ObjectStreamField[] serialPersistentFields;
  90     private static boolean compat = false;
  91     static {
  92         try {
  93             GetPropertyAction act = new GetPropertyAction("jmx.serial.form");
  94             String form = AccessController.doPrivileged(act);
  95             compat = (form != null && form.equals("1.0"));
  96         } catch (Exception e) {
  97             // OK : Too bad, no compat with 1.0
  98         }
  99         if (compat) {
 100             serialPersistentFields = oldSerialPersistentFields;
 101             serialVersionUID = oldSerialVersionUID;
 102         } else {
 103             serialPersistentFields = newSerialPersistentFields;
 104             serialVersionUID = newSerialVersionUID;
 105         }
 106     }
 107     //
 108     // END Serialization compatibility stuff
 109 
 110     //
 111     // Private members
 112     //
 113 
 114     /**
 115      * @serial Role name
 116      */
 117     private String name = null;
 118 
 119     /**
 120      * @serial {@link List} of {@link ObjectName}s of referenced MBeans
 121      */
 122     private List<ObjectName> objectNameList = new ArrayList<ObjectName>();
 123 
 124     //
 125     // Constructors
 126     //
 127 
 128     /**
 129      * <p>Make a new Role object.
 130      * No check is made that the ObjectNames in the role value exist in
 131      * an MBean server.  That check will be made when the role is set
 132      * in a relation.
 133      *
 134      * @param roleName  role name
 135      * @param roleValue  role value (List of ObjectName objects)
 136      *
 137      * @exception IllegalArgumentException  if null parameter
 138      */
 139     public Role(String roleName,
 140                 List<ObjectName> roleValue)
 141         throws IllegalArgumentException {
 142 
 143         if (roleName == null || roleValue == null) {
 144             String excMsg = "Invalid parameter";
 145             throw new IllegalArgumentException(excMsg);
 146         }
 147 
 148         setRoleName(roleName);
 149         setRoleValue(roleValue);
 150 
 151         return;
 152     }
 153 
 154     //
 155     // Accessors
 156     //
 157 
 158     /**
 159      * Retrieves role name.
 160      *
 161      * @return the role name.
 162      *
 163      * @see #setRoleName
 164      */
 165     public String getRoleName() {
 166         return name;
 167     }
 168 
 169     /**
 170      * Retrieves role value.
 171      *
 172      * @return ArrayList of ObjectName objects for referenced MBeans.
 173      *
 174      * @see #setRoleValue
 175      */
 176     public List<ObjectName> getRoleValue() {
 177         return objectNameList;
 178     }
 179 
 180     /**
 181      * Sets role name.
 182      *
 183      * @param roleName  role name
 184      *
 185      * @exception IllegalArgumentException  if null parameter
 186      *
 187      * @see #getRoleName
 188      */
 189     public void setRoleName(String roleName)
 190         throws IllegalArgumentException {
 191 
 192         if (roleName == null) {
 193             String excMsg = "Invalid parameter.";
 194             throw new IllegalArgumentException(excMsg);
 195         }
 196 
 197         name = roleName;
 198         return;
 199     }
 200 
 201     /**
 202      * Sets role value.
 203      *
 204      * @param roleValue  List of ObjectName objects for referenced
 205      * MBeans.
 206      *
 207      * @exception IllegalArgumentException  if null parameter
 208      *
 209      * @see #getRoleValue
 210      */
 211     public void setRoleValue(List<ObjectName> roleValue)
 212         throws IllegalArgumentException {
 213 
 214         if (roleValue == null) {
 215             String excMsg = "Invalid parameter.";
 216             throw new IllegalArgumentException(excMsg);
 217         }
 218 
 219         objectNameList = new ArrayList<ObjectName>(roleValue);
 220         return;
 221     }
 222 
 223     /**
 224      * Returns a string describing the role.
 225      *
 226      * @return the description of the role.
 227      */
 228     public String toString() {
 229         StringBuilder result = new StringBuilder();
 230         result.append("role name: " + name + "; role value: ");
 231         for (Iterator<ObjectName> objNameIter = objectNameList.iterator();
 232              objNameIter.hasNext();) {
 233             ObjectName currObjName = objNameIter.next();
 234             result.append(currObjName.toString());
 235             if (objNameIter.hasNext()) {
 236                 result.append(", ");
 237             }
 238         }
 239         return result.toString();
 240     }
 241 
 242     //
 243     // Misc
 244     //
 245 
 246     /**
 247      * Clone the role object.
 248      *
 249      * @return a Role that is an independent copy of the current Role object.
 250      */
 251     public Object clone() {
 252 
 253         try {
 254             return new Role(name, objectNameList);
 255         } catch (IllegalArgumentException exc) {
 256             return null; // can't happen
 257         }
 258     }
 259 
 260     /**
 261      * Returns a string for the given role value.
 262      *
 263      * @param roleValue  List of ObjectName objects
 264      *
 265      * @return A String consisting of the ObjectNames separated by
 266      * newlines (\n).
 267      *
 268      * @exception IllegalArgumentException  if null parameter
 269      */
 270     public static String roleValueToString(List<ObjectName> roleValue)
 271         throws IllegalArgumentException {
 272 
 273         if (roleValue == null) {
 274             String excMsg = "Invalid parameter";
 275             throw new IllegalArgumentException(excMsg);
 276         }
 277 
 278         StringBuilder result = new StringBuilder();
 279         for (ObjectName currObjName : roleValue) {
 280             if (result.length() > 0)
 281                 result.append("\n");
 282             result.append(currObjName.toString());
 283         }
 284         return result.toString();
 285     }
 286 
 287     /**
 288      * Deserializes a {@link Role} from an {@link ObjectInputStream}.
 289      */
 290     private void readObject(ObjectInputStream in)
 291             throws IOException, ClassNotFoundException {
 292       if (compat)
 293       {
 294         // Read an object serialized in the old serial form
 295         //
 296         ObjectInputStream.GetField fields = in.readFields();
 297         name = (String) fields.get("myName", null);
 298         if (fields.defaulted("myName"))
 299         {
 300           throw new NullPointerException("myName");
 301         }
 302         objectNameList = cast(fields.get("myObjNameList", null));
 303         if (fields.defaulted("myObjNameList"))
 304         {
 305           throw new NullPointerException("myObjNameList");
 306         }
 307       }
 308       else
 309       {
 310         // Read an object serialized in the new serial form
 311         //
 312         in.defaultReadObject();
 313       }
 314     }
 315 
 316 
 317     /**
 318      * Serializes a {@link Role} to an {@link ObjectOutputStream}.
 319      */
 320     private void writeObject(ObjectOutputStream out)
 321             throws IOException {
 322       if (compat)
 323       {
 324         // Serializes this instance in the old serial form
 325         //
 326         ObjectOutputStream.PutField fields = out.putFields();
 327         fields.put("myName", name);
 328         fields.put("myObjNameList", objectNameList);
 329         out.writeFields();
 330       }
 331       else
 332       {
 333         // Serializes this instance in the new serial form
 334         //
 335         out.defaultWriteObject();
 336       }
 337     }
 338 }