0001 /*
0002 * Copyright 2002-2007 Sun Microsystems, Inc. All Rights Reserved.
0003 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
0004 *
0005 * This code is free software; you can redistribute it and/or modify it
0006 * under the terms of the GNU General Public License version 2 only, as
0007 * published by the Free Software Foundation. Sun designates this
0008 * particular file as subject to the "Classpath" exception as provided
0009 * by Sun in the LICENSE file that accompanied this code.
0010 *
0011 * This code is distributed in the hope that it will be useful, but WITHOUT
0012 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
0013 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
0014 * version 2 for more details (a copy is included in the LICENSE file that
0015 * accompanied this code).
0016 *
0017 * You should have received a copy of the GNU General Public License version
0018 * 2 along with this work; if not, write to the Free Software Foundation,
0019 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
0020 *
0021 * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
0022 * CA 95054 USA or visit www.sun.com if you need additional information or
0023 * have any questions.
0024 */
0025
0026 package javax.management;
0027
0028 import java.io.IOException;
0029 import java.io.ObjectInputStream;
0030 import java.security.Permission;
0031
0032 /**
0033 * <p>Permission controlling access to MBeanServer operations. If a
0034 * security manager has been set using {@link
0035 * System#setSecurityManager}, most operations on the MBean Server
0036 * require that the caller's permissions imply an MBeanPermission
0037 * appropriate for the operation. This is described in detail in the
0038 * documentation for the {@link MBeanServer} interface.</p>
0039 *
0040 * <p>As with other {@link Permission} objects, an MBeanPermission can
0041 * represent either a permission that you <em>have</em> or a
0042 * permission that you <em>need</em>. When a sensitive operation is
0043 * being checked for permission, an MBeanPermission is constructed
0044 * representing the permission you need. The operation is only
0045 * allowed if the permissions you have {@link #implies imply} the
0046 * permission you need.</p>
0047 *
0048 * <p>An MBeanPermission contains four items of information:</p>
0049 *
0050 * <ul>
0051 *
0052 * <li><p>The <em>action</em>. For a permission you need,
0053 * this is one of the actions in the list <a
0054 * href="#action-list">below</a>. For a permission you have, this is
0055 * a comma-separated list of those actions, or <code>*</code>,
0056 * representing all actions.</p>
0057 *
0058 * <p>The action is returned by {@link #getActions()}.</p>
0059 *
0060 * <li><p>The <em>class name</em>.</p>
0061 *
0062 * <p>For a permission you need, this is the class name of an MBean
0063 * you are accessing, as returned by {@link
0064 * MBeanServer#getMBeanInfo(ObjectName)
0065 * MBeanServer.getMBeanInfo(name)}.{@link MBeanInfo#getClassName()
0066 * getClassName()}. Certain operations do not reference a class name,
0067 * in which case the class name is null.</p>
0068 *
0069 * <p>For a permission you have, this is either empty or a <em>class
0070 * name pattern</em>. A class name pattern is a string following the
0071 * Java conventions for dot-separated class names. It may end with
0072 * "<code>.*</code>" meaning that the permission grants access to any
0073 * class that begins with the string preceding "<code>.*</code>". For
0074 * instance, "<code>javax.management.*</code>" grants access to
0075 * <code>javax.management.MBeanServerDelegate</code> and
0076 * <code>javax.management.timer.Timer</code>, among other classes.</p>
0077 *
0078 * <p>A class name pattern can also be empty or the single character
0079 * "<code>*</code>", both of which grant access to any class.</p>
0080 *
0081 * <li><p>The <em>member</em>.</p>
0082 *
0083 * <p>For a permission you need, this is the name of the attribute or
0084 * operation you are accessing. For operations that do not reference
0085 * an attribute or operation, the member is null.</p>
0086 *
0087 * <p>For a permission you have, this is either the name of an attribute
0088 * or operation you can access, or it is empty or the single character
0089 * "<code>*</code>", both of which grant access to any member.</p>
0090 *
0091 * <li><p>The <em>object name</em>.</p>
0092 *
0093 * <p>For a permission you need, this is the {@link ObjectName} of the
0094 * MBean you are accessing. For operations that do not reference a
0095 * single MBean, it is null. It is never an object name pattern.</p>
0096 *
0097 * <p>For a permission you have, this is the {@link ObjectName} of the
0098 * MBean or MBeans you can access. It may be an object name pattern
0099 * to grant access to all MBeans whose names match the pattern. It
0100 * may also be empty, which grants access to all MBeans whatever their
0101 * name.</p>
0102 *
0103 * </ul>
0104 *
0105 * <p>If you have an MBeanPermission, it allows operations only if all
0106 * four of the items match.</p>
0107 *
0108 * <p>The class name, member, and object name can be written together
0109 * as a single string, which is the <em>name</em> of this permission.
0110 * The name of the permission is the string returned by {@link
0111 * Permission#getName() getName()}. The format of the string is:</p>
0112 *
0113 * <blockquote>
0114 * <code>className#member[objectName]</code>
0115 * </blockquote>
0116 *
0117 * <p>The object name is written using the usual syntax for {@link
0118 * ObjectName}. It may contain any legal characters, including
0119 * <code>]</code>. It is terminated by a <code>]</code> character
0120 * that is the last character in the string.</p>
0121 *
0122 * <p>One or more of the <code>className</code>, <code>member</code>,
0123 * or <code>objectName</code> may be omitted. If the
0124 * <code>member</code> is omitted, the <code>#</code> may be too (but
0125 * does not have to be). If the <code>objectName</code> is omitted,
0126 * the <code>[]</code> may be too (but does not have to be). It is
0127 * not legal to omit all three items, that is to have a <em>name</em>
0128 * that is the empty string.</p>
0129 *
0130 * <p>One or more of the <code>className</code>, <code>member</code>,
0131 * or <code>objectName</code> may be the character "<code>-</code>",
0132 * which is equivalent to a null value. A null value is implied by
0133 * any value (including another null value) but does not imply any
0134 * other value.</p>
0135 *
0136 * <p><a name="action-list">The possible actions are these:</a></p>
0137 *
0138 * <ul>
0139 * <li>addNotificationListener</li>
0140 * <li>getAttribute</li>
0141 * <li>getClassLoader</li>
0142 * <li>getClassLoaderFor</li>
0143 * <li>getClassLoaderRepository</li>
0144 * <li>getDomains</li>
0145 * <li>getMBeanInfo</li>
0146 * <li>getObjectInstance</li>
0147 * <li>instantiate</li>
0148 * <li>invoke</li>
0149 * <li>isInstanceOf</li>
0150 * <li>queryMBeans</li>
0151 * <li>queryNames</li>
0152 * <li>registerMBean</li>
0153 * <li>removeNotificationListener</li>
0154 * <li>setAttribute</li>
0155 * <li>unregisterMBean</li>
0156 * </ul>
0157 *
0158 * <p>In a comma-separated list of actions, spaces are allowed before
0159 * and after each action.</p>
0160 *
0161 * @since 1.5
0162 */
0163 public class MBeanPermission extends Permission {
0164
0165 private static final long serialVersionUID = -2416928705275160661L;
0166
0167 /**
0168 * Actions list.
0169 */
0170 private static final int AddNotificationListener = 0x00001;
0171 private static final int GetAttribute = 0x00002;
0172 private static final int GetClassLoader = 0x00004;
0173 private static final int GetClassLoaderFor = 0x00008;
0174 private static final int GetClassLoaderRepository = 0x00010;
0175 private static final int GetDomains = 0x00020;
0176 private static final int GetMBeanInfo = 0x00040;
0177 private static final int GetObjectInstance = 0x00080;
0178 private static final int Instantiate = 0x00100;
0179 private static final int Invoke = 0x00200;
0180 private static final int IsInstanceOf = 0x00400;
0181 private static final int QueryMBeans = 0x00800;
0182 private static final int QueryNames = 0x01000;
0183 private static final int RegisterMBean = 0x02000;
0184 private static final int RemoveNotificationListener = 0x04000;
0185 private static final int SetAttribute = 0x08000;
0186 private static final int UnregisterMBean = 0x10000;
0187
0188 /**
0189 * No actions.
0190 */
0191 private static final int NONE = 0x00000;
0192
0193 /**
0194 * All actions.
0195 */
0196 private static final int ALL = AddNotificationListener
0197 | GetAttribute | GetClassLoader | GetClassLoaderFor
0198 | GetClassLoaderRepository | GetDomains | GetMBeanInfo
0199 | GetObjectInstance | Instantiate | Invoke | IsInstanceOf
0200 | QueryMBeans | QueryNames | RegisterMBean
0201 | RemoveNotificationListener | SetAttribute
0202 | UnregisterMBean;
0203
0204 /**
0205 * The actions string.
0206 */
0207 private String actions;
0208
0209 /**
0210 * The actions mask.
0211 */
0212 private transient int mask;
0213
0214 /**
0215 * The classname prefix that must match. If null, is implied by any
0216 * classNamePrefix but does not imply any non-null classNamePrefix.
0217 */
0218 private transient String classNamePrefix;
0219
0220 /**
0221 * True if classNamePrefix must match exactly. Otherwise, the
0222 * className being matched must start with classNamePrefix.
0223 */
0224 private transient boolean classNameExactMatch;
0225
0226 /**
0227 * The member that must match. If null, is implied by any member
0228 * but does not imply any non-null member.
0229 */
0230 private transient String member;
0231
0232 /**
0233 * The objectName that must match. If null, is implied by any
0234 * objectName but does not imply any non-null objectName.
0235 */
0236 private transient ObjectName objectName;
0237
0238 /**
0239 * Parse <code>actions</code> parameter.
0240 */
0241 private void parseActions() {
0242
0243 int mask;
0244
0245 if (actions == null)
0246 throw new IllegalArgumentException("MBeanPermission: "
0247 + "actions can't be null");
0248 if (actions.equals(""))
0249 throw new IllegalArgumentException("MBeanPermission: "
0250 + "actions can't be empty");
0251
0252 mask = getMask(actions);
0253
0254 if ((mask & ALL) != mask)
0255 throw new IllegalArgumentException("Invalid actions mask");
0256 if (mask == NONE)
0257 throw new IllegalArgumentException("Invalid actions mask");
0258 this .mask = mask;
0259 }
0260
0261 /**
0262 * Parse <code>name</code> parameter.
0263 */
0264 private void parseName() {
0265 String name = getName();
0266
0267 if (name == null)
0268 throw new IllegalArgumentException("MBeanPermission name "
0269 + "cannot be null");
0270
0271 if (name.equals(""))
0272 throw new IllegalArgumentException("MBeanPermission name "
0273 + "cannot be empty");
0274
0275 /* The name looks like "class#member[objectname]". We subtract
0276 elements from the right as we parse, so after parsing the
0277 objectname we have "class#member" and after parsing the
0278 member we have "class". Each element is optional. */
0279
0280 // Parse ObjectName
0281 int openingBracket = name.indexOf("[");
0282 if (openingBracket == -1) {
0283 // If "[on]" missing then ObjectName("*:*")
0284 //
0285 objectName = ObjectName.WILDCARD;
0286 } else {
0287 if (!name.endsWith("]")) {
0288 throw new IllegalArgumentException("MBeanPermission: "
0289 + "The ObjectName in the "
0290 + "target name must be "
0291 + "included in square " + "brackets");
0292 } else {
0293 // Create ObjectName
0294 //
0295 try {
0296 // If "[]" then ObjectName("*:*")
0297 //
0298 String on = name.substring(openingBracket + 1, name
0299 .length() - 1);
0300 if (on.equals(""))
0301 objectName = ObjectName.WILDCARD;
0302 else if (on.equals("-"))
0303 objectName = null;
0304 else
0305 objectName = new ObjectName(on);
0306 } catch (MalformedObjectNameException e) {
0307 throw new IllegalArgumentException(
0308 "MBeanPermission: "
0309 + "The target name does "
0310 + "not specify a valid "
0311 + "ObjectName");
0312 }
0313 }
0314
0315 name = name.substring(0, openingBracket);
0316 }
0317
0318 // Parse member
0319
0320 int poundSign = name.indexOf("#");
0321
0322 if (poundSign == -1)
0323 setMember("*");
0324 else {
0325 String memberName = name.substring(poundSign + 1);
0326 setMember(memberName);
0327 name = name.substring(0, poundSign);
0328 }
0329
0330 // Parse className
0331
0332 setClassName(name);
0333 }
0334
0335 /**
0336 * Assign fields based on className, member, and objectName
0337 * parameters.
0338 */
0339 private void initName(String className, String member,
0340 ObjectName objectName) {
0341 setClassName(className);
0342 setMember(member);
0343 this .objectName = objectName;
0344 }
0345
0346 private void setClassName(String className) {
0347 if (className == null || className.equals("-")) {
0348 classNamePrefix = null;
0349 classNameExactMatch = false;
0350 } else if (className.equals("") || className.equals("*")) {
0351 classNamePrefix = "";
0352 classNameExactMatch = false;
0353 } else if (className.endsWith(".*")) {
0354 // Note that we include the "." in the required prefix
0355 classNamePrefix = className.substring(0,
0356 className.length() - 1);
0357 classNameExactMatch = false;
0358 } else {
0359 classNamePrefix = className;
0360 classNameExactMatch = true;
0361 }
0362 }
0363
0364 private void setMember(String member) {
0365 if (member == null || member.equals("-"))
0366 this .member = null;
0367 else if (member.equals(""))
0368 this .member = "*";
0369 else
0370 this .member = member;
0371 }
0372
0373 /**
0374 * <p>Create a new MBeanPermission object with the specified target name
0375 * and actions.</p>
0376 *
0377 * <p>The target name is of the form
0378 * "<code>className#member[objectName]</code>" where each part is
0379 * optional. It must not be empty or null.</p>
0380 *
0381 * <p>The actions parameter contains a comma-separated list of the
0382 * desired actions granted on the target name. It must not be
0383 * empty or null.</p>
0384 *
0385 * @param name the triplet "className#member[objectName]".
0386 * @param actions the action string.
0387 *
0388 * @exception IllegalArgumentException if the <code>name</code> or
0389 * <code>actions</code> is invalid.
0390 */
0391 public MBeanPermission(String name, String actions) {
0392 super (name);
0393
0394 parseName();
0395
0396 this .actions = actions;
0397 parseActions();
0398 }
0399
0400 /**
0401 * <p>Create a new MBeanPermission object with the specified target name
0402 * (class name, member, object name) and actions.</p>
0403 *
0404 * <p>The class name, member and object name parameters define a
0405 * target name of the form
0406 * "<code>className#member[objectName]</code>" where each part is
0407 * optional. This will be the result of {@link #getName()} on the
0408 * resultant MBeanPermission.</p>
0409 *
0410 * <p>The actions parameter contains a comma-separated list of the
0411 * desired actions granted on the target name. It must not be
0412 * empty or null.</p>
0413 *
0414 * @param className the class name to which this permission applies.
0415 * May be null or <code>"-"</code>, which represents a class name
0416 * that is implied by any class name but does not imply any other
0417 * class name.
0418 * @param member the member to which this permission applies. May
0419 * be null or <code>"-"</code>, which represents a member that is
0420 * implied by any member but does not imply any other member.
0421 * @param objectName the object name to which this permission
0422 * applies. May be null, which represents an object name that is
0423 * implied by any object name but does not imply any other object
0424 * name.
0425 * @param actions the action string.
0426 */
0427 public MBeanPermission(String className, String member,
0428 ObjectName objectName, String actions) {
0429
0430 super (makeName(className, member, objectName));
0431 initName(className, member, objectName);
0432
0433 this .actions = actions;
0434 parseActions();
0435 }
0436
0437 private static String makeName(String className, String member,
0438 ObjectName objectName) {
0439 final StringBuilder name = new StringBuilder();
0440 if (className == null)
0441 className = "-";
0442 name.append(className);
0443 if (member == null)
0444 member = "-";
0445 name.append("#" + member);
0446 if (objectName == null)
0447 name.append("[-]");
0448 else
0449 name.append("[").append(objectName.getCanonicalName())
0450 .append("]");
0451
0452 /* In the interests of legibility for Permission.toString(), we
0453 transform the empty string into "*". */
0454 if (name.length() == 0)
0455 return "*";
0456 else
0457 return name.toString();
0458 }
0459
0460 /**
0461 * Returns the "canonical string representation" of the actions. That is,
0462 * this method always returns present actions in alphabetical order.
0463 *
0464 * @return the canonical string representation of the actions.
0465 */
0466 public String getActions() {
0467
0468 if (actions == null)
0469 actions = getActions(this .mask);
0470
0471 return actions;
0472 }
0473
0474 /**
0475 * Returns the "canonical string representation"
0476 * of the actions from the mask.
0477 */
0478 private static String getActions(int mask) {
0479 final StringBuilder sb = new StringBuilder();
0480 boolean comma = false;
0481
0482 if ((mask & AddNotificationListener) == AddNotificationListener) {
0483 comma = true;
0484 sb.append("addNotificationListener");
0485 }
0486
0487 if ((mask & GetAttribute) == GetAttribute) {
0488 if (comma)
0489 sb.append(',');
0490 else
0491 comma = true;
0492 sb.append("getAttribute");
0493 }
0494
0495 if ((mask & GetClassLoader) == GetClassLoader) {
0496 if (comma)
0497 sb.append(',');
0498 else
0499 comma = true;
0500 sb.append("getClassLoader");
0501 }
0502
0503 if ((mask & GetClassLoaderFor) == GetClassLoaderFor) {
0504 if (comma)
0505 sb.append(',');
0506 else
0507 comma = true;
0508 sb.append("getClassLoaderFor");
0509 }
0510
0511 if ((mask & GetClassLoaderRepository) == GetClassLoaderRepository) {
0512 if (comma)
0513 sb.append(',');
0514 else
0515 comma = true;
0516 sb.append("getClassLoaderRepository");
0517 }
0518
0519 if ((mask & GetDomains) == GetDomains) {
0520 if (comma)
0521 sb.append(',');
0522 else
0523 comma = true;
0524 sb.append("getDomains");
0525 }
0526
0527 if ((mask & GetMBeanInfo) == GetMBeanInfo) {
0528 if (comma)
0529 sb.append(',');
0530 else
0531 comma = true;
0532 sb.append("getMBeanInfo");
0533 }
0534
0535 if ((mask & GetObjectInstance) == GetObjectInstance) {
0536 if (comma)
0537 sb.append(',');
0538 else
0539 comma = true;
0540 sb.append("getObjectInstance");
0541 }
0542
0543 if ((mask & Instantiate) == Instantiate) {
0544 if (comma)
0545 sb.append(',');
0546 else
0547 comma = true;
0548 sb.append("instantiate");
0549 }
0550
0551 if ((mask & Invoke) == Invoke) {
0552 if (comma)
0553 sb.append(',');
0554 else
0555 comma = true;
0556 sb.append("invoke");
0557 }
0558
0559 if ((mask & IsInstanceOf) == IsInstanceOf) {
0560 if (comma)
0561 sb.append(',');
0562 else
0563 comma = true;
0564 sb.append("isInstanceOf");
0565 }
0566
0567 if ((mask & QueryMBeans) == QueryMBeans) {
0568 if (comma)
0569 sb.append(',');
0570 else
0571 comma = true;
0572 sb.append("queryMBeans");
0573 }
0574
0575 if ((mask & QueryNames) == QueryNames) {
0576 if (comma)
0577 sb.append(',');
0578 else
0579 comma = true;
0580 sb.append("queryNames");
0581 }
0582
0583 if ((mask & RegisterMBean) == RegisterMBean) {
0584 if (comma)
0585 sb.append(',');
0586 else
0587 comma = true;
0588 sb.append("registerMBean");
0589 }
0590
0591 if ((mask & RemoveNotificationListener) == RemoveNotificationListener) {
0592 if (comma)
0593 sb.append(',');
0594 else
0595 comma = true;
0596 sb.append("removeNotificationListener");
0597 }
0598
0599 if ((mask & SetAttribute) == SetAttribute) {
0600 if (comma)
0601 sb.append(',');
0602 else
0603 comma = true;
0604 sb.append("setAttribute");
0605 }
0606
0607 if ((mask & UnregisterMBean) == UnregisterMBean) {
0608 if (comma)
0609 sb.append(',');
0610 else
0611 comma = true;
0612 sb.append("unregisterMBean");
0613 }
0614
0615 return sb.toString();
0616 }
0617
0618 /**
0619 * Returns the hash code value for this object.
0620 *
0621 * @return a hash code value for this object.
0622 */
0623 public int hashCode() {
0624 return this .getName().hashCode() + this .getActions().hashCode();
0625 }
0626
0627 /**
0628 * Converts an action String to an integer action mask.
0629 *
0630 * @param action the action string.
0631 * @return the action mask.
0632 */
0633 private static int getMask(String action) {
0634
0635 /*
0636 * BE CAREFUL HERE! PARSING ORDER IS IMPORTANT IN THIS ALGORITHM.
0637 *
0638 * The 'string length' test must be performed for the lengthiest
0639 * strings first.
0640 *
0641 * In this permission if the "unregisterMBean" string length test is
0642 * performed after the "registerMBean" string length test the algorithm
0643 * considers the 'unregisterMBean' action as being the 'registerMBean'
0644 * action and a parsing error is returned.
0645 */
0646
0647 int mask = NONE;
0648
0649 if (action == null) {
0650 return mask;
0651 }
0652
0653 if (action.equals("*")) {
0654 return ALL;
0655 }
0656
0657 char[] a = action.toCharArray();
0658
0659 int i = a.length - 1;
0660 if (i < 0)
0661 return mask;
0662
0663 while (i != -1) {
0664 char c;
0665
0666 // skip whitespace
0667 while ((i != -1)
0668 && ((c = a[i]) == ' ' || c == '\r' || c == '\n'
0669 || c == '\f' || c == '\t'))
0670 i--;
0671
0672 // check for the known strings
0673 int matchlen;
0674
0675 if (i >= 25 && /* removeNotificationListener */
0676 (a[i - 25] == 'r') && (a[i - 24] == 'e')
0677 && (a[i - 23] == 'm') && (a[i - 22] == 'o')
0678 && (a[i - 21] == 'v') && (a[i - 20] == 'e')
0679 && (a[i - 19] == 'N') && (a[i - 18] == 'o')
0680 && (a[i - 17] == 't') && (a[i - 16] == 'i')
0681 && (a[i - 15] == 'f') && (a[i - 14] == 'i')
0682 && (a[i - 13] == 'c') && (a[i - 12] == 'a')
0683 && (a[i - 11] == 't') && (a[i - 10] == 'i')
0684 && (a[i - 9] == 'o') && (a[i - 8] == 'n')
0685 && (a[i - 7] == 'L') && (a[i - 6] == 'i')
0686 && (a[i - 5] == 's') && (a[i - 4] == 't')
0687 && (a[i - 3] == 'e') && (a[i - 2] == 'n')
0688 && (a[i - 1] == 'e') && (a[i] == 'r')) {
0689 matchlen = 26;
0690 mask |= RemoveNotificationListener;
0691 } else if (i >= 23 && /* getClassLoaderRepository */
0692 (a[i - 23] == 'g') && (a[i - 22] == 'e')
0693 && (a[i - 21] == 't') && (a[i - 20] == 'C')
0694 && (a[i - 19] == 'l') && (a[i - 18] == 'a')
0695 && (a[i - 17] == 's') && (a[i - 16] == 's')
0696 && (a[i - 15] == 'L') && (a[i - 14] == 'o')
0697 && (a[i - 13] == 'a') && (a[i - 12] == 'd')
0698 && (a[i - 11] == 'e') && (a[i - 10] == 'r')
0699 && (a[i - 9] == 'R') && (a[i - 8] == 'e')
0700 && (a[i - 7] == 'p') && (a[i - 6] == 'o')
0701 && (a[i - 5] == 's') && (a[i - 4] == 'i')
0702 && (a[i - 3] == 't') && (a[i - 2] == 'o')
0703 && (a[i - 1] == 'r') && (a[i] == 'y')) {
0704 matchlen = 24;
0705 mask |= GetClassLoaderRepository;
0706 } else if (i >= 22 && /* addNotificationListener */
0707 (a[i - 22] == 'a') && (a[i - 21] == 'd')
0708 && (a[i - 20] == 'd') && (a[i - 19] == 'N')
0709 && (a[i - 18] == 'o') && (a[i - 17] == 't')
0710 && (a[i - 16] == 'i') && (a[i - 15] == 'f')
0711 && (a[i - 14] == 'i') && (a[i - 13] == 'c')
0712 && (a[i - 12] == 'a') && (a[i - 11] == 't')
0713 && (a[i - 10] == 'i') && (a[i - 9] == 'o')
0714 && (a[i - 8] == 'n') && (a[i - 7] == 'L')
0715 && (a[i - 6] == 'i') && (a[i - 5] == 's')
0716 && (a[i - 4] == 't') && (a[i - 3] == 'e')
0717 && (a[i - 2] == 'n') && (a[i - 1] == 'e')
0718 && (a[i] == 'r')) {
0719 matchlen = 23;
0720 mask |= AddNotificationListener;
0721 } else if (i >= 16 && /* getClassLoaderFor */
0722 (a[i - 16] == 'g') && (a[i - 15] == 'e')
0723 && (a[i - 14] == 't') && (a[i - 13] == 'C')
0724 && (a[i - 12] == 'l') && (a[i - 11] == 'a')
0725 && (a[i - 10] == 's') && (a[i - 9] == 's')
0726 && (a[i - 8] == 'L') && (a[i - 7] == 'o')
0727 && (a[i - 6] == 'a') && (a[i - 5] == 'd')
0728 && (a[i - 4] == 'e') && (a[i - 3] == 'r')
0729 && (a[i - 2] == 'F') && (a[i - 1] == 'o')
0730 && (a[i] == 'r')) {
0731 matchlen = 17;
0732 mask |= GetClassLoaderFor;
0733 } else if (i >= 16 && /* getObjectInstance */
0734 (a[i - 16] == 'g') && (a[i - 15] == 'e')
0735 && (a[i - 14] == 't') && (a[i - 13] == 'O')
0736 && (a[i - 12] == 'b') && (a[i - 11] == 'j')
0737 && (a[i - 10] == 'e') && (a[i - 9] == 'c')
0738 && (a[i - 8] == 't') && (a[i - 7] == 'I')
0739 && (a[i - 6] == 'n') && (a[i - 5] == 's')
0740 && (a[i - 4] == 't') && (a[i - 3] == 'a')
0741 && (a[i - 2] == 'n') && (a[i - 1] == 'c')
0742 && (a[i] == 'e')) {
0743 matchlen = 17;
0744 mask |= GetObjectInstance;
0745 } else if (i >= 14 && /* unregisterMBean */
0746 (a[i - 14] == 'u') && (a[i - 13] == 'n')
0747 && (a[i - 12] == 'r') && (a[i - 11] == 'e')
0748 && (a[i - 10] == 'g') && (a[i - 9] == 'i')
0749 && (a[i - 8] == 's') && (a[i - 7] == 't')
0750 && (a[i - 6] == 'e') && (a[i - 5] == 'r')
0751 && (a[i - 4] == 'M') && (a[i - 3] == 'B')
0752 && (a[i - 2] == 'e') && (a[i - 1] == 'a')
0753 && (a[i] == 'n')) {
0754 matchlen = 15;
0755 mask |= UnregisterMBean;
0756 } else if (i >= 13 && /* getClassLoader */
0757 (a[i - 13] == 'g') && (a[i - 12] == 'e')
0758 && (a[i - 11] == 't') && (a[i - 10] == 'C')
0759 && (a[i - 9] == 'l') && (a[i - 8] == 'a')
0760 && (a[i - 7] == 's') && (a[i - 6] == 's')
0761 && (a[i - 5] == 'L') && (a[i - 4] == 'o')
0762 && (a[i - 3] == 'a') && (a[i - 2] == 'd')
0763 && (a[i - 1] == 'e') && (a[i] == 'r')) {
0764 matchlen = 14;
0765 mask |= GetClassLoader;
0766 } else if (i >= 12 && /* registerMBean */
0767 (a[i - 12] == 'r') && (a[i - 11] == 'e')
0768 && (a[i - 10] == 'g') && (a[i - 9] == 'i')
0769 && (a[i - 8] == 's') && (a[i - 7] == 't')
0770 && (a[i - 6] == 'e') && (a[i - 5] == 'r')
0771 && (a[i - 4] == 'M') && (a[i - 3] == 'B')
0772 && (a[i - 2] == 'e') && (a[i - 1] == 'a')
0773 && (a[i] == 'n')) {
0774 matchlen = 13;
0775 mask |= RegisterMBean;
0776 } else if (i >= 11 && /* getAttribute */
0777 (a[i - 11] == 'g') && (a[i - 10] == 'e')
0778 && (a[i - 9] == 't') && (a[i - 8] == 'A')
0779 && (a[i - 7] == 't') && (a[i - 6] == 't')
0780 && (a[i - 5] == 'r') && (a[i - 4] == 'i')
0781 && (a[i - 3] == 'b') && (a[i - 2] == 'u')
0782 && (a[i - 1] == 't') && (a[i] == 'e')) {
0783 matchlen = 12;
0784 mask |= GetAttribute;
0785 } else if (i >= 11 && /* getMBeanInfo */
0786 (a[i - 11] == 'g') && (a[i - 10] == 'e')
0787 && (a[i - 9] == 't') && (a[i - 8] == 'M')
0788 && (a[i - 7] == 'B') && (a[i - 6] == 'e')
0789 && (a[i - 5] == 'a') && (a[i - 4] == 'n')
0790 && (a[i - 3] == 'I') && (a[i - 2] == 'n')
0791 && (a[i - 1] == 'f') && (a[i] == 'o')) {
0792 matchlen = 12;
0793 mask |= GetMBeanInfo;
0794 } else if (i >= 11 && /* isInstanceOf */
0795 (a[i - 11] == 'i') && (a[i - 10] == 's')
0796 && (a[i - 9] == 'I') && (a[i - 8] == 'n')
0797 && (a[i - 7] == 's') && (a[i - 6] == 't')
0798 && (a[i - 5] == 'a') && (a[i - 4] == 'n')
0799 && (a[i - 3] == 'c') && (a[i - 2] == 'e')
0800 && (a[i - 1] == 'O') && (a[i] == 'f')) {
0801 matchlen = 12;
0802 mask |= IsInstanceOf;
0803 } else if (i >= 11 && /* setAttribute */
0804 (a[i - 11] == 's') && (a[i - 10] == 'e')
0805 && (a[i - 9] == 't') && (a[i - 8] == 'A')
0806 && (a[i - 7] == 't') && (a[i - 6] == 't')
0807 && (a[i - 5] == 'r') && (a[i - 4] == 'i')
0808 && (a[i - 3] == 'b') && (a[i - 2] == 'u')
0809 && (a[i - 1] == 't') && (a[i] == 'e')) {
0810 matchlen = 12;
0811 mask |= SetAttribute;
0812 } else if (i >= 10 && /* instantiate */
0813 (a[i - 10] == 'i') && (a[i - 9] == 'n')
0814 && (a[i - 8] == 's') && (a[i - 7] == 't')
0815 && (a[i - 6] == 'a') && (a[i - 5] == 'n')
0816 && (a[i - 4] == 't') && (a[i - 3] == 'i')
0817 && (a[i - 2] == 'a') && (a[i - 1] == 't')
0818 && (a[i] == 'e')) {
0819 matchlen = 11;
0820 mask |= Instantiate;
0821 } else if (i >= 10 && /* queryMBeans */
0822 (a[i - 10] == 'q') && (a[i - 9] == 'u')
0823 && (a[i - 8] == 'e') && (a[i - 7] == 'r')
0824 && (a[i - 6] == 'y') && (a[i - 5] == 'M')
0825 && (a[i - 4] == 'B') && (a[i - 3] == 'e')
0826 && (a[i - 2] == 'a') && (a[i - 1] == 'n')
0827 && (a[i] == 's')) {
0828 matchlen = 11;
0829 mask |= QueryMBeans;
0830 } else if (i >= 9 && /* getDomains */
0831 (a[i - 9] == 'g') && (a[i - 8] == 'e') && (a[i - 7] == 't')
0832 && (a[i - 6] == 'D') && (a[i - 5] == 'o')
0833 && (a[i - 4] == 'm') && (a[i - 3] == 'a')
0834 && (a[i - 2] == 'i') && (a[i - 1] == 'n')
0835 && (a[i] == 's')) {
0836 matchlen = 10;
0837 mask |= GetDomains;
0838 } else if (i >= 9 && /* queryNames */
0839 (a[i - 9] == 'q') && (a[i - 8] == 'u') && (a[i - 7] == 'e')
0840 && (a[i - 6] == 'r') && (a[i - 5] == 'y')
0841 && (a[i - 4] == 'N') && (a[i - 3] == 'a')
0842 && (a[i - 2] == 'm') && (a[i - 1] == 'e')
0843 && (a[i] == 's')) {
0844 matchlen = 10;
0845 mask |= QueryNames;
0846 } else if (i >= 5 && /* invoke */
0847 (a[i - 5] == 'i') && (a[i - 4] == 'n') && (a[i - 3] == 'v')
0848 && (a[i - 2] == 'o') && (a[i - 1] == 'k')
0849 && (a[i] == 'e')) {
0850 matchlen = 6;
0851 mask |= Invoke;
0852 } else {
0853 // parse error
0854 throw new IllegalArgumentException(
0855 "Invalid permission: " + action);
0856 }
0857
0858 // make sure we didn't just match the tail of a word
0859 // like "ackbarfaccept". Also, skip to the comma.
0860 boolean seencomma = false;
0861 while (i >= matchlen && !seencomma) {
0862 switch (a[i - matchlen]) {
0863 case ',':
0864 seencomma = true;
0865 break;
0866 case ' ':
0867 case '\r':
0868 case '\n':
0869 case '\f':
0870 case '\t':
0871 break;
0872 default:
0873 throw new IllegalArgumentException(
0874 "Invalid permission: " + action);
0875 }
0876 i--;
0877 }
0878
0879 // point i at the location of the comma minus one (or -1).
0880 i -= matchlen;
0881 }
0882
0883 return mask;
0884 }
0885
0886 /**
0887 * <p>Checks if this MBeanPermission object "implies" the
0888 * specified permission.</p>
0889 *
0890 * <p>More specifically, this method returns true if:</p>
0891 *
0892 * <ul>
0893 *
0894 * <li> <i>p</i> is an instance of MBeanPermission; and</li>
0895 *
0896 * <li> <i>p</i> has a null className or <i>p</i>'s className
0897 * matches this object's className; and</li>
0898 *
0899 * <li> <i>p</i> has a null member or <i>p</i>'s member matches this
0900 * object's member; and</li>
0901 *
0902 * <li> <i>p</i> has a null object name or <i>p</i>'s
0903 * object name matches this object's object name; and</li>
0904 *
0905 * <li> <i>p</i>'s actions are a subset of this object's actions</li>
0906 *
0907 * </ul>
0908 *
0909 * <p>If this object's className is "<code>*</code>", <i>p</i>'s
0910 * className always matches it. If it is "<code>a.*</code>", <i>p</i>'s
0911 * className matches it if it begins with "<code>a.</code>".</p>
0912 *
0913 * <p>If this object's member is "<code>*</code>", <i>p</i>'s
0914 * member always matches it.</p>
0915 *
0916 * <p>If this object's objectName <i>n1</i> is an object name pattern,
0917 * <i>p</i>'s objectName <i>n2</i> matches it if
0918 * {@link ObjectName#equals <i>n1</i>.equals(<i>n2</i>)} or if
0919 * {@link ObjectName#apply <i>n1</i>.apply(<i>n2</i>)}.</p>
0920 *
0921 * <p>A permission that includes the <code>queryMBeans</code> action
0922 * is considered to include <code>queryNames</code> as well.</p>
0923 *
0924 * @param p the permission to check against.
0925 * @return true if the specified permission is implied by this object,
0926 * false if not.
0927 */
0928 public boolean implies(Permission p) {
0929 if (!(p instanceof MBeanPermission))
0930 return false;
0931
0932 MBeanPermission that = (MBeanPermission) p;
0933
0934 // Actions
0935 //
0936 // The actions in 'this' permission must be a
0937 // superset of the actions in 'that' permission
0938 //
0939
0940 /* "queryMBeans" implies "queryNames" */
0941 if ((this .mask & QueryMBeans) == QueryMBeans) {
0942 if (((this .mask | QueryNames) & that.mask) != that.mask) {
0943 //System.out.println("action [with QueryNames] does not imply");
0944 return false;
0945 }
0946 } else {
0947 if ((this .mask & that.mask) != that.mask) {
0948 //System.out.println("action does not imply");
0949 return false;
0950 }
0951 }
0952
0953 // Target name
0954 //
0955 // The 'className' check is true iff:
0956 // 1) the className in 'this' permission is omitted or "*", or
0957 // 2) the className in 'that' permission is omitted or "*", or
0958 // 3) the className in 'this' permission does pattern
0959 // matching with the className in 'that' permission.
0960 //
0961 // The 'member' check is true iff:
0962 // 1) the member in 'this' permission is omitted or "*", or
0963 // 2) the member in 'that' permission is omitted or "*", or
0964 // 3) the member in 'this' permission equals the member in
0965 // 'that' permission.
0966 //
0967 // The 'object name' check is true iff:
0968 // 1) the object name in 'this' permission is omitted or "*:*", or
0969 // 2) the object name in 'that' permission is omitted or "*:*", or
0970 // 3) the object name in 'this' permission does pattern
0971 // matching with the object name in 'that' permission.
0972 //
0973
0974 /* Check if this.className implies that.className.
0975
0976 If that.classNamePrefix is empty that means the className is
0977 irrelevant for this permission check. Otherwise, we do not
0978 expect that "that" contains a wildcard, since it is a
0979 needed permission. So we assume that.classNameExactMatch. */
0980
0981 if (that.classNamePrefix == null) {
0982 // bottom is implied
0983 } else if (this .classNamePrefix == null) {
0984 // bottom implies nothing but itself
0985 return false;
0986 } else if (this .classNameExactMatch) {
0987 if (!that.classNameExactMatch)
0988 return false; // exact never implies wildcard
0989 if (!that.classNamePrefix.equals(this .classNamePrefix))
0990 return false; // exact match fails
0991 } else {
0992 // prefix match, works even if "that" is also a wildcard
0993 // e.g. a.* implies a.* and a.b.*
0994 if (!that.classNamePrefix.startsWith(this .classNamePrefix))
0995 return false;
0996 }
0997
0998 /* Check if this.member implies that.member */
0999
1000 if (that.member == null) {
1001 // bottom is implied
1002 } else if (this .member == null) {
1003 // bottom implies nothing but itself
1004 return false;
1005 } else if (this .member.equals("*")) {
1006 // wildcard implies everything (including itself)
1007 } else if (!this .member.equals(that.member)) {
1008 return false;
1009 }
1010
1011 /* Check if this.objectName implies that.objectName */
1012
1013 if (that.objectName == null) {
1014 // bottom is implied
1015 } else if (this .objectName == null) {
1016 // bottom implies nothing but itself
1017 return false;
1018 } else if (!this .objectName.apply(that.objectName)) {
1019 /* ObjectName.apply returns false if that.objectName is a
1020 wildcard so we also allow equals for that case. This
1021 never happens during real permission checks, but means
1022 the implies relation is reflexive. */
1023 if (!this .objectName.equals(that.objectName))
1024 return false;
1025 }
1026
1027 return true;
1028 }
1029
1030 /**
1031 * Checks two MBeanPermission objects for equality. Checks
1032 * that <i>obj</i> is an MBeanPermission, and has the same
1033 * name and actions as this object.
1034 * <P>
1035 * @param obj the object we are testing for equality with this object.
1036 * @return true if obj is an MBeanPermission, and has the
1037 * same name and actions as this MBeanPermission object.
1038 */
1039 public boolean equals(Object obj) {
1040 if (obj == this )
1041 return true;
1042
1043 if (!(obj instanceof MBeanPermission))
1044 return false;
1045
1046 MBeanPermission that = (MBeanPermission) obj;
1047
1048 return (this .mask == that.mask)
1049 && (this .getName().equals(that.getName()));
1050 }
1051
1052 /**
1053 * Deserialize this object based on its name and actions.
1054 */
1055 private void readObject(ObjectInputStream in) throws IOException,
1056 ClassNotFoundException {
1057 in.defaultReadObject();
1058 parseName();
1059 parseActions();
1060 }
1061 }
|