123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550 |
- /* MBeanPermission.java -- Permissions controlling server access.
- Copyright (C) 2006 Free Software Foundation, Inc.
- This file is part of GNU Classpath.
- GNU Classpath is free software; you can redistribute it and/or modify
- it under the terms of the GNU General Public License as published by
- the Free Software Foundation; either version 2, or (at your option)
- any later version.
- GNU Classpath 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 for more details.
- You should have received a copy of the GNU General Public License
- along with GNU Classpath; see the file COPYING. If not, write to the
- Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
- 02110-1301 USA.
- Linking this library statically or dynamically with other modules is
- making a combined work based on this library. Thus, the terms and
- conditions of the GNU General Public License cover the whole
- combination.
- As a special exception, the copyright holders of this library give you
- permission to link this library with independent modules to produce an
- executable, regardless of the license terms of these independent
- modules, and to copy and distribute the resulting executable under
- terms of your choice, provided that you also meet, for each linked
- independent module, the terms and conditions of the license of that
- module. An independent module is a module which is not derived from
- or based on this library. If you modify this library, you may extend
- this exception to your version of the library, but you are not
- obligated to do so. If you do not wish to do so, delete this
- exception statement from your version. */
- package javax.management;
- import gnu.java.lang.CPStringBuilder;
- import java.security.Permission;
- import java.io.IOException;
- import java.io.ObjectInputStream;
- import java.util.HashSet;
- import java.util.Iterator;
- import java.util.Set;
- import java.util.TreeSet;
- /**
- * <p>
- * Represents the permissions required to perform
- * operations using the {@link MBeanServer}. As with
- * all {@link java.security.Permission} objects, an
- * instance of this class either represents a permission
- * already held or one that is required to access a
- * particular service. In the case of {@link MBeanPermission}s,
- * implication checks are made using an instance of this class
- * when a user requests an operation from the server, and a
- * {@link SecurityManager} is in place.
- * </p>
- * <p>
- * An {@link MBeanPermission} consists of four elements,
- * which all have to match for the permission to be implied.
- * These are as follows:
- * </p>
- * <ol>
- * <li><strong>The action</strong>. For a required permission,
- * this is a single value. For a permission held by the user,
- * this is a list of comma-separated actions (with spaces allowed),
- * or <code>*</code> (representing all actions). {@link #getActions()}
- * returns this value.</li>
- * <li><strong>The class name</strong>. For a required permission,
- * this is the class name of the bean being accessed, if any. If
- * a bean isn't involved in this action, the value is <code>null</code>.
- * For a permission held by the user, it has one of three values:
- * <ol>
- * <li>The empty string, implying any class.</li>
- * <li><code>*</code>, also implying any class.</li>
- * <li>A class name pattern, which may specify a single class
- * (e.g. <code>java.lang.Object</code>) or a series of classes
- * using the wildcard character <code>*</code> (e.g.
- * <code>javax.swing.*</code>.)</li>
- * </ol></li>
- * <li><strong>The member</strong>. For a required permission,
- * this is the member of the bean being accessed (an attribute
- * or operation), if any. If a member of the bean isn't involved
- * in this action, the value is <code>null</code>.
- * For a permission held by the user, it has one of three values:
- * <ol>
- * <li>The empty string, implying any member.</li>
- * <li><code>*</code>, also implying any member.</li>
- * <li>The name of a member.</li>
- * </ol></li>
- * <li>The object name</strong>. For a required permission,
- * this is the {@link ObjectName} of the bean being accessed, if
- * any. If a bean isn't involved in this action, the value is
- * <code>null</code>. The name may not be a pattern.
- * For a permission held by the user, it may be the empty
- * string (allowing everything) or an {@link ObjectName}
- * pattern.
- * </li></ol>
- * {@link #getName()} returns the latter three of these as a
- * single string:
- * </p>
- * <p><code>className#member[objectName]</code></p>
- * <p>
- * where <code>""</code> is disallowed, as, although any of
- * the elements may be omitted, not all of them should be
- * left out simultaneously. <code>"-"</code> is used to
- * represent <code>null</code>. When this occurs in a
- * required permission, anything may match it. When this
- * forms part of a permission held by the user, it only
- * matches another <code>null</code> value.
- * </p>
- * <p>The list of valid actions is as follows:</p>
- * <ul>
- * <li>addNotificationListener</li>
- * <li>getAttribute</li>
- * <li>getClassLoader</li>
- * <li>getClassLoaderFor</li>
- * <li>getClassLoaderRepository</li>
- * <li>getDomains</li>
- * <li>getMBeanInfo</li>
- * <li>getObjectInstance</li>
- * <li>instantiate</li>
- * <li>invoke</li>
- * <li>isInstanceOf</li>
- * <li>queryMBeans</li>
- * <li>queryNames</li>
- * <li>registerMBean</li>
- * <li>removeNotificationListener</li>
- * <li>setAttribute</li>
- * <li>unregisterMBean</li>
- * </ul>
- *
- * @author Andrew John Hughes (gnu_andrew@member.fsf.org)
- * @since 1.5
- */
- public class MBeanPermission
- extends Permission
- {
- /**
- * Compatible with JDK 1.5
- */
- private static final long serialVersionUID = -2416928705275160661L;
- /**
- * The list of actions associated with this permission.
- */
- private String actions;
- /**
- * The list of actions as an ordered set.
- */
- private transient Set<String> actionSet;
- /**
- * The set of valid actions.
- */
- private static final Set<String> validSet;
- /**
- * Initialise the set of valid actions.
- */
- static
- {
- validSet = new HashSet<String>();
- validSet.add("addNotificationListener");
- validSet.add("getAttribute");
- validSet.add("getClassLoader");
- validSet.add("getClassLoaderFor");
- validSet.add("getClassLoaderRepository");
- validSet.add("getDomains");
- validSet.add("getMBeanInfo");
- validSet.add("getObjectInstance");
- validSet.add("instantiate");
- validSet.add("invoke");
- validSet.add("isInstanceOf");
- validSet.add("queryMBeans");
- validSet.add("queryNames");
- validSet.add("registerMBean");
- validSet.add("removeNotificationListener");
- validSet.add("setAttribute");
- validSet.add("unregisterMBean");
- }
- /**
- * Constructs a new {@link MBeanPermission} with the specified name
- * and actions. The name is of the form <code>className#member[objectName]</code>,
- * where each element is optional, but a completely empty or <code>null</code>
- * name is disallowed. Actions are specified as a comma-separated list
- * and may also not be empty or <code>null</code>.
- *
- * @param name the name of the permission.
- * @param actions the actions associated with this permission.
- * @throws IllegalArgumentException if the name or actions are invalid.
- */
- public MBeanPermission(String name, String actions)
- {
- super(name);
- if (name == null || name.length() == 0)
- throw new IllegalArgumentException("The supplied name was null or empty.");
- if (actions == null || actions.length() == 0)
- throw new IllegalArgumentException("The supplied action list was null or empty.");
- this.actions = actions;
- updateActionSet();
- }
- /**
- * Constructs a new {@link MBeanPermission} with the specified class name,
- * member, object name and actions. The name of the permission is created
- * using the form <code>className#member[objectName]</code>,
- * where each element is optional, but an empty or <code>null</code>
- * name is disallowed. Actions are specified as a comma-separated list
- * and may also not be empty or <code>null</code>.
- *
- * @param className the name of the class to which this permission applies,
- * or either <code>null</code> or <code>"-"</code> for a
- * value which may be implied by any class name, but not
- * imply any class name itself.
- * @param member the member of the class to which this permission applies,
- * or either <code>null</code> or <code>"-"</code> for a
- * value which may be implied by any member, but not
- * imply any member itself.
- * @param name the {@link ObjectName} to which this permission applies,
- * or <code>null</code> for a value which may be implied by
- * any object name, but not imply any object name itself.
- * @param actions the actions associated with this permission.
- */
- public MBeanPermission(String className, String member,
- ObjectName name, String actions)
- {
- this((className == null ? "-" : className) + "#"
- + (member == null ? "-" : member) + "["
- + (name == null ? "-" : name.toString()) + "]", actions);
- }
- /**
- * Returns true if the given object is also an {@link MBeanPermission}
- * with the same name and actions.
- *
- * @param obj the object to test.
- * @return true if the object is an {@link MBeanPermission} with
- * the same name and actions.
- */
- public boolean equals(Object obj)
- {
- if (obj instanceof MBeanPermission)
- {
- MBeanPermission p = (MBeanPermission) obj;
- return (p.getName().equals(getName()) &&
- p.getActions().equals(actions));
- }
- return false;
- }
- /**
- * Returns the list of actions in alphabetical order.
- *
- * @return the list of actions.
- */
- public String getActions()
- {
- Iterator<String> it = actionSet.iterator();
- CPStringBuilder builder = new CPStringBuilder();
- while (it.hasNext())
- {
- builder.append(it.next());
- if (it.hasNext())
- builder.append(",");
- }
- return builder.toString();
- }
- /**
- * Returns the hashcode of the permission as the sum
- * of the hashcodes of the name and actions.
- *
- * @return the hashcode of the permission.
- */
- public int hashCode()
- {
- return getName().hashCode() + actions.hashCode();
- }
- /**
- * <p>
- * Returns true if this permission implies the supplied permission.
- * This happens if the following holds:
- * </p>
- * <ul>
- * <li>The supplied permission is an {@link MBeanPermission}</li>
- * <li>The supplied permission has either a <code>null</code> classname
- * or its classname matches the classname of this permission. A
- * classname of <code>"*"</code> for this permission always matches
- * the classname of the supplied permission. Generally, <code>'*'</code>
- * acts as a wildcard, so <code>".*"</code> matches <code>'.'</code>
- * followed by anything.</li>
- * <li>The supplied permission has either a <code>null</code> member
- * or its member matches the member of this permission. A member of
- * <code>"*"</code> for this permission always matches the member
- * of the supplied permission.</li>
- * <li>The supplied permission has either a <code>null</code> object name
- * or its object name matches the object name of this permission. If the
- * object name of this permission is a pattern, {@link ObjectName#apply(ObjectName)}
- * may be used as well.</li>
- * <li>The supplied permission's actions are a subset of the actions
- * of this permission. If the <code>queryMBeans</code> action is presented,
- * the <code>queryNames</code> action is implied.</li>
- * </ul>
- *
- * @param p the permission to check that this permission implies.
- * @return true if this permission implies <code>p</code>.
- */
- public boolean implies(Permission p)
- {
- if (p instanceof MBeanPermission)
- {
- MBeanPermission mp = (MBeanPermission) p;
- NameHolder pName = new NameHolder(mp.getName());
- NameHolder name = new NameHolder(getName());
- if (!(name.equals(pName)))
- return false;
- for (String nextAction : mp.actionSet)
- {
- boolean found = actions.contains(nextAction);
- if (!found)
- if (nextAction.equals("queryNames"))
- found = actions.contains("queryMBeans");
- if (!found)
- return false;
- }
- return true;
- }
- return false;
- }
- /**
- * Small helper class to handle deconstruction of the name.
- *
- * @author Andrew John Hughes (gnu_andrew@member.fsf.org)
- */
- private class NameHolder
- {
- /**
- * The class name.
- */
- private String className;
- /**
- * The member.
- */
- private String member;
- /**
- * The object name.
- */
- private ObjectName objectName;
- /**
- * Constructs a broken-down name from a given name.
- *
- * @param name the name to break down.
- */
- public NameHolder(String name)
- {
- String objectName = null;
- int memberIndex = name.indexOf("#");
- int onIndex = name.indexOf("[");
- if (onIndex == -1)
- {
- if (memberIndex == -1)
- className = name;
- else
- {
- className = name.substring(0, memberIndex);
- member = name.substring(memberIndex + 1);
- }
- }
- else
- {
- if (memberIndex == -1)
- {
- className = name.substring(0, onIndex);
- objectName = name.substring(onIndex + 1,
- name.length() - 1);
- }
- else
- {
- className = name.substring(0, memberIndex);
- member = name.substring(memberIndex + 1, onIndex);
- objectName = name.substring(onIndex + 1,
- name.length() - 1);
- }
- }
- if (className.equals("-"))
- className = null;
- if (member.equals("-"))
- member = null;
- if (objectName == null || objectName.equals("-"))
- this.objectName = null;
- else
- try
- {
- this.objectName = new ObjectName(objectName);
- }
- catch (MalformedObjectNameException e)
- {
- throw (Error)
- (new InternalError("Invalid object name.").initCause(e));
- }
- }
- /**
- * <p>
- * Returns true if the supplied object is also a
- * {@link NameHolder} and the following holds:
- * </p>
- * <ul>
- * <li>The supplied classname is <code>null</code> or the two match. A
- * classname of <code>"*"</code> for this holder always matches
- * the classname of the supplied holder. Generally, <code>'*'</code>
- * acts as a wildcard, so <code>".*"</code> matches <code>'.'</code>
- * followed by anything.</li>
- * <li>The supplied name holder has either a <code>null</code> member
- * or its member matches the member of this name holder. A member of
- * <code>"*"</code> for this name holder always matches the member
- * of the supplied name holder.</li>
- * <li>The supplied name holder has either a <code>null</code> object name
- * or its object name matches the object name of this name holder. If the
- * object name of this name holder is a pattern,
- * {@link ObjectName#apply(ObjectName)} may be used as well.</li>
- * </ul>
- *
- * @param obj the object to compare with this.
- * @return true if the above holds.
- */
- public boolean equals(Object obj)
- {
- if (obj instanceof NameHolder)
- {
- NameHolder nh = (NameHolder) obj;
- boolean cn = false;
- String ocn = nh.getClassName();
- if (ocn == null || className.equals("*"))
- cn = true;
- else
- {
- int wcIndex = className.indexOf("*");
- if (wcIndex != -1)
- cn = ocn.startsWith(className.substring(0, wcIndex));
- else
- cn = ocn.equals(className);
- }
- boolean m = false;
- String om = nh.getMember();
- if (om == null || member.equals("*"))
- m = true;
- else
- m = om.equals(member);
- boolean on = false;
- ObjectName oon = nh.getObjectName();
- if (oon == null)
- on = true;
- else if (objectName.isPattern())
- on = objectName.apply(oon);
- else
- on = oon.equals(objectName);
- return (cn && m && on);
- }
- return false;
- }
- /**
- * Returns the class name.
- */
- public String getClassName()
- {
- return className;
- }
- /**
- * Returns the member.
- */
- public String getMember()
- {
- return member;
- }
- /**
- * Returns the object name.
- */
- public ObjectName getObjectName()
- {
- return objectName;
- }
- }
- /**
- * Updates the action set from the current value of
- * the actions string.
- */
- private void updateActionSet()
- {
- String[] actionsArray = actions.split(",");
- actionSet = new TreeSet<String>();
- for (int a = 0; a < actionsArray.length; ++a)
- actionSet.add(actionsArray[a].trim());
- }
- /**
- * Reads the object from a stream and ensures the incoming
- * data is valid.
- *
- * @param in the input stream.
- * @throws IOException if an I/O error occurs.
- * @throws ClassNotFoundException if a class used by the object
- * can not be found.
- */
- private void readObject(ObjectInputStream in)
- throws IOException, ClassNotFoundException
- {
- in.defaultReadObject();
- updateActionSet();
- checkActions();
- }
- /**
- * Checks that the actions used in this permission
- * are from the valid set.
- *
- * @throws IllegalArgumentException if the name or actions are invalid.
- */
- private void checkActions()
- {
- for (String action : actionSet)
- {
- if (!(validSet.contains(action)))
- throw new IllegalArgumentException("Invalid action "
- + action + " found.");
- }
- }
- }
|