KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > javax > management > MBeanServerPermission


1 /*
2  * @(#)MBeanServerPermission.java 1.26 03/12/19
3  *
4  * Copyright 2004 Sun Microsystems, Inc. All rights reserved.
5  * SUN PROPRIETARY/CONFIDENTIAL. Use is subject to license terms.
6  */

7
8 package javax.management;
9
10 import java.io.IOException JavaDoc;
11 import java.io.ObjectInputStream JavaDoc;
12 import java.security.BasicPermission JavaDoc;
13 import java.security.Permission JavaDoc;
14 import java.security.PermissionCollection JavaDoc;
15 import java.util.Collections JavaDoc;
16 import java.util.Enumeration JavaDoc;
17 import java.util.Set JavaDoc;
18 import java.util.StringTokenizer JavaDoc;
19
20 /** A Permission to perform actions related to MBeanServers.
21     The <em>name</em> of the permission specifies the operation requested
22     or granted by the permission. For a granted permission, it can be
23     <code>*</code> to allow all of the MBeanServer operations specified below.
24     Otherwise, for a granted or requested permission, it must be one of the
25     following:
26     <dl>
27     <dt>createMBeanServer</dt>
28     <dd>Create a new MBeanServer object using the method
29     {@link MBeanServerFactory#createMBeanServer()} or
30     {@link MBeanServerFactory#createMBeanServer(java.lang.String)}.
31     <dt>findMBeanServer</dt>
32     <dd>Find an MBeanServer with a given name, or all MBeanServers in this
33     JVM, using the method {@link MBeanServerFactory#findMBeanServer}.
34     <dt>newMBeanServer</dt>
35     <dd>Create a new MBeanServer object without keeping a reference to it,
36     using the method {@link MBeanServerFactory#newMBeanServer()} or
37     {@link MBeanServerFactory#newMBeanServer(java.lang.String)}.
38     <dt>releaseMBeanServer</dt>
39     <dd>Remove the MBeanServerFactory's reference to an MBeanServer,
40     using the method {@link MBeanServerFactory#releaseMBeanServer}.
41     </dl>
42     The <em>name</em> of the permission can also denote a list of one or more
43     comma-separated operations. Spaces are allowed at the beginning and
44     end of the <em>name</em> and before and after commas.
45     <p>
46     <code>MBeanServerPermission("createMBeanServer")</code> implies
47     <code>MBeanServerPermission("newMBeanServer")</code>.
48  *
49  * @since 1.5
50  * @since.unbundled JMX 1.1
51  */

52 public class MBeanServerPermission extends BasicPermission JavaDoc {
53     private static final long serialVersionUID = -5661980843569388590L;
54
55     private final static int
56     CREATE = 0,
57     FIND = 1,
58     NEW = 2,
59     RELEASE = 3,
60     N_NAMES = 4;
61
62     private final static String JavaDoc[] names = {
63     "createMBeanServer",
64     "findMBeanServer",
65     "newMBeanServer",
66     "releaseMBeanServer",
67     };
68
69     private final static int
70     CREATE_MASK = 1<<CREATE,
71     FIND_MASK = 1<<FIND,
72     NEW_MASK = 1<<NEW,
73     RELEASE_MASK = 1<<RELEASE,
74     ALL_MASK = CREATE_MASK|FIND_MASK|NEW_MASK|RELEASE_MASK;
75
76     /*
77      * Map from permission masks to canonical names. This array is
78      * filled in on demand.
79      *
80      * This isn't very scalable. If we have more than five or six
81      * permissions, we should consider doing this differently,
82      * e.g. with a Map.
83      */

84     private final static String JavaDoc[] canonicalNames = new String JavaDoc[1 << N_NAMES];
85
86     /*
87      * The target names mask. This is not private to avoid having to
88      * generate accessor methods for accesses from the collection class.
89      *
90      * This mask includes implied bits. So if it has CREATE_MASK then
91      * it necessarily has NEW_MASK too.
92      */

93     transient int mask;
94
95     /** <p>Create a new MBeanServerPermission with the given name.</p>
96     <p>This constructor is equivalent to
97     <code>MBeanServerPermission(name,null)</code>.</p>
98     @param name the name of the granted permission. It must
99     respect the constraints spelt out in the description of the
100     {@link MBeanServerPermission} class.
101     @exception NullPointerException if the name is null.
102     @exception IllegalArgumentException if the name is not
103     <code>*</code> or one of the allowed names or a comma-separated
104         list of the allowed names.
105     */

106     public MBeanServerPermission(String JavaDoc name) {
107     this(name, null);
108     }
109
110     /** <p>Create a new MBeanServerPermission with the given name.</p>
111     @param name the name of the granted permission. It must
112     respect the constraints spelt out in the description of the
113     {@link MBeanServerPermission} class.
114     @param actions the associated actions. This parameter is not
115     currently used and must be null or the empty string.
116     @exception NullPointerException if the name is null.
117     @exception IllegalArgumentException if the name is not
118     <code>*</code> or one of the allowed names or a comma-separated
119         list of the allowed names, or if <code>actions</code> is a non-null
120         non-empty string. */

121     public MBeanServerPermission(String JavaDoc name, String JavaDoc actions) {
122         super(getCanonicalName(parseMask(name)), actions);
123
124     /* It's annoying to have to parse the name twice, but since
125        Permission.getName() is final and since we can't access "this"
126        until after the call to the superclass constructor, there
127        isn't any very clean way to do this. MBeanServerPermission
128        objects aren't constructed very often, luckily. */

129     mask = parseMask(name);
130
131     /* Check that actions is a null empty string */
132     if (actions != null && actions.length() > 0)
133         throw new IllegalArgumentException JavaDoc("MBeanServerPermission " +
134                            "actions must be null: " +
135                            actions);
136     }
137
138     MBeanServerPermission(int mask) {
139     super(getCanonicalName(mask));
140     this.mask = impliedMask(mask);
141     }
142
143     private void readObject(ObjectInputStream JavaDoc in)
144         throws IOException JavaDoc, ClassNotFoundException JavaDoc {
145     in.defaultReadObject();
146     mask = parseMask(getName());
147     }
148
149     static int simplifyMask(int mask) {
150     if ((mask & CREATE_MASK) != 0)
151         mask &= ~NEW_MASK;
152     return mask;
153     }
154
155     static int impliedMask(int mask) {
156     if ((mask & CREATE_MASK) != 0)
157         mask |= NEW_MASK;
158     return mask;
159     }
160
161     static String JavaDoc getCanonicalName(int mask) {
162     if (mask == ALL_MASK)
163         return "*";
164
165     mask = simplifyMask(mask);
166
167     synchronized (canonicalNames) {
168         if (canonicalNames[mask] == null)
169         canonicalNames[mask] = makeCanonicalName(mask);
170     }
171
172     return canonicalNames[mask];
173     }
174
175     private static String JavaDoc makeCanonicalName(int mask) {
176     StringBuffer JavaDoc buf = new StringBuffer JavaDoc();
177     for (int i = 0; i < N_NAMES; i++) {
178         if ((mask & (1<<i)) != 0) {
179         if (buf.length() > 0)
180             buf.append(',');
181         buf.append(names[i]);
182         }
183     }
184     return buf.toString().intern();
185     /* intern() avoids duplication when the mask has only
186        one bit, so is equivalent to the string constants
187        we have for the names[] array. */

188     }
189
190     /* Convert the string into a bitmask, including bits that
191        are implied by the permissions in the string. */

192     private static int parseMask(String JavaDoc name) {
193     /* Check that target name is a non-null non-empty string */
194     if (name == null) {
195         throw new NullPointerException JavaDoc("MBeanServerPermission: " +
196                        "target name can't be null");
197     }
198
199     name = name.trim();
200     if (name.equals("*"))
201         return ALL_MASK;
202
203     /* If the name is empty, nameIndex will barf. */
204     if (name.indexOf(',') < 0)
205         return impliedMask(1 << nameIndex(name.trim()));
206
207     int mask = 0;
208
209     StringTokenizer JavaDoc tok = new StringTokenizer JavaDoc(name, ",");
210     while (tok.hasMoreTokens()) {
211         String JavaDoc action = tok.nextToken();
212         int i = nameIndex(action.trim());
213         mask |= (1 << i);
214     }
215
216     return impliedMask(mask);
217     }
218
219     private static int nameIndex(String JavaDoc name)
220         throws IllegalArgumentException JavaDoc {
221     for (int i = 0; i < N_NAMES; i++) {
222         if (names[i].equals(name))
223         return i;
224     }
225     final String JavaDoc msg =
226         "Invalid MBeanServerPermission name: \"" + name + "\"";
227     throw new IllegalArgumentException JavaDoc(msg);
228     }
229
230     public int hashCode() {
231     return mask;
232     }
233
234     /**
235      * <p>Checks if this MBeanServerPermission object "implies" the specified
236      * permission.</p>
237      *
238      * <p>More specifically, this method returns true if:</p>
239      *
240      * <ul>
241      * <li> <i>p</i> is an instance of MBeanServerPermission,</li>
242      * <li> <i>p</i>'s target names are a subset of this object's target
243      * names</li>
244      * </ul>
245      *
246      * <p>The <code>createMBeanServer</code> permission implies the
247      * <code>newMBeanServer</code> permission.</p>
248      *
249      * @param p the permission to check against.
250      * @return true if the specified permission is implied by this object,
251      * false if not.
252      */

253     public boolean implies(Permission JavaDoc p) {
254     if (!(p instanceof MBeanServerPermission JavaDoc))
255         return false;
256
257     MBeanServerPermission JavaDoc that = (MBeanServerPermission JavaDoc) p;
258
259     return ((this.mask & that.mask) == that.mask);
260     }
261
262     /**
263      * Checks two MBeanServerPermission objects for equality. Checks that
264      * <i>obj</i> is an MBeanServerPermission, and represents the same
265      * list of allowable actions as this object.
266      * <P>
267      * @param obj the object we are testing for equality with this object.
268      * @return true if the objects are equal.
269      */

270     public boolean equals(Object JavaDoc obj) {
271     if (obj == this)
272         return true;
273
274     if (! (obj instanceof MBeanServerPermission JavaDoc))
275         return false;
276
277     MBeanServerPermission JavaDoc that = (MBeanServerPermission JavaDoc) obj;
278
279     return (this.mask == that.mask);
280     }
281
282     public PermissionCollection JavaDoc newPermissionCollection() {
283     return new MBeanServerPermissionCollection();
284     }
285 }
286
287 /**
288  * Class returned by {@link MBeanServerPermission#newPermissionCollection()}.
289  *
290  * @serial include
291  */

292
293 /*
294  * Since every collection of MBSP can be represented by a single MBSP,
295  * that is what our PermissionCollection does. We need to define a
296  * PermissionCollection because the one inherited from BasicPermission
297  * doesn't know that createMBeanServer implies newMBeanServer.
298  *
299  * Though the serial form is defined, the TCK does not check it. We do
300  * not require independent implementations to duplicate it. Even though
301  * PermissionCollection is Serializable, instances of this class will
302  * hardly ever be serialized, and different implementations do not
303  * typically exchange serialized permission collections.
304  *
305  * If we did require that a particular form be respected here, we would
306  * logically also have to require it for
307  * MBeanPermission.newPermissionCollection, which would preclude an
308  * implementation from defining a PermissionCollection there with an
309  * optimized "implies" method.
310  */

311 class MBeanServerPermissionCollection extends PermissionCollection JavaDoc {
312     /** @serial Null if no permissions in collection, otherwise a
313     single permission that is the union of all permissions that
314     have been added. */

315     private MBeanServerPermission JavaDoc collectionPermission;
316
317     private static final long serialVersionUID = -5661980843569388590L;
318
319     public synchronized void add(Permission JavaDoc permission) {
320     if (!(permission instanceof MBeanServerPermission JavaDoc)) {
321         final String JavaDoc msg =
322         "Permission not an MBeanServerPermission: " + permission;
323         throw new IllegalArgumentException JavaDoc(msg);
324     }
325     if (isReadOnly())
326         throw new SecurityException JavaDoc("Read-only permission collection");
327     MBeanServerPermission JavaDoc mbsp = (MBeanServerPermission JavaDoc) permission;
328     if (collectionPermission == null)
329         collectionPermission = mbsp;
330     else if (!collectionPermission.implies(permission)) {
331         int newmask = collectionPermission.mask | mbsp.mask;
332         collectionPermission = new MBeanServerPermission JavaDoc(newmask);
333     }
334     }
335
336     public synchronized boolean implies(Permission JavaDoc permission) {
337     return (collectionPermission != null &&
338         collectionPermission.implies(permission));
339     }
340
341     public synchronized Enumeration JavaDoc elements() {
342     Set JavaDoc set;
343     if (collectionPermission == null)
344         set = Collections.EMPTY_SET;
345     else
346         set = Collections.singleton(collectionPermission);
347     return Collections.enumeration(set);
348     }
349 }
350
Popular Tags