KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > org > jahia > services > acl > JahiaACL


1 //
2
// ____.
3
// __/\ ______| |__/\. _______
4
// __ .____| | \ | +----+ \
5
// _______| /--| | | - \ _ | : - \_________
6
// \\______: :---| : : | : | \________>
7
// |__\---\_____________:______: :____|____:_____\
8
// /_____|
9
//
10
// . . . i n j a h i a w e t r u s t . . .
11
//
12
//
13
// 18.04.2001 NK Added group in group support
14
// 18.04.2001 NK Added Multi site support
15

16
17 package org.jahia.services.acl;
18
19 import org.apache.log4j.Logger;
20 import org.jahia.exceptions.JahiaException;
21 import org.jahia.exceptions.database.JahiaDatabaseException;
22 import org.jahia.registries.ServicesRegistry;
23 import org.jahia.services.usermanager.JahiaGroup;
24 import org.jahia.services.usermanager.JahiaGroupManagerService;
25 import org.jahia.services.usermanager.JahiaUser;
26
27 import java.io.Serializable JavaDoc;
28 import java.security.Principal JavaDoc;
29 import java.security.acl.Group JavaDoc;
30 import java.util.Enumeration JavaDoc;
31 import java.util.HashMap JavaDoc;
32 import java.util.Hashtable JavaDoc;
33 import java.util.Iterator JavaDoc;
34 import java.util.Map JavaDoc;
35 import java.util.Vector JavaDoc;
36 import org.jahia.params.ParamBean;
37 import org.jahia.bin.Jahia;
38
39
40 /**
41  * This class is private, not visible. It's only an internal class. To use the
42  * standard ACLs for Jahia content, look at JahiaBaseACL.
43  *
44  * @author Khue NGuyen
45  * @author Serge Huber
46  * @author David Jilli
47  * @author Fulco Houkes
48  * @author MAP
49  * @version 1.1 (Inheritance cut and misc cleaning)
50  */

51 class JahiaACL implements ACLInfo, Serializable JavaDoc, ParentACLFinder, ACLResourceInterface {
52     private static final long serialVersionUID = 1L;
53     
54     private static Logger logger = Logger.getLogger (JahiaACL.class);
55
56     /** This is the termination ACL ID constant. */
57     public static final int TERMINATION_ACL_ID = 0;
58
59     /** ACL unique identification number */
60     private int mID;
61
62     /** ACL parent unique identification number */
63     private int mParentID = 0; // Hollis to Foux in case there is no parent shoud the id -1 or 0 ?
64

65     /** ACL inheritance flag; 0 : inherit, 1 : no inheritance */
66     private int mInheritance;
67
68     /**
69      * User permissions entries
70      *
71      * @associates JahiaACLEntry
72      */

73     private Hashtable JavaDoc mUserEntries;
74
75     /**
76      * Group permissions entries
77      *
78      * @associates JahiaACLEntry
79      */

80     private Hashtable JavaDoc mGroupEntries;
81
82     /**
83      * Constructor
84      *
85      * @param id ACL unique identification number.
86      * @param parentID Reference to the parentACL. Can be null if there is no
87      * parent available.
88      * @param inheritance The inheritance flag (NO_INHERITANCE, INHERITANCE)
89      */

90     protected JahiaACL (int id, int parentID, int inheritance) {
91         mID = id;
92         mInheritance = inheritance;
93         mParentID = parentID;
94         mUserEntries = new Hashtable JavaDoc ();
95         mGroupEntries = new Hashtable JavaDoc ();
96     }
97
98     /**
99      * Return the ACL's unique identification number
100      *
101      * @return Return an int representing the ACL's unique identification number.
102      */

103     public final int getID () {
104         return mID;
105     }
106
107     /**
108      * Return the ACL's parent ACL ID.
109      *
110      * @return Return the parent's ACL ID.
111      */

112     public final int getParentID () {
113         return mParentID;
114     }
115
116     /**
117      * Get the inheritance flag from the ACL
118      *
119      * @return the ACL inheritance status.
120      */

121     public final int getInheritance () {
122         return mInheritance;
123     }
124
125     /**
126      * Set the inheritance flag to the ACL and update cache
127      *
128      * @param inheritance The inheritance flag (INHERITANCE, NO_INHERITANCE).
129      *
130      * @return true if inheritance flag set correctly.
131      */

132     public final boolean setInheritance (int inheritance) {
133         mInheritance = inheritance;
134         try {
135             return AclDBUtils.getInstance ().updateACL (this);
136         } catch (JahiaDatabaseException ex) {
137             return false;
138         }
139     }
140
141     /**
142      * This method is the implementation of the ParentACLFinder interface,
143      * and this will be the default mechanism for parent lookup when no other
144      * is specified.
145      * Return the parent ACL reference.
146      *
147      * @param aclResource the object containing an ACL for which we want to
148      * find the parent.
149      * @return Return the parent ACL reference.
150      */

151     public ACLResourceInterface getParent(ACLResourceInterface aclResource) {
152         JahiaACL acl = getInternalACL(aclResource);
153         JahiaACL mParentACL;
154         // we haven't tried yet to load the ACL from persistant storage,
155
// let's try that now.
156
if (acl.getParentID() <= 0) {
157             // we are in the case of a root ACL, let's signal the fact that
158
// there is no parent...
159
return null;
160         }
161
162         if (acl.getParentID() == getID()) {
163             // can this happen ?
164
logger.warn("Parent ID of ACL is the same as the current ID (" +
165                         getID() + ")! Probable recursive loop");
166             return this;
167         }
168
169         try {
170             mParentACL =
171                 ServicesRegistry.getInstance().getJahiaACLManagerService().
172                 lookupACL(
173                     acl.getParentID());
174             return mParentACL;
175         } catch (JahiaException je) {
176             logger.debug("Parent ACL not found in persistant storage", je);
177             mParentACL = null;
178             return mParentACL;
179         }
180     }
181
182     /**
183      * Get the current user permissions. If the user has no entry in the ACL
184      * getUserEntry returns null.
185      *
186      * @param user Reference to the user object
187      *
188      * @return Return the requested acl entry, null if it doesn't exist.
189      */

190     public JahiaACLEntry getUserEntry (JahiaUser user) {
191         if (user != null) {
192             return (JahiaACLEntry) mUserEntries.get (user.getName ());
193         }
194         return null;
195     }
196
197     /**
198      * Set the new user permissions. If the user already has an entry in the
199      * ACL, the old permissions are overriden. If the user has no entry, the
200      * specified persmission are added as is.
201      *
202      * @param user Reference to the user object
203      * @param entry Reference to the ACL entry.
204      *
205      * @return Return true on success, or false on any failure.
206      */

207     public synchronized boolean setUserEntry (JahiaUser user, JahiaACLEntry entry) {
208         if ((user == null) || (entry == null)) {
209             return false;
210         }
211
212         boolean result;
213         JahiaACLEntry currentEntry =
214                 (JahiaACLEntry) mUserEntries.get (user.getName ());
215
216         try {
217             if (currentEntry == null) {
218                 result = AclDBUtils.getInstance ().addACLEntry (mID, USER_TYPE_ENTRY,
219                         user.getName (), entry.getState (), entry.getTriState ());
220             } else {
221                 result = AclDBUtils.getInstance ().updateACLEntry (mID, USER_TYPE_ENTRY,
222                         user.getName (), entry.getState (), entry.getTriState ());
223             }
224         } catch (JahiaDatabaseException ex) {
225             return false;
226         }
227
228         if (result) {
229             mUserEntries.put (user.getName (), entry);
230         }
231         return result;
232     }
233
234     /**
235      * Set the current ACL user entries.
236      *
237      * @param userEntries The user entries hash table.
238      */

239     public void setUserEntries (Hashtable JavaDoc userEntries) {
240         mUserEntries = userEntries;
241     }
242
243     /**
244      * Remove the ACL entry associated with the specified user.
245      *
246      * @param user The user reference.
247      *
248      * @return Return <code>true</code> if the user entry could be removed
249      * successfully from the ACL.
250      */

251     public synchronized boolean removeUserEntry (JahiaUser user) {
252         boolean result = false;
253         if (user != null) {
254             try {
255                 result = AclDBUtils.getInstance ().removeACLEntry (mID, USER_TYPE_ENTRY,
256                         user.getName ());
257                 if (result) {
258                     mUserEntries.remove (user.getName ());
259                     return true;
260                 }
261             } catch (JahiaDatabaseException ex) {
262             }
263         }
264         return result;
265     }
266
267     /**
268      * Remove all the group type entries from the ACL
269      *
270      * @param type User or group given by ACLInfo : USER_TYPE_ENTRY,
271      * GROUP_TYPE_ENTRY, ...
272      *
273      * @return Return true on success or false on any failure.
274      */

275     protected synchronized boolean clearEntries (int type) {
276         boolean result = false;
277         try {
278             result = AclDBUtils.getInstance ().removeACLEntries (mID, type);
279             if (result) {
280                 if (type == USER_TYPE_ENTRY) {
281                     mUserEntries.clear();
282                 } else if (type == GROUP_TYPE_ENTRY) {
283                     mGroupEntries.clear();
284                 }
285             }
286         } catch (JahiaDatabaseException ex) {
287         }
288
289         return result;
290     }
291
292     /**
293      * Return all the user names present in the ACL object having the same
294      * rights as specified.
295      *
296      * @param parentACLFinder an implementation of the parent ACL finder
297      * interface that allows finding of the parent object for the object
298      * passed as the aclResource parameter.
299      * @param aclResource the object on which we are working on, to be passed
300      * to the parent ACL finder implementation when looking for it's parent.
301      * @param entry Access rights bits map. Set this parameter to null to get
302      * all the user names regarding their access rights.
303      *
304      * @return Return a Vector holding all the String representation of the
305      * users' usernames. The returned Vector is never null, but if no
306      * user is present in the ACL, it will be empty.
307      */

308     public Vector JavaDoc getUsernameList (ParentACLFinder parentACLFinder, ACLResourceInterface aclResource, JahiaACLEntry entry) {
309         Map JavaDoc map = new HashMap JavaDoc(mUserEntries.size());
310         recursePermissions (parentACLFinder, aclResource, map, null);
311         return getNameList (map, entry);
312     }
313
314     /**
315      * Same as the other getUsernameList method except that it uses the
316      * current ACL as ParentACLFinder implementation and as the ACLResource
317      * @see #getUsernameList(ParentACLFinder, ACLResourceInterface, JahiaACLEntry)
318      *
319      * @param entry Access rights bits map. Set this parameter to null to get
320      * all the user names regarding their access rights.
321      *
322      * @return Return a Vector holding all the String representation of the
323      * users' usernames. The returned Vector is never null, but if no
324      * user is present in the ACL, it will be empty.
325      */

326     public Vector JavaDoc getUsernameList (JahiaACLEntry entry) {
327         return getUsernameList(this, this, entry);
328     }
329
330     /**
331      * Return all the user names present in the ACL object having the same
332      * rights as specified, including users members of groups having the same
333      * rights as specified.
334      *
335      * @param parentACLFinder an implementation of the parent ACL finder
336      * interface that allows finding of the parent object for the object
337      * passed as the aclResource parameter.
338      * @param aclResource the object on which we are working on, to be passed
339      * to the parent ACL finder implementation when looking for it's parent.
340      * @param entry Access rights bits map. Set this parameter to null to get all the
341      * user names regarding their access rights. Only one bit of the entry
342      * should be set to ACL_YES!
343      *
344      * @return Return a Vector holding all the String representation of the users'
345      * usernames. The returned Vector is never null, but if no user is
346      * present in the ACL, it will be empty.
347      */

348     public Vector JavaDoc getUsernameListAlsoGroupUsers (ParentACLFinder parentACLFinder, ACLResourceInterface aclResource, JahiaACLEntry entry) {
349         Hashtable JavaDoc userTable = new Hashtable JavaDoc (mUserEntries.size());
350         Hashtable JavaDoc groupTable = new Hashtable JavaDoc (mGroupEntries.size());
351         recursePermissions (parentACLFinder, aclResource, userTable, groupTable);
352
353         Vector JavaDoc result = getNameList (userTable, entry);
354         for (int k = 0; k < result.size (); k++) {
355             logger.debug ("Name=" + (String JavaDoc) result.get (k));
356             ACLResourceInterface parent = getParent(aclResource);
357             if (parent != null && parent.getACL() != null) {
358                 JahiaUser user = ServicesRegistry
359                         .getInstance ()
360                         .getJahiaUserManagerService ()
361                         .lookupUser ((String JavaDoc) result.get (k));
362                 JahiaACLEntry parentEntry = getInternalACL(parent).getUserEntry (user);
363                 if (parentEntry != null) {
364                     logger.debug ("parentAclEntry=" + parentEntry.toString ());
365                 }
366             }
367
368         }
369         Vector JavaDoc groupList = getNameList (groupTable, entry);
370
371         userTable = null;
372         groupTable = null;
373
374         // add in the result all users from every group that also have this
375
// access except for users that have excplicitely a NO access
376
for (int i = 0; i < groupList.size (); i++) {
377             String JavaDoc groupname = (String JavaDoc) groupList.elementAt (i);
378             JahiaGroup group = ServicesRegistry.getInstance ().
379                                getJahiaGroupManagerService ().lookupGroup (groupname);
380             if (group == null) {
381                 logger.warn("Group " + groupname + " not found in manager service but present in ACL " + getID());
382                 continue;
383             }
384             Enumeration JavaDoc membersEnum = group.members ();
385
386             if (membersEnum != null) {
387
388                 Principal JavaDoc p = null;
389
390                 while (membersEnum.hasMoreElements ()) {
391
392                     p = (Principal JavaDoc) membersEnum.nextElement ();
393                     if (!(p instanceof Group)) {
394
395                         JahiaUser user = (JahiaUser) p;
396                         if ((user != null) && (!result.contains (user.getName ()))) {
397
398                             // check if the user has access for this permission!
399

400
401                             if (entry == null) {
402                                 result.add (user.getName ());
403                             } else {
404                                 /**
405                                  * @todo FIXME
406                                  * What the hell are you doing here Dada's ??
407                                  * -Fulco-
408                                  */

409
410                                 // the user has the right for this permission ?
411
int permBit = -1;
412                                 for (int j = 0; j < 3; j++) {
413                                     if (entry.getPermission (j) ==
414                                             JahiaACLEntry.ACL_YES) {
415                                         permBit = j;
416                                     }
417                                 }
418                                 if ((permBit != -1) &&
419                                         (this.getPermission (parentACLFinder, aclResource, user, permBit))) {
420                                     result.add (user.getName ());
421                                 }
422                             }
423                         }
424                         user = null;
425                     }
426                 }
427                 p = null;
428             }
429             groupname = null;
430             group = null;
431             membersEnum = null;
432         }
433         return result;
434     }
435
436     /**
437      * Same as the other getUsernameListAlsoGroupUsers method except that it uses the
438      * current ACL as ParentACLFinder implementation and as the ACLResource
439      * @see #getUsernameListAlsoGroupUsers(ParentACLFinder, ACLResourceInterface, JahiaACLEntry)
440      *
441      * @param entry Access rights bits map. Set this parameter to null to get all the
442      * user names regarding their access rights. Only one bit of the entry
443      * should be set to ACL_YES!
444      *
445      * @return Return a Vector holding all the String representation of the users'
446      * usernames. The returned Vector is never null, but if no user is
447      * present in the ACL, it will be empty.
448      */

449     public Vector JavaDoc getUsernameListAlsoGroupUsers (JahiaACLEntry entry) {
450         return getUsernameListAlsoGroupUsers(this, this, entry);
451     }
452
453     /**
454      * Get the current group permissions. If the group has no entry in the ACL
455      * getGroupEntry returns null.
456      *
457      * @param group Reference to the group object
458      *
459      * @return Return the requested acl entry, null if it doesn't exist.
460      */

461     public JahiaACLEntry getGroupEntry (JahiaGroup group) {
462         if (group != null) {
463             return (JahiaACLEntry) mGroupEntries.get (group.getName ());
464         }
465         return null;
466     }
467
468     /**
469      * Set the new group permissions. If the group already has an entry in the
470      * ACL, the old permissions are overriden. If the group has no entry, the
471      * specified persmission are added as is.
472      *
473      * @param group Reference to the group object
474      * @param entry Reference to the ACL entry.
475      *
476      * @return Return true on success, or false on any failure.
477      */

478     public synchronized boolean setGroupEntry (JahiaGroup group, JahiaACLEntry entry) {
479         if ((group == null) || (entry == null)) {
480             return false;
481         }
482
483         boolean result;
484         JahiaACLEntry tmp = (JahiaACLEntry) mGroupEntries.get (group.getName ());
485
486         try {
487             if (tmp == null) {
488                 result = AclDBUtils.getInstance ().addACLEntry (mID, GROUP_TYPE_ENTRY,
489                         group.getName (), entry.getState (), entry.getTriState ());
490             } else {
491                 result = AclDBUtils.getInstance ().updateACLEntry (mID, GROUP_TYPE_ENTRY,
492                         group.getName (), entry.getState (), entry.getTriState ());
493             }
494         } catch (JahiaDatabaseException ex) {
495             logger.error("Error while setting ACL entry for group " + group.getGroupKey(), ex);
496             result = false;
497             tmp = null;
498         }
499         tmp = null;
500
501         if (result) {
502             mGroupEntries.put (group.getName (), entry);
503         }
504
505         return result;
506     }
507
508     /**
509      * Set the current ACL group entries.
510      *
511      * @param groupEntries The group entries hash table.
512      */

513     public void setGroupEntries (Hashtable JavaDoc groupEntries) {
514         mGroupEntries = groupEntries;
515     }
516
517     /**
518      * Remove the specified group from the ACL entry.
519      *
520      * @param group The group to remove.
521      *
522      * @return true if group removed successfully.
523      */

524     public synchronized boolean removeGroupEntry (JahiaGroup group) {
525         if (group == null) {
526             return false;
527         }
528
529         try {
530             if (AclDBUtils.getInstance ().removeACLEntry (mID, GROUP_TYPE_ENTRY, group.getName ())) {
531                 mGroupEntries.remove (group.getName ());
532                 return true;
533             }
534         } catch (JahiaDatabaseException ex) {
535         }
536
537         return false;
538     }
539
540     /**
541      * Return all the group names present in the ACL object having the same
542      * rights as specified, but not the Administrator group
543      *
544      * @param parentACLFinder an implementation of the parent ACL finder
545      * interface that allows finding of the parent object for the object
546      * passed as the aclResource parameter.
547      * @param aclResource the object on which we are working on, to be passed
548      * to the parent ACL finder implementation when looking for it's parent.
549      * @param entry Access rights bits map. Set this parameter to null to get all the
550      * group names regarding their access rights.
551      *
552      * @return Return a Vector holding all the String representation of the
553      * groupnames. The returned Vector is never null, but if no group is
554      * present in the ACL, it will be empty.
555      */

556     public Vector JavaDoc getGroupnameListNoAdmin (ParentACLFinder parentACLFinder, ACLResourceInterface aclResource, JahiaACLEntry entry) {
557         Vector JavaDoc result = getGroupnameList (parentACLFinder, aclResource, entry);
558         for (int i = 0; i < result.size (); i++) {
559             String JavaDoc adminGroup = (String JavaDoc) result.elementAt (i);
560             if (adminGroup.indexOf (JahiaGroupManagerService.ADMINISTRATORS_GROUPNAME) == 0)
561                 result.removeElementAt (i--);
562         }
563         return result;
564     }
565
566     /**
567      * Same as the other getGroupnameListNoAdmin method except that it uses the
568      * current ACL as ParentACLFinder implementation and as the ACLResource
569      * @see #getGroupnameListNoAdmin(ParentACLFinder, ACLResourceInterface, JahiaACLEntry)
570      *
571      * @param entry Access rights bits map. Set this parameter to null to get all the
572      * group names regarding their access rights.
573      *
574      * @return Return a Vector holding all the String representation of the
575      * groupnames. The returned Vector is never null, but if no group is
576      * present in the ACL, it will be empty.
577      */

578     public Vector JavaDoc getGroupnameListNoAdmin (JahiaACLEntry entry) {
579         return getGroupnameListNoAdmin(this, this, entry);
580     }
581
582     /**
583      * Return all the group names present in the ACL object having the same
584      * rights as specified.
585      *
586      * @param parentACLFinder an implementation of the parent ACL finder
587      * interface that allows finding of the parent object for the object
588      * passed as the aclResource parameter.
589      * @param aclResource the object on which we are working on, to be passed
590      * to the parent ACL finder implementation when looking for it's parent.
591      * @param entry Access rights bits map. Set this parameter to null to get all the
592      * group names regarding their access rights.
593      *
594      * @return Return a Vector holding all the String representation of the
595      * groups' usernames. The returned Vector is never null, but if no
596      * group is present in the ACL, it will be empty.
597      */

598     public Vector JavaDoc getGroupnameList (ParentACLFinder parentACLFinder, ACLResourceInterface aclResource, JahiaACLEntry entry) {
599         Map JavaDoc table = new HashMap JavaDoc(mGroupEntries.size());
600         recursePermissions (parentACLFinder, aclResource, null, table);
601         Vector JavaDoc result = getNameList (table, entry);
602         table = null;
603         return result;
604     }
605
606     /**
607      * Same as the other getGroupNameList method except that it uses the
608      * current ACL as ParentACLFinder implementation and as the ACLResource
609      * @see #getGroupnameList(ParentACLFinder, ACLResourceInterface, JahiaACLEntry)
610      * @param entry Access rights bits map. Set this parameter to null to get all the
611      * group names regarding their access rights.
612      * @return Return a Vector holding all the String representation of the
613      * groups' usernames. The returned Vector is never null, but if no
614      * group is present in the ACL, it will be empty.
615      */

616     public Vector JavaDoc getGroupnameList (JahiaACLEntry entry) {
617         return getGroupnameList(this, this, entry);
618     }
619
620     /**
621      * Check the permission of a given group recursively from the acl tree.
622      *
623      * @param parentACLFinder an implementation of the parent ACL finder
624      * interface that allows finding of the parent object for the object
625      * passed as the aclResource parameter.
626      * @param aclResource the object on which we are working on, to be passed
627      * to the parent ACL finder implementation when looking for it's parent.
628      * @param group Reference to a non-null group object.
629      * @param permission Bit index of the requested access, this index should be defined as
630      * a constant in the derived classes.
631      *
632      * @return True if the specified group has the requested rights in the ACL,
633      * or in one of the parent's ACLs.
634      */

635     public boolean getPermission (ParentACLFinder parentACLFinder, ACLResourceInterface aclResource, JahiaGroup group, int permission) {
636         boolean result = false;
637
638         if (group != null) {
639             Map JavaDoc map = new HashMap JavaDoc(mGroupEntries.size());
640             recursePermissions (parentACLFinder, aclResource, null, map);
641             JahiaACLEntry entry = (JahiaACLEntry) map.get (group.getName ());
642             if (entry != null) {
643                 result = (entry.getPermission (permission) ==
644                         JahiaACLEntry.ACL_YES);
645             }
646             map = null;
647             entry = null;
648         }
649         if (logger.isDebugEnabled()) {
650             logger.debug("JahiaACL{" + mID + ", " + mParentID + ", "
651                     + mInheritance + "}.getPermission("
652                     + (group != null ? group.getGroupKey() : null) + ", "
653                     + permission + "):" + result);
654         }
655         return result;
656     }
657
658     /**
659      * Same as the other getPermission method except that it uses the
660      * current ACL as ParentACLFinder implementation and as the ACLResource
661      * @see #getPermission(ParentACLFinder, ACLResourceInterface, JahiaGroup, int)
662      *
663      * @param group Reference to a non-null group object.
664      * @param permission Bit index of the requested access, this index should be defined as
665      * a constant in the derived classes.
666      *
667      * @return True if the specified group has the requested rights in the ACL,
668      * or in one of the parent's ACLs.
669      */

670     public boolean getPermission (JahiaGroup group, int permission) {
671         return getPermission(this, this, group, permission);
672     }
673
674     /**
675      * Check the permission of a given user recursively from the acl tree.
676      *
677      * @param parentACLFinder an implementation of the parent ACL finder
678      * interface that allows finding of the parent object for the object
679      * passed as the aclResource parameter.
680      * @param aclResource the object on which we are working on, to be passed
681      * to the parent ACL finder implementation when looking for it's parent.
682      * @param user Reference to a non-null user object.
683      * @param permission Bit index of the requested access, this index should be defined as
684      * a constant in the derived classes.
685      *
686      * @return True if the specified user has the requested rights in the ACL,
687      * or in one of the parent's ACLs.
688      *
689      */

690     public boolean getPermission (ParentACLFinder parentACLFinder, ACLResourceInterface aclResource, JahiaUser user, int permission) {
691         int result = -1;
692
693         if (user == null) {
694             return false;
695         }
696
697         try {
698
699             // First check if the user is member of the administrators group.
700
// if it's the case, then give the user all the rights.
701

702             /**
703              * @todo FIXME_MULTISITE Hollis , the administrator grp is deducted
704              * from user.getSiteID() problem here ? This is clearly a serious
705              * problem, as it means that administrators from ANY site have full
706              * access to all Jahia content ! Actually the siteID should come
707              * from the content object. Maybe with the new modifications that
708              * pass the ACLResourceInterface we could use reflection to try
709              * to retrieve the siteID from the content object.
710              **/

711             ParamBean paramBean = Jahia.getThreadParamBean();
712             JahiaGroup adminGroup = null;
713             int contextSiteID = -1;
714             if (paramBean != null) {
715                 contextSiteID = paramBean.getSiteID();
716             } else {
717                 logger.debug("Warning, no ParamBean found in thread context, using user siteID to resolve administrator group lookup ! Possible false permissions !");
718                 contextSiteID = user.getSiteID();
719             }
720
721             if (contextSiteID != -1) {
722                 adminGroup = ServicesRegistry.getInstance()
723                              .getJahiaGroupManagerService().getAdministratorGroup(
724                     contextSiteID);
725                 if (adminGroup != null) {
726                     if (adminGroup.isMember(user)) {
727                         result = 1;
728                     }
729                 }
730             } else {
731                 logger.warn("User comes from LDAP, so we can test it's apartanence to the administrators group when we have no site ID");
732             }
733             //logger.debug("step1 result=" + result);
734

735             if (result == -1) {
736                 adminGroup = null;
737
738                 // Compute recursively the user and group permission according to
739
// the ACL entries flags.
740
Map JavaDoc userMap = new HashMap JavaDoc(mUserEntries.size());
741                 Map JavaDoc groupMap = new HashMap JavaDoc(mGroupEntries.size());
742                 recursePermissions (parentACLFinder, aclResource, userMap, groupMap);
743
744
745                 // Check if the user is explicitely mentioned in the ACL, look up
746
// recursively the user in the tree.
747
result = getUserPermissionInMap (user, permission, userMap);
748
749                 //logger.debug("step2 result=" + result);
750

751                 if (result == -1) {
752                     // seems the user has not been found directly in the ACL tree,
753
// check now if the user is member of one of the specified group
754
// in the ACL.
755
result = getUserPermissionInGroupMap (user, permission,
756                             groupMap);
757                 }
758                 //logger.debug("step3 result=" + result);
759
}
760         } catch (NullPointerException JavaDoc ex) {
761             result = 0;
762         }
763
764         if (logger.isDebugEnabled()) {
765             logger.debug("JahiaACL{" + mID + ", " + mParentID + ", "
766                     + mInheritance + "}.getPermission("
767                     + (user != null ? user.getUserKey() : null) + ", "
768                     + permission + "): " + (result == 1));
769         }
770
771         // return true only if one of the groups in the ACL tree has the
772
// requested permission and if the user is member of this group.
773
return (result == 1);
774     }
775
776     /**
777      * Same as the other getPermission method except that it uses the
778      * current ACL as ParentACLFinder implementation and as the ACLResource
779      * @see #getPermission(ParentACLFinder, ACLResourceInterface, JahiaUser, int)
780      *
781      * @param user Reference to a non-null user object.
782      * @param permission Bit index of the requested access, this index should be defined as
783      * a constant in the derived classes.
784      *
785      * @return True if the specified user has the requested rights in the ACL,
786      * or in one of the parent's ACLs.
787      */

788     public boolean getPermission (JahiaUser user, int permission) {
789         return getPermission(this, this, user, permission);
790     }
791
792     /**
793      * Convert the actual ACL object to String containing all neccessary information
794      * to verify the integrity.
795      *
796      * @return The String to display
797      */

798     public String JavaDoc toString () {
799         StringBuffer JavaDoc buffer = new StringBuffer JavaDoc ();
800         String JavaDoc key = null;
801         JahiaACLEntry entry = null;
802
803         buffer.append ("\n");
804         buffer.append ("Detail of ACL object [");
805         buffer.append (Integer.toString (mID));
806         buffer.append ("] :\n");
807         buffer.append (" -ACL parent ID = ");
808
809         if ((getParent(this) != null) &&
810             (getParent(this).getACL() != null)) {
811             buffer.append (Integer.toString (mParentID));
812         } else {
813             buffer.append ("-no parent-");
814         }
815         buffer.append ("\n");
816         buffer.append (" -ACL inheritance = ");
817         buffer.append (Integer.toString (mInheritance));
818
819         buffer.append ("\n\n");
820
821         // get the user accesses
822
buffer.append (" -Local user access : ");
823         Enumeration JavaDoc usernames = mUserEntries.keys ();
824         if (usernames.hasMoreElements ()) {
825             buffer.append ("\n");
826             while (usernames.hasMoreElements ()) {
827                 key = (String JavaDoc) usernames.nextElement ();
828                 entry = (JahiaACLEntry) mUserEntries.get (key);
829                 int state = entry.getState ();
830                 int triState = entry.getTriState ();
831                 buffer.append (" -" + key + " : [" + Integer.toBinaryString (state) +
832                         "] [" + Integer.toBinaryString (triState) + "]\n");
833             }
834         } else {
835             buffer.append ("-no users-\n");
836         }
837
838         // Get the group accesses
839
buffer.append (" -Local group access : ");
840         Enumeration JavaDoc groupnames = mGroupEntries.keys ();
841         if (groupnames.hasMoreElements ()) {
842             buffer.append ("\n");
843             while (groupnames.hasMoreElements ()) {
844                 key = (String JavaDoc) groupnames.nextElement ();
845                 entry = (JahiaACLEntry) mGroupEntries.get (key);
846                 int state = entry.getState ();
847                 int triState = entry.getTriState ();
848                 buffer.append (" -" + key + " : [" + Integer.toBinaryString (state) +
849                         "] [" + Integer.toBinaryString (triState) + "]\n");
850             }
851         } else {
852             buffer.append ("-no groups-\n");
853         }
854
855         // Get the recursed permissions
856
Hashtable JavaDoc userTable = new Hashtable JavaDoc (mUserEntries.size());
857         Hashtable JavaDoc groupTable = new Hashtable JavaDoc (mGroupEntries.size());
858         recursePermissions (this, this, userTable, groupTable);
859
860         buffer.append (" -recursed user access : ");
861         usernames = userTable.keys ();
862         if (usernames.hasMoreElements ()) {
863             buffer.append ("\n");
864             while (usernames.hasMoreElements ()) {
865                 key = (String JavaDoc) usernames.nextElement ();
866                 entry = (JahiaACLEntry) userTable.get (key);
867                 int state = entry.getState ();
868                 int triState = entry.getTriState ();
869                 buffer.append (" -" + key + " : [" + Integer.toBinaryString (state) +
870                         "] [" + Integer.toBinaryString (triState) + "]\n");
871             }
872         } else {
873             buffer.append ("-no users-\n");
874         }
875
876         buffer.append (" -recursed group access : ");
877         groupnames = groupTable.keys ();
878         if (groupnames.hasMoreElements ()) {
879             buffer.append ("\n");
880             while (groupnames.hasMoreElements ()) {
881                 key = (String JavaDoc) groupnames.nextElement ();
882                 entry = (JahiaACLEntry) groupTable.get (key);
883                 int state = entry.getState ();
884                 int triState = entry.getTriState ();
885                 buffer.append (" -" + key + " : [" + Integer.toBinaryString (state) +
886                         "] [" + Integer.toBinaryString (triState) + "]\n");
887             }
888         } else {
889             buffer.append ("-no groups-\n");
890         }
891
892         usernames = null;
893         groupnames = null;
894         userTable = null;
895         groupTable = null;
896         key = null;
897         entry = null;
898
899         return buffer.toString ();
900     }
901
902     /**
903      * Test if a user has a certain permission in a hashtable
904      *
905      * @param user the user for which to test the permission
906      * @param permission the permission we wish to find
907      * @param table the table containing userKeys as keys, and JahiaACLEntry
908      * objects as values.
909      *
910      * @return Return 1 if the user has the requested permission, 0 if the user
911      * has no permission and -1 if the user was not found.
912      *
913      */

914     private int getUserPermissionInMap (JahiaUser user, int permission, Map JavaDoc map) {
915         int result = -1; // start as if the user was not found.
916

917         //check if the user is in entries
918
JahiaACLEntry entry = (JahiaACLEntry) map.get (user.getName ());
919         if (entry != null) {
920             switch (entry.getPermission (permission)) {
921                 case JahiaACLEntry.ACL_YES:
922                     result = 1;
923                     break;
924
925                 case JahiaACLEntry.ACL_NO:
926                     result = 0;
927                     break;
928             }
929         }
930         entry = null;
931
932         return result;
933     }
934
935     /**
936      * Test if the user has a certain permission through group entries in a
937      * hashtable.
938      *
939      * @param user the user for which to test the permission
940      * @param permission the permission we wish to find
941      * @param table the table containing groupKeys as keys, and JahiaACLEntry
942      * objects as values.
943      *
944      * @return Return 1 if the user has the requested permission, 0 if the user
945      * has no permission and -1 if the user was not found.
946      *
947      */

948     private int getUserPermissionInGroupMap (JahiaUser user, int permission,
949                                                    Map JavaDoc map) {
950         int result = -1;
951
952         // Check if the user has the requested permission in one of the group entries.
953
for (Iterator JavaDoc keys = map.keySet().iterator(); keys.hasNext();) {
954             String JavaDoc groupKey = (String JavaDoc) keys.next();
955             JahiaGroup group = ServicesRegistry.getInstance ().
956                     getJahiaGroupManagerService ().lookupGroup (groupKey);
957
958             if (group != null) {
959                 //System.out.println (group.toString());
960

961                 // Check if the user is member of the group
962

963                 if (group.isMember (user)) {
964                     //System.out.println ("FH : user ["+user.getUsername()+"::"+user.getName()+"] is member of group ["+group.getName()+"::"+group.getGroupname()+"]");
965

966                     // if it's the first time the user is found in a group, set by default
967
// the "deny" permission. If the user has the permission, it will be
968
// given later.
969
if (result < 0) {
970                         result = 0;
971                     }
972
973                     // Get the permission entries for the group and check it.
974
JahiaACLEntry entry = (JahiaACLEntry) map.get (groupKey);
975                     if (entry.getPermission (permission) ==
976                             JahiaACLEntry.ACL_YES) {
977                         result = 1;
978                     }
979                     entry = null;
980                 } else {
981                     //System.out.println ("FH : user ["+user.getUsername()+"::"+user.getName()+"] is not member of group ["+group.getName()+"::"+group.getGroupname()+"]");
982
}
983
984             } // if
985
} // while
986

987         return result;
988     }
989
990     /**
991      * Find permissions recursively. This method populates the hashtables
992      * userTable and groupTable passed in parameter.
993      *
994      * @param parentACLFinder an implementation of the parent ACL finder
995      * interface that allows finding of the parent object for the object
996      * passed as the aclResource parameter.
997      * @param aclResource the object on which we are working on, to be passed
998      * to the parent ACL finder implementation when looking for it's parent.
999      * @param userTable the hashtable containing userKeys as keys, and
1000     * JahiaACLEntry objects as values. This table contains the permissions
1001     * for users on the current object.
1002     * @param groupTable the hashtable containing groupKeys as keys, and
1003     * JahiaACLEntry objects as values. This table contains the permissions
1004     * for groups on the current object.
1005     */

1006    private void recursePermissions (ParentACLFinder parentACLFinder, ACLResourceInterface aclResource, Map JavaDoc userTable, Map JavaDoc groupTable) {
1007
1008        if (userTable != null) {
1009            buildPermissions (userTable, mUserEntries);
1010        }
1011        if (groupTable != null) {
1012            buildPermissions (groupTable, mGroupEntries);
1013        }
1014        ACLResourceInterface parentACLResource = parentACLFinder.getParent(aclResource);
1015        if (parentACLResource != null &&
1016            getInternalACL(parentACLResource) != null &&
1017            mInheritance == 0) {
1018            getInternalACL(parentACLResource).recursePermissions (parentACLFinder, parentACLResource, userTable, groupTable);
1019        }
1020    }
1021
1022    /**
1023     * Copies the local ACL permissions into an hashtable passed in parameter.
1024     * This is used during recursive ACL visiting in order to gather all
1025     * permissions from ACLs into a single user or group permission hashtable
1026     *
1027     * @param table the table in which we will insert the permissions copied
1028     * from the local permission table
1029     * @param localTable the local permission table to copy the values from
1030     * (provided they augment the permission, otherwise we don't copy).
1031     *
1032     */

1033    private static final void buildPermissions (Map JavaDoc map, Map JavaDoc localMap) {
1034        // for each ACL user/group entry check if it doesn't already exist in the
1035
// global user entries hashtable. If it does, add only permission that
1036
// should be herited by the current user entry.
1037
for (Iterator JavaDoc keys = localMap.keySet().iterator(); keys.hasNext();) {
1038            String JavaDoc key = (String JavaDoc) keys.next();
1039
1040            if (key != null) {
1041                JahiaACLEntry entry = (JahiaACLEntry) map.get (key);
1042                JahiaACLEntry localEntry = (JahiaACLEntry) localMap.get (key);
1043
1044                // if the user already exist, add some permission if needed,
1045
// otherwise add the user entry in the table.
1046
if (entry != null) {
1047                    int tristate = entry.getTriState ();
1048                    int localTristate = localEntry.getTriState ();
1049
1050                    // 1. get the bit mask of the permissions to be inherited
1051
int mask = ((~localTristate) & tristate);
1052
1053                    // if there is some bits to set, go for it, otherwise give up
1054
// and go to the next user.
1055
if (mask != 0) {
1056                        int state = entry.getState ();
1057
1058                        // 2. get the permission to set
1059
int permissionMask = (localEntry.getState () & mask);
1060
1061                        // 3. compute the new entry state
1062
state = (state | permissionMask);
1063
1064                        // 4. compute the new entry tristate
1065
tristate = ((~mask) & tristate);
1066
1067                        // finally update the state and tristate
1068
entry.set (state, tristate);
1069                    }
1070                } else {
1071                    map.put (key, localEntry.clone ());
1072                }
1073            }
1074        } // while
1075

1076    }
1077
1078    /**
1079     * Get the user/group name list from the hashtable according to a set of
1080     * permissions.
1081     *
1082     * @param hashtable the hashtable containing the user/group keys and
1083     * JahiaACLEntry objects
1084     * @param entry the JahiaACLEntry object to match with the values of the
1085     * hashtable.
1086     *
1087     * @return a vector of user/group name.
1088     */

1089    private Vector JavaDoc getNameList (Map JavaDoc map, JahiaACLEntry entry) {
1090        Vector JavaDoc result;
1091
1092        if (entry == null) {
1093            return getKeysFromHashMap (map);
1094        } else {
1095            result = new Vector JavaDoc ();
1096            for (Iterator JavaDoc keys = map.keySet().iterator(); keys.hasNext();) {
1097                String JavaDoc name = (String JavaDoc) keys.next();
1098                JahiaACLEntry hashtableEntry = (JahiaACLEntry) map.get (name);
1099                if (hashtableEntry.hasSameBitsActivated (entry)) {
1100                    result.add (name);
1101                }
1102            }
1103        }
1104        return result;
1105    }
1106
1107    /**
1108     * Copies (doesn't clone!) the hashtable's keys into a vector.
1109     *
1110     * @param map the source map from which we want to copy the
1111     * keys.
1112     *
1113     * @return a vector of hashtable keys.
1114     */

1115    protected Vector JavaDoc getKeysFromHashMap (Map JavaDoc map) {
1116        Vector JavaDoc vect = new Vector JavaDoc(map.size());
1117        for (Iterator JavaDoc keys = map.keySet().iterator(); keys.hasNext();) {
1118            vect.add(keys.next());
1119        }
1120        return vect;
1121    }
1122
1123    /**
1124     * Return all the ACL user entries.
1125     *
1126     * @return Return a hashtable of all the ACL user entries. Format is
1127     * (String) userName, (JahiaACLEntry) aclEntry
1128     */

1129    public Hashtable JavaDoc getAllUserEntries () {
1130        return mUserEntries;
1131    }
1132
1133    /**
1134     * Return clone of all the ACL group entries.
1135     *
1136     * @return Return a hashtable clone of all the ACL group entries. Format is
1137     * (String) groupName, (JahiaACLEntry) aclEntry
1138     */

1139    public Hashtable JavaDoc getAllGroupEntries () {
1140        return mGroupEntries;
1141    }
1142
1143    /**
1144     * Set the new parent ACL.
1145     *
1146     * @param parentACL Reference of the parent ACL. Set to <code>null</code> if the ACL
1147     * has no parent.
1148     *
1149     * @throws JahiaDatabaseException
1150     */

1151    public void setParentACL (JahiaACL parentACL)
1152            throws JahiaDatabaseException {
1153        setParentACL (parentACL, true);
1154    }
1155
1156    /**
1157     * Set the new parent ACL.
1158     *
1159     * @param parentACL Reference of the parent ACL. Set to <code>null</code> if the ACL
1160     * has no parent.
1161     * @param update true if the setted parent has to be updated into the database.
1162     *
1163     * @throws JahiaDatabaseException
1164     */

1165    protected void setParentACL (JahiaACL parentACL, boolean update)
1166            throws JahiaDatabaseException {
1167        if (parentACL == null) {
1168            throw new JahiaDatabaseException (
1169                    "Could not set parent of ACL because the parameter passed as the parent is null",
1170                    JahiaDatabaseException.ACL_ERROR);
1171        }
1172
1173        mParentID = parentACL.getID ();
1174
1175        if (update) {
1176            AclDBUtils.getInstance ().updateACL (this);
1177        }
1178    }
1179
1180    /**
1181     * Clone the current ACL.
1182     *
1183     * @return The new ACL cloned, null if unsuccessfull.
1184     */

1185    public Object JavaDoc clone() {
1186        final JahiaACL acl = new JahiaACL(mID, mParentID, mInheritance);
1187        acl.setUserEntries(new Hashtable JavaDoc(mUserEntries));
1188        acl.setGroupEntries(new Hashtable JavaDoc(mGroupEntries));
1189        return acl;
1190    }
1191
1192    /**
1193     * Return true if the given aclId is in this acl parents path
1194     *
1195     * @param aclId the ACL identifier that we want to test recursively for
1196     * presence in this ACL's parents.
1197     *
1198     * @return true if the ACL identifier is present in this ACL's parents,
1199     * false otherwise
1200     */

1201    public boolean isAclInParents (int aclId) {
1202        JahiaACL parentAcl = getInternalACL(this.getParent (this));
1203        if (parentAcl == null) {
1204            return false;
1205        }
1206        if (parentAcl.getID () == aclId) {
1207            return true;
1208        }
1209        return parentAcl.isAclInParents (aclId);
1210    }
1211
1212    /* below are methods that implement the ACLResourceInterface */
1213
1214    public JahiaBaseACL getACL() {
1215        try {
1216            return new JahiaBaseACL(getID());
1217        } catch (Throwable JavaDoc t) {
1218            // this should never happen
1219
return null;
1220        }
1221    }
1222
1223    public int getAclID() {
1224        return getID();
1225    }
1226
1227    private JahiaACL getInternalACL(ACLResourceInterface aclResource) {
1228        if (aclResource.getACL() == null) {
1229            return null;
1230        }
1231        return aclResource.getACL().getACL();
1232    }
1233}
1234
Popular Tags