/*
 * Copyright (c) 1999, 2012, Oracle and/or its affiliates. All rights reserved.
 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
 *
 * This code is free software; you can redistribute it and/or modify it
 * under the terms of the GNU General Public License version 2 only, as
 * published by the Free Software Foundation.  Oracle designates this
 * particular file as subject to the "Classpath" exception as provided
 * by Oracle in the LICENSE file that accompanied this code.
 *
 * This code is distributed in the hope that it will be useful, but WITHOUT
 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
 * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
 * version 2 for more details (a copy is included in the LICENSE file that
 * accompanied this code).
 *
 * You should have received a copy of the GNU General Public License version
 * 2 along with this work; if not, write to the Free Software Foundation,
 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
 *
 * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
 * or visit www.oracle.com if you need additional information or have any
 * questions.
 */

package javax.crypto;

import java.security.*;
import java.util.Enumeration;
import java.util.Hashtable;
import java.util.Vector;
import java.util.NoSuchElementException;
import java.util.concurrent.ConcurrentHashMap;
import java.io.Serializable;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.io.BufferedReader;
import java.io.ObjectStreamField;
import java.io.ObjectInputStream;
import java.io.ObjectInputStream.GetField;
import java.io.ObjectOutputStream;
import java.io.ObjectOutputStream.PutField;
import java.io.IOException;

This class contains CryptoPermission objects, organized into PermissionCollections according to algorithm names.

When the add method is called to add a CryptoPermission, the CryptoPermission is stored in the appropriate PermissionCollection. If no such collection exists yet, the algorithm name associated with the CryptoPermission object is determined and the newPermissionCollection method is called on the CryptoPermission or CryptoAllPermission class to create the PermissionCollection and add it to the Permissions object.

Author:Sharon Liu
See Also:
Since:1.4
/** * This class contains CryptoPermission objects, organized into * PermissionCollections according to algorithm names. * * <p>When the <code>add</code> method is called to add a * CryptoPermission, the CryptoPermission is stored in the * appropriate PermissionCollection. If no such * collection exists yet, the algorithm name associated with * the CryptoPermission object is * determined and the <code>newPermissionCollection</code> method * is called on the CryptoPermission or CryptoAllPermission class to * create the PermissionCollection and add it to the Permissions object. * * @see javax.crypto.CryptoPermission * @see java.security.PermissionCollection * @see java.security.Permissions * * @author Sharon Liu * @since 1.4 */
final class CryptoPermissions extends PermissionCollection implements Serializable { private static final long serialVersionUID = 4946547168093391015L;
@serialFieldperms java.util.Hashtable
/** * @serialField perms java.util.Hashtable */
private static final ObjectStreamField[] serialPersistentFields = { new ObjectStreamField("perms", Hashtable.class), }; // Switched from Hashtable to ConcurrentHashMap to improve scalability. // To maintain serialization compatibility, this field is made transient // and custom readObject/writeObject methods are used. private transient ConcurrentHashMap<String,PermissionCollection> perms;
Creates a new CryptoPermissions object containing no CryptoPermissionCollections.
/** * Creates a new CryptoPermissions object containing * no CryptoPermissionCollections. */
CryptoPermissions() { perms = new ConcurrentHashMap<String,PermissionCollection>(7); }
Populates the crypto policy from the specified InputStream into this CryptoPermissions object.
Params:
  • in – the InputStream to load from.
Throws:
/** * Populates the crypto policy from the specified * InputStream into this CryptoPermissions object. * * @param in the InputStream to load from. * * @exception SecurityException if cannot load * successfully. */
void load(InputStream in) throws IOException, CryptoPolicyParser.ParsingException { CryptoPolicyParser parser = new CryptoPolicyParser(); parser.read(new BufferedReader(new InputStreamReader(in, "UTF-8"))); CryptoPermission[] parsingResult = parser.getPermissions(); for (int i = 0; i < parsingResult.length; i++) { this.add(parsingResult[i]); } }
Returns true if this CryptoPermissions object doesn't contain any CryptoPermission objects; otherwise, returns false.
/** * Returns true if this CryptoPermissions object doesn't * contain any CryptoPermission objects; otherwise, returns * false. */
boolean isEmpty() { return perms.isEmpty(); }
Adds a permission object to the PermissionCollection for the algorithm returned by (CryptoPermission)permission.getAlgorithm(). This method creates a new PermissionCollection object (and adds the permission to it) if an appropriate collection does not yet exist.

Params:
  • permission – the Permission object to add.
Throws:
See Also:
  • isReadOnly
/** * Adds a permission object to the PermissionCollection for the * algorithm returned by * <code>(CryptoPermission)permission.getAlgorithm()</code>. * * This method creates * a new PermissionCollection object (and adds the permission to it) * if an appropriate collection does not yet exist. <p> * * @param permission the Permission object to add. * * @exception SecurityException if this CryptoPermissions object is * marked as readonly. * * @see isReadOnly */
public void add(Permission permission) { if (isReadOnly()) throw new SecurityException("Attempt to add a Permission " + "to a readonly CryptoPermissions " + "object"); if (!(permission instanceof CryptoPermission)) return; CryptoPermission cryptoPerm = (CryptoPermission)permission; PermissionCollection pc = getPermissionCollection(cryptoPerm); pc.add(cryptoPerm); String alg = cryptoPerm.getAlgorithm(); perms.putIfAbsent(alg, pc); }
Checks if this object's PermissionCollection for permissons of the specified permission's algorithm implies the specified permission. Returns true if the checking succeeded.
Params:
  • permission – the Permission object to check.
Returns:true if "permission" is implied by the permissions in the PermissionCollection it belongs to, false if not.
/** * Checks if this object's PermissionCollection for permissons * of the specified permission's algorithm implies the specified * permission. Returns true if the checking succeeded. * * @param permission the Permission object to check. * * @return true if "permission" is implied by the permissions * in the PermissionCollection it belongs to, false if not. * */
public boolean implies(Permission permission) { if (!(permission instanceof CryptoPermission)) { return false; } CryptoPermission cryptoPerm = (CryptoPermission)permission; PermissionCollection pc = getPermissionCollection(cryptoPerm.getAlgorithm()); return pc.implies(cryptoPerm); }
Returns an enumeration of all the Permission objects in all the PermissionCollections in this CryptoPermissions object.
Returns:an enumeration of all the Permissions.
/** * Returns an enumeration of all the Permission objects in all the * PermissionCollections in this CryptoPermissions object. * * @return an enumeration of all the Permissions. */
public Enumeration<Permission> elements() { // go through each Permissions in the hash table // and call their elements() function. return new PermissionsEnumerator(perms.elements()); }
Returns a CryptoPermissions object which represents the minimum of the specified CryptoPermissions object and this CryptoPermissions object.
Params:
  • other – the CryptoPermission object to compare with this object.
/** * Returns a CryptoPermissions object which * represents the minimum of the specified * CryptoPermissions object and this * CryptoPermissions object. * * @param other the CryptoPermission * object to compare with this object. */
CryptoPermissions getMinimum(CryptoPermissions other) { if (other == null) { return null; } if (this.perms.containsKey(CryptoAllPermission.ALG_NAME)) { return other; } if (other.perms.containsKey(CryptoAllPermission.ALG_NAME)) { return this; } CryptoPermissions ret = new CryptoPermissions(); PermissionCollection thatWildcard = other.perms.get(CryptoPermission.ALG_NAME_WILDCARD); int maxKeySize = 0; if (thatWildcard != null) { maxKeySize = ((CryptoPermission) thatWildcard.elements().nextElement()).getMaxKeySize(); } // For each algorithm in this CryptoPermissions, // find out if there is anything we should add into // ret. Enumeration<String> thisKeys = this.perms.keys(); while (thisKeys.hasMoreElements()) { String alg = thisKeys.nextElement(); PermissionCollection thisPc = this.perms.get(alg); PermissionCollection thatPc = other.perms.get(alg); CryptoPermission[] partialResult; if (thatPc == null) { if (thatWildcard == null) { // The other CryptoPermissions // doesn't allow this given // algorithm at all. Just skip this // algorithm. continue; } partialResult = getMinimum(maxKeySize, thisPc); } else { partialResult = getMinimum(thisPc, thatPc); } for (int i = 0; i < partialResult.length; i++) { ret.add(partialResult[i]); } } PermissionCollection thisWildcard = this.perms.get(CryptoPermission.ALG_NAME_WILDCARD); // If this CryptoPermissions doesn't // have a wildcard, we are done. if (thisWildcard == null) { return ret; } // Deal with the algorithms only appear // in the other CryptoPermissions. maxKeySize = ((CryptoPermission) thisWildcard.elements().nextElement()).getMaxKeySize(); Enumeration<String> thatKeys = other.perms.keys(); while (thatKeys.hasMoreElements()) { String alg = thatKeys.nextElement(); if (this.perms.containsKey(alg)) { continue; } PermissionCollection thatPc = other.perms.get(alg); CryptoPermission[] partialResult; partialResult = getMinimum(maxKeySize, thatPc); for (int i = 0; i < partialResult.length; i++) { ret.add(partialResult[i]); } } return ret; }
Get the minimum of the two given PermissionCollection thisPc and thatPc.
Params:
  • thisPc – the first given PermissionColloection object.
  • thatPc – the second given PermissionCollection object.
/** * Get the minimum of the two given PermissionCollection * <code>thisPc</code> and <code>thatPc</code>. * * @param thisPc the first given PermissionColloection * object. * * @param thatPc the second given PermissionCollection * object. */
private CryptoPermission[] getMinimum(PermissionCollection thisPc, PermissionCollection thatPc) { Vector<CryptoPermission> permVector = new Vector<CryptoPermission>(2); Enumeration<Permission> thisPcPermissions = thisPc.elements(); // For each CryptoPermission in // thisPc object, do the following: // 1) if this CryptoPermission is implied // by thatPc, this CryptoPermission // should be returned, and we can // move on to check the next // CryptoPermission in thisPc. // 2) otherwise, we should return // all CryptoPermissions in thatPc // which // are implied by this CryptoPermission. // Then we can move on to the // next CryptoPermission in thisPc. while (thisPcPermissions.hasMoreElements()) { CryptoPermission thisCp = (CryptoPermission)thisPcPermissions.nextElement(); Enumeration<Permission> thatPcPermissions = thatPc.elements(); while (thatPcPermissions.hasMoreElements()) { CryptoPermission thatCp = (CryptoPermission)thatPcPermissions.nextElement(); if (thatCp.implies(thisCp)) { permVector.addElement(thisCp); break; } if (thisCp.implies(thatCp)) { permVector.addElement(thatCp); } } } CryptoPermission[] ret = new CryptoPermission[permVector.size()]; permVector.copyInto(ret); return ret; }
Returns all the CryptoPermission objects in the given PermissionCollection object whose maximum keysize no greater than maxKeySize. For all CryptoPermission objects with a maximum keysize greater than maxKeySize, this method constructs a corresponding CryptoPermission object whose maximum keysize is set to maxKeySize, and includes that in the result.
Params:
  • maxKeySize – the given maximum key size.
  • pc – the given PermissionCollection object.
/** * Returns all the CryptoPermission objects in the given * PermissionCollection object * whose maximum keysize no greater than <code>maxKeySize</code>. * For all CryptoPermission objects with a maximum keysize greater * than <code>maxKeySize</code>, this method constructs a * corresponding CryptoPermission object whose maximum keysize is * set to <code>maxKeySize</code>, and includes that in the result. * * @param maxKeySize the given maximum key size. * * @param pc the given PermissionCollection object. */
private CryptoPermission[] getMinimum(int maxKeySize, PermissionCollection pc) { Vector<CryptoPermission> permVector = new Vector<CryptoPermission>(1); Enumeration<Permission> enum_ = pc.elements(); while (enum_.hasMoreElements()) { CryptoPermission cp = (CryptoPermission)enum_.nextElement(); if (cp.getMaxKeySize() <= maxKeySize) { permVector.addElement(cp); } else { if (cp.getCheckParam()) { permVector.addElement( new CryptoPermission(cp.getAlgorithm(), maxKeySize, cp.getAlgorithmParameterSpec(), cp.getExemptionMechanism())); } else { permVector.addElement( new CryptoPermission(cp.getAlgorithm(), maxKeySize, cp.getExemptionMechanism())); } } } CryptoPermission[] ret = new CryptoPermission[permVector.size()]; permVector.copyInto(ret); return ret; }
Returns the PermissionCollection for the specified algorithm. Returns null if there isn't such a PermissionCollection.
Params:
  • alg – the algorithm name.
/** * Returns the PermissionCollection for the * specified algorithm. Returns null if there * isn't such a PermissionCollection. * * @param alg the algorithm name. */
PermissionCollection getPermissionCollection(String alg) { // If this CryptoPermissions includes CryptoAllPermission, // we should return CryptoAllPermission. PermissionCollection pc = perms.get(CryptoAllPermission.ALG_NAME); if (pc == null) { pc = perms.get(alg); // If there isn't a PermissionCollection for // the given algorithm,we should return the // PermissionCollection for the wildcard // if there is one. if (pc == null) { pc = perms.get(CryptoPermission.ALG_NAME_WILDCARD); } } return pc; }
Returns the PermissionCollection for the algorithm associated with the specified CryptoPermission object. Creates such a PermissionCollection if such a PermissionCollection does not exist yet.
Params:
  • cryptoPerm – the CryptoPermission object.
/** * Returns the PermissionCollection for the algorithm * associated with the specified CryptoPermission * object. Creates such a PermissionCollection * if such a PermissionCollection does not * exist yet. * * @param cryptoPerm the CryptoPermission object. */
private PermissionCollection getPermissionCollection( CryptoPermission cryptoPerm) { String alg = cryptoPerm.getAlgorithm(); PermissionCollection pc = perms.get(alg); if (pc == null) { pc = cryptoPerm.newPermissionCollection(); } return pc; } private void readObject(ObjectInputStream s) throws IOException, ClassNotFoundException { ObjectInputStream.GetField fields = s.readFields(); @SuppressWarnings("unchecked") Hashtable<String,PermissionCollection> permTable = (Hashtable<String,PermissionCollection>) (fields.get("perms", null)); if (permTable != null) { perms = new ConcurrentHashMap<String,PermissionCollection>(permTable); } else { perms = new ConcurrentHashMap<String,PermissionCollection>(); } } private void writeObject(ObjectOutputStream s) throws IOException { Hashtable<String,PermissionCollection> permTable = new Hashtable<String,PermissionCollection>(perms); ObjectOutputStream.PutField fields = s.putFields(); fields.put("perms", permTable); s.writeFields(); } } final class PermissionsEnumerator implements Enumeration<Permission> { // all the perms private Enumeration<PermissionCollection> perms; // the current set private Enumeration<Permission> permset; PermissionsEnumerator(Enumeration<PermissionCollection> e) { perms = e; permset = getNextEnumWithMore(); } public synchronized boolean hasMoreElements() { // if we enter with permissionimpl null, we know // there are no more left. if (permset == null) return false; // try to see if there are any left in the current one if (permset.hasMoreElements()) return true; // get the next one that has something in it... permset = getNextEnumWithMore(); // if it is null, we are done! return (permset != null); } public synchronized Permission nextElement() { // hasMoreElements will update permset to the next permset // with something in it... if (hasMoreElements()) { return permset.nextElement(); } else { throw new NoSuchElementException("PermissionsEnumerator"); } } private Enumeration<Permission> getNextEnumWithMore() { while (perms.hasMoreElements()) { PermissionCollection pc = perms.nextElement(); Enumeration<Permission> next = pc.elements(); if (next.hasMoreElements()) return next; } return null; } }