org.osgi.service.application.ApplicationAdminPermission Maven / Gradle / Ivy
Show all versions of hello-world-plugin Show documentation
/*
* Copyright (c) OSGi Alliance (2004, 2013). All Rights Reserved.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.osgi.service.application;
import java.security.Permission;
import java.util.Hashtable;
import java.util.StringTokenizer;
import java.util.Vector;
import org.osgi.framework.Filter;
import org.osgi.framework.FrameworkUtil;
import org.osgi.framework.InvalidSyntaxException;
/**
* This class implements permissions for manipulating applications and their
* instances.
*
* ApplicationAdminPermission can be targeted to applications that matches the
* specified filter.
*
* ApplicationAdminPermission may be granted for different actions:
* {@code lifecycle}, {@code schedule} and {@code lock}. The permission
* {@code schedule} implies the permission {@code lifecycle}.
*
* @author $Id: c8c799ae29ff5bb6095e22d201b47a3445eb42cb $
*/
public class ApplicationAdminPermission extends Permission {
private static final long serialVersionUID = 1L;
/**
* Allows the lifecycle management of the target applications.
*/
public static final String LIFECYCLE_ACTION = "lifecycle";
/**
* Allows scheduling of the target applications. The permission to schedule
* an application implies that the scheduler can also manage the lifecycle
* of that application i.e. {@code schedule} implies {@code lifecycle}
*/
public static final String SCHEDULE_ACTION = "schedule";
/**
* Allows setting/unsetting the locking state of the target applications.
*/
public static final String LOCK_ACTION = "lock";
private ApplicationDescriptor applicationDescriptor;
/**
* Constructs an ApplicationAdminPermission. The {@code filter} specifies
* the target application. The {@code filter} is an LDAP-style filter, the
* recognized properties are {@code signer} and {@code pid}. The pattern
* specified in the {@code signer} is matched with the Distinguished Name
* chain used to sign the application. Wildcards in a DN are not matched
* according to the filter string rules, but according to the rules defined
* for a DN chain. The attribute {@code pid} is matched with the PID of the
* application according to the filter string rules.
*
* If the {@code filter} is {@code null} then it matches {@code "*"}. If
* {@code actions} is {@code "*"} then it identifies all the possible
* actions.
*
* @param filter filter to identify application. The value {@code null} is
* equivalent to {@code "*"} and it indicates "all application".
* @param actions comma-separated list of the desired actions granted on the
* applications or "*" means all the actions. It must not be
* {@code null}. The order of the actions in the list is not
* significant.
* @throws InvalidSyntaxException is thrown if the specified {@code filter}
* is not syntactically correct.
*
* @exception NullPointerException is thrown if the actions parameter is
* {@code null}
*
* @see ApplicationDescriptor
* @see org.osgi.framework.AdminPermission
*/
public ApplicationAdminPermission(String filter, String actions) throws InvalidSyntaxException {
super(filter == null ? "*" : filter);
if (filter == null)
filter = "*";
if (actions == null)
throw new NullPointerException("Action string cannot be null!");
this.applicationDescriptor = null;
this.filter = (filter == null ? "*" : filter);
this.actions = actions;
if (!filter.equals("*") && !filter.equals("<>"))
FrameworkUtil.createFilter(this.filter); // check if the filter is
// valid
init();
}
/**
* This contructor should be used when creating
* {@code ApplicationAdminPermission} instance for {@code checkPermission}
* call.
*
* @param application the tareget of the operation, it must not be
* {@code null}
* @param actions the required operation. it must not be {@code null}
* @throws NullPointerException if any of the arguments is null.
*/
public ApplicationAdminPermission(ApplicationDescriptor application, String actions) {
super(application.getApplicationId());
if (application == null || actions == null)
throw new NullPointerException("ApplicationDescriptor and action string cannot be null!");
this.filter = application.getApplicationId();
this.applicationDescriptor = application;
this.actions = actions;
init();
}
/**
* This method can be used in the {@link java.security.ProtectionDomain}
* implementation in the {@code implies} method to insert the application ID
* of the current application into the permission being checked. This
* enables the evaluation of the {@code <>} pseudo targets.
*
* @param applicationId the ID of the current application.
* @return the permission updated with the ID of the current application
*/
public ApplicationAdminPermission setCurrentApplicationId(String applicationId) {
ApplicationAdminPermission newPerm = null;
if (this.applicationDescriptor == null) {
try {
newPerm = new ApplicationAdminPermission(this.filter, this.actions);
} catch (InvalidSyntaxException e) {
throw new RuntimeException(e); /* this can never happen */
}
} else
newPerm = new ApplicationAdminPermission(this.applicationDescriptor, this.actions);
newPerm.applicationID = applicationId;
return newPerm;
}
/**
* Checks if the specified {@code permission} is implied by this permission.
* The method returns true under the following conditions:
*
* - This permission was created by specifying a filter (see
* {@link #ApplicationAdminPermission(String, String)})
* - The implied {@code otherPermission} was created for a particular
* {@link ApplicationDescriptor} (see
* {@link #ApplicationAdminPermission(ApplicationDescriptor, String)})
* - The {@code filter} of this permission mathes the
* {@code ApplicationDescriptor} specified in the {@code otherPermission}.
* If the filter in this permission is the {@code <
>} pseudo target,
* then the currentApplicationId set in the {@code otherPermission} is
* compared to the application Id of the target
* {@code ApplicationDescriptor}.
* - The list of permitted actions in this permission contains all actions
* required in the {@code otherPermission}
*
* Otherwise the method returns false.
*
* @param otherPermission the implied permission
* @return true if this permission implies the {@code otherPermission},
* false otherwise.
*/
public boolean implies(Permission otherPermission) {
if (otherPermission == null)
return false;
if (!(otherPermission instanceof ApplicationAdminPermission))
return false;
ApplicationAdminPermission other = (ApplicationAdminPermission) otherPermission;
if (!filter.equals("*")) {
if (other.applicationDescriptor == null)
return false;
if (filter.equals("<>")) {
if (other.applicationID == null)
return false; /* it cannot be, this might be a bug */
if (!other.applicationID.equals(other.applicationDescriptor.getApplicationId()))
return false;
} else {
Hashtable props = new Hashtable();
props.put("pid", other.applicationDescriptor.getApplicationId());
props.put("signer", new SignerWrapper(other.applicationDescriptor));
Filter flt = getFilter();
if (flt == null)
return false;
if (!flt.match(props))
return false;
}
}
if (!actionsVector.containsAll(other.actionsVector))
return false;
return true;
}
public boolean equals(Object with) {
if (with == null || !(with instanceof ApplicationAdminPermission))
return false;
ApplicationAdminPermission other = (ApplicationAdminPermission) with;
// Compare actions:
if (other.actionsVector.size() != actionsVector.size())
return false;
for (int i = 0; i != actionsVector.size(); i++)
if (!other.actionsVector.contains(actionsVector.get(i)))
return false;
return equal(this.filter, other.filter) && equal(this.applicationDescriptor, other.applicationDescriptor) && equal(this.applicationID, other.applicationID);
}
/**
* Compares parameters for equality. If both object are null, they are
* considered equal.
*
* @param a object to compare
* @param b other object to compare
* @return true if both objects are equal or both are null
*/
private static boolean equal(Object a, Object b) {
// This equation is true if both references are null or both point
// to the same object. In both cases they are considered as equal.
if (a == b) {
return true;
}
return a.equals(b);
}
public int hashCode() {
int hc = 0;
for (int i = 0; i != actionsVector.size(); i++)
hc ^= ((String) actionsVector.get(i)).hashCode();
hc ^= (null == this.filter) ? 0 : this.filter.hashCode();
hc ^= (null == this.applicationDescriptor) ? 0 : this.applicationDescriptor.hashCode();
hc ^= (null == this.applicationID) ? 0 : this.applicationID.hashCode();
return hc;
}
/**
* Returns the actions of this permission.
*
* @return the actions specified when this permission was created
*/
public String getActions() {
return actions;
}
private String applicationID;
private static final Vector ACTIONS = new Vector();
private Vector actionsVector;
private final String filter;
private final String actions;
private Filter appliedFilter = null;
static {
ACTIONS.add(LIFECYCLE_ACTION);
ACTIONS.add(SCHEDULE_ACTION);
ACTIONS.add(LOCK_ACTION);
}
private static Vector actionsVector(String actions) {
Vector v = new Vector();
StringTokenizer t = new StringTokenizer(actions.toUpperCase(), ",");
while (t.hasMoreTokens()) {
String action = t.nextToken().trim();
v.add(action.toLowerCase());
}
if (v.contains(SCHEDULE_ACTION) && !v.contains(LIFECYCLE_ACTION))
v.add(LIFECYCLE_ACTION);
return v;
}
private static class SignerWrapper extends Object {
private String pattern;
private ApplicationDescriptor appDesc;
/**
* @param pattern
*/
public SignerWrapper(String pattern) {
this.pattern = pattern;
}
SignerWrapper(ApplicationDescriptor appDesc) {
this.appDesc = appDesc;
}
public boolean equals(Object o) {
if (!(o instanceof SignerWrapper))
return false;
SignerWrapper other = (SignerWrapper) o;
ApplicationDescriptor matchAppDesc = appDesc != null ? appDesc : other.appDesc;
String matchPattern = appDesc != null ? other.pattern : pattern;
return matchAppDesc.matchDNChain(matchPattern);
}
}
private void init() {
actionsVector = actionsVector(actions);
if (actions.equals("*"))
actionsVector = actionsVector(LIFECYCLE_ACTION + "," + SCHEDULE_ACTION + "," + LOCK_ACTION);
else
if (!ACTIONS.containsAll(actionsVector))
throw new IllegalArgumentException("Illegal action!");
applicationID = null;
}
private Filter getFilter() {
if (appliedFilter == null) {
try {
appliedFilter = FrameworkUtil.createFilter(filter);
} catch (InvalidSyntaxException e) {
// we will return null
}
}
return appliedFilter;
}
}