Package org.osgi.framework

Source Code of org.osgi.framework.AdminPermission$SignerWrapper

/*
* $Header: /cvsroot/eclipse/org.eclipse.osgi/osgi/src/org/osgi/framework/AdminPermission.java,v 1.23 2007/02/26 16:37:21 twatson Exp $
*
* Copyright (c) OSGi Alliance (2000, 2007). 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.framework;

import java.io.IOException;
import java.security.*;
import java.util.*;
import org.eclipse.osgi.framework.internal.core.AbstractBundle;
import org.eclipse.osgi.framework.internal.core.FilterImpl;

/**
* A bundle's authority to perform specific privileged administrative operations
* on or to get sensitive information about a bundle. The actions for this
* permission are:
*
* <pre>
*  Action               Methods
*  class                Bundle.loadClass
*  execute              Bundle.start
*                       Bundle.stop
*                       StartLevel.setBundleStartLevel
*  extensionLifecycle   BundleContext.installBundle for extension bundles
*                       Bundle.update for extension bundles
*                       Bundle.uninstall for extension bundles
*  lifecycle            BundleContext.installBundle
*                       Bundle.update
*                       Bundle.uninstall
*  listener             BundleContext.addBundleListener for SynchronousBundleListener
*                       BundleContext.removeBundleListener for SynchronousBundleListener
*  metadata             Bundle.getHeaders
*                       Bundle.getLocation
*  resolve              PackageAdmin.refreshPackages
*                       PackageAdmin.resolveBundles
*  resource             Bundle.getResource
*                       Bundle.getResources
*                       Bundle.getEntry
*                       Bundle.getEntryPaths
*                       Bundle.findEntries
*                       Bundle resource/entry URL creation
*  startlevel           StartLevel.setStartLevel
*                       StartLevel.setInitialBundleStartLevel
*  context              Bundle.getBundleContext                    
*                      
* </pre>
*
* <p>
* The special action &quot;*&quot; will represent all actions.
* <p>
* The name of this permission is a filter expression. The filter gives access
* to the following parameters:
* <ul>
* <li>signer - A Distinguished Name chain used to sign a bundle. Wildcards in
* a DN are not matched according to the filter string rules, but according to
* the rules defined for a DN chain.</li>
* <li>location - The location of a bundle.</li>
* <li>id - The bundle ID of the designated bundle.</li>
* <li>name - The symbolic name of a bundle.</li>
* </ul>
*
* @ThreadSafe
* @version $Revision: 1.23 $
*/

public final class AdminPermission extends BasicPermission {
  static final long  serialVersionUID  = 207051004521261705L;

  /**
   * The action string <code>class</code> (Value is "class").
   * @since 1.3
   */
  public final static String      CLASS        = "class";
  /**
   * The action string <code>execute</code> (Value is "execute").
   * @since 1.3
   */
  public final static String      EXECUTE        = "execute";
  /**
   * The action string <code>extensionLifecycle</code> (Value is
   * "extensionLifecycle").
   * @since 1.3
   */
  public final static String      EXTENSIONLIFECYCLE  = "extensionLifecycle";
  /**
   * The action string <code>lifecycle</code> (Value is "lifecycle").
   * @since 1.3
   */
  public final static String      LIFECYCLE      = "lifecycle";
  /**
   * The action string <code>listener</code> (Value is "listener").
   * @since 1.3
   */
  public final static String      LISTENER      = "listener";
  /**
   * The action string <code>metadata</code> (Value is "metadata").
   * @since 1.3
   */
  public final static String      METADATA      = "metadata";
  /**
   * The action string <code>resolve</code> (Value is "resolve").
   * @since 1.3
   */
  public final static String      RESOLVE        = "resolve";
  /**
   * The action string <code>resource</code> (Value is "resource").
   * @since 1.3
   */
  public final static String      RESOURCE      = "resource";
  /**
   * The action string <code>startlevel</code> (Value is "startlevel").
   * @since 1.3
   */
  public final static String      STARTLEVEL      = "startlevel";

  /**
   * The action string <code>context</code> (Value is "context").
   * @since 1.4
   */
  public final static String      CONTEXT        = "context";

    private final static int ACTION_CLASS        = 0x00000001;
    private final static int ACTION_EXECUTE        = 0x00000002;
    private final static int ACTION_LIFECYCLE      = 0x00000004;
    private final static int ACTION_LISTENER      = 0x00000008;
    private final static int ACTION_METADATA      = 0x00000010;
    private final static int ACTION_RESOLVE        = 0x00000040;
    private final static int ACTION_RESOURCE      = 0x00000080;
    private final static int ACTION_STARTLEVEL      = 0x00000100;
  private final static int ACTION_EXTENSIONLIFECYCLE  = 0x00000200;
  private final static int ACTION_CONTEXT = 0x00000400;
    private final static int ACTION_ALL =
    ACTION_CLASS         |
    ACTION_EXECUTE         |
    ACTION_LIFECYCLE       |
    ACTION_LISTENER       |
      ACTION_METADATA       |
    ACTION_RESOLVE         |
    ACTION_RESOURCE       |
    ACTION_STARTLEVEL      |
    ACTION_EXTENSIONLIFECYCLE |
    ACTION_CONTEXT;
    private final static int ACTION_NONE = 0;
 
  /**
   * Indicates that this AdminPermission refers to all bundles
   * @serial
   */
  private boolean wildcard;
 
  /**
   * An x.500 distinguished name used to match a bundle's signature - only used if
   * wildcard is false and bundle = null
   * @serial
   */
  private String filter;

    /**
     * The actions in canonical form.
     *
     * @serial
     */
    private String actions = null;

    /**
     * The actions mask.
     */
  private transient int action_mask = ACTION_NONE;

  /**
   * The bundle governed by this AdminPermission - only used if
   * wildcard is false and filter == null
   */
  private transient Bundle bundle;

    /**
     * If this AdminPermission was constructed with a bundle, this dictionary holds
     * the properties of that bundle, used to match a filter in implies.
     * This is not initialized until necessary, and then cached in this object.
     */
    private transient Dictionary bundleProperties;
   
    /**
     * If this AdminPermission was constructed with a filter, this dictionary holds
     * a Filter matching object used to evaluate the filter in implies.
     * This is not initialized until necessary, and then cached in this object
     */
    private transient Filter filterImpl;
   
  /**
   * Creates a new <code>AdminPermission</code> object that matches all
   * bundles and has all actions. Equivalent to AdminPermission("*","*");
   */
  public AdminPermission() {
    this("*",AdminPermission.ACTION_ALL); //$NON-NLS-1$
  }

  /**
   * Create a new AdminPermission.
   *
   * This constructor must only be used to create a permission that is going
   * to be checked.
   * <p>
   * Examples:
   *
   * <pre>
   * (signer=\*,o=ACME,c=US)  
   * (&amp;(signer=\*,o=ACME,c=US)(name=com.acme.*)(location=http://www.acme.com/bundles/*))
   * (id&gt;=1)
   * </pre>
   *
   * <p>
   * When a signer key is used within the filter expression the signer value
   * must escape the special filter chars ('*', '(', ')').
   * <p>
   * Null arguments are equivalent to "*".
   *
   * @param filter A filter expression that can use signer, location, id, and
   *        name keys. A value of &quot;*&quot; or <code>null</code> matches
   *        all bundle.
   * @param actions <code>class</code>, <code>execute</code>,
   *        <code>extensionLifecycle</code>, <code>lifecycle</code>,
   *        <code>listener</code>, <code>metadata</code>,
   *        <code>resolve</code>, <code>resource</code>,
   *        <code>startlevel</code> or <code>context</code>. A value of "*" or <code>null</code>
   *        indicates all actions
   */
  public AdminPermission(String filter, String actions) {
      //arguments will be null if called from a PermissionInfo defined with
      //no args
      this(
          (filter == null ? "*" : filter), //$NON-NLS-1$
        getMask((actions == null ? "*" : actions)) //$NON-NLS-1$
        );
  }

  /**
   * Creates a new <code>AdminPermission</code> object to be used by the
   * code that must check a <code>Permission</code> object.
   *
   * @param bundle A bundle
   * @param actions <code>class</code>, <code>execute</code>,
   *        <code>extensionLifecycle</code>, <code>lifecycle</code>,
   *        <code>listener</code>, <code>metadata</code>,
   *        <code>resolve</code>, <code>resource</code>,
   *        <code>startlevel</code>, <code>context</code>.
   * @since 1.3
   */
  public AdminPermission(Bundle bundle, String actions) {
    super(createName(bundle));
      this.bundle = bundle;
      this.wildcard = false;
      this.filter = null;
      this.action_mask = getMask(actions);
  }

  /**
   * Create a permission name from a Bundle
   *
   * @param bundle Bundle to use to create permission name.
   * @return permission name.
   */
  private static String createName(Bundle bundle) {
    StringBuffer sb = new StringBuffer();
    sb.append("(id=");
    sb.append(bundle.getBundleId());
    sb.append(")");
    return sb.toString();
  }

  /**
   * Determines the equality of two <code>AdminPermission</code> objects.
   *
   * @param obj The object being compared for equality with this object.
   * @return <code>true</code> if <code>obj</code> is equivalent to this
   *         <code>AdminPermission</code>; <code>false</code> otherwise.
   */
  public boolean equals(Object obj) {
        if (obj == this) {
          return true;
        }
       
    if (!(obj instanceof AdminPermission)) {
            return false;
        }
       
        AdminPermission a = (AdminPermission) obj;

        return (action_mask == a.action_mask) &&
            (wildcard == a.wildcard) &&
            (bundle == null ? a.bundle == null : (a.bundle == null ? false : bundle.getBundleId() == a.bundle.getBundleId())) &&
        (filter == null ? a.filter == null : filter.equals(a.filter));
  }

  /**
   * Returns the hash code value for this object.
   *
   * @return Hash code value for this object.
   */
  public int hashCode() {
    return getName().hashCode() ^ getActions().hashCode();
  }

  /**
   * Returns the canonical string representation of the
   * <code>AdminPermission</code> actions.
   *
   * <p>
   * Always returns present <code>AdminPermission</code> actions in the
   * following order: <code>class</code>, <code>execute</code>,
   * <code>extensionLifecycle</code>, <code>lifecycle</code>,
   * <code>listener</code>, <code>metadata</code>, <code>resolve</code>,
   * <code>resource</code>, <code>startlevel</code>, <code>context</code>.
   *
   * @return Canonical string representation of the
   *         <code>AdminPermission</code> actions.
   */
  public String getActions() {
    if (actions == null) {
      StringBuffer sb = new StringBuffer();
     
      if ((action_mask & ACTION_CLASS) == ACTION_CLASS) {
        sb.append(CLASS);
        sb.append(',');
      }

      if ((action_mask & ACTION_EXECUTE) == ACTION_EXECUTE) {
        sb.append(EXECUTE);
        sb.append(',');
      }

      if ((action_mask & ACTION_EXTENSIONLIFECYCLE) == ACTION_EXTENSIONLIFECYCLE) {
        sb.append(EXTENSIONLIFECYCLE);
        sb.append(',');
      }

      if ((action_mask & ACTION_LIFECYCLE) == ACTION_LIFECYCLE) {
        sb.append(LIFECYCLE);
        sb.append(',');
      }

      if ((action_mask & ACTION_LISTENER) == ACTION_LISTENER) {
        sb.append(LISTENER);
        sb.append(',');
      }
     
      if ((action_mask & ACTION_METADATA) == ACTION_METADATA) {
        sb.append(METADATA);
        sb.append(',');
      }

      if ((action_mask & ACTION_RESOLVE) == ACTION_RESOLVE) {
        sb.append(RESOLVE);
        sb.append(',');
      }

      if ((action_mask & ACTION_RESOURCE) == ACTION_RESOURCE) {
        sb.append(RESOURCE);
        sb.append(',');
      }

      if ((action_mask & ACTION_STARTLEVEL) == ACTION_STARTLEVEL) {
        sb.append(STARTLEVEL);
        sb.append(',');
      }

      if ((action_mask & ACTION_CONTEXT) == ACTION_CONTEXT) {
        sb.append(CONTEXT);
        sb.append(',');
      }

      //remove trailing comma
      if (sb.length() > 0) {
        sb.setLength(sb.length()-1);
      }
     
      actions = sb.toString();
    }
    return actions;
  }

  /**
   * Determines if the specified permission is implied by this object. This
   * method throws an exception if the specified permission was not
   * constructed with a bundle.
   *
   * <p>
   * This method returns <code>true</code> if the specified permission is an
   * AdminPermission AND
   * <ul>
   * <li>this object's filter matches the specified permission's bundle ID,
   * bundle symbolic name, bundle location and bundle signer distinguished
   * name chain OR</li>
   * <li>this object's filter is "*"</li>
   * </ul>
   * AND this object's actions include all of the specified permission's
   * actions.
   * <p>
   * Special case: if the specified permission was constructed with "*"
   * filter, then this method returns <code>true</code> if this object's
   * filter is "*" and this object's actions include all of the specified
   * permission's actions
   *
   * @param p The permission to interrogate.
   *
   * @return <code>true</code> if the specified permission is implied by
   *         this object; <code>false</code> otherwise.
   * @throws RuntimeException if specified permission was not constructed with
   *         a bundle or "*"
   */
  public boolean implies(Permission p) {
      if (!(p instanceof AdminPermission))
        return false;
      AdminPermission target = (AdminPermission)p;
      //check actions first - much faster
      if ((action_mask & target.action_mask)!=target.action_mask)
        return false;
      //if passed in a filter, puke
      if (target.filter != null)
        throw new RuntimeException("Cannot imply a filter"); //$NON-NLS-1$
      //special case - only wildcard implies wildcard
      if (target.wildcard)
        return wildcard;

      //check our name
      if (filter != null) {
        //it's a filter
        Filter filterImpl = getFilterImpl();
      return filterImpl != null && filterImpl.match(target.getProperties());
      } else if (wildcard) {
        //it's "*"
        return true;
      } else {
        //it's a bundle id
        return bundle.equals(target.bundle);
      }
  }

  /**
   * Returns a new <code>PermissionCollection</code> object suitable for
   * storing <code>AdminPermission</code>s.
   *
   * @return A new <code>PermissionCollection</code> object.
   */
  public PermissionCollection newPermissionCollection() {
        return(new AdminPermissionCollection());
  }

    /**
     * Package private constructor used by AdminPermissionCollection.
     *
     * @param filter name filter
     * @param action_mask mask
     */
    AdminPermission(String filter, int action_mask) {
      super(filter);
     
      //name must be either * or a filter
      if (filter.equals("*")) { //$NON-NLS-1$
        this.wildcard = true;
        this.filter = null;
      } else {
      this.wildcard = false;
      this.filter = filter;
      }
      this.bundle = null;
      this.action_mask = action_mask;
    }

    /**
     * Parse action string into action mask.
     *
     * @param actions Action string.
     * @return action mask.
     */
    private static int getMask(String actions) {
   
      boolean seencomma = false;

      int mask = ACTION_NONE;

      if (actions == null) {
        return mask;
      }

      char[] a = actions.toCharArray();

      int i = a.length - 1;
      if (i < 0)
        return mask;

      while (i != -1) {
        char c;

        // skip whitespace
        while ((i!=-1) && ((c = a[i]) == ' ' ||
            c == '\r' ||
          c == '\n' ||
          c == '\f' ||
          c == '\t'))
          i--;

        // check for the known strings
        int matchlen;

        if (i >= 4 &&
          (a[i-4] == 'c' || a[i-4] == 'C') &&
          (a[i-3] == 'l' || a[i-3] == 'L') &&
          (a[i-2] == 'a' || a[i-2] == 'A') &&
          (a[i-1] == 's' || a[i-1] == 'S') &&
            (a[i] == 's' ||   a[i] == 'S'))
      {
        matchlen = 5;
        mask |= ACTION_CLASS;
 
        } else if (i >= 6 &&
          (a[i-6] == 'e' || a[i-6] == 'E') &&
          (a[i-5] == 'x' || a[i-5] == 'X') &&
          (a[i-4] == 'e' || a[i-4] == 'E') &&
          (a[i-3] == 'c' || a[i-3] == 'C') &&
          (a[i-2] == 'u' || a[i-2] == 'U') &&
          (a[i-1] == 't' || a[i-1] == 'T') &&
            (a[i] == 'e' ||   a[i] == 'E'))
      {
        matchlen = 7;
        mask |= ACTION_EXECUTE;
       
      } else if (i >= 17 &&
          (a[i-17] == 'e' || a[i-17] == 'E') &&
          (a[i-16] == 'x' || a[i-16] == 'X') &&
          (a[i-15] == 't' || a[i-15] == 'T') &&
          (a[i-14] == 'e' || a[i-14] == 'E') &&
          (a[i-13] == 'n' || a[i-13] == 'N') &&
          (a[i-12] == 's' || a[i-12] == 'S') &&
          (a[i-11] == 'i' || a[i-11] == 'I') &&
          (a[i-10] == 'o' || a[i-10] == 'O') &&
          (a[i-9] == 'n' || a[i-9] == 'N') &&
          (a[i-8] == 'l' || a[i-8] == 'L') &&
          (a[i-7] == 'i' || a[i-7] == 'I') &&
          (a[i-6] == 'f' || a[i-6] == 'F') &&
          (a[i-5] == 'e' || a[i-5] == 'E') &&
          (a[i-4] == 'c' || a[i-4] == 'C') &&
          (a[i-3] == 'y' || a[i-3] == 'Y') &&
          (a[i-2] == 'c' || a[i-2] == 'C') &&
          (a[i-1] == 'l' || a[i-1] == 'L') &&
            (a[i] == 'e' ||   a[i] == 'E'))
        {
          matchlen = 18;
          mask |= ACTION_EXTENSIONLIFECYCLE;

        } else if (i >= 8 &&
          (a[i-8] == 'l' || a[i-8] == 'L') &&
          (a[i-7] == 'i' || a[i-7] == 'I') &&
          (a[i-6] == 'f' || a[i-6] == 'F') &&
          (a[i-5] == 'e' || a[i-5] == 'E') &&
          (a[i-4] == 'c' || a[i-4] == 'C') &&
          (a[i-3] == 'y' || a[i-3] == 'Y') &&
          (a[i-2] == 'c' || a[i-2] == 'C') &&
          (a[i-1] == 'l' || a[i-1] == 'L') &&
            (a[i] == 'e' ||   a[i] == 'E'))
      {
        matchlen = 9;
        mask |= ACTION_LIFECYCLE;
       
      } else if (i >= 7 &&
          (a[i-7] == 'l' || a[i-7] == 'L') &&
          (a[i-6] == 'i' || a[i-6] == 'I') &&
          (a[i-5] == 's' || a[i-5] == 'S') &&
          (a[i-4] == 't' || a[i-4] == 'T') &&
          (a[i-3] == 'e' || a[i-3] == 'E') &&
          (a[i-2] == 'n' || a[i-2] == 'N') &&
          (a[i-1] == 'e' || a[i-1] == 'E') &&
            (a[i] == 'r' ||   a[i] == 'R'))
      {
        matchlen = 8;
        mask |= ACTION_LISTENER;
     
      } else if (i >= 7 &&
            (a[i-7] == 'm' || a[i-7] == 'M') &&
                  (a[i-6] == 'e' || a[i-6] == 'E') &&
                  (a[i-5] == 't' || a[i-5] == 'T') &&
                  (a[i-4] == 'a' || a[i-4] == 'A') &&
                  (a[i-3] == 'd' || a[i-3] == 'D') &&
                  (a[i-2] == 'a' || a[i-2] == 'A') &&
          (a[i-1] == 't' || a[i-1] == 'T') &&
            (a[i] == 'a' ||   a[i] == 'A'))
        {
          matchlen = 8;
          mask |= ACTION_METADATA;

        } else if (i >= 6 &&
          (a[i-6] == 'r' || a[i-6] == 'R') &&
          (a[i-5] == 'e' || a[i-5] == 'E') &&
          (a[i-4] == 's' || a[i-4] == 'S') &&
          (a[i-3] == 'o' || a[i-3] == 'O') &&
          (a[i-2] == 'l' || a[i-2] == 'L') &&
          (a[i-1] == 'v' || a[i-1] == 'V') &&
            (a[i] == 'e' ||   a[i] == 'E'))
        {
          matchlen = 7;
          mask |= ACTION_RESOLVE;
         
        } else if (i >= 7 &&
              (a[i-7] == 'r' || a[i-7] == 'R') &&
            (a[i-6] == 'e' || a[i-6] == 'E') &&
            (a[i-5] == 's' || a[i-5] == 'S') &&
            (a[i-4] == 'o' || a[i-4] == 'O') &&
            (a[i-3] == 'u' || a[i-3] == 'U') &&
            (a[i-2] == 'r' || a[i-2] == 'R') &&
            (a[i-1] == 'c' || a[i-1] == 'C') &&
              (a[i] == 'e' ||   a[i] == 'E'))
      {
          matchlen = 8;
          mask |= ACTION_RESOURCE;

        } else if (i >= 9 &&
          (a[i-9] == 's' || a[i-9] == 'S') &&
          (a[i-8] == 't' || a[i-8] == 'T') &&
          (a[i-7] == 'a' || a[i-7] == 'A') &&
          (a[i-6] == 'r' || a[i-6] == 'R') &&
          (a[i-5] == 't' || a[i-5] == 'T') &&
          (a[i-4] == 'l' || a[i-4] == 'L') &&
          (a[i-3] == 'e' || a[i-3] == 'E') &&
          (a[i-2] == 'v' || a[i-2] == 'V') &&
          (a[i-1] == 'e' || a[i-1] == 'E') &&
            (a[i] == 'l' ||   a[i] == 'L'))
        {
          matchlen = 10;
          mask |= ACTION_STARTLEVEL;

        } else if (i >= 6 &&
          (a[i-6] == 'c' || a[i-6] == 'C') &&
          (a[i-5] == 'o' || a[i-5] == 'O') &&
          (a[i-4] == 'n' || a[i-4] == 'N') &&
          (a[i-3] == 't' || a[i-3] == 'T') &&
          (a[i-2] == 'e' || a[i-2] == 'E') &&
          (a[i-1] == 'x' || a[i-1] == 'X') &&
            (a[i] == 't' ||   a[i] == 'T'))
        {
          matchlen = 7;
          mask |= ACTION_CONTEXT;

        } else if (i >= 0 &&

          (a[i] == '*'))
        {
          matchlen = 1;
          mask |= ACTION_ALL;

      } else {
        // parse error
        throw new IllegalArgumentException(
            "invalid permission: " + actions); //$NON-NLS-1$
        }

        // make sure we didn't just match the tail of a word
        // like "ackbarfstartlevel".  Also, skip to the comma.
        seencomma = false;
        while (i >= matchlen && !seencomma) {
          switch(a[i-matchlen]) {
            case ',':
              seencomma = true;
              /*FALLTHROUGH*/
            case ' ': case '\r': case '\n':
            case '\f': case '\t':
              break;
            default:
              throw new IllegalArgumentException(
                  "invalid permission: " + actions); //$NON-NLS-1$
          }
          i--;
        }

        // point i at the location of the comma minus one (or -1).
        i -= matchlen;
    }

    if (seencomma) {
        throw new IllegalArgumentException("invalid permission: " + //$NON-NLS-1$
                        actions);
    }

    return mask;
    }
    
    /**
     * Called by <code><@link AdminPermission#implies(Permission)></code> on an AdminPermission
     * which was constructed with a Bundle.  This method loads a dictionary with the
     * filter-matchable properties of this bundle.  The dictionary is cached so this lookup
     * only happens once.
     *
     * This method should only be called on an AdminPermission which was constructed with a
     * bundle
     *
     * @return a dictionary of properties for this bundle
     */
    private Dictionary getProperties() {
      if (bundleProperties == null) {
        bundleProperties = new Hashtable();

        AccessController.doPrivileged(new PrivilegedAction() {
        public Object run() {
            //set Id
            bundleProperties.put("id",new Long(bundle.getBundleId())); //$NON-NLS-1$
           
            //set location
            bundleProperties.put("location",bundle.getLocation()); //$NON-NLS-1$
           
            //set name
            if (bundle.getSymbolicName() != null)
              bundleProperties.put("name",bundle.getSymbolicName()); //$NON-NLS-1$
           
            //set signers
            bundleProperties.put("signer",new SignerWrapper(bundle)); //$NON-NLS-1$
           
            return null;
        }
      });
      }        
      return bundleProperties;
    }

    private static class SignerWrapper extends Object {
      private Bundle bundle;
      private String pattern;
      public SignerWrapper(String pattern) {
        this.pattern = pattern;         
      }
      SignerWrapper(Bundle bundle) {
        this.bundle = bundle;
      }
     
    public boolean equals(Object o) {
      if (!(o instanceof SignerWrapper))
        return false;
      SignerWrapper other = (SignerWrapper) o;
      AbstractBundle matchBundle = (AbstractBundle) (bundle != null ? bundle : other.bundle);
      String matchPattern = bundle != null ? other.pattern : pattern;
      return matchBundle.getBundleData().matchDNChain(matchPattern);
    }
    }
   
    /**
     * Called by <tt><@link AdminPermission#implies(Permission)></tt> on an AdminPermission
     * which was constructed with a filter.  This method loads a FilterImpl with the
     * filter specification of this AdminPermission.  The filter is cached so this work
     * only happens once.
     *
     * This method should only be called on an AdminPermission which was constructed with a
     * filter
     *
     * @return a filterImpl for this bundle
     */
    private Filter getFilterImpl() {
      if (filterImpl == null) {
        try {
          int pos = filter.indexOf("signer"); //$NON-NLS-1$
          if (pos != -1){
         
            //there may be a signer attribute
            StringBuffer filterBuf = new StringBuffer(filter);
            int numAsteriskFound = 0; //use as offset to replace in buffer
           
            int walkbackPos; //temp pos

            //find occurences of (signer= and escape out *'s
            while (pos != -1) {

              //walk back and look for '(' to see if this is an attr
              walkbackPos = pos-1;
             
              //consume whitespace
              while(walkbackPos >= 0 && Character.isWhitespace(filter.charAt(walkbackPos))) {
                walkbackPos--;
              }
              if (walkbackPos <0) {
                //filter is invalid - FilterImpl will throw error
                break;
              }
             
              //check to see if we have unescaped '('
              if (filter.charAt(walkbackPos) != '(' || (walkbackPos > 0 && filter.charAt(walkbackPos-1) == '\\')) {
                //'(' was escaped or not there
                pos = filter.indexOf("signer",pos+6); //$NON-NLS-1$
                continue;
              }            
              pos+=6; //skip over 'signer'

              //found signer - consume whitespace before '='
              while (Character.isWhitespace(filter.charAt(pos))) {
                pos++;
              }

              //look for '='
              if (filter.charAt(pos) != '=') {
                //attr was signerx - keep looking
                pos = filter.indexOf("signer",pos); //$NON-NLS-1$
                continue;
              }
              pos++; //skip over '='
             
              //found signer value - escape '*'s
              while (!(filter.charAt(pos) == ')' && filter.charAt(pos-1) != '\\')) {
                if (filter.charAt(pos) == '*') {
                  filterBuf.insert(pos+numAsteriskFound,'\\');
                  numAsteriskFound++;
                }
                pos++;
              }

              //end of signer value - look for more?
              pos = filter.indexOf("signer",pos); //$NON-NLS-1$
            } //end while (pos != -1)
            filter = filterBuf.toString();
          } //end if (pos != -1)

          filterImpl = new FilterImpl(filter);
      } catch (InvalidSyntaxException e) {
        //we will return null
      }
      }        
      return filterImpl;
    }

  /**
   * Returns the current action mask.
   * <p>
   * Used by the AdminPermissionCollection class.
   *
   * @return Current action mask.
   */
  int getMask() {
    return action_mask;
  }

  private synchronized void writeObject(java.io.ObjectOutputStream s) throws IOException {
    // Write out the actions. The superclass takes care of the name
    // call getActions to make sure actions field is initialized
    if (actions == null)
      getActions();
    if (filter == null && !wildcard)
      throw new UnsupportedOperationException("cannot serialize"); //$NON-NLS-1$
    s.defaultWriteObject();
  }

  /**
   * readObject is called to restore the state of this permission from a
   * stream.
   */
  private synchronized void readObject(java.io.ObjectInputStream s) throws IOException, ClassNotFoundException {
    // Read in the action, then initialize the rest
    s.defaultReadObject();
    action_mask = getMask(actions);
  }
}

/**
* Stores a collection of <code>AdminPermission</code>s.
*/
final class AdminPermissionCollection extends PermissionCollection
{
  private static final long serialVersionUID = 3906372644575328048L;
  /**
     * Collection of permissions.
     *
     * @serial
     */
  private Hashtable permissions;

    /**
     * Create an empty AdminPermissions object.
     *
     */

    public AdminPermissionCollection()
    {
        permissions = new Hashtable();       
    }

    /**
     * Adds a permission to the <code>AdminPermission</code> objects. The key for
     * the hashtable is the name
     *
     * @param permission The <code>AdminPermission</code> object to add.
     *
     * @exception IllegalArgumentException If the permission is not an
     * <code>AdminPermission</code> instance.
     *
     * @exception SecurityException If this <code>AdminPermissionCollection</code>
     * object has been marked read-only.
     */
    public void add(Permission permission)
    {
        if (! (permission instanceof AdminPermission))
            throw new IllegalArgumentException("invalid permission: "+ //$NON-NLS-1$
                                               permission);
        if (isReadOnly())
            throw new SecurityException("attempt to add a Permission to a " + //$NON-NLS-1$
                                        "readonly AdminCollection"); //$NON-NLS-1$
        AdminPermission ap = (AdminPermission) permission;
      AdminPermission existing = (AdminPermission) permissions.get(ap.getName());
      if (existing != null){
        int oldMask = existing.getMask();
        int newMask = ap.getMask();
       
        if (oldMask != newMask) {
          permissions.put(existing.getName(),
              new AdminPermission(existing.getName(), oldMask | newMask));
        }
      } else {
        permissions.put(ap.getName(), ap);
      }
    }


    /**
     * Determines if the specified permissions implies the permissions
     * expressed in <code>permission</code>.
     *
     * @param permission The Permission object to compare with the <code>AdminPermission</code>
     *  objects in this collection.
     *
     * @return <code>true</code> if <code>permission</code> is implied by an
     * <code>AdminPermission</code> in this collection, <code>false</code> otherwise.
     */
    public boolean implies(Permission permission)
    {
        if (!(permission instanceof AdminPermission))
            return(false);

        AdminPermission target = (AdminPermission) permission;
       
        //just iterate one by one
        Iterator permItr = permissions.values().iterator();
       
        while(permItr.hasNext())
          if (((AdminPermission)permItr.next()).implies(target))
            return true;
        return false;
    }

    /**
     * Returns an enumeration of all <code>AdminPermission</code> objects in the
     * container.
     *
     * @return Enumeration of all <code>AdminPermission</code> objects.
     */

    public Enumeration elements()
    {
        return(Collections.enumeration(permissions.values()));
    }
}
TOP

Related Classes of org.osgi.framework.AdminPermission$SignerWrapper

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.