1 /***
2 * Subject.java
3 *
4 * This file is part of the creme library.
5 * The creme library intends to ease the development effort of large
6 * applications by providing easy to use support classes.
7 *
8 * Copyright (C) 2003 Denis Bregeon
9 *
10 * This library is free software; you can redistribute it and/or
11 * modify it under the terms of the GNU Lesser General Public
12 * License as published by the Free Software Foundation; either
13 * version 2.1 of the License, or (at your option) any later version.
14 *
15 * This library is distributed in the hope that it will be useful,
16 * but WITHOUT ANY WARRANTY; without even the implied warranty of
17 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
18 * Lesser General Public License for more details.
19 *
20 * You should have received a copy of the GNU Lesser General Public
21 * License along with this library; if not, write to the Free Software
22 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
23 *
24 * contact information: dbregeon@sourceforge.net
25 */
26 package org.jcreme.permissioning;
27
28 import java.util.Hashtable;
29 import java.util.Vector;
30
31 import org.jcreme.enumerations.Enumeration;
32
33 /***
34 *
35 * @author $Author: dbregeon $
36 * @version $Revision: 1.1 $
37 */
38 public abstract class Subject extends Enumeration {
39 protected static final Hashtable fromName = new Hashtable();
40
41 /***
42 * The leaf task that is solved by the Subject.
43 */
44 protected Task task = null;
45
46 /***
47 * The Domain to which the Subject belongs.
48 */
49 protected Domain domain = null;
50
51 protected Subject(String name) {
52 super(name);
53 }
54
55
56
57
58
59
60 protected Hashtable getFromName() {
61 return fromName;
62 }
63
64 public void setDomain(Domain d) {
65 this.domain = d;
66 }
67
68 public Domain getDomain() {
69 return this.domain;
70 }
71
72 public void setTask(Task t) throws IllegalArgumentException {
73 if ((t != null) && (!t.isLeaf())) {
74 throw new IllegalArgumentException("Task has to be a Leaf.");
75 }
76 this.task = t;
77 }
78
79 public static Subject[] getSubjects() {
80 return (Subject[]) fromName.values().toArray(new Subject[0]);
81 }
82
83 public static Enumeration[] getValues() {
84 return (Enumeration[]) fromName.values().toArray(new Enumeration[0]);
85 }
86
87 /***
88 * @param u
89 * @param t
90 * is set by the invocation path. It is otherwise impossible to
91 * determine a Task that will give a single meaningful business
92 * Purpose.
93 * @param parameters
94 * @param accessTypes
95 * @throws NoPermissionException
96 * @throws IllegalArgumentException
97 */
98 protected void checkParameters(User u, Task t, Object[] parameters,
99 AccessType[] accessTypes) throws NoPermissionException,
100 IllegalArgumentException {
101 if (u == null) {
102 throw new IllegalArgumentException("Null is not a valid User.");
103 }
104 if (t == null) {
105 throw new IllegalArgumentException("Null is not a valid Task.");
106 }
107 if ((parameters == null) || (accessTypes == null)
108 || (parameters.length != accessTypes.length)) {
109 throw new IllegalArgumentException(
110 "accessTyprs and parameters array are not of the same size or are null.");
111 }
112 if (!checkTask(t)) {
113 throw new NoPermissionException(
114 "Subject's Task is not a child of the invoking Task " + t);
115 }
116 if (!checkRoles(u, t)) {
117 throw new NoPermissionException("User " + u
118 + " has no Role to perform Task " + t);
119 }
120 PoliciedObject object = null;
121 for (int i = 0; i < parameters.length; i++) {
122 if (parameters[i] instanceof PoliciedObject) {
123 object = (PoliciedObject) parameters[i];
124 if (!checkAccess(object.getObjectType(), accessTypes[i])) {
125 throw new NoPermissionException("User " + u
126 + " has no permission to access data of type "
127 + object.getObjectType());
128 }
129 if (!checkPurpose(u, t, object.getObjectPolicy(),
130 accessTypes[i])) {
131 throw new NoPermissionException("Policy forbids user " + u
132 + " to access data.");
133 }
134 }
135 }
136 }
137
138 /***
139 * This method filters the provided parameters against the requested access
140 * and returns only the objects that can be rightfully accessed.
141 *
142 * @param u
143 * @param t
144 * @param parameters
145 * @param accessTypes
146 * @return
147 * @throws IllegalArgumentException
148 */
149 public Object[] filterObjects(User u, Task t, Object[] parameters,
150 AccessType[] accessTypes) throws IllegalArgumentException {
151 if (u == null) {
152 throw new IllegalArgumentException("Null is not a valid User.");
153 }
154 if (t == null) {
155 throw new IllegalArgumentException("Null is not a valid Task.");
156 }
157 if ((parameters == null) || (accessTypes == null)
158 || (parameters.length != accessTypes.length)) {
159 throw new IllegalArgumentException(
160 "accessTyprs and parameters array are not of the same size or are null.");
161 }
162 Vector result = new Vector();
163 PoliciedObject object = null;
164 for (int i = 0; i < parameters.length; i++) {
165 if (parameters[i] instanceof PoliciedObject) {
166 object = (PoliciedObject) parameters[i];
167 if ((checkAccess(object.getObjectType(), accessTypes[i]))
168 && (checkPurpose(u, t, object.getObjectPolicy(),
169 accessTypes[i]))) {
170 result.add(object);
171 }
172 }
173 }
174 return result.toArray();
175 }
176
177 /***
178 *
179 * @param u
180 * @param t
181 * @param parameters
182 * @param accessTypes
183 * @return
184 * @throws NoPermissionException
185 */
186 public boolean canInvoke(User u, Task t, Object[] parameters,
187 AccessType[] accessTypes) throws NoPermissionException {
188 boolean result = false;
189 try {
190 checkParameters(u, t, parameters, accessTypes);
191 result = true;
192 } catch (NoPermissionException e) {
193
194 } catch (IllegalArgumentException e) {
195
196 }
197 return result;
198 }
199
200 /***
201 * Checks if the user's roles are compatible with the invocation Task and
202 * the subject domain.
203 *
204 * @param u
205 * @param t
206 * @return
207 */
208 public boolean checkRoles(User u, Task t) {
209 boolean result = false;
210 Role[] roles = u.getRoles();
211 for (int i = 0; (!result) && (i < roles.length); i++) {
212 result = ((roles[i].hasTask(t)) && (roles[i].getDomain() == this.domain));
213 }
214 return result;
215 }
216
217 /***
218 * This method checks whether the invocation task is compatible with the
219 * subject's task.
220 *
221 * @param t
222 * is set by the invocation path. It is otherwise impossible to
223 * determine a Task that will give a single meaningful business
224 * Purpose.
225 * @return
226 */
227 public boolean checkTask(Task t) {
228 return (t != null) && (t.isSubTask(this.task));
229 }
230
231 /***
232 * This method is used to determine if the Subject can access a particular
233 * type.
234 *
235 * @param type
236 * @param access
237 */
238 public boolean checkAccess(ObjectType type, AccessType access) {
239 return (type != null) && (access != null)
240 && (type.canAccess(this.domain, access));
241 }
242
243 /***
244 * Checks if the calling task (business) purpose matches the subject task's
245 * purpose. Checks the ObjectPolicy for the given purpose and access. This
246 * method has to be used to check invocation parameters but also to filter
247 * out return values.
248 *
249 * @param user
250 * @param t
251 * @param policy
252 * @param access
253 * @return
254 */
255 public boolean checkPurpose(User user, Task t, ObjectPolicy policy,
256 AccessType access) {
257 return (user != null) && (t != null) && (policy != null)
258 && (access != null)
259 && (t.getPurpose().hasParent(this.task.getPurpose()))
260 && (policy.accessAuthorized(user, t.getPurpose(), access));
261 }
262
263 }