/**
   * Adds a permission to this permission collection.
   *
   * @param permission The Permission object to add.
   * @throws IllegalArgumentException If the specified permission is not a CapabilityPermission
   *     object.
   * @throws SecurityException If this {@code CapabilityPermissionCollection} object has been marked
   *     read-only.
   */
  @Override
  public void add(final Permission permission) {
    if (!(permission instanceof CapabilityPermission)) {
      throw new IllegalArgumentException("invalid permission: " + permission);
    }
    if (isReadOnly()) {
      throw new SecurityException(
          "attempt to add a Permission to a " + "readonly PermissionCollection");
    }

    final CapabilityPermission cp = (CapabilityPermission) permission;
    if (cp.bundle != null) {
      throw new IllegalArgumentException("cannot add to collection: " + cp);
    }

    final String name = cp.getName();
    final Filter f = cp.filter;
    synchronized (this) {
      /* select the bucket for the permission */
      Map<String, CapabilityPermission> pc;
      if (f != null) {
        pc = filterPermissions;
        if (pc == null) {
          filterPermissions = pc = new HashMap<String, CapabilityPermission>();
        }
      } else {
        pc = permissions;
      }
      final CapabilityPermission existing = pc.get(name);

      if (existing != null) {
        final int oldMask = existing.action_mask;
        final int newMask = cp.action_mask;
        if (oldMask != newMask) {
          pc.put(name, new CapabilityPermission(name, oldMask | newMask));
        }
      } else {
        pc.put(name, cp);
      }

      if (!all_allowed) {
        if (name.equals("*")) {
          all_allowed = true;
        }
      }
    }
  }
  /**
   * Determines the equality of two CapabilityPermission objects.
   *
   * <p>Checks that specified object has the same name and action as this {@code
   * CapabilityPermission}.
   *
   * @param obj The object to test for equality.
   * @return true if obj is a {@code CapabilityPermission}, and has the same name and actions as
   *     this {@code CapabilityPermission} object; {@code false} otherwise.
   */
  @Override
  public boolean equals(Object obj) {
    if (obj == this) {
      return true;
    }

    if (!(obj instanceof CapabilityPermission)) {
      return false;
    }

    CapabilityPermission cp = (CapabilityPermission) obj;

    return (action_mask == cp.action_mask)
        && getName().equals(cp.getName())
        && ((attributes == cp.attributes)
            || ((attributes != null) && (attributes.equals(cp.attributes))))
        && ((bundle == cp.bundle) || ((bundle != null) && bundle.equals(cp.bundle)));
  }
  /**
   * Determines if a set of permissions implies the permissions expressed in {@code permission}.
   *
   * @param permission The Permission object to compare.
   * @return {@code true} if {@code permission} is a proper subset of a permission in the set;
   *     {@code false} otherwise.
   */
  @Override
  public boolean implies(final Permission permission) {
    if (!(permission instanceof CapabilityPermission)) {
      return false;
    }
    final CapabilityPermission requested = (CapabilityPermission) permission;
    /* if requested permission has a filter, then it is an invalid argument */
    if (requested.filter != null) {
      return false;
    }

    String requestedName = requested.getName();
    final int desired = requested.action_mask;
    int effective = CapabilityPermission.ACTION_NONE;

    Collection<CapabilityPermission> perms;
    synchronized (this) {
      Map<String, CapabilityPermission> pc = permissions;
      CapabilityPermission cp;
      /* short circuit if the "*" Permission was added */
      if (all_allowed) {
        cp = pc.get("*");
        if (cp != null) {
          effective |= cp.action_mask;
          if ((effective & desired) == desired) {
            return true;
          }
        }
      }

      /*
       * strategy: Check for full match first. Then work our way up the
       * name looking for matches on a.b.*
       */
      cp = pc.get(requestedName);
      if (cp != null) {
        /* we have a direct hit! */
        effective |= cp.action_mask;
        if ((effective & desired) == desired) {
          return true;
        }
      }
      /* work our way up the tree... */
      int last;
      int offset = requestedName.length() - 1;
      while ((last = requestedName.lastIndexOf(".", offset)) != -1) {
        requestedName = requestedName.substring(0, last + 1) + "*";
        cp = pc.get(requestedName);
        if (cp != null) {
          effective |= cp.action_mask;
          if ((effective & desired) == desired) {
            return true;
          }
        }
        offset = last - 1;
      }
      /*
       * we don't have to check for "*" as it was already checked before
       * we were called.
       */
      pc = filterPermissions;
      if (pc == null) {
        return false;
      }
      perms = pc.values();
    }
    /* iterate one by one over filteredPermissions */
    for (CapabilityPermission perm : perms) {
      if (perm.implies0(requested, effective)) {
        return true;
      }
    }
    return false;
  }