/*
 * 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.relation;

import javax.management.Notification;
import javax.management.ObjectName;

import java.io.InvalidObjectException;
import java.io.IOException;
import java.io.ObjectInputStream;
import java.io.ObjectOutputStream;
import java.io.ObjectStreamField;

import java.security.AccessController;
import java.security.PrivilegedAction;

import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collections;
import java.util.HashSet;
import java.util.List;
import java.util.Set;

import com.sun.jmx.mbeanserver.GetPropertyAction;
import static com.sun.jmx.mbeanserver.Util.cast;

A notification of a change in the Relation Service. A RelationNotification notification is sent when a relation is created via the Relation Service, or an MBean is added as a relation in the Relation Service, or a role is updated in a relation, or a relation is removed from the Relation Service.

The serialVersionUID of this class is -6871117877523310399L.

Since:1.5
/** * A notification of a change in the Relation Service. * A RelationNotification notification is sent when a relation is created via * the Relation Service, or an MBean is added as a relation in the Relation * Service, or a role is updated in a relation, or a relation is removed from * the Relation Service. * * <p>The <b>serialVersionUID</b> of this class is <code>-6871117877523310399L</code>. * * @since 1.5 */
@SuppressWarnings("serial") // serialVersionUID not constant public class RelationNotification extends Notification { // Serialization compatibility stuff: // Two serial forms are supported in this class. The selected form depends // on system property "jmx.serial.form": // - "1.0" for JMX 1.0 // - any other value for JMX 1.1 and higher // // Serial version for old serial form private static final long oldSerialVersionUID = -2126464566505527147L; // // Serial version for new serial form private static final long newSerialVersionUID = -6871117877523310399L; // // Serializable fields in old serial form private static final ObjectStreamField[] oldSerialPersistentFields = { new ObjectStreamField("myNewRoleValue", ArrayList.class), new ObjectStreamField("myOldRoleValue", ArrayList.class), new ObjectStreamField("myRelId", String.class), new ObjectStreamField("myRelObjName", ObjectName.class), new ObjectStreamField("myRelTypeName", String.class), new ObjectStreamField("myRoleName", String.class), new ObjectStreamField("myUnregMBeanList", ArrayList.class) }; // // Serializable fields in new serial form private static final ObjectStreamField[] newSerialPersistentFields = { new ObjectStreamField("newRoleValue", List.class), new ObjectStreamField("oldRoleValue", List.class), new ObjectStreamField("relationId", String.class), new ObjectStreamField("relationObjName", ObjectName.class), new ObjectStreamField("relationTypeName", String.class), new ObjectStreamField("roleName", String.class), new ObjectStreamField("unregisterMBeanList", List.class) }; // // Actual serial version and serial form private static final long serialVersionUID;
@serialFieldrelationId String Relation identifier of created/removed/updated relation
@serialFieldrelationTypeName String Relation type name of created/removed/updated relation
@serialFieldrelationObjName ObjectName ObjectName of the relation MBean of created/removed/updated relation (only if the relation is represented by an MBean)
@serialFieldunregisterMBeanList List List of ObjectNames of referenced MBeans to be unregistered due to relation removal
@serialFieldroleName String Name of updated role (only for role update)
@serialFieldoldRoleValue List Old role value (ArrayList of ObjectNames) (only for role update)
@serialFieldnewRoleValue List New role value (ArrayList of ObjectNames) (only for role update)
/** * @serialField relationId String Relation identifier of * created/removed/updated relation * @serialField relationTypeName String Relation type name of * created/removed/updated relation * @serialField relationObjName ObjectName {@link ObjectName} of * the relation MBean of created/removed/updated relation (only if * the relation is represented by an MBean) * @serialField unregisterMBeanList List List of {@link * ObjectName}s of referenced MBeans to be unregistered due to * relation removal * @serialField roleName String Name of updated role (only for role update) * @serialField oldRoleValue List Old role value ({@link * ArrayList} of {@link ObjectName}s) (only for role update) * @serialField newRoleValue List New role value ({@link * ArrayList} of {@link ObjectName}s) (only for role update) */
private static final ObjectStreamField[] serialPersistentFields; private static boolean compat = false; static { try { GetPropertyAction act = new GetPropertyAction("jmx.serial.form"); String form = AccessController.doPrivileged(act); compat = (form != null && form.equals("1.0")); } catch (Exception e) { // OK : Too bad, no compat with 1.0 } if (compat) { serialPersistentFields = oldSerialPersistentFields; serialVersionUID = oldSerialVersionUID; } else { serialPersistentFields = newSerialPersistentFields; serialVersionUID = newSerialVersionUID; } } // // END Serialization compatibility stuff // // Notification types //
Type for the creation of an internal relation.
/** * Type for the creation of an internal relation. */
public static final String RELATION_BASIC_CREATION = "jmx.relation.creation.basic";
Type for the relation MBean added into the Relation Service.
/** * Type for the relation MBean added into the Relation Service. */
public static final String RELATION_MBEAN_CREATION = "jmx.relation.creation.mbean";
Type for an update of an internal relation.
/** * Type for an update of an internal relation. */
public static final String RELATION_BASIC_UPDATE = "jmx.relation.update.basic";
Type for the update of a relation MBean.
/** * Type for the update of a relation MBean. */
public static final String RELATION_MBEAN_UPDATE = "jmx.relation.update.mbean";
Type for the removal from the Relation Service of an internal relation.
/** * Type for the removal from the Relation Service of an internal relation. */
public static final String RELATION_BASIC_REMOVAL = "jmx.relation.removal.basic";
Type for the removal from the Relation Service of a relation MBean.
/** * Type for the removal from the Relation Service of a relation MBean. */
public static final String RELATION_MBEAN_REMOVAL = "jmx.relation.removal.mbean"; // // Private members //
@serialRelation identifier of created/removed/updated relation
/** * @serial Relation identifier of created/removed/updated relation */
private String relationId = null;
@serialRelation type name of created/removed/updated relation
/** * @serial Relation type name of created/removed/updated relation */
private String relationTypeName = null;
@serialObjectName of the relation MBean of created/removed/updated relation (only if the relation is represented by an MBean)
/** * @serial {@link ObjectName} of the relation MBean of created/removed/updated relation * (only if the relation is represented by an MBean) */
private ObjectName relationObjName = null;
@serialList of ObjectNames of referenced MBeans to be unregistered due to relation removal
/** * @serial List of {@link ObjectName}s of referenced MBeans to be unregistered due to * relation removal */
private List<ObjectName> unregisterMBeanList = null;
@serialName of updated role (only for role update)
/** * @serial Name of updated role (only for role update) */
private String roleName = null;
@serialOld role value (ArrayList of ObjectNames) (only for role update)
/** * @serial Old role value ({@link ArrayList} of {@link ObjectName}s) (only for role update) */
private List<ObjectName> oldRoleValue = null;
@serialNew role value (ArrayList of ObjectNames) (only for role update)
/** * @serial New role value ({@link ArrayList} of {@link ObjectName}s) (only for role update) */
private List<ObjectName> newRoleValue = null; // // Constructors //
Creates a notification for either a relation creation (RelationSupport object created internally in the Relation Service, or an MBean added as a relation) or for a relation removal from the Relation Service.
Params:
  • notifType – type of the notification; either:

    - RELATION_BASIC_CREATION

    - RELATION_MBEAN_CREATION

    - RELATION_BASIC_REMOVAL

    - RELATION_MBEAN_REMOVAL

  • sourceObj – source object, sending the notification. This is either an ObjectName or a RelationService object. In the latter case it must be the MBean emitting the notification; the MBean Server will rewrite the source to be the ObjectName under which that MBean is registered.
  • sequence – sequence number to identify the notification
  • timeStamp – time stamp
  • message – human-readable message describing the notification
  • id – relation id identifying the relation in the Relation Service
  • typeName – name of the relation type
  • objectName – ObjectName of the relation object if it is an MBean (null for relations internally handled by the Relation Service)
  • unregMBeanList – list of ObjectNames of referenced MBeans expected to be unregistered due to relation removal (only for removal, due to CIM qualifiers, can be null)
Throws:
  • IllegalArgumentException – if:

    - no value for the notification type

    - the notification type is not RELATION_BASIC_CREATION, RELATION_MBEAN_CREATION, RELATION_BASIC_REMOVAL or RELATION_MBEAN_REMOVAL

    - no source object

    - the source object is not a Relation Service

    - no relation id

    - no relation type name

/** * Creates a notification for either a relation creation (RelationSupport * object created internally in the Relation Service, or an MBean added as a * relation) or for a relation removal from the Relation Service. * * @param notifType type of the notification; either: * <P>- RELATION_BASIC_CREATION * <P>- RELATION_MBEAN_CREATION * <P>- RELATION_BASIC_REMOVAL * <P>- RELATION_MBEAN_REMOVAL * @param sourceObj source object, sending the notification. This is either * an ObjectName or a RelationService object. In the latter case it must be * the MBean emitting the notification; the MBean Server will rewrite the * source to be the ObjectName under which that MBean is registered. * @param sequence sequence number to identify the notification * @param timeStamp time stamp * @param message human-readable message describing the notification * @param id relation id identifying the relation in the Relation * Service * @param typeName name of the relation type * @param objectName ObjectName of the relation object if it is an MBean * (null for relations internally handled by the Relation Service) * @param unregMBeanList list of ObjectNames of referenced MBeans * expected to be unregistered due to relation removal (only for removal, * due to CIM qualifiers, can be null) * * @exception IllegalArgumentException if: * <P>- no value for the notification type * <P>- the notification type is not RELATION_BASIC_CREATION, * RELATION_MBEAN_CREATION, RELATION_BASIC_REMOVAL or * RELATION_MBEAN_REMOVAL * <P>- no source object * <P>- the source object is not a Relation Service * <P>- no relation id * <P>- no relation type name */
public RelationNotification(String notifType, Object sourceObj, long sequence, long timeStamp, String message, String id, String typeName, ObjectName objectName, List<ObjectName> unregMBeanList) throws IllegalArgumentException { super(notifType, sourceObj, sequence, timeStamp, message); if (!isValidBasicStrict(notifType,sourceObj,id,typeName) || !isValidCreate(notifType)) { throw new IllegalArgumentException("Invalid parameter."); } relationId = id; relationTypeName = typeName; relationObjName = safeGetObjectName(objectName); unregisterMBeanList = safeGetObjectNameList(unregMBeanList); }
Creates a notification for a role update in a relation.
Params:
  • notifType – type of the notification; either:

    - RELATION_BASIC_UPDATE

    - RELATION_MBEAN_UPDATE

  • sourceObj – source object, sending the notification. This is either an ObjectName or a RelationService object. In the latter case it must be the MBean emitting the notification; the MBean Server will rewrite the source to be the ObjectName under which that MBean is registered.
  • sequence – sequence number to identify the notification
  • timeStamp – time stamp
  • message – human-readable message describing the notification
  • id – relation id identifying the relation in the Relation Service
  • typeName – name of the relation type
  • objectName – ObjectName of the relation object if it is an MBean (null for relations internally handled by the Relation Service)
  • name – name of the updated role
  • newValue – new role value (List of ObjectName objects)
  • oldValue – old role value (List of ObjectName objects)
Throws:
/** * Creates a notification for a role update in a relation. * * @param notifType type of the notification; either: * <P>- RELATION_BASIC_UPDATE * <P>- RELATION_MBEAN_UPDATE * @param sourceObj source object, sending the notification. This is either * an ObjectName or a RelationService object. In the latter case it must be * the MBean emitting the notification; the MBean Server will rewrite the * source to be the ObjectName under which that MBean is registered. * @param sequence sequence number to identify the notification * @param timeStamp time stamp * @param message human-readable message describing the notification * @param id relation id identifying the relation in the Relation * Service * @param typeName name of the relation type * @param objectName ObjectName of the relation object if it is an MBean * (null for relations internally handled by the Relation Service) * @param name name of the updated role * @param newValue new role value (List of ObjectName objects) * @param oldValue old role value (List of ObjectName objects) * * @exception IllegalArgumentException if null parameter */
public RelationNotification(String notifType, Object sourceObj, long sequence, long timeStamp, String message, String id, String typeName, ObjectName objectName, String name, List<ObjectName> newValue, List<ObjectName> oldValue ) throws IllegalArgumentException { super(notifType, sourceObj, sequence, timeStamp, message); if (!isValidBasicStrict(notifType,sourceObj,id,typeName) || !isValidUpdate(notifType,name,newValue,oldValue)) { throw new IllegalArgumentException("Invalid parameter."); } relationId = id; relationTypeName = typeName; relationObjName = safeGetObjectName(objectName); roleName = name; oldRoleValue = safeGetObjectNameList(oldValue); newRoleValue = safeGetObjectNameList(newValue); } // // Accessors //
Returns the relation identifier of created/removed/updated relation.
Returns:the relation id.
/** * Returns the relation identifier of created/removed/updated relation. * * @return the relation id. */
public String getRelationId() { return relationId; }
Returns the relation type name of created/removed/updated relation.
Returns:the relation type name.
/** * Returns the relation type name of created/removed/updated relation. * * @return the relation type name. */
public String getRelationTypeName() { return relationTypeName; }
Returns the ObjectName of the created/removed/updated relation.
Returns:the ObjectName if the relation is an MBean, otherwise null.
/** * Returns the ObjectName of the * created/removed/updated relation. * * @return the ObjectName if the relation is an MBean, otherwise null. */
public ObjectName getObjectName() { return relationObjName; }
Returns the list of ObjectNames of MBeans expected to be unregistered due to a relation removal (only for relation removal).
Returns:a List of ObjectName.
/** * Returns the list of ObjectNames of MBeans expected to be unregistered * due to a relation removal (only for relation removal). * * @return a {@link List} of {@link ObjectName}. */
public List<ObjectName> getMBeansToUnregister() { List<ObjectName> result; if (unregisterMBeanList != null) { result = new ArrayList<ObjectName>(unregisterMBeanList); } else { result = Collections.emptyList(); } return result; }
Returns name of updated role of updated relation (only for role update).
Returns:the name of the updated role.
/** * Returns name of updated role of updated relation (only for role update). * * @return the name of the updated role. */
public String getRoleName() { String result = null; if (roleName != null) { result = roleName; } return result; }
Returns old value of updated role (only for role update).
Returns:the old value of the updated role.
/** * Returns old value of updated role (only for role update). * * @return the old value of the updated role. */
public List<ObjectName> getOldRoleValue() { List<ObjectName> result; if (oldRoleValue != null) { result = new ArrayList<ObjectName>(oldRoleValue); } else { result = Collections.emptyList(); } return result; }
Returns new value of updated role (only for role update).
Returns:the new value of the updated role.
/** * Returns new value of updated role (only for role update). * * @return the new value of the updated role. */
public List<ObjectName> getNewRoleValue() { List<ObjectName> result; if (newRoleValue != null) { result = new ArrayList<ObjectName>(newRoleValue); } else { result = Collections.emptyList(); } return result; } // // Misc // // Initializes members // // -param notifKind 1 for creation/removal, 2 for update // -param notifType type of the notification; either: // - RELATION_BASIC_UPDATE // - RELATION_MBEAN_UPDATE // for an update, or: // - RELATION_BASIC_CREATION // - RELATION_MBEAN_CREATION // - RELATION_BASIC_REMOVAL // - RELATION_MBEAN_REMOVAL // for a creation or removal // -param sourceObj source object, sending the notification. Will always // be a RelationService object. // -param sequence sequence number to identify the notification // -param timeStamp time stamp // -param message human-readable message describing the notification // -param id relation id identifying the relation in the Relation // Service // -param typeName name of the relation type // -param objectName ObjectName of the relation object if it is an MBean // (null for relations internally handled by the Relation Service) // -param unregMBeanList list of ObjectNames of MBeans expected to be // removed due to relation removal // -param name name of the updated role // -param newValue new value (List of ObjectName objects) // -param oldValue old value (List of ObjectName objects) // // -exception IllegalArgumentException if: // - no value for the notification type // - incorrect notification type // - no source object // - the source object is not a Relation Service // - no relation id // - no relation type name // - no role name (for role update) // - no role old value (for role update) // - no role new value (for role update) // Despite the fact, that validation in constructor of RelationNotification prohibit // creation of the class instance with null sourceObj its possible to set it to null later // by public setSource() method. // So we should relax validation rules to preserve serialization behavior compatibility. private boolean isValidBasicStrict(String notifType, Object sourceObj, String id, String typeName){ if (sourceObj == null) { return false; } return isValidBasic(notifType,sourceObj,id,typeName); } private boolean isValidBasic(String notifType, Object sourceObj, String id, String typeName){ if (notifType == null || id == null || typeName == null) { return false; } if (sourceObj != null && ( !(sourceObj instanceof RelationService) && !(sourceObj instanceof ObjectName))) { return false; } return true; } private boolean isValidCreate(String notifType) { String[] validTypes= {RelationNotification.RELATION_BASIC_CREATION, RelationNotification.RELATION_MBEAN_CREATION, RelationNotification.RELATION_BASIC_REMOVAL, RelationNotification.RELATION_MBEAN_REMOVAL}; Set<String> ctSet = new HashSet<String>(Arrays.asList(validTypes)); return ctSet.contains(notifType); } private boolean isValidUpdate(String notifType, String name, List<ObjectName> newValue, List<ObjectName> oldValue) { if (!(notifType.equals(RelationNotification.RELATION_BASIC_UPDATE)) && !(notifType.equals(RelationNotification.RELATION_MBEAN_UPDATE))) { return false; } if (name == null || oldValue == null || newValue == null) { return false; } return true; } private ArrayList<ObjectName> safeGetObjectNameList(List<ObjectName> src){ ArrayList<ObjectName> dest = null; if (src != null) { dest = new ArrayList<ObjectName>(); for (ObjectName item : src) { // NPE thrown if we attempt to add null object dest.add(ObjectName.getInstance(item)); } } return dest; } private ObjectName safeGetObjectName(ObjectName src){ ObjectName dest = null; if (src != null) { dest = ObjectName.getInstance(src); } return dest; }
Deserializes a RelationNotification from an ObjectInputStream.
/** * Deserializes a {@link RelationNotification} from an {@link ObjectInputStream}. */
private void readObject(ObjectInputStream in) throws IOException, ClassNotFoundException { String tmpRelationId, tmpRelationTypeName, tmpRoleName; ObjectName tmpRelationObjName; List<ObjectName> tmpNewRoleValue, tmpOldRoleValue, tmpUnregMBeanList; ObjectInputStream.GetField fields = in.readFields(); if (compat) { tmpRelationId = (String)fields.get("myRelId", null); tmpRelationTypeName = (String)fields.get("myRelTypeName", null); tmpRoleName = (String)fields.get("myRoleName", null); tmpRelationObjName = (ObjectName)fields.get("myRelObjName", null); tmpNewRoleValue = cast(fields.get("myNewRoleValue", null)); tmpOldRoleValue = cast(fields.get("myOldRoleValue", null)); tmpUnregMBeanList = cast(fields.get("myUnregMBeanList", null)); } else { tmpRelationId = (String)fields.get("relationId", null); tmpRelationTypeName = (String)fields.get("relationTypeName", null); tmpRoleName = (String)fields.get("roleName", null); tmpRelationObjName = (ObjectName)fields.get("relationObjName", null); tmpNewRoleValue = cast(fields.get("newRoleValue", null)); tmpOldRoleValue = cast(fields.get("oldRoleValue", null)); tmpUnregMBeanList = cast(fields.get("unregisterMBeanList", null)); } // Validate fields we just read, throw InvalidObjectException // if something goes wrong String notifType = super.getType(); if (!isValidBasic(notifType,super.getSource(),tmpRelationId,tmpRelationTypeName) || (!isValidCreate(notifType) && !isValidUpdate(notifType,tmpRoleName,tmpNewRoleValue,tmpOldRoleValue))) { super.setSource(null); throw new InvalidObjectException("Invalid object read"); } // assign deserialized vaules to object fields relationObjName = safeGetObjectName(tmpRelationObjName); newRoleValue = safeGetObjectNameList(tmpNewRoleValue); oldRoleValue = safeGetObjectNameList(tmpOldRoleValue); unregisterMBeanList = safeGetObjectNameList(tmpUnregMBeanList); relationId = tmpRelationId; relationTypeName = tmpRelationTypeName; roleName = tmpRoleName; } /** * Serializes a {@link RelationNotification} to an {@link ObjectOutputStream}. */ private void writeObject(ObjectOutputStream out) throws IOException { if (compat) { // Serializes this instance in the old serial form // ObjectOutputStream.PutField fields = out.putFields(); fields.put("myNewRoleValue", newRoleValue); fields.put("myOldRoleValue", oldRoleValue); fields.put("myRelId", relationId); fields.put("myRelObjName", relationObjName); fields.put("myRelTypeName", relationTypeName); fields.put("myRoleName",roleName); fields.put("myUnregMBeanList", unregisterMBeanList); out.writeFields(); } else { // Serializes this instance in the new serial form // out.defaultWriteObject(); } } }