Source code: com/RuntimeCollective/permission/bean/SimplePermissible.java
1 /* $Header: /home/CVS/rjp/src/com/RuntimeCollective/permission/bean/SimplePermissible.java,v 1.15 2003/09/30 15:12:49 joe Exp $
2 * $Revision: 1.15 $
3 * $Date: 2003/09/30 15:12:49 $
4 *
5 * ====================================================================
6 *
7 * Josephine : http://www.runtime-collective.com/josephine/index.html
8 *
9 * Copyright (C) 2003 Runtime Collective
10 *
11 * This product includes software developed by the
12 * Apache Software Foundation (http://www.apache.org/).
13 *
14 * This library is free software; you can redistribute it and/or
15 * modify it under the terms of the GNU Lesser General Public
16 * License as published by the Free Software Foundation; either
17 * version 2.1 of the License, or (at your option) any later version.
18 *
19 * This library is distributed in the hope that it will be useful,
20 * but WITHOUT ANY WARRANTY; without even the implied warranty of
21 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
22 * Lesser General Public License for more details.
23 *
24 * You should have received a copy of the GNU Lesser General Public
25 * License along with this library; if not, write to the Free Software
26 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
27 *
28 */
29
30 package com.RuntimeCollective.permission.bean;
31
32 import com.RuntimeCollective.permission.PermissionException;
33 import com.RuntimeCollective.permission.bean.Permissible;
34 import com.RuntimeCollective.webapps.RuntimeDataSource;
35 import com.RuntimeCollective.webapps.RuntimeParameters;
36 import com.RuntimeCollective.webapps.bean.User;
37 import com.RuntimeCollective.webapps.bean.Session;
38 import com.RuntimeCollective.webapps.IndexedEntityBeanStore;
39 import com.RuntimeCollective.webapps.ReturnPathContainer;
40 import com.RuntimeCollective.webapps.HttpSessionReturnPathContainer;
41
42 import java.sql.SQLException;
43 import java.util.HashMap;
44 import java.util.Iterator;
45 import java.util.Vector;
46 import javax.servlet.http.HttpSession;
47
48 /**
49 * A simple implementation of Permissible.
50 *
51 * @version $Id: SimplePermissible.java,v 1.15 2003/09/30 15:12:49 joe Exp $
52 */
53 public class SimplePermissible implements Permissible {
54
55 // ---Inherited from EntityBean---------------------------
56
57 /** The name of the database table for this bean type. */
58 public static final String DATABASE_TABLE = "permission_permissible";
59 public static final String DATABASE_PRULEMAP_TABLE = "permission_perm_prule_map";
60
61 /** This object's id */
62 protected int id;
63
64 /** Set the unique id of this bean instance. */
65 public void setId(int id) {
66 this.id = id;
67 }
68
69 /** Get the unique id of this bean instance. */
70 public int getId() {
71 return id;
72 }
73
74 /** Save this bean to the database.
75 * <br>
76 * We assume this bean's PermissionRules have already been saved.
77 */
78 public void save() {
79
80 try {
81 // write Permissible data
82 RuntimeDataSource.save(id, DATABASE_TABLE, new String[] { }, new Object[] { } );
83
84 // write the Rule mappings
85 saveRules();
86
87 } catch (SQLException e) {
88 throw new PermissionException("SimplePermissible "+id+" could not save() : "+e);
89 }
90 }
91
92 /** Save the Rule mappings */
93 public void saveRules() throws SQLException {
94
95 // clear old PermissionRules mappings
96 RuntimeDataSource.update(new String[] { "delete from "+DATABASE_PRULEMAP_TABLE+" where permissible_id = "+id } );
97
98 // write PermissionRules mappings
99 // we assume the PermissionRules have already been saved
100 Vector updates = new Vector();
101 String[] updates_array;
102 Iterator actions = getActions();
103 String action;
104
105 while (actions.hasNext()) {
106 action = (String) actions.next();
107 updates.add((new StringBuffer(115)).append("insert into ").append(DATABASE_PRULEMAP_TABLE).append(" (permissible_id, action, prule_id) values (").append(id).append(" ,'").append(action).append("', ").append((Integer) PermissionRuleIds.get(action)).append(")").toString());
108 }
109
110 if (!updates.isEmpty()) {
111 updates_array = new String[updates.size()];
112 for (int i=0; i<updates.size(); i++)
113 updates_array[i] = (String) updates.get(i);
114 RuntimeDataSource.update(updates_array);
115 }
116 }
117
118
119
120 /** Delete this bean from the database. */
121 public void delete() {
122 try {
123 String[] updates = new String[] { "delete from "+DATABASE_PRULEMAP_TABLE+" where permissible_id = "+id, "delete from "+DATABASE_TABLE+" where id = "+id };
124 RuntimeDataSource.update(updates);
125
126 } catch (SQLException e) {
127 throw new PermissionException("SimplePermissible "+id+" could not delete() : "+e);
128 }
129 }
130
131 /** Construct a new blank SimplePermissible, giving it a new unique ID. */
132 public SimplePermissible() {
133 try {
134 setId(RuntimeDataSource.nextId());
135
136 } catch (SQLException e) {
137 throw new PermissionException("SimplePermissible could not SimplePermissible() : "+e);
138 }
139 }
140
141 /** Get a current SimplePermissible from the RuntimeDataSource, given an id.
142 * @param id ID of the SimplePermissible.
143 */
144 public SimplePermissible(int id) {
145
146 // it's a shame this has to be here, but there is no alternative apparently
147 // do we use the flat table?
148 try {
149 if ("true".equals(RuntimeParameters.get("siteNodeUseFlatTable")))
150 if (IndexedEntityBeanStore.checkClassExtendsOrImplementsAnother(getClass().getName(), "com.RuntimeCollective.sitemap.bean.SiteNode"))
151 return;
152 } catch (RuntimeException e) {
153 // param not set, constinue as normal
154 }
155
156 try {
157
158 // load the core Permissible data
159 int no_fields = 1;
160 Object[] result = RuntimeDataSource.queryRow("select t.id from "+DATABASE_TABLE+" t where t.id = "+id);
161 if (result.length != no_fields)
162 throw new PermissionException("SimplePermissible could not SimplePermissible("+id+"), : "+result.length+" fields found in "+DATABASE_TABLE+" instead of "+no_fields+".");
163 setId(Integer.parseInt(result[0].toString()));
164
165 // load the PermissionRule mappings
166 loadRules(id);
167
168 } catch (SQLException e) {
169 throw new PermissionException("SimplePermissible could not SimplePermissible("+id+") : "+e);
170 }
171 }
172
173 /** Load the rule mappings data */
174 public void loadRules(int id) throws SQLException {
175 Object[][] rows = RuntimeDataSource.queryRows("select action, prule_id from "+DATABASE_PRULEMAP_TABLE+" where permissible_id = "+id);
176 String action;
177 int prule_id;
178
179 for (int i=0; i<rows.length; i++) {
180 action = (String) rows[i][0];
181 prule_id = Integer.parseInt(rows[i][1].toString());
182 PermissionRuleIds.put(action, new Integer(prule_id));
183 }
184 }
185
186
187 // ---Inherited from PermissionBean---------------------------
188
189 /** Can a user "edit" this Bean. */
190 public boolean canEdit(User user) {
191 return canPerformAction(EDIT_ACTION, user);
192 }
193
194 /** Can a user "view" this Bean. */
195 public boolean canView(User user) {
196 return canPerformAction(VIEW_ACTION, user);
197 }
198
199 //---Permissible specific methods---------------------
200
201 /** The PermissionRules for each action */
202 protected HashMap PermissionRuleIds = new HashMap();
203
204 /**
205 * Set the PermissionRule for a given action on this Bean.
206 * @param action, the action to constrain
207 * @param permissionRule, the rule to use for this action
208 */
209 public void setActionPermissionRule(String action, PermissionRule permissionRule) {
210 if ((action != null) && (!action.equals(""))) {
211 if (permissionRule != null)
212 PermissionRuleIds.put(action, new Integer(permissionRule.getId()));
213 else if (permissionRule == null)
214 PermissionRuleIds.remove(action);
215 }
216 }
217
218 /**
219 * Get the PermissionRule for a given action on this Bean.
220 * @param action, the action
221 * @return the permissionRule currently in use for the action
222 */
223 public PermissionRule getActionPermissionRule(String action) {
224 Integer ruleId = (Integer) PermissionRuleIds.get(action);
225 if (ruleId != null) {
226 try {
227 return (PermissionRule) RuntimeParameters.getStore().get("com.RuntimeCollective.permission.bean.PermissionRule", ruleId.intValue());
228 } catch (RuntimeException e) {
229 throw new PermissionException("SimplePermissible "+id+" could not getActionPermissionRule("+action+") : "+e);
230 }
231 } else
232 return null;
233 }
234
235 /** Remove any PermissionRules for a given action on this Bean.
236 * @param action the action
237 */
238 public void removeActionPermissionRule(String action) {
239 if ( (action != null) && (!action.equals("")) )
240 PermissionRuleIds.remove( action );
241 }
242
243
244
245 /**
246 * Can a given User perform a given action on that Bean?
247 * @param action, the action to be performed
248 * @param user, the user who is trying to perform the action
249 * @return a boolean, yes the user can perform the action, or no
250 */
251 public boolean canPerformAction(String action, User user) {
252 PermissionRule rule = getActionPermissionRule(action);
253 if (rule != null)
254 return rule.accepts(user);
255 else
256 return false;
257 }
258
259 /**
260 * Get the path of the page where the Session should be sent in order
261 * to (maybe) get authorised for an action.
262 * Also sets required attributes in the Session.
263 * <p>
264 * On submission of that page, the Session should be checked again,
265 * as there may be more than one page to go to.
266 *
267 * @deprecated This method was modified not to refer to Client Tier classes (HttpSession). Use instead:
268 * <code>getAuthorisationPathForAction(action, (User) session.getAttribute(RuntimeParameters.get("logonUserKey")), (Session) session.getAttribute(Session.SESSION_KEY), new HttpSessionReturnPathContainer(session), returnPath)</code>
269 * @param action, the action
270 * @param session, the session who would like to be authorised
271 * @param returnPath, where the session should be sent back after going to that page
272 * @return a String, the local path to go to, or null if the session is accepted
273 */
274 public String getAuthorisationPathForAction(String action, HttpSession session, String returnPath) {
275 Object sessionUser = session.getAttribute(RuntimeParameters.get("logonUserKey"));
276 if (sessionUser != null) {
277 sessionUser = RuntimeParameters.getStore().get(User.class.getName(), ((User)sessionUser).getId());
278 }
279 return getAuthorisationPathForAction(action, (User)sessionUser, (Session) session.getAttribute(Session.SESSION_KEY), new HttpSessionReturnPathContainer(session), returnPath);
280 }
281
282 /**
283 * Get the path of the page where a User should be sent in order
284 * to (maybe) get authorised for an action.
285 * <p>
286 * On submission of that resulting page, the user should be checked again,
287 * as there may be more than one page to go to before he/she is authorised.
288 * @param action, the action
289 * @param user, the user, possibly null if the user hasn't been identified
290 * @param session, the general purpose webapps session that the user is using ATM, possibly null
291 * @param rpContainer, something on which to put the return path, if necessaru
292 * @param returnPath, where the user should be sent back after going to that page
293 * @return a String, the local path to go to, or null if the session is accepted
294 */
295 public String getAuthorisationPathForAction(String action, User user, Session session, ReturnPathContainer rpContainer, String returnPath) {
296
297 PermissionRule rule = getActionPermissionRule(action);
298
299 if (rule != null)
300 return rule.getAuthorisationPath(user, session, rpContainer, returnPath);
301 else
302 // by default we let people in - so watch out those actions typo
303 // (necessary to give people access to pages which don't have any PR set up)
304 return null;
305 }
306
307 /**
308 * Get an Iterator of the actions constrained until now.
309 * @return an Iterator of Strings
310 */
311 public Iterator getActions() {
312 return PermissionRuleIds.keySet().iterator();
313 }
314 }
315
316
317
318