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
26package javax.management.relation;
27
28import static com.sun.jmx.mbeanserver.Util.cast;
29import com.sun.jmx.mbeanserver.GetPropertyAction;
30
31import java.io.IOException;
32import java.io.ObjectInputStream;
33import java.io.ObjectOutputStream;
34import java.io.ObjectStreamField;
35import java.io.Serializable;
36
37import java.security.AccessController;
38
39import java.util.ArrayList;
40import java.util.Iterator;
41import java.util.List;
42
43import 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
55public 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}
339