1/*
2 * Copyright (c) 2000, 2012, Oracle and/or its affiliates. All rights reserved.
3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
4 *
5 * This code is free software; you can redistribute it and/or modify it
6 * under the terms of the GNU General Public License version 2 only, as
7 * published by the Free Software Foundation.  Oracle designates this
8 * particular file as subject to the "Classpath" exception as provided
9 * by Oracle in the LICENSE file that accompanied this code.
10 *
11 * This code is distributed in the hope that it will be useful, but WITHOUT
12 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
13 * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
14 * version 2 for more details (a copy is included in the LICENSE file that
15 * accompanied this code).
16 *
17 * You should have received a copy of the GNU General Public License version
18 * 2 along with this work; if not, write to the Free Software Foundation,
19 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
20 *
21 * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
22 * or visit www.oracle.com if you need additional information or have any
23 * questions.
24 */
25
26package com.sun.rmi.rmid;
27
28import java.security.*;
29import java.io.*;
30import java.util.*;
31
32/**
33 * The ExecPermission class represents permission for rmid to execute
34 * a specific command to launch an activation group.  An ExecPermission
35 * consists of a pathname of a command to launch an activation group.
36 * <P>
37 * Pathname is the pathname of the file or directory to grant rmid
38 * execute permission.  A pathname that ends in "/*" (where "/" is
39 * the file separator character, <code>File.separatorChar</code>) indicates
40 * all the files and directories contained in that directory. A pathname
41 * that ends with "/-" indicates (recursively) all files
42 * and subdirectories contained in that directory. A pathname consisting of
43 * the special token "{@code <<ALL FILES>>}" matches <b>any</b> file.
44 * <P>
45 * Note: A pathname consisting of a single "*" indicates all the files
46 * in the current directory, while a pathname consisting of a single "-"
47 * indicates all the files in the current directory and
48 * (recursively) all files and subdirectories contained in the current
49 * directory.
50 *
51 *
52 * @author Ann Wollrath
53 *
54 * @serial exclude
55 */
56public final class ExecPermission extends Permission
57{
58    /**
59     * UID for serialization
60     */
61    private static final long serialVersionUID = -6208470287358147919L;
62
63    private transient FilePermission fp;
64
65    /**
66     * Creates a new ExecPermission object with the specified path.
67     * <i>path</i> is the pathname of a file or directory.
68     *
69     * <p>A pathname that ends in "/*" (where "/" is
70     * the file separator character, <code>File.separatorChar</code>) indicates
71     * a directory and all the files contained in that directory. A pathname
72     * that ends with "/-" indicates a directory and (recursively) all files
73     * and subdirectories contained in that directory. The special pathname
74     * "{@code <<ALL FILES>>}" matches all files.
75     *
76     * <p>A pathname consisting of a single "*" indicates all the files
77     * in the current directory, while a pathname consisting of a single "-"
78     * indicates all the files in the current directory and
79     * (recursively) all files and subdirectories contained in the current
80     * directory.
81     *
82     * @param path the pathname of the file/directory.
83     */
84    public ExecPermission(String path) {
85        super(path);
86        init(path);
87    }
88
89    /**
90     * Creates a new ExecPermission object with the specified path.
91     * <i>path</i> is the pathname of a file or directory.
92     *
93     * <p>A pathname that ends in "/*" (where "/" is
94     * the file separator character, <code>File.separatorChar</code>) indicates
95     * a directory and all the files contained in that directory. A pathname
96     * that ends with "/-" indicates a directory and (recursively) all files
97     * and subdirectories contained in that directory. The special pathname
98     * "{@code <<ALL FILES>>}" matches all files.
99     *
100     * <p>A pathname consisting of a single "*" indicates all the files
101     * in the current directory, while a pathname consisting of a single "-"
102     * indicates all the files in the current directory and
103     * (recursively) all files and subdirectories contained in the current
104     * directory.
105     *
106     * @param path the pathname of the file/directory.
107     * @param actions the action string (unused)
108     */
109    public ExecPermission(String path, String actions) {
110        this(path);
111    }
112
113    /**
114     * Checks if this ExecPermission object "implies" the specified permission.
115     * <P>
116     * More specifically, this method returns true if:
117     * <ul>
118     * <li> <i>p</i> is an instanceof ExecPermission, and
119     * <li> <i>p</i>'s pathname is implied by this object's
120     *      pathname. For example, "/tmp/*" implies "/tmp/foo", since
121     *      "/tmp/*" encompasses the "/tmp" directory and all files in that
122     *      directory, including the one named "foo".
123     * </ul>
124     * @param p the permission to check against.
125     *
126     * @return true if the specified permission is implied by this object,
127     * false if not.
128     */
129    public boolean implies(Permission p) {
130        if (!(p instanceof ExecPermission))
131            return false;
132
133        ExecPermission that = (ExecPermission) p;
134
135        return fp.implies(that.fp);
136    }
137
138    /**
139     * Checks two ExecPermission objects for equality.
140     * Checks that <i>obj</i>'s class is the same as this object's class
141     * and has the same name as this object.
142     *
143     * @param obj the object we are testing for equality with this object.
144     * @return true if <i>obj</i> is an ExecPermission, and has the same
145     * pathname as this ExecPermission object, false otherwise.
146     */
147    public boolean equals(Object obj) {
148        if (obj == this)
149            return true;
150
151        if (! (obj instanceof ExecPermission))
152            return false;
153
154        ExecPermission that = (ExecPermission) obj;
155
156        return fp.equals(that.fp);
157    }
158
159    /**
160     * Returns the hash code value for this object.
161     *
162     * @return a hash code value for this object.
163     */
164    public int hashCode() {
165        return this.fp.hashCode();
166    }
167
168    /**
169     * Returns the canonical string representation of the actions.
170     *
171     * @return the canonical string representation of the actions.
172     */
173    public String getActions() {
174        return "";
175    }
176
177    /**
178     * Returns a new PermissionCollection object for storing
179     * ExecPermission objects.
180     * <p>
181     * A ExecPermissionCollection stores a collection of
182     * ExecPermission permissions.
183     *
184     * <p>ExecPermission objects must be stored in a manner that allows
185     * them to be inserted in any order, but that also enables the
186     * PermissionCollection <code>implies</code> method
187     * to be implemented in an efficient (and consistent) manner.
188     *
189     * @return a new PermissionCollection object suitable for
190     * storing ExecPermissions.
191     */
192    public PermissionCollection newPermissionCollection() {
193        return new ExecPermissionCollection();
194    }
195
196    /**
197     * readObject is called to restore the state of the ExecPermission
198     * from a stream.
199     */
200    private synchronized void readObject(java.io.ObjectInputStream s)
201         throws IOException, ClassNotFoundException
202    {
203        s.defaultReadObject();
204        // init is called to initialize the rest of the values.
205        init(getName());
206    }
207
208    /**
209     * Initialize a ExecPermission object. Common to all constructors.
210     * Also called during de-serialization.
211     */
212    private void init(String path) {
213        this.fp = new FilePermission(path, "execute");
214    }
215
216    /**
217     * A ExecPermissionCollection stores a collection
218     * of ExecPermission permissions. ExecPermission objects
219     * must be stored in a manner that allows them to be inserted in any
220     * order, but enable the implies function to evaluate the implies
221     * method in an efficient (and consistent) manner.
222     *
223     * @serial include
224     */
225    private static class ExecPermissionCollection
226        extends PermissionCollection
227        implements java.io.Serializable
228    {
229        private Vector<Permission> permissions;
230
231        private static final long serialVersionUID = -3352558508888368273L;
232
233        /**
234         * Create an empty ExecPermissionCollection.
235         */
236        public ExecPermissionCollection() {
237            permissions = new Vector<>();
238        }
239
240        /**
241         * Adds a permission to the collection.
242         *
243         * @param permission the Permission object to add.
244         *
245         * @exception IllegalArgumentException - if the permission is not a
246         *                                       ExecPermission
247         *
248         * @exception SecurityException - if this ExecPermissionCollection
249         *                                object has been marked readonly
250         */
251        public void add(Permission permission)
252        {
253            if (! (permission instanceof ExecPermission))
254                throw new IllegalArgumentException("invalid permission: "+
255                                                   permission);
256            if (isReadOnly())
257                throw new SecurityException("attempt to add a Permission to a readonly PermissionCollection");
258
259            permissions.addElement(permission);
260        }
261
262        /**
263         * Check and see if this set of permissions implies the permissions
264         * expressed in "permission".
265         *
266         * @param p the Permission object to compare
267         *
268         * @return true if "permission" is a proper subset of a permission in
269         * the set, false if not.
270         */
271        public boolean implies(Permission permission)
272        {
273            if (! (permission instanceof ExecPermission))
274                return false;
275
276            Enumeration<Permission> e = permissions.elements();
277
278            while (e.hasMoreElements()) {
279                ExecPermission x = (ExecPermission)e.nextElement();
280                if (x.implies(permission)) {
281                    return true;
282                }
283            }
284            return false;
285        }
286
287        /**
288         * Returns an enumeration of all the ExecPermission objects in the
289         * container.
290         *
291         * @return an enumeration of all the ExecPermission objects.
292         */
293        public Enumeration<Permission> elements()
294        {
295            return permissions.elements();
296        }
297    }
298}
299