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.util;
19
20import java.io.IOException;
21import java.io.ObjectInputStream;
22import java.io.ObjectOutputStream;
23import java.io.ObjectStreamField;
24import java.security.Permission;
25import java.security.PermissionCollection;
26
27/**
28 * A {@code PermissionCollection} for holding {@code PropertyPermission}s.
29 */
30class PropertyPermissionCollection extends PermissionCollection {
31
32    private static final long serialVersionUID = 7015263904581634791L;
33
34    Hashtable<String, Permission> permissions = new Hashtable<String, Permission>(
35            30);
36
37    @Override
38    public void add(Permission perm) {
39        if (!isReadOnly()) {
40            Permission prev = permissions.put(perm.getName(), perm);
41            /*
42             * If the permission already existed but with only "read" or "write"
43             * set, then replace with both set.
44             */
45            if (prev != null && !prev.getActions().equals(perm.getActions())) {
46                Permission np = new PropertyPermission(perm.getName(),
47                        "read,write"); //$NON-NLS-1$
48                permissions.put(perm.getName(), np);
49            }
50        } else {
51            throw new IllegalStateException();
52        }
53    }
54
55    @Override
56    public Enumeration<Permission> elements() {
57        return permissions.elements();
58    }
59
60    @Override
61    public boolean implies(Permission perm) {
62        Enumeration<Permission> elemEnum = elements();
63        while (elemEnum.hasMoreElements()) {
64            if ((elemEnum.nextElement()).implies(perm)) {
65                return true;
66            }
67        }
68        /*
69         * At this point, the only way it can succeed is if both read and write
70         * are set, and these are separately granted by two different
71         * permissions with one representing a parent directory.
72         */
73        return perm.getActions().equals("read,write") //$NON-NLS-1$
74                && implies(new PropertyPermission(perm.getName(), "read")) //$NON-NLS-1$
75                && implies(new PropertyPermission(perm.getName(), "write")); //$NON-NLS-1$
76    }
77
78    private static final ObjectStreamField[] serialPersistentFields = {
79            new ObjectStreamField("permissions", Hashtable.class), //$NON-NLS-1$
80            new ObjectStreamField("all_allowed", Boolean.TYPE) }; //$NON-NLS-1$
81
82    private void writeObject(ObjectOutputStream stream) throws IOException {
83        ObjectOutputStream.PutField fields = stream.putFields();
84        fields.put("permissions", permissions); //$NON-NLS-1$
85        fields.put("all_allowed", false); //$NON-NLS-1$
86        stream.writeFields();
87    }
88
89    @SuppressWarnings("unchecked")
90    private void readObject(ObjectInputStream stream) throws IOException,
91            ClassNotFoundException {
92        ObjectInputStream.GetField fields = stream.readFields();
93        permissions = (Hashtable<String, Permission>) fields.get(
94                "permissions", null); //$NON-NLS-1$
95    }
96}
97