1/*
2 *  Licensed to the Apache Software Foundation (ASF) under one or more
3 *  contributor license agreements.  See the NOTICE file distributed with
4 *  this work for additional information regarding copyright ownership.
5 *  The ASF licenses this file to You under the Apache License, Version 2.0
6 *  (the "License"); you may not use this file except in compliance with
7 *  the License.  You may obtain a copy of the License at
8 *
9 *     http://www.apache.org/licenses/LICENSE-2.0
10 *
11 *  Unless required by applicable law or agreed to in writing, software
12 *  distributed under the License is distributed on an "AS IS" BASIS,
13 *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14 *  See the License for the specific language governing permissions and
15 *  limitations under the License.
16 */
17
18package java.security;
19
20import java.io.IOException;
21import java.io.ObjectInputStream;
22import java.io.ObjectOutputStream;
23import java.io.ObjectStreamField;
24import java.util.Enumeration;
25import java.util.NoSuchElementException;
26
27import org.apache.harmony.security.internal.nls.Messages;
28
29/**
30 * Specific {@code PermissionCollection} for storing {@code AllPermission}s. All
31 * instances of {@code AllPermission} are equivalent, so it is enough to store a
32 * single added instance.
33 *
34 * @see AllPermission
35 */
36final class AllPermissionCollection extends PermissionCollection {
37
38    private static final long serialVersionUID = -4023755556366636806L;
39
40    private static final ObjectStreamField[] serialPersistentFields = { new ObjectStreamField(
41        "all_allowed", Boolean.TYPE), }; //$NON-NLS-1$
42
43    // Single element of collection.
44    private transient Permission all;
45
46    /**
47     * Adds an {@code AllPermission} to the collection.
48     */
49    @Override
50    public void add(Permission permission) {
51        if (isReadOnly()) {
52            throw new SecurityException(Messages.getString("security.15")); //$NON-NLS-1$
53        }
54        if (!(permission instanceof AllPermission)) {
55            throw new IllegalArgumentException(Messages.getString("security.16", //$NON-NLS-1$
56                permission));
57        }
58        all = permission;
59    }
60
61    /**
62     * Returns the enumeration of the collection.
63     */
64    @Override
65    public Enumeration<Permission> elements() {
66        return new SingletonEnumeration<Permission>(all);
67    }
68
69    /**
70     * An auxiliary implementation for enumerating a single object.
71     *
72     */
73    final static class SingletonEnumeration<E> implements Enumeration<E> {
74
75        private E element;
76
77        /**
78         * Constructor taking the single element.
79         * @param single the element
80         */
81        public SingletonEnumeration(E single) {
82            element = single;
83        }
84
85        /**
86         * Returns true if the element is not enumerated yet.
87         */
88        public boolean hasMoreElements() {
89            return element != null;
90        }
91
92        /**
93         * Returns the element and clears internal reference to it.
94         */
95        public E nextElement() {
96            if (element == null) {
97                throw new NoSuchElementException(Messages.getString("security.17")); //$NON-NLS-1$
98            }
99            E last = element;
100            element = null;
101            return last;
102        }
103    }
104
105    /**
106     * Indicates whether the argument permission is implied by the receiver.
107     * {@code AllPermission} objects imply all other permissions.
108     *
109     * @return boolean {@code true} if the argument permission is implied by the
110     *         receiver, and {@code false} if it is not.
111     * @param permission
112     *            the permission to check.
113     */
114    @Override
115    public boolean implies(Permission permission) {
116        return all != null;
117    }
118
119    /**
120     * Writes the fields according to expected format, adding the boolean field
121     * {@code all_allowed} which is {@code true} if this collection is not
122     * empty.
123     */
124    private void writeObject(java.io.ObjectOutputStream out) throws IOException {
125        ObjectOutputStream.PutField fields = out.putFields();
126        fields.put("all_allowed", all != null); //$NON-NLS-1$
127        out.writeFields();
128    }
129
130    /**
131     * Restores internal state.
132     */
133    private void readObject(java.io.ObjectInputStream in) throws IOException,
134        ClassNotFoundException {
135        ObjectInputStream.GetField fields = in.readFields();
136        if (fields.get("all_allowed", false)) { //$NON-NLS-1$
137            all = new AllPermission();
138        }
139    }
140}
141