001: /*
002: * Licensed to the Apache Software Foundation (ASF) under one or more
003: * contributor license agreements. See the NOTICE file distributed with
004: * this work for additional information regarding copyright ownership.
005: * The ASF licenses this file to You under the Apache License, Version 2.0
006: * (the "License"); you may not use this file except in compliance with
007: * the License. You may obtain a copy of the License at
008: *
009: * http://www.apache.org/licenses/LICENSE-2.0
010: *
011: * Unless required by applicable law or agreed to in writing, software
012: * distributed under the License is distributed on an "AS IS" BASIS,
013: * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
014: * See the License for the specific language governing permissions and
015: * limitations under the License.
016: */
017:
018: /**
019: * @author Alexey V. Varlamov
020: * @version $Revision$
021: */package java.security;
022:
023: import java.io.IOException;
024: import java.io.InvalidObjectException;
025: import java.io.ObjectInputStream;
026: import java.io.ObjectOutputStream;
027: import java.io.ObjectStreamField;
028: import java.io.Serializable;
029: import java.util.Enumeration;
030: import java.util.HashMap;
031: import java.util.Hashtable;
032: import java.util.Iterator;
033: import java.util.Map;
034: import java.util.NoSuchElementException;
035:
036: import org.apache.harmony.security.internal.nls.Messages;
037:
038: /**
039: * A heterogeneous collection of permissions.
040: *
041: */
042: public final class Permissions extends PermissionCollection implements
043: Serializable {
044:
045: /**
046: * @com.intel.drl.spec_ref
047: */
048: private static final long serialVersionUID = 4858622370623524688L;
049:
050: private static final ObjectStreamField[] serialPersistentFields = {
051: new ObjectStreamField("perms", Hashtable.class), //$NON-NLS-1$
052: new ObjectStreamField(
053: "allPermission", PermissionCollection.class), }; //$NON-NLS-1$
054:
055: // Hash to store PermissionCollection's
056: private transient Map klasses = new HashMap();
057:
058: /**
059: * @com.intel.drl.spec_ref
060: */
061: private boolean allEnabled; // = false;
062:
063: /**
064: * Adds the argument to the collection.
065: *
066: *
067: * @param permission
068: * java.security.Permission the permission to add to the
069: * collection
070: */
071: public void add(Permission permission) {
072: if (isReadOnly()) {
073: throw new SecurityException(Messages
074: .getString("security.15")); //$NON-NLS-1$
075: }
076:
077: if (permission == null) {
078: throw new NullPointerException(Messages
079: .getString("security.20")); //$NON-NLS-1$
080: }
081:
082: Class klass = permission.getClass();
083: PermissionCollection klassMates = (PermissionCollection) klasses
084: .get(klass);
085:
086: if (klassMates == null) {
087: synchronized (klasses) {
088: klassMates = (PermissionCollection) klasses.get(klass);
089: if (klassMates == null) {
090:
091: klassMates = permission.newPermissionCollection();
092: if (klassMates == null) {
093: klassMates = new PermissionsHash();
094: }
095: klasses.put(klass, klassMates);
096: }
097: }
098: }
099: klassMates.add(permission);
100:
101: if (klass == AllPermission.class) {
102: allEnabled = true;
103: }
104: }
105:
106: /**
107: * Answers an enumeration of the permissions in the receiver.
108: *
109: *
110: * @return Enumeration the permissions in the receiver.
111: */
112: public Enumeration<Permission> elements() {
113: return new MetaEnumeration(klasses.values().iterator());
114: }
115:
116: /**
117: * An auxiliary implementation for enumerating individual permissions from a
118: * collection of PermissionCollections.
119: *
120: */
121: final static class MetaEnumeration implements Enumeration {
122:
123: private Iterator pcIter;
124:
125: private Enumeration current;
126:
127: /**
128: * Initiates this enumeration.
129: *
130: * @param outer an iterator over external collection of
131: * PermissionCollections
132: */
133: public MetaEnumeration(Iterator outer) {
134: pcIter = outer;
135: current = getNextEnumeration();
136: }
137:
138: private Enumeration getNextEnumeration() {
139: while (pcIter.hasNext()) {
140: Enumeration en = ((PermissionCollection) pcIter.next())
141: .elements();
142: if (en.hasMoreElements()) {
143: return en;
144: }
145: }
146: return null;
147: }
148:
149: /**
150: * Indicates if there are more elements to enumerate.
151: */
152: public boolean hasMoreElements() {
153: return current != null /* && current.hasMoreElements() */;
154: }
155:
156: /**
157: * Returns next element.
158: */
159: public Object nextElement() {
160: if (current != null) {
161: //assert current.hasMoreElements();
162: Object next = current.nextElement();
163: if (!current.hasMoreElements()) {
164: current = getNextEnumeration();
165: }
166:
167: return next;
168: }
169: throw new NoSuchElementException(Messages
170: .getString("security.17")); //$NON-NLS-1$
171: }
172: }
173:
174: /**
175: * Indicates whether the argument permission is implied by the permissions
176: * contained in the receiver.
177: *
178: *
179: * @return boolean <code>true</code> if the argument permission is implied
180: * by the permissions in the receiver, and <code>false</code> if
181: * it is not.
182: * @param permission
183: * java.security.Permission the permission to check
184: */
185: public boolean implies(Permission permission) {
186: if (permission == null) {
187: // RI compatible
188: throw new NullPointerException(Messages
189: .getString("security.21")); //$NON-NLS-1$
190: }
191: if (allEnabled) {
192: return true;
193: }
194: Class klass = permission.getClass();
195: PermissionCollection klassMates = null;
196:
197: UnresolvedPermissionCollection billets = (UnresolvedPermissionCollection) klasses
198: .get(UnresolvedPermission.class);
199: if (billets != null && billets.hasUnresolved(permission)) {
200: // try to fill up klassMates with freshly resolved permissions
201: synchronized (klasses) {
202: klassMates = (PermissionCollection) klasses.get(klass);
203: try {
204: klassMates = billets.resolveCollection(permission,
205: klassMates);
206: } catch (Exception ignore) {
207: //TODO log warning
208: ignore.printStackTrace();
209: }
210:
211: if (klassMates != null) {
212: //maybe klassMates were just created
213: // so put them into common map
214: klasses.put(klass, klassMates);
215: // very uncommon case, but not improbable one
216: if (klass == AllPermission.class) {
217: allEnabled = true;
218: }
219: }
220: }
221: } else {
222: klassMates = (PermissionCollection) klasses.get(klass);
223: }
224:
225: if (klassMates != null) {
226: return klassMates.implies(permission);
227: }
228: return false;
229: }
230:
231: /**
232: * Reads the object from stream and checks for consistency.
233: */
234: private void readObject(java.io.ObjectInputStream in)
235: throws IOException, ClassNotFoundException {
236: ObjectInputStream.GetField fields = in.readFields();
237: Map perms = (Map) fields.get("perms", null); //$NON-NLS-1$
238: klasses = new HashMap();
239: synchronized (klasses) {
240: for (Iterator iter = perms.entrySet().iterator(); iter
241: .hasNext();) {
242: Map.Entry entry = (Map.Entry) iter.next();
243: Class key = (Class) entry.getKey();
244: PermissionCollection pc = (PermissionCollection) entry
245: .getValue();
246: if (key != pc.elements().nextElement().getClass()) {
247: throw new InvalidObjectException(Messages
248: .getString("security.22")); //$NON-NLS-1$
249: }
250: klasses.put(key, pc);
251: }
252: }
253: allEnabled = fields.get("allPermission", null) != null; //$NON-NLS-1$
254: if (allEnabled && !klasses.containsKey(AllPermission.class)) {
255: throw new InvalidObjectException(Messages
256: .getString("security.23")); //$NON-NLS-1$
257: }
258: }
259:
260: /**
261: * Outputs fields via default mechanism.
262: */
263: private void writeObject(java.io.ObjectOutputStream out)
264: throws IOException {
265: ObjectOutputStream.PutField fields = out.putFields();
266: fields.put("perms", new Hashtable(klasses)); //$NON-NLS-1$
267: fields.put("allPermission", allEnabled ? klasses //$NON-NLS-1$
268: .get(AllPermission.class) : null);
269: out.writeFields();
270: }
271: }
|