1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17 package org.apache.jetspeed.security;
18
19 import java.security.Permission;
20
21 /***
22 * <p>Folder permission.</p>
23 * <p>This code was partially inspired from:</p>
24 * <ul>
25 * <li>The article : <a href="http://www-106.ibm.com/developerworks/library/j-jaas/">
26 * Extend JAAS for class instance-level authorization.</a></li>
27 * <li>The FilePermission implementation from the JDK in order to support recursive permissions & wild card</li>
28 * </ul>
29 * <p/>
30 * This class represents access to a portal content/folder or document. A FolderPermission consists
31 * of a pathname and a set of actions valid for that pathname.
32 * <p/>
33 * Pathname is the pathname of the folder or document granted the specified
34 * actions. A pathname that ends in "/*" (where "/" is
35 * the separator character) indicates all the folders and documents contained in that folder.
36 * A pathname that ends with "/-" indicates (recursively) all documents
37 * and subfolders contained in that directory. A pathname consisting of
38 * the special token "<<ALL FILES>>" matches <b>any</b> folder or document.
39 * <p/>
40 *
41 * @author <a href="mailto:taylor@apache.org">David Sean Taylor</a>
42 * @author <a href="mailto:christophe.lombart@sword-technologies.com">Christophe Lombart</a>
43 * @version $Id: FolderPermission.java 516448 2007-03-09 16:25:47Z ate $
44 */
45 public class FolderPermission extends PortalResourcePermission
46 {
47 public static final char RECURSIVE_CHAR = '-';
48 public static final char WILD_CHAR = '*';
49 public static final String WILD_CHAR_STR = new String(new char[]{WILD_CHAR});
50 public static final char FOLDER_SEPARATOR = '/';
51 public static final String FOLDER_SEPARATOR_STR = new String(new char[]{FOLDER_SEPARATOR});
52
53
54 private boolean folder;
55
56
57 private boolean recursive;
58
59 private String cpath;
60
61 /***
62 * <p>Constructor for FolderPermission.</p>
63 *
64 * @param name The portlet name.
65 * @param actions The actions on the portlet.
66 */
67 public FolderPermission(String name, String actions)
68 {
69 super(name, actions);
70 parsePath();
71 }
72
73 /***
74 * <p>Constructor for FolderPermission.</p>
75 *
76 * @param name The portlet name.
77 * @param mask The mask of actions on the portlet.
78 */
79 public FolderPermission(String name, int mask)
80 {
81 super(name, mask);
82 parsePath();
83 }
84
85 /***
86 * <p>Parses the path.</p>
87 */
88 private void parsePath()
89 {
90 if ((cpath = getName()) == null)
91 throw new NullPointerException("name can't be null");
92
93 if (cpath.equals("<<ALL FILES>>"))
94 {
95 folder = true;
96 recursive = true;
97 cpath = "";
98 return;
99 }
100 int len = cpath.length();
101
102 if (len == 0)
103 {
104 throw new IllegalArgumentException("invalid folder reference");
105 }
106
107 char last = cpath.charAt(len - 1);
108
109 if (last == RECURSIVE_CHAR && (len == 1 || cpath.charAt(len - 2) == FOLDER_SEPARATOR))
110 {
111 folder = true;
112 recursive = true;
113 cpath = cpath.substring(0, --len);
114 }
115 else if (last == WILD_CHAR && (len == 1 || cpath.charAt(len - 2) == FOLDER_SEPARATOR))
116 {
117 folder = true;
118
119 cpath = cpath.substring(0, --len);
120 }
121 }
122
123 /***
124 * Checks if this FolderPermission object "implies" the specified permission.
125 * <p/>
126 * More specifically, this method returns true if:<p>
127 * <ul>
128 * <li> <i>p</i> is an instanceof FolderPermission,<p>
129 * <li> <i>p</i>'s actions are a proper subset of this
130 * object's actions, and <p>
131 * <li> <i>p</i>'s pathname is implied by this object's
132 * pathname. For example, "/tmp/*" implies "/tmp/foo", since
133 * "/tmp/*" encompasses the "/tmp" folder and all subfolders or documents in that
134 * directory, including the one named "foo".
135 * </ul>
136 *
137 * @param p the permission to check against.
138 * @return true if the specified permission is implied by this object,
139 * false if not.
140 */
141 public boolean implies(Permission p)
142 {
143 if (!(p instanceof FolderPermission))
144 {
145 return false;
146 }
147
148 FolderPermission that = (FolderPermission) p;
149 return ((this.mask & that.mask) == that.mask) && impliesIgnoreMask(that);
150 }
151
152 /***
153 * Checks if the Permission's actions are a proper subset of the
154 * this object's actions. Returns the effective mask iff the
155 * this FolderPermission's path also implies that FolderPermission's path.
156 *
157 * @param that the FolderPermission to check against.
158 * @return the effective mask
159 */
160 boolean impliesIgnoreMask(FolderPermission that)
161 {
162 if (this.folder)
163 {
164 if (this.recursive)
165 {
166
167
168 if (that.folder)
169 {
170 return (that.cpath.length() >= this.cpath.length()) && that.cpath.startsWith(this.cpath);
171 }
172 else
173 {
174 return ((that.cpath.length() >= this.cpath.length()) && that.cpath.startsWith(this.cpath));
175 }
176 }
177 else
178 {
179 if (that.folder)
180 {
181
182
183
184
185 if (that.recursive)
186 return false;
187 else
188 return (this.cpath.equals(that.cpath));
189 }
190 else
191 {
192 int last = that.cpath.lastIndexOf(FOLDER_SEPARATOR);
193 if (last == -1)
194 return false;
195 else
196 {
197
198
199
200 return (this.cpath.length() == (last + 1)) && this.cpath.regionMatches(0, that.cpath, 0, last + 1);
201 }
202 }
203 }
204 }
205 else
206 {
207 return (this.cpath.equals(that.cpath));
208 }
209 }
210
211 /***
212 * Checks two FolderPermission objects for equality. Checks that <i>obj</i> is
213 * a FolderPermission, and has the same pathname and actions as this object.
214 * <p/>
215 *
216 * @param obj the object we are testing for equality with this object.
217 * @return true if obj is a FolderPermission, and has the same pathname and
218 * actions as this FolderPermission object.
219 */
220 public boolean equals(Object obj)
221 {
222 if (obj == this)
223 return true;
224
225 if (!(obj instanceof FolderPermission))
226 return false;
227
228 FolderPermission that = (FolderPermission) obj;
229
230 return (this.mask == that.mask) && this.cpath.equals(that.cpath) && (this.folder == that.folder)
231 && (this.recursive == that.recursive);
232 }
233
234 /***
235 * Returns the hash code value for this object.
236 *
237 * @return a hash code value for this object.
238 */
239
240 public int hashCode()
241 {
242 return this.cpath.hashCode();
243 }
244
245
246 }