Package org.eclipse.osgi.framework.internal.core

Source Code of org.eclipse.osgi.framework.internal.core.FrameworkSecurityManager$CheckPermissionAction

/*******************************************************************************
* Copyright (c) 2005 IBM Corporation and others.
* All rights reserved. This program and the accompanying materials
* are made available under the terms of the Eclipse Public License v1.0
* which accompanies this distribution, and is available at
* http://www.eclipse.org/legal/epl-v10.html
*
* Contributors:
*     IBM Corporation - initial API and implementation
*******************************************************************************/

package org.eclipse.osgi.framework.internal.core;

import java.security.*;
import java.util.*;
import org.osgi.service.condpermadmin.Condition;

/**
*
* This security manager implements the ConditionalPermission processing for
* OSGi. It is to be used with ConditionalPermissionAdmin.
*
*/
public class FrameworkSecurityManager extends SecurityManager {
  /*
   * This is super goofy, but we need to make sure that the CheckContext and
   * CheckPermissionAction classes load early. Otherwise, we run into problems later.
   */
  static {
    Class c;
    c = CheckPermissionAction.class;
    c = CheckContext.class;
    c.getName(); // to prevent compiler warnings
  }

  static class CheckContext {
    // A non zero depth indicates that we are doing a recursive permission check.
    ArrayList depthCondSets = new ArrayList(2);
        ArrayList accs = new ArrayList(2);
    ArrayList CondClassSet;

    public int getDepth() {
      return depthCondSets.size() - 1;
    }
  }

  /**
   * Adds an array of Condition[] for a ProtectionDomain.
   *
   * @param condSet the array of Condition[] for the ProtectionDomain.
   * @return true if the condSet was added. false if this is a recursive check
   *         and ConditionalPermissions cannot be used.
   */
  boolean addConditionsForDomain(Condition condSet[][]) {
    CheckContext cc = (CheckContext) localCheckContext.get();
    if (cc == null) {
      // We are being invoked in a weird way. Perhaps the ProtectionDomain is
      // getting invoked directly.
      return false;
    }
    Vector condSets = (Vector) cc.depthCondSets.get(cc.getDepth());
    if (condSets == null) {
      condSets = new Vector(2);
      cc.depthCondSets.set(cc.getDepth(), condSets);
    }
    condSets.add(condSet);
    return true;
  }

  ThreadLocal localCheckContext = new ThreadLocal();

  static class CheckPermissionAction implements PrivilegedAction {
    Permission perm;
    Object context;
    FrameworkSecurityManager fsm;

    CheckPermissionAction(FrameworkSecurityManager fsm, Permission perm, Object context) {
      this.fsm = fsm;
      this.perm = perm;
      this.context = context;
    }

    public Object run() {
      fsm.internalCheckPermission(perm, context);
      return null;
    }
  }

  public void checkPermission(Permission perm, Object context) {
    AccessController.doPrivileged(new CheckPermissionAction(this, perm, context));
  }

  /**
     * Gets the AccessControlContext currently being evaluated by
     * the SecurityManager.
     *
   * @return the AccessControlContext currently being evaluated by the SecurityManager, or
     * null if no AccessControlContext is being evaluted. Note: this method will
     * return null if the permission check is being done directly on the AccessControlContext
     * rather than the SecurityManager.
   */
  public AccessControlContext getContextToBeChecked() {
        CheckContext cc = (CheckContext) localCheckContext.get();
        if (cc != null && cc.accs != null && !cc.accs.isEmpty())
            return (AccessControlContext) cc.accs.get(cc.accs.size()-1);
        return null;
    }
   
  public void internalCheckPermission(Permission perm, Object context) {
    AccessControlContext acc = (AccessControlContext) context;
    CheckContext cc = (CheckContext) localCheckContext.get();
    if (cc == null) {
      cc = new CheckContext();
      localCheckContext.set(cc);
    }
    cc.depthCondSets.add(null); // initialize postponed condition set to null
        cc.accs.add(acc);
    try {
      acc.checkPermission(perm);
      // We want to pop the first set of postponed conditions and process them
      Vector remainingSets = (Vector) cc.depthCondSets.get(cc.getDepth());
      if (remainingSets != null) {
        /*
         * In this bit of code we have to try every possible combination
         * of conditional permissions that still need to be evaluated. We
         * do this using recursion to keep track of the different
         * combinations we have tried. The top call will setup the different
         * combinations for the first protection domain with unevaluated
         * conditions. The final call will actually evaluate the condition.
         * If a good combination is found, it will immediately bubble
         * up.
         */
        Hashtable condContextDict = new Hashtable(2);
        // The remainder we will process recursively.
        Condition conds[][] = (Condition[][]) remainingSets.remove(0);
        for (int i = 0; i < conds.length; i++)
          if (recursiveCheck(remainingSets, conds[i], null, condContextDict, cc))
            return; // found a pass return without SecurityException
        throw new SecurityException("Conditions not satisfied"); //$NON-NLS-1$
      }
    } finally {
      cc.depthCondSets.remove(cc.getDepth());
            cc.accs.remove(cc.accs.size()-1);
    }
  }

  /**
   * Checks that at least one combination of the Condition[] in the Vector can
   * be satisfied along with the passed array of Conditions.
   *
   * @param remainingSets the Vector of Condition[][] to check.
   * @param conditions the conditions that must be satisfied.
   * @param condDict a dictionary that will be filled with the Conditions to
   *        check.
   * @param condContextDict a Dictionary of Dictionaries that will be passed
   *        to Condition.isSatisfied when performing repeated check.
   * @param cc the CheckContext
   * @return true if a successful combination was found.
   */
  private boolean recursiveCheck(Vector remainingSets, Condition[] conditions, Hashtable condDict, Hashtable condContextDict, CheckContext cc) {
    // clone condDict and clone each Vector in the condDict
    if (condDict == null) {
      condDict = new Hashtable(2);
    } else {
      Hashtable copyCondDict = new Hashtable(2);
      for (Enumeration keys = condDict.keys(); keys.hasMoreElements();) {
        Object key = keys.nextElement();
        copyCondDict.put(key, ((Vector) condDict.get(key)).clone());
      }
      condDict = copyCondDict;
    }
    for (int i = 0; i < conditions.length; i++) {
      if (conditions[i] == null)
        continue;
      Vector condList = (Vector) condDict.get(conditions[i].getClass());
      if (condList == null) {
        condList = new Vector();
        condDict.put(conditions[i].getClass(), condList);
      }
      condList.add(conditions[i]);
    }
    if (remainingSets.size() > 0) {
      Condition conds[][] = (Condition[][]) remainingSets.get(0);
      Vector newSets = (Vector) remainingSets.clone();
      newSets.remove(0);
      for (int i = 0; i < conds.length; i++)
        if (recursiveCheck(newSets, conds[i], condDict, condContextDict, cc))
          return true;
      return false;
    }
    Enumeration keys = condDict.keys();
    while (keys.hasMoreElements()) {
      Class key = (Class) keys.nextElement();
      Vector conds = (Vector) condDict.get(key);
      if (conds.size() == 0)
        continue; // This should never happen since we only add to the condDict if there is a condition
      Condition condArray[] = (Condition[]) conds.toArray(new Condition[conds.size()]);
      Dictionary context = (Dictionary) condContextDict.get(key);
      if (context == null) {
        context = new Hashtable(2);
        condContextDict.put(key, context);
      }
      if (cc.CondClassSet == null)
        cc.CondClassSet = new ArrayList(2);
      if (cc.CondClassSet.contains(condArray[0].getClass()))
        return false; // doing recursion into same condition class
      cc.CondClassSet.add(condArray[0].getClass());
      try {
        if (!condArray[0].isSatisfied(condArray, context))
          return false;
      } finally {
        cc.CondClassSet.remove(condArray[0].getClass());
      }
    }
    return true;
  }

  public void checkPermission(Permission perm) {
    checkPermission(perm, getSecurityContext());
  }

  public Object getSecurityContext() {
    return AccessController.getContext();
  }
}
TOP

Related Classes of org.eclipse.osgi.framework.internal.core.FrameworkSecurityManager$CheckPermissionAction

TOP
Copyright © 2018 www.massapi.com. All rights reserved.
All source code are property of their respective owners. Java is a trademark of Sun Microsystems, Inc and owned by ORACLE Inc. Contact coftware#gmail.com.