001    //$HeadURL: svn+ssh://jwilden@svn.wald.intevation.org/deegree/base/branches/2.5_testing/src/org/deegree/security/drm/SecurityTransaction.java $
002    /*----------------------------------------------------------------------------
003     This file is part of deegree, http://deegree.org/
004     Copyright (C) 2001-2009 by:
005     Department of Geography, University of Bonn
006     and
007     lat/lon GmbH
008    
009     This library is free software; you can redistribute it and/or modify it under
010     the terms of the GNU Lesser General Public License as published by the Free
011     Software Foundation; either version 2.1 of the License, or (at your option)
012     any later version.
013     This library is distributed in the hope that it will be useful, but WITHOUT
014     ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
015     FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more
016     details.
017     You should have received a copy of the GNU Lesser General Public License
018     along with this library; if not, write to the Free Software Foundation, Inc.,
019     59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
020    
021     Contact information:
022    
023     lat/lon GmbH
024     Aennchenstr. 19, 53177 Bonn
025     Germany
026     http://lat-lon.de/
027    
028     Department of Geography, University of Bonn
029     Prof. Dr. Klaus Greve
030     Postfach 1147, 53001 Bonn
031     Germany
032     http://www.geographie.uni-bonn.de/deegree/
033    
034     e-mail: info@deegree.org
035     ----------------------------------------------------------------------------*/
036    package org.deegree.security.drm;
037    
038    import static org.deegree.security.drm.SecurityAccessManager.getInstance;
039    import static org.deegree.security.drm.model.Privilege.ADDOBJECT;
040    
041    import java.util.ArrayList;
042    import java.util.Collection;
043    import java.util.HashSet;
044    import java.util.Iterator;
045    import java.util.List;
046    
047    import org.deegree.framework.util.StringPair;
048    import org.deegree.security.GeneralSecurityException;
049    import org.deegree.security.UnauthorizedException;
050    import org.deegree.security.drm.model.Group;
051    import org.deegree.security.drm.model.Privilege;
052    import org.deegree.security.drm.model.Right;
053    import org.deegree.security.drm.model.RightSet;
054    import org.deegree.security.drm.model.RightType;
055    import org.deegree.security.drm.model.Role;
056    import org.deegree.security.drm.model.SecurableObject;
057    import org.deegree.security.drm.model.SecuredObject;
058    import org.deegree.security.drm.model.Service;
059    import org.deegree.security.drm.model.User;
060    
061    /**
062     * 
063     * 
064     * 
065     * @author <a href="mailto:poth@lat-lon.de">Andreas Poth</a>
066     * @author last edited by: $Author: aschmitz $
067     * 
068     * @version $Revision: 25490 $, $Date: 2010-07-26 11:47:34 +0200 (Mo, 26 Jul 2010) $
069     */
070    public class SecurityTransaction extends SecurityAccess {
071    
072        private Role adminRole;
073    
074        private long timestamp;
075    
076        /**
077         * @param user
078         * @param registry
079         * @param adminRole
080         */
081        SecurityTransaction( User user, SecurityRegistry registry, Role adminRole ) {
082            super( user, registry );
083            this.adminRole = adminRole;
084            this.timestamp = System.currentTimeMillis();
085        }
086    
087        /**
088         * Returns the conjunction of an array of roles plus a single role.
089         * 
090         * @param roles
091         * @param role
092         * @return the conjunction of an array of roles plus a single role.
093         */
094        public Role[] addRoles( Role[] roles, Role role ) {
095            HashSet<Role> roleSet = new HashSet<Role>( roles.length + 1 );
096            roleSet.add( role );
097            for ( int i = 0; i < roles.length; i++ ) {
098                roleSet.add( roles[i] );
099            }
100            return roleSet.toArray( new Role[roleSet.size()] );
101        }
102    
103        /**
104         * Deletes all data from the underlying <code>Registry</code> and sets the default objects (SEC_ADMIN user, role and
105         * group) and standard rights and privileges.
106         * 
107         * @throws GeneralSecurityException
108         */
109        public void clean()
110                                throws GeneralSecurityException {
111            SecurityAccessManager.getInstance().verify( this );
112            registry.clean( this );
113        }
114    
115        /**
116         * Removes a <code>Group</code> from the <code>Registry</code>.
117         * 
118         * This means:
119         * <ul>
120         * <li>owner role ($G:GROUPNAME) is removed
121         * <li>group is removed
122         * </ul>
123         * 
124         * NOTE: Only performed if the acting user has the 'delete'-right on the group object.
125         * 
126         * @param group
127         * @throws GeneralSecurityException
128         * @throws UnauthorizedException
129         */
130        public void deregisterGroup( Group group )
131                                throws GeneralSecurityException, UnauthorizedException {
132            SecurityAccessManager.getInstance().verify( this );
133            checkForRight( RightType.DELETE, group );
134            try {
135                Role ownerRole = registry.getRoleByName( this, "$G:" + group.getName() );
136                registry.deregisterRole( this, ownerRole );
137            } catch ( UnknownException e ) {
138            }
139            registry.deregisterGroup( this, group );
140        }
141    
142        /**
143         * Removes a <code>Role</code> from the <code>Registry</code>.
144         * 
145         * This means:
146         * <ul>
147         * <li>owner role ($R:ROLENAME) is removed
148         * <li>role is removed
149         * </ul>
150         * 
151         * NOTE: Only performed if acting user has the 'delete'-right on the role object.
152         * 
153         * @param role
154         * @throws GeneralSecurityException
155         * @throws UnauthorizedException
156         */
157        public void deregisterRole( Role role )
158                                throws GeneralSecurityException, UnauthorizedException {
159            SecurityAccessManager.getInstance().verify( this );
160            checkForRight( RightType.DELETE, role );
161            try {
162                Role ownerRole = registry.getRoleByName( this, "$R:" + role.getName() );
163                registry.deregisterRole( this, ownerRole );
164            } catch ( UnknownException e ) {
165            }
166            registry.deregisterRole( this, role );
167        }
168    
169        /**
170         * Removes a <code>SecuredObject</code> from the <code>Registry</code>.
171         * 
172         * This means:
173         * <ul>
174         * <li>owner role ($O:OBJECTNAME) is removed
175         * <li>object is removed
176         * </ul>
177         * 
178         * NOTE: Only performed if acting user has the 'delete'-right on the secured object.
179         * 
180         * @param object
181         * @throws GeneralSecurityException
182         * @throws UnauthorizedException
183         */
184        public void deregisterSecuredObject( SecuredObject object )
185                                throws GeneralSecurityException, UnauthorizedException {
186            SecurityAccessManager.getInstance().verify( this );
187            checkForRight( RightType.DELETE, object );
188            try {
189                Role ownerRole = registry.getRoleByName( this, "$O:" + object.getName() );
190                registry.deregisterRole( this, ownerRole );
191            } catch ( UnknownException e ) {
192            }
193            registry.deregisterSecuredObject( this, object );
194        }
195    
196        /**
197         * Removes a <code>User</code> from the <code>Registry</code>.
198         * 
199         * This means:
200         * <ul>
201         * <li>owner role ($U:USERNAME) is removed
202         * <li>user is removed
203         * </ul>
204         * 
205         * NOTE: Only performed if acting user has the 'delete'-right on the user object.
206         * 
207         * @param user
208         * @throws GeneralSecurityException
209         * @throws UnauthorizedException
210         */
211        public void deregisterUser( User user )
212                                throws GeneralSecurityException, UnauthorizedException {
213            SecurityAccessManager.getInstance().verify( this );
214            checkForRight( RightType.DELETE, user );
215            try {
216                Role ownerRole = registry.getRoleByName( this, "$U:" + user.getName() );
217                registry.deregisterRole( this, ownerRole );
218            } catch ( UnknownException e ) {
219                e.printStackTrace();
220            }
221            registry.deregisterUser( this, user );
222        }
223    
224        /**
225         * 
226         * @return timestamp
227         */
228        public long getTimestamp() {
229            return timestamp;
230        }
231    
232        /**
233         * Registers a new <code>Group</code> to the <code>Registry</code>.
234         * 
235         * This means:
236         * <ul>
237         * <li>a group is created in the registry
238         * <li>a corresponding owner role is created: $G:GROUPNAME
239         * <li>rights for the owner role are set up; creator has delete, update and grant rights on the group, administrator
240         * role gets these right, too
241         * </ul>
242         * 
243         * NOTE: Only performed if acting user has the 'addgroup'-privilege.
244         * 
245         * @param name
246         * @param title
247         * @return the new Group
248         * @throws GeneralSecurityException
249         */
250        public Group registerGroup( String name, String title )
251                                throws GeneralSecurityException {
252            SecurityAccessManager.getInstance().verify( this );
253            checkForPrivilege( Privilege.ADDGROUP );
254            if ( name.startsWith( "$" ) ) {
255                throw new GeneralSecurityException( "Groupname '" + name + "' is invalid. The '$'-character is for "
256                                                    + "internal use only." );
257            }
258            Group group = registry.registerGroup( this, name, title );
259            // only add owner role if lock holder is not the administrator
260            if ( this.user.getID() != User.ID_SEC_ADMIN ) {
261                Role ownerRole = registry.registerRole( this, "$G:" + name );
262                registry.setRolesForUser( this, user, addRoles( registry.getRolesForUser( this, user ), ownerRole ) );
263                registry.setRights( this, group, ownerRole, new Right[] { new Right( group, RightType.DELETE ),
264                                                                         new Right( group, RightType.UPDATE ),
265                                                                         new Right( group, RightType.GRANT ) } );
266            }
267            registry.setRights( this, group, adminRole, new Right[] { new Right( group, RightType.DELETE ),
268                                                                     new Right( group, RightType.UPDATE ),
269                                                                     new Right( group, RightType.GRANT ) } );
270            return group;
271        }
272    
273        /**
274         * Registers a new <code>Role</code> to the <code>Registry</code>.
275         * 
276         * This means:
277         * <ul>
278         * <li>a role is created in the registry
279         * <li>a corresponding owner role is created: $R:ROLENAME
280         * <li>rights for the owner role are set up; creator has delete, update and grant rights on the role, administrator
281         * role gets these right, too
282         * </ul>
283         * 
284         * NOTE: Only performed if acting user has the 'addrole'-privilege.
285         * 
286         * @param name
287         * @return the new Role
288         * @throws GeneralSecurityException
289         */
290        public Role registerRole( String name )
291                                throws GeneralSecurityException {
292            SecurityAccessManager.getInstance().verify( this );
293            checkForPrivilege( Privilege.ADDROLE );
294            if ( name.startsWith( "$" ) ) {
295                throw new GeneralSecurityException( "Rolename '" + name + "' is invalid. The '$'-character is for "
296                                                    + "internal use only." );
297            }
298    
299            Role role = registry.registerRole( this, name );
300            if ( this.user.getID() != User.ID_SEC_ADMIN ) {
301                Role ownerRole = registry.registerRole( this, "$R:" + name );
302                registry.setRolesForUser( this, user, addRoles( registry.getRolesForUser( this, user ), ownerRole ) );
303                registry.setRights( this, role, ownerRole, new Right[] { new Right( role, RightType.DELETE ),
304                                                                        new Right( role, RightType.UPDATE ),
305                                                                        new Right( role, RightType.GRANT ) } );
306            }
307            registry.setRights( this, role, adminRole, new Right[] { new Right( role, RightType.DELETE ),
308                                                                    new Right( role, RightType.UPDATE ),
309                                                                    new Right( role, RightType.GRANT ) } );
310            return role;
311        }
312    
313        /**
314         * Registers a new <code>SecuredObject</code> to the <code>Registry</code>.
315         * 
316         * This means:
317         * <ul>
318         * <li>a secured object is created in the registry
319         * <li>a corresponding owner role is created: $O:OBJECTNAME
320         * <li>rights for the owner role are set up; creator has delete, update and grant rights on the object,
321         * administrator role gets these right, too
322         * </ul>
323         * 
324         * @param type
325         * @param name
326         * @param title
327         * @return the new SecuredObject
328         * @throws GeneralSecurityException
329         */
330        public SecuredObject registerSecuredObject( String type, String name, String title )
331                                throws GeneralSecurityException {
332            SecurityAccessManager.getInstance().verify( this );
333            checkForPrivilege( Privilege.ADDOBJECT );
334            if ( name.startsWith( "$" ) ) {
335                throw new GeneralSecurityException( "Objectname '" + name + "' is invalid. The '$'-character is for "
336                                                    + "internal use only." );
337            }
338            SecuredObject object = registry.registerSecuredObject( this, type, name, title );
339            if ( this.user.getID() != User.ID_SEC_ADMIN ) {
340                Role ownerRole = registry.registerRole( this, "$O:" + name );
341                registry.setRolesForUser( this, user, addRoles( registry.getRolesForUser( this, user ), ownerRole ) );
342                registry.setRights( this, object, ownerRole, new Right[] { new Right( object, RightType.DELETE ),
343                                                                          new Right( object, RightType.UPDATE ),
344                                                                          new Right( object, RightType.GRANT ) } );
345            }
346            registry.setRights( this, object, adminRole, new Right[] { new Right( object, RightType.DELETE ),
347                                                                      new Right( object, RightType.UPDATE ),
348                                                                      new Right( object, RightType.GRANT ) } );
349            return object;
350        }
351    
352        /**
353         * Registers a new <code>User</code> to the <code>Registry</code>.
354         * 
355         * This means:
356         * <ul>
357         * <li>a user is created in the registry
358         * <li>a corresponding owner role is created: $U:USERNAME
359         * <li>rights for the owner role are set up; creator has delete, update and grant rights on the user, administrator
360         * role gets these right, too
361         * </ul>
362         * 
363         * NOTE: Only performed if acting user has the 'adduser'-privilege.
364         * 
365         * @param name
366         * @param password
367         *            null means that password checking is disabled
368         * @param lastName
369         * @param firstName
370         * @param mailAddress
371         * @return the new User
372         * @throws GeneralSecurityException
373         */
374        public User registerUser( String name, String password, String lastName, String firstName, String mailAddress )
375                                throws GeneralSecurityException {
376            SecurityAccessManager.getInstance().verify( this );
377            checkForPrivilege( Privilege.ADDUSER );
378            if ( name.startsWith( "$" ) ) {
379                throw new GeneralSecurityException( "Username '" + name + "' is invalid. The '$'-character is for "
380                                                    + "internal use only." );
381            }
382            User user = registry.registerUser( this, name, password, lastName, firstName, mailAddress );
383    
384            // only add owner role if lock holder is not the administrator
385            if ( this.user.getID() != User.ID_SEC_ADMIN ) {
386                Role ownerRole = registry.registerRole( this, "$U:" + name );
387                registry.setRolesForUser( this, user, addRoles( registry.getRolesForUser( this, user ), ownerRole ) );
388                registry.setRights( this, user, ownerRole, new Right[] { new Right( user, RightType.DELETE ),
389                                                                        new Right( user, RightType.UPDATE ),
390                                                                        new Right( user, RightType.GRANT ) } );
391            }
392            registry.setRights( this, user, adminRole, new Right[] { new Right( user, RightType.DELETE ),
393                                                                    new Right( user, RightType.UPDATE ),
394                                                                    new Right( user, RightType.GRANT ) } );
395            return user;
396        }
397    
398        /**
399         * Updates the data of an existing <code>User</code> in the <code>Registry</code>.
400         * 
401         * NOTE: Only performed if acting user has the 'update'-right on the user.
402         * 
403         * @param user
404         * @throws GeneralSecurityException
405         */
406        public void updateUser( User user )
407                                throws GeneralSecurityException {
408            SecurityAccessManager.getInstance().verify( this );
409            checkForRight( RightType.UPDATE, user );
410            registry.updateUser( this, user );
411        }
412    
413        /**
414         * Sets the <code>Group</code> s that a given <code>Group</code> is a DIRECT member of.
415         * 
416         * NOTE: Only performed if the acting user has the 'grant'-right for all the groups that are requested to be added /
417         * removed.
418         * 
419         * @param group
420         * @param newGroups
421         * @throws GeneralSecurityException
422         * @throws UnauthorizedException
423         */
424        public void setGroupsForGroup( Group group, Group[] newGroups )
425                                throws GeneralSecurityException, UnauthorizedException {
426            SecurityAccessManager.getInstance().verify( this );
427            Group[] oldGroups = group.getGroups( this );
428    
429            // build set for old groups
430            HashSet<Group> oldGroupSet = new HashSet<Group>( oldGroups.length );
431            for ( int i = 0; i < oldGroups.length; i++ ) {
432                oldGroupSet.add( oldGroups[i] );
433            }
434            // build set for new groups
435            HashSet<Group> newGroupSet = new HashSet<Group>( oldGroups.length );
436            for ( int i = 0; i < newGroups.length; i++ ) {
437                newGroupSet.add( newGroups[i] );
438            }
439    
440            // check grant right for all groups requested to be removed
441            Iterator<Group> it = oldGroupSet.iterator();
442            while ( it.hasNext() ) {
443                Group currGroup = it.next();
444                if ( !newGroupSet.contains( currGroup ) ) {
445                    checkForRight( RightType.GRANT, group );
446                }
447            }
448    
449            // check grant right for all groups requested to be added
450            it = newGroupSet.iterator();
451            while ( it.hasNext() ) {
452                Group currGroup = it.next();
453                if ( !oldGroupSet.contains( currGroup ) ) {
454                    checkForRight( RightType.GRANT, group );
455                }
456            }
457            registry.setGroupsForGroup( this, group, newGroups );
458        }
459    
460        /**
461         * Sets the <code>Groups</code> that a given <code>User</code> is a DIRECT member of.
462         * 
463         * NOTE: Only performed if the acting user has the 'grant'-right for all the groups that are requested to be added /
464         * removed.
465         * 
466         * @param user
467         * @param newGroups
468         * @throws GeneralSecurityException
469         * @throws UnauthorizedException
470         */
471        public void setGroupsForUser( User user, Group[] newGroups )
472                                throws GeneralSecurityException, UnauthorizedException {
473            SecurityAccessManager.getInstance().verify( this );
474            Group[] oldGroups = user.getGroups( this );
475    
476            // build set for old groups
477            HashSet<Group> oldGroupSet = new HashSet<Group>( oldGroups.length );
478            for ( int i = 0; i < oldGroups.length; i++ ) {
479                oldGroupSet.add( oldGroups[i] );
480            }
481            // build set for new groups
482            HashSet<Group> newGroupSet = new HashSet<Group>( oldGroups.length );
483            for ( int i = 0; i < newGroups.length; i++ ) {
484                newGroupSet.add( newGroups[i] );
485            }
486    
487            // check grant right for all groups requested to be removed
488            Iterator<Group> it = oldGroupSet.iterator();
489            while ( it.hasNext() ) {
490                Group group = it.next();
491                if ( !newGroupSet.contains( group ) ) {
492                    checkForRight( RightType.GRANT, group );
493                }
494            }
495    
496            // check grant right for all groups requested to be added
497            it = newGroupSet.iterator();
498            while ( it.hasNext() ) {
499                Group group = it.next();
500                if ( !oldGroupSet.contains( group ) ) {
501                    checkForRight( RightType.GRANT, group );
502                }
503            }
504            registry.setGroupsForUser( this, user, newGroups );
505        }
506    
507        /**
508         * Sets the members (groups) for a group.
509         * 
510         * NOTE: Only performed if the acting user has the 'grant'-right on the group.
511         * 
512         * @param group
513         * @param groups
514         * @throws GeneralSecurityException
515         * @throws UnauthorizedException
516         */
517        public void setGroupsInGroup( Group group, Group[] groups )
518                                throws GeneralSecurityException, UnauthorizedException {
519            SecurityAccessManager.getInstance().verify( this );
520            checkForRight( RightType.GRANT, group );
521            registry.setGroupsInGroup( this, group, groups );
522        }
523    
524        /**
525         * Sets the groups to be associated with the given role.
526         * 
527         * NOTE: Only performed if the acting user has the 'grant'-right on the role.
528         * 
529         * @param role
530         * @param groups
531         * @throws GeneralSecurityException
532         *             if not permitted
533         * @throws UnauthorizedException
534         */
535        public void setGroupsWithRole( Role role, Group[] groups )
536                                throws GeneralSecurityException, UnauthorizedException {
537            SecurityAccessManager.getInstance().verify( this );
538            checkForRight( RightType.GRANT, role );
539            registry.setGroupsWithRole( this, role, groups );
540        }
541    
542        /**
543         * Sets the privileges for a certain role.
544         * 
545         * NOTE: Only performed if the acting user has all the privileges he is trying to grant.
546         * 
547         * FIXME: Shouldn't that be "... to grant / withdraw"?
548         * 
549         * @param role
550         * @param privileges
551         * @throws GeneralSecurityException
552         *             if not permitted
553         */
554        public void setPrivilegesForRole( Role role, Privilege[] privileges )
555                                throws GeneralSecurityException {
556            SecurityAccessManager.getInstance().verify( this );
557            Privilege[] holderPrivileges = user.getPrivileges( this );
558            HashSet<Privilege> holderSet = new HashSet<Privilege>( holderPrivileges.length );
559            for ( int i = 0; i < holderPrivileges.length; i++ ) {
560                holderSet.add( holderPrivileges[i] );
561            }
562            for ( int i = 0; i < privileges.length; i++ ) {
563                if ( !holderSet.contains( privileges[i] ) ) {
564                    throw new GeneralSecurityException( "The requested operation requires the privilege '"
565                                                        + privileges[i].getName() + "'." );
566                }
567            }
568            registry.setPrivilegesForRole( this, role, privileges );
569        }
570    
571        /**
572         * @param transaction
573         * @param services
574         * @param role
575         * @throws GeneralSecurityException
576         */
577        public void setServicesRights( Collection<Integer> services, Role role )
578                                throws GeneralSecurityException {
579            SecurityAccessManager.getInstance().verify( this );
580            checkForRight( RightType.UPDATE, role );
581            registry.setServicesRights( this, services, role );
582        }
583    
584        /**
585         * Sets the <code>Rights</code> that a certain role has on a given object.
586         * 
587         * NOTE: Only performed if the acting user has the 'update'-right on the role and the 'grant'-right on the securable
588         * object.
589         * 
590         * @param object
591         * @param role
592         * @param rights
593         * @throws GeneralSecurityException
594         *             if not permitted
595         * @throws UnauthorizedException
596         */
597        public void setRights( SecurableObject object, Role role, Right[] rights )
598                                throws GeneralSecurityException, UnauthorizedException {
599            SecurityAccessManager.getInstance().verify( this );
600            checkForRight( RightType.UPDATE, role );
601            checkForRight( RightType.GRANT, object );
602            registry.setRights( this, object, role, rights );
603        }
604    
605        /**
606         * Sets one certain right that a certain role has on the given objects.
607         * 
608         * NOTE: Only performed if the acting user has the 'update'-right on the role and the 'grant'-right on the securable
609         * objects.
610         * 
611         * @param objects
612         * @param role
613         * @param right
614         * @throws GeneralSecurityException
615         *             if not permitted
616         * @throws UnauthorizedException
617         */
618        public void setRights( SecurableObject[] objects, Role role, Right right )
619                                throws GeneralSecurityException, UnauthorizedException {
620            SecurityAccessManager.getInstance().verify( this );
621            checkForRight( RightType.UPDATE, role );
622            for ( int i = 0; i < objects.length; i++ ) {
623                checkForRight( RightType.GRANT, objects[i] );
624            }
625            registry.setRights( this, objects, role, right );
626        }
627    
628        /**
629         * Adds the specified <code>Rights</code> on the passed object to the passed role. If they are already present,
630         * nothing happens.
631         * 
632         * @param object
633         * @param role
634         * @param additionalRights
635         * @throws GeneralSecurityException
636         * @throws UnauthorizedException
637         */
638        public void addRights( SecurableObject object, Role role, Right[] additionalRights )
639                                throws GeneralSecurityException, UnauthorizedException {
640            SecurityAccessManager.getInstance().verify( this );
641            checkForRight( RightType.UPDATE, role );
642            checkForRight( RightType.GRANT, object );
643            RightSet presentRights = new RightSet( registry.getRights( this, object, role ) );
644            RightSet newRights = presentRights.merge( new RightSet( additionalRights ) );
645            registry.setRights( this, object, role, newRights.toArray( object ) );
646        }
647    
648        /**
649         * Adds the specified <code>Rights</code> on the passed object to the passed role. If they are already present,
650         * nothing happens.
651         * 
652         * @param object
653         * @param role
654         * @param types
655         * @throws UnauthorizedException
656         * @throws GeneralSecurityException
657         */
658        public void addRights( SecurableObject object, Role role, RightType[] types )
659                                throws UnauthorizedException, GeneralSecurityException {
660            Right[] additionalRights = new Right[types.length];
661            for ( int i = 0; i < additionalRights.length; i++ ) {
662                additionalRights[i] = new Right( object, types[i] );
663            }
664            addRights( object, role, additionalRights );
665        }
666    
667        /**
668         * Removes all rights of the specified types that the role may have on the given <code>SecurableObject</code>.
669         * 
670         * @param object
671         * @param role
672         * @param types
673         * @throws GeneralSecurityException
674         * @throws UnauthorizedException
675         */
676        public void removeRights( SecurableObject object, Role role, RightType[] types )
677                                throws GeneralSecurityException, UnauthorizedException {
678            SecurityAccessManager.getInstance().verify( this );
679            checkForRight( RightType.UPDATE, role );
680            checkForRight( RightType.GRANT, object );
681    
682            Right[] rights = registry.getRights( this, object, role );
683            List<Right> newRightList = new ArrayList<Right>( 20 );
684            for ( int i = 0; i < rights.length; i++ ) {
685                RightType type = rights[i].getType();
686                boolean remove = true;
687                for ( int j = 0; j < types.length; j++ ) {
688                    if ( type.equals( types[j] ) ) {
689                        remove = true;
690                    }
691                }
692                if ( !remove ) {
693                    newRightList.add( rights[i] );
694                }
695            }
696            Right[] newRights = newRightList.toArray( new Right[newRightList.size()] );
697            registry.setRights( this, object, role, newRights );
698        }
699    
700        /**
701         * Sets the members (users) in a group.
702         * 
703         * NOTE: Only performed if the acting user has the 'grant'-right on the group.
704         * 
705         * @param group
706         * @param users
707         * @throws GeneralSecurityException
708         * @throws UnauthorizedException
709         */
710        public void setUsersInGroup( Group group, User[] users )
711                                throws GeneralSecurityException, UnauthorizedException {
712            SecurityAccessManager.getInstance().verify( this );
713            checkForRight( RightType.GRANT, group );
714            registry.setUsersInGroup( this, group, users );
715        }
716    
717        /**
718         * Sets the users to be associated with the given role (DIRECTLY, i.e. not via group memberships).
719         * 
720         * NOTE: Only performed if the user has the 'grant'-right on the role.
721         * 
722         * @param role
723         * @param users
724         * @throws GeneralSecurityException
725         *             if not permitted
726         * @throws UnauthorizedException
727         */
728        public void setUsersWithRole( Role role, User[] users )
729                                throws GeneralSecurityException, UnauthorizedException {
730            SecurityAccessManager.getInstance().verify( this );
731            checkForRight( RightType.GRANT, role );
732            registry.setUsersWithRole( this, role, users );
733        }
734    
735        @Override
736        public String toString() {
737            StringBuffer sb = new StringBuffer();
738            try {
739                User[] users = getAllUsers();
740    
741                sb.append( "\n\nSecurityAccess @ " + System.currentTimeMillis() );
742    
743                sb.append( "\n\n" ).append( users.length ).append( " registered users:\n" );
744                for ( int i = 0; i < users.length; i++ ) {
745                    sb.append( users[i].toString( this ) ).append( "\n" );
746                }
747                Group[] groups = getAllGroups();
748                sb.append( "\n" ).append( groups.length ).append( " registered groups:\n" );
749                for ( int i = 0; i < groups.length; i++ ) {
750                    sb.append( groups[i].toString( this ) ).append( "\n" );
751                }
752                Role[] roles = getAllRoles();
753                sb.append( "\n" ).append( roles.length ).append( " registered roles:\n" );
754                for ( int i = 0; i < roles.length; i++ ) {
755                    sb.append( roles[i].toString( this ) ).append( "\n" );
756                }
757            } catch ( Exception e ) {
758                e.printStackTrace();
759            }
760            return sb.toString();
761        }
762    
763        /**
764         * @param address
765         * @param title
766         * @param objects
767         * @param type
768         * @return the new service
769         * @throws GeneralSecurityException
770         */
771        public Service registerService( String address, String title, List<StringPair> objects, String type )
772                                throws GeneralSecurityException {
773            getInstance().verify( this );
774            checkForPrivilege( ADDOBJECT );
775            Service service = registry.registerService( this, address, title, objects, type );
776            return service;
777        }
778    
779        /**
780         * @param service
781         * @throws GeneralSecurityException
782         */
783        public void deregisterService( Service service )
784                                throws GeneralSecurityException {
785            getInstance().verify( this );
786            // it's probably not necessary to actually use the rights management for this
787            // checkForRight( DELETE, service );
788            registry.deregisterService( this, service );
789        }
790    
791        /**
792         * @param oldService
793         * @param newService
794         * @throws ReadWriteLockInvalidException
795         * @throws GeneralSecurityException
796         */
797        public void updateService( Service oldService, Service newService )
798                                throws ReadWriteLockInvalidException, GeneralSecurityException {
799            getInstance().verify( this );
800            registry.updateService( this, oldService, newService );
801        }
802    
803        /**
804         * @param service
805         * @param oldName
806         * @param newName
807         * @throws ReadWriteLockInvalidException
808         * @throws GeneralSecurityException
809         */
810        public void renameObject( Service service, String oldName, String newName )
811                                throws ReadWriteLockInvalidException, GeneralSecurityException {
812            getInstance().verify( this );
813            registry.renameObject( this, service, oldName, newName );
814        }
815    
816        /**
817         * @param service
818         * @param newTitle
819         * @param newAddress
820         * @throws GeneralSecurityException
821         */
822        public void editService( Service service, String newTitle, String newAddress )
823                                throws GeneralSecurityException {
824            getInstance().verify( this );
825            registry.editService( this, service, newTitle, newAddress );
826        }
827    
828        /**
829         *
830         */
831        void renew() {
832            this.timestamp = System.currentTimeMillis();
833        }
834    
835    }