Package net.jini.security

Source Code of net.jini.security.GrantPermission$GrantPermissionCollection

/*
* Licensed to the Apache Software Foundation (ASF) under one
* or more contributor license agreements.  See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership. The ASF licenses this file
* to you 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 net.jini.security;

import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.io.InvalidObjectException;
import java.io.NotSerializableException;
import java.io.ObjectInputStream;
import java.io.ObjectOutputStream;
import java.io.ObjectStreamField;
import java.io.StreamTokenizer;
import java.io.StringReader;
import java.lang.reflect.Constructor;
import java.lang.reflect.Modifier;
import java.security.AllPermission;
import java.security.Permission;
import java.security.PermissionCollection;
import java.security.Permissions;
import java.security.UnresolvedPermission;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collections;
import java.util.Enumeration;
import java.util.HashSet;
import java.util.Iterator;
import java.util.List;
import net.jini.security.policy.DynamicPolicy;

/**
* Permission required to dynamically grant permissions by security policy
* providers which implement the {@link DynamicPolicy} interface.  Each
* <code>GrantPermission</code> instance contains a set of permissions that can
* be granted by code authorized with the <code>GrantPermission</code>.  When
* the {@link DynamicPolicy#grant DynamicPolicy.grant} method is invoked, the
* <code>checkPermission</code> method of the installed security manager (if
* any) is called with a <code>GrantPermission</code> containing the
* permissions to grant; if the calling context does not have any permissions
* which imply the <code>GrantPermission</code>, then the grant operation will
* fail.
* <p>
* In addition to authorizing granting of contained permissions, each
* <code>GrantPermission</code> also authorizes granting of
* <code>GrantPermission</code>s for contained permissions, as well as granting
* of permissions contained within nested <code>GrantPermission</code>s.  For
* example, if <code>GrantPermission g1</code> contains <code>Permission
* p</code>, <code>g1</code> authorizes granting of both <code>p</code> and
* <code>GrantPermission(p)</code>; if <code>GrantPermission g2</code> contains
* <code>GrantPermission(p)</code>, then <code>g2</code> also authorizes
* granting of both <code>p</code> and <code>GrantPermission(p)</code>.
* <p>
* The name (also referred to as the "target name") of each
* <code>GrantPermission</code> instance carries a string representation of the
* permissions contained by the <code>GrantPermission</code>, while the actions
* string of each <code>GrantPermission</code> is always the empty string.  If
* a <code>GrantPermission</code> is serialized, only its name string is sent
* (i.e., contained permissions are not themselves serialized).  Upon
* deserialization, the set of contained permissions is reconstituted based on
* information in the name string.  <code>GrantPermission</code>s constructed
* explicitly with {@link UnresolvedPermission}s (through either the {@link
* #GrantPermission(Permission)} or {@link #GrantPermission(Permission[])}
* constructor) will have incomplete target names that cannot be used to
* instantiate other <code>GrantPermission</code>s, and will not be
* serializable--attempting to serialize such a <code>GrantPermission</code>
* will cause a <code>java.io.NotSerializableException</code> to be thrown.
* <p>
* The syntax of the target name approximates that used for specifying
* permissions in the default security policy file; it is listed below using
* the same grammar notation employed by <i>The Java(TM) Language
* Specification</i>:
* <pre>
* <i>Target</i>:
*   <i>DelimiterDeclaration</i><sub>opt</sub> <i>Permissions</i> ;<sub>opt</sub>
*  
* <i>DelimiterDeclaration</i>:
*   delim = <i>DelimiterCharacter</i>
*  
* <i>Permissions</i>:
*   <i>Permission</i>
*   <i>Permissions</i> ; <i>Permission</i>
*  
* <i>Permission</i>:
*   <i>PermissionClassName</i>
*   <i>PermissionClassName Name</i>
*   <i>PermissionClassName Name</i> , <i>Actions</i>
*  
* <i>PermissionClassName</i>:
*   <i>ClassName</i>
*  
* <i>Name</i>:
*   <i>DelimitedString</i>
*  
* <i>Actions</i>:
*   <i>DelimitedString</i>
* </pre>
* The production for <i>ClassName</i> is the same as that used in <i>The
* Java Language Specification</i><i>DelimiterCharacter</i> can be any
* unquoted non-whitespace character other than ';' (single and
* double-quote characters themselves are allowed).  If
* <i>DelimiterCharacter</i> is not specified, then the double-quote
* character is the default delimiter.  <i>DelimitedString</i> is the same
* as the <i>StringLiteral</i> production in <i>The Java Language
* Specification</i>, except that it is delimited by the
* <i>DelimiterDeclaration</i>-specified (or default) delimiter character
* instead of the double-quote character exclusively.
* <p>
* Note that if the double-quote character is used as the delimiter and the
* name or actions strings of specified permissions themselves contain nested
* double-quote characters, then those characters must be escaped (or in some
* cases doubly-escaped) appropriately.  For example, the following policy file
* entry would yield a <code>GrantPermission</code> containing a
* <code>FooPermission</code> in which the target name would include the word
* "quoted" surrounded by double-quote characters:
* <pre>
* permission net.jini.security.GrantPermission
*     "FooPermission \"a \\\"quoted\\\" string\"";
* </pre>
* For comparison, the following policy file entry which uses a custom
* delimiter would yield an equivalent <code>GrantPermission</code>:
* <pre>
* permission net.jini.security.GrantPermission
*     "delim=| FooPermission |a \"quoted\" string|";
* </pre>
* Some additional example policy file permissions:
* <pre>
* // allow granting of permission to listen for and accept connections
* permission net.jini.security.GrantPermission
*     "java.net.SocketPermission \"localhost:1024-\", \"accept,listen\"";
*
* // allow granting of permissions to read files under /foo, /bar directories
* permission net.jini.security.GrantPermission
*     "delim=' java.io.FilePermission '/foo/-', 'read'; java.io.FilePermission '/bar/-', 'read'";
*
* // allow granting of permission for client authentication as jack, with or without delegation, to any server
* permission net.jini.security.GrantPermission
*     "delim=| net.jini.security.AuthenticationPermission |javax.security.auth.x500.X500Principal \"CN=jack\"|, |delegate|";
* </pre>
*
* @author  Sun Microsystems, Inc.
* @see    DynamicPolicy#grant(Class, Principal[], Permission[])
* @since 2.0
*/
public final class GrantPermission extends Permission {

    private static final long serialVersionUID = 4668259055340724280L;
   
    private static final Class[] PARAMS0 = {};
    private static final Class[] PARAMS1 = { String.class };
    private static final Class[] PARAMS2 = { String.class, String.class };
   
    private transient Permission[] grants;
    private transient boolean unserializable;
    private transient volatile Implier implier;
    private transient volatile Integer hash;

    /**
     * Creates a <code>GrantPermission</code> for the permission(s) specified
     * in the name string.
     *
     * @param  name string describing contained permissions
     * @throws  NullPointerException if <code>name</code> is <code>null</code>
     * @throws  IllegalArgumentException if unable to parse target name
     */
    public GrantPermission(String name) {
  super(name);
  initFromName(name);
    }
   
    /**
     * Creates a <code>GrantPermission</code> for the given permission.
     *
     * @param  permission permission to allow to be granted
     * @throws  NullPointerException if <code>permission</code> is
     *     <code>null</code>
     */
    public GrantPermission(Permission permission) {
  this(new Permission[]{ permission });
    }

    /**
     * Creates a <code>GrantPermission</code> for the given permissions.  The
     * permissions array passed in is neither modified nor retained; subsequent
     * changes to the array have no effect on the <code>GrantPermission</code>.
     *
     * @param  permissions permissions to allow to be granted
     * @throws  NullPointerException if <code>permissions</code> array or any
     *     element of <code>permissions</code> array is <code>null</code>
     */
    public GrantPermission(Permission[] permissions) {
  super(constructName(permissions = (Permission[]) permissions.clone()));
  grants = flatten(permissions);
  for (int i = 0; i < permissions.length; i++) {
      if (permissions[i] instanceof UnresolvedPermission) {
    unserializable = true;
    return;
      }
  }
    }
   
    /**
     * Returns canonical string representation of this permission's actions,
     * which for <code>GrantPermission</code> is always the empty string
     * <code>""</code>.
     *
     * @return  the empty string <code>""</code>
     */
    public String getActions() {
  return "";
    }
   
    /**
     * Returns a newly created empty mutable permission collection for
     * <code>GrantPermission</code> instances.  The <code>implies</code> method
     * of the returned <code>PermissionCollection</code> instance is defined as
     * follows: for a given <code>GrantPermission g</code>, let
     * <code>c(g)</code> denote the set of all permissions contained within
     * <code>g</code> or within arbitrarily nested
     * <code>GrantPermission</code>s inside <code>g</code>, excluding nested
     * <code>GrantPermission</code>s themselves. Then, a <code>GrantPermission
     * g</code> is implied by the <code>PermissionCollection pc</code> if and
     * only if each permission in <code>c(g)</code> is implied by the union of
     * <code>c(p)</code> for all <code>p</code> in <code>pc</code>
     * <p>
     * Implication of contained
     * <code>java.security.UnresolvedPermission</code>s is special-cased: an
     * <code>UnresolvedPermission p1</code> is taken to imply another
     * <code>UnresolvedPermission p2</code> if and only if the serialized
     * representations of <code>p1</code> and <code>p2</code> are identical.
     *
     * @return  newly created empty mutable permission collection for
     *    <code>GrantPermissions</code>
     */
    public PermissionCollection newPermissionCollection() {
  return new GrantPermissionCollection();
    }
   
    /**
     * Returns <code>true</code> if the given permission is a
     * <code>GrantPermission</code> implied by this permission, or
     * <code>false</code> otherwise.  Implication is defined as follows: for a
     * given <code>GrantPermission g</code>, let <code>c(g)</code> denote the
     * set of all permissions contained within <code>g</code> or within
     * arbitrarily nested <code>GrantPermission</code>s inside <code>g</code>,
     * excluding nested <code>GrantPermission</code>s themselves.  Then, a
     * <code>GrantPermission g1</code> is implied by another
     * <code>GrantPermission g2</code> if and only if each permission in
     * <code>c(g1)</code> is implied by <code>c(g2)</code>.
     * <p>
     * Implication of contained
     * <code>java.security.UnresolvedPermission</code>s is special-cased: an
     * <code>UnresolvedPermission p1</code> is taken to imply another
     * <code>UnresolvedPermission p2</code> if and only if the serialized
     * representations of <code>p1</code> and <code>p2</code> are identical.
     *
     * @param  permission permission to check
     * @return  <code>true</code> if given permission is implied by this
     *    permission, <code>false</code> otherwise
     */
    public boolean implies(Permission permission) {
  if (!(permission instanceof GrantPermission)) {
      return false;
  }
  // perm -> perm implies infrequent, so construct implier lazily
  if (implier == null) {
      Implier imp = new Implier();
      imp.add(this);
      implier = imp;
  }
  return implier.implies(permission);
    }
   
    /**
     * Returns <code>true</code> if the given object is a
     * <code>GrantPermission</code> which both implies and is implied by this
     * permission; returns <code>false</code> otherwise.
     *
     * @param  obj object to compare against
     * @return  <code>true</code> if given object is a
     *     <code>GrantPermission</code> which both implies and is implied
     *     by this permission, <code>false</code> otherwise
     */
    public boolean equals(Object obj) {
  if (this == obj) {
      return true;
  }
  if (obj instanceof GrantPermission) {
      GrantPermission gp = (GrantPermission) obj;
      return this.implies(gp) && gp.implies(this);
  }
  return false;
    }
   
    public int hashCode() {
  if (hash == null) {
      hash = new Integer(computeHashCode());
  }
  return hash.intValue();
    }

    /**
     * Returns hash code computed by summing hash codes of each distinct
     * permission class name.
     */
    private int computeHashCode() {
  int sum = 0;
  HashSet set = new HashSet(grants.length);
  for (int i = 0; i < grants.length; i++) {
      Permission p = grants[i];
      String pcn = p.getClass().getName();
      if (p instanceof AllPermission) {
    return pcn.hashCode();
      } else if (p instanceof UnresolvedPermission) {
    pcn += ":" + p.getName();    // add name of unresolved class
      }
      if (!set.contains(pcn)) {
    set.add(pcn);
    sum += pcn.hashCode();
      }
  }
  return sum;
    }

    /**
     * Writes target name representing contained permissions.
     *
     * @throws  NotSerializableException if the <code>GrantPermission</code>
     *     was constructed explicitly with
     *     <code>java.security.UnresolvedPermission</code>s
     */
    private void writeObject(ObjectOutputStream out) throws IOException {
  if (unserializable) {
      throw new NotSerializableException(
    GrantPermission.class.getName());
  }
  out.defaultWriteObject();
    }

    /**
     * Reconstitutes contained permissions based on the information in the
     * target name.
     *
     * @throws  InvalidObjectException if the target name is <code>null</code>
     *     or does not conform to the syntax specified in the
     *     documentation for {@link GrantPermission}
     */
    private void readObject(ObjectInputStream in)
  throws IOException, ClassNotFoundException
    {
  in.defaultReadObject();
  try {
      initFromName(getName());
  } catch (RuntimeException e) {
      if (e instanceof NullPointerException ||
    e instanceof IllegalArgumentException)
      {
    InvalidObjectException ee =
        new InvalidObjectException(e.getMessage());
    ee.initCause(e);
    throw ee;
      }
      throw e;
  }
    }
   
    /**
     * Initializes GrantPermission to contain permissions described in the
     * given name.  Throws an IllegalArgumentException if the name is
     * misformatted, or specifies an invalid permission class.  Throws a
     * SecurityException if access to the class is not permitted.
     */
    private void initFromName(String name) {
  PermissionInfo[] pia = parsePermissions(name);
  ArrayList l = new ArrayList();
  for (int i = 0; i < pia.length; i++) {
      PermissionInfo pi = pia[i];

      SecurityManager sm = System.getSecurityManager();
      if (sm != null) {
    int d = pi.type.lastIndexOf('.');
    if (d != -1) {
        sm.checkPackageAccess(pi.type.substring(0, d));
    }
      }
      Class cl;
      try {
    cl = Class.forName(pi.type);
      } catch (ClassNotFoundException ex) {
    l.add(new UnresolvedPermission(
        pi.type, pi.name, pi.actions, null));
    continue;
      }
      if (!Permission.class.isAssignableFrom(cl)) {
    throw new IllegalArgumentException(
        "not a permission class: " + cl);
      }
      if (!Modifier.isPublic(cl.getModifiers())) {
    throw new IllegalArgumentException(
        "non-public permission class: " + cl);
      }
     
      if (pi.name == null) {
    try {
        Constructor c = cl.getConstructor(PARAMS0);
        l.add(c.newInstance(new Object[0]));
        continue;
    } catch (Exception ex) {
    }
      }
      if (pi.actions == null) {
    try {
        Constructor c = cl.getConstructor(PARAMS1);
        l.add(c.newInstance(new Object[]{ pi.name }));
        continue;
    } catch (Exception ex) {
    }
      }
      try {
    Constructor c = cl.getConstructor(PARAMS2);
    l.add(c.newInstance(new Object[]{ pi.name, pi.actions }));
    continue;
      } catch (Exception ex) {
      }
      throw new IllegalArgumentException(
    "uninstantiable permission class: " + cl);
  }
  grants = flatten((Permission[]) l.toArray(new Permission[l.size()]));
    }

    /**
     * Parses permission information from given GrantPermission name string.
     * Throws an IllegalArgumentException if the name string is misformatted.
     */
    private static PermissionInfo[] parsePermissions(String s) {
  try {
      ArrayList l = new ArrayList();
      StreamTokenizer st = createTokenizer(s);
      char delim = '"';

      if (st.nextToken() == StreamTokenizer.TT_WORD &&
    st.sval.equals("delim"))
      {
    if (st.nextToken() == '=') {
        if (st.nextToken() == StreamTokenizer.TT_WORD) {
      if (st.sval.length() > 1) {
          throw new IllegalArgumentException(
        "excess delimiter characters");
      }
      delim = st.sval.charAt(0);
        } else {
      delim = (char) st.ttype;
        }
        if (delim == ';') {
      throw new IllegalArgumentException(
          "illegal delimiter ';'");
        }
    } else // rewind
        st = createTokenizer(s);
    }
    st.nextToken();
      }
      st.quoteChar(delim);

      do {
    String type, name = null, actions = null;

    if (st.ttype != StreamTokenizer.TT_WORD) {
        throw new IllegalArgumentException(
      "expected permission type");
    }
    type = st.sval;
   
    // REMIND: allow unquoted name/actions?
    st.nextToken();
    if (st.ttype == StreamTokenizer.TT_EOF || st.ttype == ';') {
        l.add(new PermissionInfo(type, null, null));
        continue;
    } else if (st.ttype == delim) {
        name = st.sval;
    } else {
        throw new IllegalArgumentException(
      "expected permission name or ';'");
    }
   
    st.nextToken();
    if (st.ttype == StreamTokenizer.TT_EOF || st.ttype == ';') {
        l.add(new PermissionInfo(type, name, null));
        continue;
    } else if (st.ttype != ',') {
        throw new IllegalArgumentException("expected ',' or ';'");
    }

    if (st.nextToken() != delim) {
        throw new IllegalArgumentException(
      "expected permission actions");
    }
    actions = st.sval;
   
    st.nextToken();
    if (st.ttype == StreamTokenizer.TT_EOF || st.ttype == ';') {
        l.add(new PermissionInfo(type, name, actions));
        continue;
    } else {
        throw new IllegalArgumentException("expected ';'");
    }

      } while (st.nextToken() != StreamTokenizer.TT_EOF);

      return (PermissionInfo[]) l.toArray(new PermissionInfo[l.size()]);
  } catch (IOException ex) {
      throw (Error) new InternalError().initCause(ex);
  }
    }

    /**
     * Returns tokenizer for parsing given string.  The tokenizer is configured
     * similarly to that used by sun.security.provider.PolicyParser, except
     * that comments are disabled and no quote character is set (yet).
     */
    private static StreamTokenizer createTokenizer(String s) {
  StreamTokenizer st = new StreamTokenizer(new StringReader(s));
  st.resetSyntax();
  st.wordChars('a', 'z');
  st.wordChars('A', 'Z');
  st.wordChars('.', '.');
  st.wordChars('0', '9');
  st.wordChars('_', '_');
  st.wordChars('$', '$');
  st.wordChars(128 + 32, 255);
  st.whitespaceChars(0, ' ');
  st.lowerCaseMode(false);
  st.ordinaryChar('/');
  st.slashSlashComments(false);
  st.slashStarComments(false);
  return st;
    }

    /**
     * Constructs GrantPermission name/target string appropriate for given list
     * of permissions.
     */
    private static String constructName(Permission[] pa) {
  StringBuffer sb = new StringBuffer();
  for (int i = 0; i < pa.length; i++) {
      Permission p = pa[i];
      if (p instanceof UnresolvedPermission) {
    sb.append(p).append("; ");
      } else {
    Class cl = p.getClass();
    int nargs = maxConsArgs(cl);
    String t = cl.getName(), n = p.getName(), a = p.getActions();
    if (nargs == 2 && a != null) {
        // REMIND: handle null name?
        sb.append(t + " " + quote(n) + ", " + quote(a) + "; ");
    } else if (nargs >= 1 && n != null) {
        sb.append(t + " " + quote(n) + "; ");
    } else {
        sb.append(t + "; ");
    }
      }
  }
  return sb.toString().trim();
    }

    /**
     * Returns the maximum number of String parameters (up to 2) accepted by a
     * constructor of the given class.  Returns -1 if no matching constructor
     * (including no-arg constructor) is defined by given class.
     */
    private static int maxConsArgs(Class cl) {
  try {
      cl.getConstructor(PARAMS2);
      return 2;
  } catch (Exception ex) {
  }
  try {
      cl.getConstructor(PARAMS1);
      return 1;
  } catch (Exception ex) {
  }
  try {
      cl.getConstructor(PARAMS0);
      return 0;
  } catch (Exception ex) {
  }
  return -1;
    }

    /**
     * Returns quoted string literal that, if parsed by
     * java.io.StreamTokenizer, would yield the given string.  This method is
     * essentially a copy of com.sun.jini.config.ConfigUtil.stringLiteral; the
     * two methods are kept separate since ConfigUtil.stringLiteral could
     * conceivably escape unicode characters, while such escaping would be
     * incorrect for GrantPermission.
     */
    private static String quote(String s) {
  StringBuffer sb = new StringBuffer(s.length() + 2);
  sb.append('"');
  char[] ca = s.toCharArray();
  for (int i = 0; i < ca.length; i++) {
      char c = ca[i];
      if (c == '\\' || c == '"') {
    sb.append("\\").append(c);
      } else if (c == '\n') {
    sb.append("\\n");
      } else if (c == '\r') {
    sb.append("\\r");
      } else if (c == '\t') {
    sb.append("\\t");
      } else if (c == '\f') {
    sb.append("\\f");
      } else if (c == '\b') {
    sb.append("\\b");
      } else if (c < 0x20) {
    sb.append("\\").append(Integer.toOctalString(c));
      } else {
    sb.append(c);
      }
  }
  return sb.append('"').toString();
    }

    /**
     * Returns an array containing all non-GrantPermission permissions in the
     * given permission array, including those contained in nested
     * GrantPermissions in the array.
     */
    private static Permission[] flatten(Permission[] pa) {
  List l = new ArrayList(pa.length);
  for (int i = 0; i < pa.length; i++) {
      Permission p = pa[i];
      if (p instanceof GrantPermission) {
    l.addAll(Arrays.asList(((GrantPermission) p).grants));
      } else {
    l.add(p);
      }
  }
  return (Permission[]) l.toArray(new Permission[l.size()]);
    }

    /**
     * Parsed information about a permission.
     */
    private static class PermissionInfo {
 
  final String type;
  final String name;
  final String actions;
 
  PermissionInfo(String type, String name, String actions) {
      this.type = type;
      this.name = name;
      this.actions = actions;
  }
    }
   
    /**
     * Class for checking implication of contained permissions.
     */
    private static class Implier {
 
  private final PermissionCollection perms = new Permissions();
  private final ArrayList unresolved = new ArrayList();

  void add(GrantPermission gp) {
      for (int i = 0; i < gp.grants.length; i++) {
    Permission p = gp.grants[i];
    if (!impliesContained(p)) {
        perms.add(p);
        if (p instanceof UnresolvedPermission) {
      unresolved.add(p);
        }
    }
      }
  }
 
  boolean implies(Permission p) {
      if (!(p instanceof GrantPermission)) {
    return false;
      }
      Permission[] pa = ((GrantPermission) p).grants;
      for (int i = 0; i < pa.length; i++) {
    if (!impliesContained(pa[i])) {
        return false;
    }
      }
      return true;
  }

  private boolean impliesContained(Permission p) {
      if (p instanceof UnresolvedPermission) {
    for (Iterator i = unresolved.iterator(); i.hasNext();) {
        if (implies((UnresolvedPermission) i.next(),
        (UnresolvedPermission) p))
        {
      return true;
        }
    }
    return false;
      } else {
    return perms.implies(p);
      }
  }
 
  private static boolean implies(UnresolvedPermission p1,
               UnresolvedPermission p2)
  {
      if (p1 == p2) {
    return true;
      }
      // REMIND: use UnresolvedPermission.equals() once 4513737 fixed
      try {
    ByteArrayOutputStream bout = new ByteArrayOutputStream();
    ObjectOutputStream oout = new ObjectOutputStream(bout);

    bout.reset();
    oout.writeObject(p1);
    oout.flush();
    byte[] b1 = bout.toByteArray();
   
    oout.reset();
    bout.reset();
    oout.writeObject(p2);
    oout.flush();
    byte[] b2 = bout.toByteArray();
   
    return Arrays.equals(b1, b2);
      } catch (IOException ex) {
    throw (Error) new InternalError().initCause(ex);
      }
  }
    }

    /**
     * PermissionCollection variant returned by newPermissionCollection().
     *
     * @serial include
     */
    static class GrantPermissionCollection extends PermissionCollection {

  private static final long serialVersionUID = 8227621799817733985L;

  /**
   * @serialField perms List The permissions.
   */
  private static final ObjectStreamField[] serialPersistentFields = {
      new ObjectStreamField("perms", List.class, true)
  };

  private List perms = new ArrayList();
  private Implier implier = new Implier();

  public synchronized void add(Permission p) {
      if (!(p instanceof GrantPermission)) {
    throw new IllegalArgumentException("invalid permission: " + p);
      }
      if (isReadOnly()) {
    throw new SecurityException(
        "can't add to read-only PermissionCollection");
      }
      perms.add(p);
      implier.add((GrantPermission) p);
  }
 
  public synchronized Enumeration elements() {
      return Collections.enumeration(perms);
  }
 
  public synchronized boolean implies(Permission p) {
      return implier.implies(p);
  }

  public synchronized void setReadOnly() {
      super.setReadOnly();
  }

  public synchronized boolean isReadOnly() {
      return super.isReadOnly();
  }

  /**
   * Writes the permissions list.
   */
  private synchronized void writeObject(ObjectOutputStream s)
      throws IOException
  {
      s.defaultWriteObject();
  }

  /**
   * Verifies the permissions list.
   *
   * @throws InvalidObjectException if the list is
   *      <code>null</code> or any element is not an instance of
   *      <code>GrantPermission</code>
   */
  private void readObject(ObjectInputStream s)
      throws IOException, ClassNotFoundException
  {
      s.defaultReadObject();
      if (perms == null) {
    throw new InvalidObjectException("list cannot be null");
      }
      if (!perms.getClass().equals(ArrayList.class)) {
    perms = new ArrayList(perms);
      }
      if (perms.contains(null)) {
    throw new InvalidObjectException(
        "element must be a GrantPermission");
      }

      GrantPermission[] pa;
      try {
    pa = (GrantPermission[])
        perms.toArray(new GrantPermission[perms.size()]);
      } catch (ArrayStoreException e) {
    throw new InvalidObjectException(
        "element must be a GrantPermission");
      }

      implier = new Implier();
      for (int i = 0; i < pa.length; i++) {
    implier.add(pa[i]);
      }
  }
    }
}
TOP

Related Classes of net.jini.security.GrantPermission$GrantPermissionCollection

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.