KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > org > hsqldb > Grantee


1 /* Copyright (c) 2001-2005, The HSQL Development Group
2  * All rights reserved.
3  *
4  * Redistribution and use in source and binary forms, with or without
5  * modification, are permitted provided that the following conditions are met:
6  *
7  * Redistributions of source code must retain the above copyright notice, this
8  * list of conditions and the following disclaimer.
9  *
10  * Redistributions in binary form must reproduce the above copyright notice,
11  * this list of conditions and the following disclaimer in the documentation
12  * and/or other materials provided with the distribution.
13  *
14  * Neither the name of the HSQL Development Group nor the names of its
15  * contributors may be used to endorse or promote products derived from this
16  * software without specific prior written permission.
17  *
18  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
19  * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
20  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
21  * ARE DISCLAIMED. IN NO EVENT SHALL HSQL DEVELOPMENT GROUP, HSQLDB.ORG,
22  * OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
23  * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
24  * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
25  * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
26  * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
27  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
28  * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
29  */

30
31
32 package org.hsqldb;
33
34 import org.hsqldb.HsqlNameManager.HsqlName;
35 import org.hsqldb.lib.HashSet;
36 import org.hsqldb.lib.IntValueHashMap;
37 import org.hsqldb.lib.Iterator;
38 import org.hsqldb.lib.Set;
39
40 /**
41  * A Grantee Object holds the name, access and administrative rights for a
42  * particular grantee.<p>
43  * It supplies the methods used to grant, revoke, test
44  * and check a grantee's access rights to other database objects.
45  * It also holds a reference to the common PUBLIC User Object,
46  * which represent the special user refered to in
47  * GRANT ... TO PUBLIC statements.<p>
48  * The check(), isAccessible() and getGrantedClassNames() methods check the
49  * rights granted to the PUBLIC User Object, in addition to individually
50  * granted rights, in order to decide which rights exist for the user.
51  *
52  * Method names ending in Direct indicate methods which do not recurse
53  * to look through Roles which "this" object is a member of.
54  *
55  * We use the word "Admin" (e.g., in private variable "admin" and method
56  * "isAdmin()) to mean this Grantee has admin priv by any means.
57  * We use the word "adminDirect" (e.g., in private variable "adminDirect"
58  * and method "isAdminDirect()) to mean this Grantee has admin priv
59  * directly.
60  *
61  * @author boucherb@users
62  * @author fredt@usrs
63  * @author unsaved@users
64  *
65  * @version 1.8.0
66  * @since 1.8.0
67  */

68 public class Grantee {
69
70     boolean isRole;
71
72     /**
73      * true if this grantee has database administrator priv directly
74      * (ie., not by membership in any role)
75      */

76     private boolean isAdminDirect = false;
77
78     /** true if this grantee has database administrator priv by any means. */
79     private boolean isAdmin = false;
80
81     /** contains righs granted direct, or via roles, expept those of PUBLIC */
82     private IntValueHashMap fullRightsMap = new IntValueHashMap();
83
84     /**
85      * Grantee name.
86      */

87     private String JavaDoc granteeName;
88
89     /** map with database object identifier keys and access privileges values */
90     private IntValueHashMap rightsMap;
91
92     /** These are the DIRECT roles. Each of these may contain nested roles */
93     HashSet roles = new HashSet();
94
95     /**
96      * The special PUBLIC Grantee object. <p>
97      *
98      * Note: All Grantee objects except the special
99      * SYS and PUBLIC Grantee objects contain a reference to this object
100      */

101     private Grantee pubGrantee;
102
103     /** Needed only to give access to the roles for this database */
104     private GranteeManager granteeManager;
105
106     /**
107      * Constructor, with a argument reference to the PUBLIC User Object which
108      * is null if this is the SYS or PUBLIC user.
109      *
110      * The dependency upon a GranteeManager is undesirable. Hopefully we
111      * can get rid of this dependency with an IOC or Listener re-design.
112      */

113     Grantee(String JavaDoc name, Grantee inGrantee,
114             GranteeManager man) throws HsqlException {
115
116         rightsMap = new IntValueHashMap();
117         granteeName = name;
118         granteeManager = man;
119         pubGrantee = inGrantee;
120     }
121
122     String JavaDoc getName() {
123         return granteeName;
124     }
125
126     /**
127      * Retrieves the map object that represents the rights that have been
128      * granted on database objects. <p>
129      *
130      * The map has keys and values with the following interpretation: <P>
131      *
132      * <UL>
133      * <LI> The keys are generally (but not limited to) objects having
134      * an attribute or value equal to the name of an actual database
135      * object.
136      *
137      * <LI> Specifically, the keys act as database object identifiers.
138      *
139      * <LI> The values are always Integer objects, each formed by combining
140      * a set of flags, one for each of the access rights defined in
141      * UserManager: {SELECT, INSERT, UPDATE and DELETE}.
142      * </UL>
143      */

144     IntValueHashMap getRights() {
145
146         // necessary to create the script
147
return rightsMap;
148     }
149
150     /**
151      * Grant a role
152      */

153     public void grant(String JavaDoc role) throws HsqlException {
154         roles.add(role);
155     }
156
157     /**
158      * Revoke a direct role only
159      */

160     public void revoke(String JavaDoc role) throws HsqlException {
161
162         if (!hasRoleDirect(role)) {
163             throw Trace.error(Trace.DONT_HAVE_ROLE, role);
164         }
165
166         roles.remove(role);
167     }
168
169     /**
170      * Gets direct roles, not roles nested within them.
171      */

172     public HashSet getDirectRoles() {
173         return roles;
174     }
175
176     String JavaDoc getDirectRolesString() {
177         return setToString(roles);
178     }
179
180     String JavaDoc getAllRolesString() {
181         return setToString(getAllRoles());
182     }
183
184     public String JavaDoc setToString(Set set) {
185
186         // Should be sorted
187
// Iterator it = (new java.util.TreeSet(roles)).iterator();
188
Iterator it = set.iterator();
189         StringBuffer JavaDoc sb = new StringBuffer JavaDoc();
190
191         while (it.hasNext()) {
192             if (sb.length() > 0) {
193                 sb.append(',');
194             }
195
196             sb.append(it.next());
197         }
198
199         return sb.toString();
200     }
201
202     /**
203      * Gets direct and nested roles.
204      */

205     public HashSet getAllRoles() {
206
207         HashSet newSet = new HashSet();
208
209         addGranteeAndRoles(newSet);
210
211         // Since we added "Grantee" in addition to Roles, need to remove self.
212
newSet.remove(granteeName);
213
214         return newSet;
215     }
216
217     /**
218      * Adds to given Set this.sName plus all roles and nested roles.
219      *
220      * @return Given role with new elements added.
221      */

222     private HashSet addGranteeAndRoles(HashSet set) {
223
224         String JavaDoc candidateRole;
225
226         set.add(granteeName);
227
228         Iterator it = roles.iterator();
229
230         while (it.hasNext()) {
231             candidateRole = (String JavaDoc) it.next();
232
233             if (!set.contains(candidateRole)) {
234                 try {
235                     granteeManager.getRole(candidateRole).addGranteeAndRoles(
236                         set);
237                 } catch (HsqlException he) {
238                     throw new RuntimeException JavaDoc(he.getMessage());
239                 }
240             }
241         }
242
243         return set;
244     }
245
246     public boolean hasRoleDirect(String JavaDoc role) {
247         return roles.contains(role);
248     }
249
250     public boolean hasRole(String JavaDoc role) {
251         return getAllRoles().contains(role);
252     }
253
254     public String JavaDoc allRolesString() {
255
256         HashSet allRoles = getAllRoles();
257
258         if (allRoles.size() < 1) {
259             return null;
260         }
261
262         Iterator it = getAllRoles().iterator();
263         StringBuffer JavaDoc sb = new StringBuffer JavaDoc();
264
265         while (it.hasNext()) {
266             if (sb.length() > 0) {
267                 sb.append(',');
268             }
269
270             sb.append((String JavaDoc) it.next());
271         }
272
273         return sb.toString();
274     }
275
276     /**
277      * Grants the specified rights on the specified database object. <p>
278      *
279      * Keys stored in rightsMap for database tables are their HsqlName
280      * attribute. This allows rights to persist when a table is renamed. <p>
281      */

282     void grant(Object JavaDoc dbobject, int rights) {
283
284         if (rights == 0) {
285             return;
286         }
287
288         int n = rightsMap.get(dbobject, 0);
289
290         n |= rights;
291
292         rightsMap.put(dbobject, n);
293     }
294
295     /**
296      * Revokes the specified rights on the specified database object. <p>
297      *
298      * If, after removing the specified rights, no rights remain on the
299      * database object, then the key/value pair for that object is removed
300      * from the rights map
301      */

302     void revoke(Object JavaDoc dbobject, int rights) {
303
304         if (rights == 0) {
305             return;
306         }
307
308         int n = rightsMap.get(dbobject, 0);
309
310         if (n == 0) {
311             return;
312         }
313
314         rights = n & (GranteeManager.ALL - rights);
315
316         if (rights == 0) {
317             rightsMap.remove(dbobject);
318         } else {
319             rightsMap.put(dbobject, rights);
320         }
321     }
322
323     /**
324      * Revokes all rights on the specified database object.<p>
325      *
326      * This method removes any existing mapping from the rights map
327      */

328     void revokeDbObject(Object JavaDoc dbobject) {
329         rightsMap.remove(dbobject);
330         fullRightsMap.remove(dbobject);
331     }
332
333     /**
334      * Revokes all rights from this Grantee object. The map is cleared and
335      * the database administrator role attribute is set false.
336      */

337     void clearPrivileges() {
338
339         roles.clear();
340         rightsMap.clear();
341         fullRightsMap.clear();
342
343         isAdminDirect = false;
344     }
345
346     /**
347      * Checks if any of the rights represented by the rights
348      * argument have been granted on the specified database object. <p>
349      *
350      * This is done by checking that a mapping exists in the rights map
351      * from the dbobject argument for at least one of the rights
352      * contained in the rights argument. Otherwise, it throws.
353      */

354     void check(HsqlName dbobject, int rights) throws HsqlException {
355
356         if (!isAccessible(dbobject, rights)) {
357             throw Trace.error(Trace.ACCESS_IS_DENIED);
358         }
359     }
360
361     void check(String JavaDoc dbobject) throws HsqlException {
362
363         if (!isAccessible(dbobject)) {
364             throw Trace.error(Trace.ACCESS_IS_DENIED);
365         }
366     }
367
368     /**
369      * Returns true if any of the rights represented by the
370      * rights argument has been granted on the database object identified
371      * by the dbobject argument. <p>
372      *
373      * This is done by checking that a mapping exists in the rights map
374      * from the dbobject argument for at least one of the rights
375      * contained in the rights argument.
376      *
377      * Only does one level of recursion to check the PUBLIC role.
378      */

379     boolean isAccessible(HsqlName dbObject, int rights) throws HsqlException {
380
381         if (isAdmin) {
382             return true;
383         }
384
385         if (pubGrantee != null && pubGrantee.isAccessible(dbObject, rights)) {
386             return true;
387         }
388
389         int n = fullRightsMap.get(dbObject, 0);
390
391         if (n != 0) {
392             return (n & rights) != 0;
393         }
394
395         return false;
396     }
397
398     /**
399      * Returns true if any right at all has been granted to this User object
400      * on the database object identified by the dbObject argument.
401      */

402     boolean isAccessible(String JavaDoc functionName) throws HsqlException {
403
404         if (functionName.startsWith("org.hsqldb.Library")
405                 || functionName.startsWith("java.lang.Math")) {
406             return true;
407         }
408
409         if (isAdmin) {
410             return true;
411         }
412
413         if (pubGrantee != null && pubGrantee.isAccessible(functionName)) {
414             return true;
415         }
416
417         int n = fullRightsMap.get(functionName, 0);
418
419         return n != 0;
420     }
421
422     /**
423      * Returns true if any of the rights represented by the
424      * rights argument has been granted on the database object identified
425      * by the dbObject argument. <p>
426      *
427      * This is done by checking that a mapping exists in the rights map
428      * from the dbObject argument for at least one of the rights
429      * contained in the rights argument.
430      *
431      * Considers none of pubGranee, nested roles, admin privs, globally
432      * available Class object.
433      */

434     protected boolean isDirectlyAccessible(Object JavaDoc dbObject,
435                                            int rights) throws HsqlException {
436
437         int n = rightsMap.get(dbObject, 0);
438
439         if (n != 0) {
440             return (n & rights) != 0;
441         }
442
443         return false;
444     }
445
446     /**
447      * Returns true if any right at all has been granted to this User object
448      * on the database object identified by the dbObject argument.
449      */

450     boolean isAccessible(HsqlName dbObject) throws HsqlException {
451         return isAccessible(dbObject, GranteeManager.ALL);
452     }
453
454     /**
455      * Checks whether this Grantee has administrative privs either directly
456      * or indirectly. Otherwise it throws.
457      */

458     void checkAdmin() throws HsqlException {
459
460         if (!isAdmin()) {
461             throw Trace.error(Trace.ACCESS_IS_DENIED);
462         }
463     }
464
465     /**
466      * Returns true if this Grantee has administrative privs either directly
467      * or indirectly.
468      */

469     boolean isAdmin() {
470         return isAdmin;
471     }
472
473     /**
474      * Returns true if this grantee object is for a user with Direct
475      * database administrator privileges.
476      * I.e., if this User/Role has Admin priv. directly, not via a
477      * nested Role.
478      */

479     boolean isAdminDirect() {
480         return isAdminDirect;
481     }
482
483     /**
484      * Retrieves the distinct set of Java <code>Class</code> FQNs
485      * for which this <code>User</code> object has been
486      * granted <code>ALL</code> (the Class execution privilege). <p>
487      * @param andToPublic if <code>true</code>, then the set includes the
488      * names of classes accessible to this <code>User</code> object
489      * through grants to its Roles + <code>PUBLIC</code>
490      * <code>User</code> object attribute, else only role grants
491      * + direct grants are included.
492      * @return the distinct set of Java Class FQNs for which this
493      * this <code>User</code> object has been granted
494      * <code>ALL</code>.
495      */

496     HashSet getGrantedClassNames(boolean andToPublic) throws HsqlException {
497
498         IntValueHashMap rights;
499         Object JavaDoc key;
500         int right;
501         Iterator i;
502
503         rights = rightsMap;
504
505         HashSet out = getGrantedClassNamesDirect();
506
507         if (andToPublic && pubGrantee != null) {
508             rights = pubGrantee.rightsMap;
509             i = rights.keySet().iterator();
510
511             while (i.hasNext()) {
512                 key = i.next();
513
514                 if (key instanceof String JavaDoc) {
515                     right = rights.get(key, 0);
516
517                     if (right == GranteeManager.ALL) {
518                         out.add(key);
519                     }
520                 }
521             }
522         }
523
524         Iterator it = getAllRoles().iterator();
525
526         while (it.hasNext()) {
527             out.addAll(
528                 ((Grantee) granteeManager.getRole(
529                     (String JavaDoc) it.next())).getGrantedClassNamesDirect());
530         }
531
532         return out;
533     }
534
535     /**
536      * Retrieves the distinct set of Java <code>Class</code> FQNs
537      * for which this <code>User</code> object has directly been
538      * granted <code>ALL</code> (the Class execution privilege).
539      *
540      * Does NOT check nested the pubGrantee nor nested roles.
541      * @return the distinct set of Java Class FQNs for which this
542      * this <code>User</code> object has been granted
543      * <code>ALL</code>.
544      *
545      */

546     HashSet getGrantedClassNamesDirect() throws HsqlException {
547
548         IntValueHashMap rights;
549         HashSet out;
550         Object JavaDoc key;
551         int right;
552         Iterator i;
553
554         rights = rightsMap;
555         out = new HashSet();
556         i = rightsMap.keySet().iterator();
557
558         while (i.hasNext()) {
559             key = i.next();
560
561             if (key instanceof String JavaDoc) {
562                 right = rights.get(key, 0);
563
564                 if (right == GranteeManager.ALL) {
565                     out.add(key);
566                 }
567             }
568         }
569
570         return out;
571     }
572
573     /**
574      * Retrieves a string[] whose elements are the names of the rights
575      * explicitly granted with the GRANT command to this <code>User</code>
576      * object on the <code>Table</code> object identified by the
577      * <code>name</code> argument.
578      * * @return array of Strings naming the rights granted to this
579      * <code>User</code> object on the <code>Table</code> object
580      * identified by the <code>name</code> argument.
581      * @param name a <code>Table</code> object identifier
582      *
583      */

584     String JavaDoc[] listGrantedTablePrivileges(HsqlName name) {
585         return GranteeManager.getRightsArray(rightsMap.get(name, 0));
586     }
587
588     /**
589      * Violates naming convention (for backward compatibility).
590      * Should be "setAdminDirect(boolean").
591      */

592     void setAdminDirect() {
593         isAdmin = isAdminDirect = true;
594     }
595
596     /**
597      * Recursive method used with ROLE Grantee objects to set the fullRightsMap
598      * and admin flag for all the roles.
599      *
600      * If a new ROLE is granted to a ROLE Grantee object, the ROLE should first
601      * be added to the Set of ROLE Grantee objects (roles) for the grantee.
602      * The grantee will be the parameter.
603      *
604      * If the direct permissions granted to an existing ROLE Grentee is
605      * modified no extra initial action is necessary.
606      * The existing Grantee will b the parameter.
607      *
608      * If an existing ROLE is REVOKEed from a ROLE, it should first be removed
609      * from the set of ROLE Grantee objects in the containing ROLE.
610      * The containing ROLE will be the parameter.
611      *
612      * If an existing ROLE is DROPped, all its privileges should be cleared
613      * first. The ROLE will be the parameter. After calling this method on
614      * all other roles, the DROPped role should be removed from all grantees.
615      *
616      * After the initial modification, this method should be called iteratively
617      * on all the ROLE Grantee objects contained in RoleManager.
618      *
619      * The updateAllRights() method is then called iteratively on all the
620      * USER Grantee objects contained in UserManager.
621      * @param role a modified, revoked or dropped role.
622      * @return true if this Grantee has possibly changed as a result
623      */

624     boolean updateNestedRoles(String JavaDoc role) {
625
626         boolean hasNested = false;
627         boolean isSelf = role.equals(granteeName);
628
629         if (!isSelf) {
630             Iterator it = roles.iterator();
631
632             while (it.hasNext()) {
633                 String JavaDoc roleName = (String JavaDoc) it.next();
634
635                 try {
636                     Grantee currentRole = granteeManager.getRole(roleName);
637
638                     hasNested |= currentRole.updateNestedRoles(role);
639                 } catch (HsqlException e) {}
640             }
641         }
642
643         if (hasNested) {
644             updateAllRights();
645         }
646
647         return hasNested || isSelf;
648     }
649
650     /**
651      * Method used with all Grantee objects to set the full set of rights
652      * according to those inherited form ROLE Grantee objects and those
653      * granted to the object itself.
654      */

655     void updateAllRights() {
656
657         fullRightsMap.clear();
658
659         isAdmin = isAdminDirect;
660
661         Iterator it = roles.iterator();
662
663         while (it.hasNext()) {
664             String JavaDoc roleName = (String JavaDoc) it.next();
665
666             try {
667                 Grantee currentRole = granteeManager.getRole(roleName);
668
669                 fullRightsMap.putAll(currentRole.fullRightsMap);
670
671                 isAdmin |= currentRole.isAdmin();
672             } catch (HsqlException e) {}
673         }
674
675         fullRightsMap.putAll(rightsMap);
676     }
677 }
678
Popular Tags