/* 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 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; /** *
* 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. *
** An {@link MBeanPermission} consists of four elements, * which all have to match for the permission to be implied. * These are as follows: *
**
(representing all actions). {@link #getActions()}
* returns this value.null
.
* For a permission held by the user, it has one of three values:
* *
, also implying any class.java.lang.Object
) or a series of classes
* using the wildcard character *
(e.g.
* javax.swing.*
.)null
.
* For a permission held by the user, it has one of three values:
* *
, also implying any member.null
. 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.
* className#member[objectName]
* where ""
is disallowed, as, although any of
* the elements may be omitted, not all of them should be
* left out simultaneously. "-"
is used to
* represent null
. 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 null
value.
*
The list of valid actions is as follows:
*className#member[objectName]
,
* where each element is optional, but a completely empty or null
* name is disallowed. Actions are specified as a comma-separated list
* and may also not be empty or null
.
*
* @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 className#member[objectName]
,
* where each element is optional, but an empty or null
* name is disallowed. Actions are specified as a comma-separated list
* and may also not be empty or null
.
*
* @param className the name of the class to which this permission applies,
* or either null
or "-"
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 null
or "-"
for a
* value which may be implied by any member, but not
* imply any member itself.
* @param objectName the {@link ObjectName} to which this permission applies,
* or null
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 it = actionSet.iterator();
StringBuilder builder = new StringBuilder();
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();
}
/**
* * Returns true if this permission implies the supplied permission. * This happens if the following holds: *
*null
classname
* or its classname matches the classname of this permission. A
* classname of "*"
for this permission always matches
* the classname of the supplied permission. Generally, '*'
* acts as a wildcard, so ".*"
matches '.'
* followed by anything.null
member
* or its member matches the member of this permission. A member of
* "*"
for this permission always matches the member
* of the supplied permission.null
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.queryMBeans
action is presented,
* the queryNames
action is implied.p
.
*/
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;
Iterator i = mp.getActionSet().iterator();
while (i.hasNext())
{
String nextAction = (String) i.next();
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));
}
}
/**
* * Returns true if the supplied object is also a * {@link NameHolder} and the following holds: *
*null
or the two match. A
* classname of "*"
for this holder always matches
* the classname of the supplied holder. Generally, '*'
* acts as a wildcard, so ".*"
matches '.'
* followed by anything.null
member
* or its member matches the member of this name holder. A member of
* "*"
for this name holder always matches the member
* of the supplied name holder.null
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.