001    //$HeadURL: svn+ssh://rbezema@svn.wald.intevation.org/deegree/base/branches/2.2_testing/src/org/deegree/security/drm/SecurityAccess.java $
002    /*----------------    FILE HEADER  ------------------------------------------
003    
004     This file is part of deegree.
005     Copyright (C) 2001-2008 by:
006     EXSE, Department of Geography, University of Bonn
007     http://www.giub.uni-bonn.de/deegree/
008     lat/lon GmbH
009     http://www.lat-lon.de
010    
011     This library is free software; you can redistribute it and/or
012     modify it under the terms of the GNU Lesser General Public
013     License as published by the Free Software Foundation; either
014     version 2.1 of the License, or (at your option) any later version.
015    
016     This library is distributed in the hope that it will be useful,
017     but WITHOUT ANY WARRANTY; without even the implied warranty of
018     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
019     Lesser General Public License for more details.
020    
021     You should have received a copy of the GNU Lesser General Public
022     License along with this library; if not, write to the Free Software
023     Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
024    
025     Contact:
026    
027     Andreas Poth
028     lat/lon GmbH
029     Aennchenstr. 19
030     53115 Bonn
031     Germany
032     E-Mail: poth@lat-lon.de
033    
034     Prof. Dr. Klaus Greve
035     Department of Geography
036     University of Bonn
037     Meckenheimer Allee 166
038     53115 Bonn
039     Germany
040     E-Mail: greve@giub.uni-bonn.de
041    
042     ---------------------------------------------------------------------------*/
043    package org.deegree.security.drm;
044    
045    import java.util.HashSet;
046    import java.util.Iterator;
047    import java.util.Stack;
048    
049    import org.deegree.security.GeneralSecurityException;
050    import org.deegree.security.UnauthorizedException;
051    import org.deegree.security.drm.model.Group;
052    import org.deegree.security.drm.model.Privilege;
053    import org.deegree.security.drm.model.RightType;
054    import org.deegree.security.drm.model.Role;
055    import org.deegree.security.drm.model.SecurableObject;
056    import org.deegree.security.drm.model.SecuredObject;
057    import org.deegree.security.drm.model.User;
058    
059    /**
060     * 
061     * 
062     * 
063     * @version $Revision: 9346 $
064     * @author <a href="mailto:poth@lat-lon.de">Andreas Poth</a>
065     * @author last edited by: $Author: apoth $
066     * 
067     * @version 1.0. $Revision: 9346 $, $Date: 2007-12-27 17:39:07 +0100 (Do, 27 Dez 2007) $
068     * 
069     * @since 2.0
070     */
071    public class SecurityAccess {
072    
073        protected User user;
074    
075        protected SecurityRegistry registry;
076    
077        SecurityAccess( User user, SecurityRegistry registry ) {
078            this.user = user;
079            this.registry = registry;
080        }
081    
082        public User getUser() {
083            return user;
084        }
085    
086        public User getUserByName( String name )
087                                throws GeneralSecurityException {
088            return registry.getUserByName( this, name );
089        }
090    
091        public User getUserById( int id )
092                                throws GeneralSecurityException {
093            return registry.getUserById( this, id );
094        }
095    
096        public Group getGroupByName( String name )
097                                throws GeneralSecurityException {
098            return registry.getGroupByName( this, name );
099        }
100    
101        public Group getGroupById( int id )
102                                throws GeneralSecurityException {
103            return registry.getGroupById( this, id );
104        }
105    
106        public Role getRoleByName( String name )
107                                throws GeneralSecurityException {
108            return registry.getRoleByName( this, name );
109        }
110    
111        public Role[] getRolesByNS( String ns )
112                                throws GeneralSecurityException {
113            return registry.getRolesByNS( this, ns );
114        }
115    
116        public Role getRoleById( int id )
117                                throws GeneralSecurityException {
118            return registry.getRoleById( this, id );
119        }
120    
121        public RightType getRightByName( String name )
122                                throws GeneralSecurityException {
123            return registry.getRightTypeByName( this, name );
124        }
125    
126        public Privilege getPrivilegeByName( String name )
127                                throws GeneralSecurityException {
128            return registry.getPrivilegeByName( this, name );
129        }
130    
131        public SecuredObject getSecuredObjectById( int id )
132                                throws GeneralSecurityException {
133            return registry.getSecuredObjectById( this, id );
134        }
135    
136        public SecuredObject getSecuredObjectByName( String name, String type )
137                                throws GeneralSecurityException {
138            return registry.getSecuredObjectByName( this, name, type );
139        }
140    
141        public SecuredObject[] getSecuredObjectsByNS( String ns, String type )
142                                throws GeneralSecurityException {
143            return registry.getSecuredObjectsByNS( this, ns, type );
144        }
145    
146        public User[] getAllUsers()
147                                throws GeneralSecurityException {
148            return registry.getAllUsers( this );
149        }
150    
151        public Group[] getAllGroups()
152                                throws GeneralSecurityException {
153            return registry.getAllGroups( this );
154        }
155    
156        public SecuredObject[] getAllSecuredObjects( String type )
157                                throws GeneralSecurityException {
158            return registry.getAllSecuredObjects( this, type );
159        }
160    
161        /**
162         * Retrieves all <code>Role</code> s from the <code>Registry</code>, except those that are
163         * only used internally (these have a namespace starting with the $ symbol);
164         * 
165         * @throws GeneralSecurityException
166         */
167        public Role[] getAllRoles()
168                                throws GeneralSecurityException {
169            return registry.getAllRoles( this );
170        }
171    
172        /**
173         * Returns all <code>Role</code> s that the given <code>User</code> is associated with
174         * (directly and via group memberships).
175         * 
176         * @param user
177         * @throws GeneralSecurityException
178         */
179        public Role[] getAllRolesForUser( User user )
180                                throws GeneralSecurityException {
181    
182            HashSet<Group> allGroups = new HashSet<Group>();
183            Stack<Group> groupStack = new Stack<Group>();
184            Group[] groups = registry.getGroupsForUser( this, user );
185            for ( int i = 0; i < groups.length; i++ ) {
186                groupStack.push( groups[i] );
187            }
188    
189            // collect all groups that user is member of
190            while ( !groupStack.isEmpty() ) {
191                Group currentGroup = groupStack.pop();
192                allGroups.add( currentGroup );
193                groups = registry.getGroupsForGroup( this, currentGroup );
194                for ( int i = 0; i < groups.length; i++ ) {
195                    if ( !allGroups.contains( groups[i] ) ) {
196                        allGroups.add( groups[i] );
197                        groupStack.push( groups[i] );
198                    }
199                }
200            }
201    
202            HashSet<Role> allRoles = new HashSet<Role>();
203    
204            // add all directly associated roles
205            Role[] roles = registry.getRolesForUser( this, user );
206            for ( int i = 0; i < roles.length; i++ ) {
207                allRoles.add( roles[i] );
208            }
209    
210            // add all roles that are associated via group membership
211            Iterator it = allGroups.iterator();
212            while ( it.hasNext() ) {
213                Group group = (Group) it.next();
214                roles = registry.getRolesForGroup( this, group );
215                for ( int i = 0; i < roles.length; i++ ) {
216                    allRoles.add( roles[i] );
217                }
218            }
219            return allRoles.toArray( new Role[allRoles.size()] );
220        }
221    
222        /**
223         * Returns all <code>Role</code> s that the given <code>Group</code> is associated with
224         * (directly and via group memberships).
225         * 
226         * @param group
227         * @throws GeneralSecurityException
228         */
229        public Role[] getAllRolesForGroup( Group group )
230                                throws GeneralSecurityException {
231    
232            HashSet<Group> allGroups = new HashSet<Group>();
233            Stack<Group> groupStack = new Stack<Group>();
234            groupStack.push( group );
235    
236            while ( !groupStack.isEmpty() ) {
237                Group currentGroup = groupStack.pop();
238                Group[] groups = registry.getGroupsForGroup( this, currentGroup );
239                for ( int i = 0; i < groups.length; i++ ) {
240                    if ( !allGroups.contains( groups[i] ) ) {
241                        allGroups.add( groups[i] );
242                        groupStack.push( groups[i] );
243                    }
244                }
245            }
246    
247            HashSet<Role> allRoles = new HashSet<Role>();
248            Iterator it = allGroups.iterator();
249            while ( it.hasNext() ) {
250                Role[] roles = registry.getRolesForGroup( this, (Group) it.next() );
251                for ( int i = 0; i < roles.length; i++ ) {
252                    allRoles.add( roles[i] );
253                }
254            }
255            return allRoles.toArray( new Role[allRoles.size()] );
256        }
257    
258        /**
259         * Tries to find a cyle in the groups relations of the <code>Registry</code>.
260         * 
261         * @return indicates the cycle's nodes (groups)
262         */
263        public Group[] findGroupCycle()
264                                throws GeneralSecurityException {
265            Group[] allGroups = getAllGroups();
266            for ( int i = 0; i < allGroups.length; i++ ) {
267                Stack<Group> path = new Stack<Group>();
268                if ( findGroupCycle( allGroups[i], path ) ) {
269                    return path.toArray( new Group[path.size()] );
270                }
271            }
272            return null;
273        }
274    
275        /**
276         * Recursion part for the <code>findGroupCycle</code> -algorithm.
277         * <p>
278         * Modified depth first search.
279         * 
280         * @param group
281         * @param path
282         * @return
283         * @throws GeneralSecurityException
284         */
285        private boolean findGroupCycle( Group group, Stack<Group> path )
286                                throws GeneralSecurityException {
287            if ( path.contains( group ) ) {
288                path.push( group );
289                return true;
290            }
291            path.push( group );
292            Group[] members = registry.getGroupsForGroup( this, group );
293            for ( int i = 0; i < members.length; i++ ) {
294                if ( findGroupCycle( members[i], path ) ) {
295                    return true;
296                }
297            }
298            path.pop();
299            return false;
300        }
301    
302        /**
303         * Checks if the associated <code>User</code> has a certain <code>Privilege</code>.
304         * 
305         * @param privilege
306         * @throws GeneralSecurityException
307         *             if holder does not have the privilege
308         */
309        protected void checkForPrivilege( Privilege privilege )
310                                throws GeneralSecurityException {
311            if ( !user.hasPrivilege( this, privilege ) ) {
312                throw new GeneralSecurityException( "The requested operation requires the privilege '"
313                                                    + privilege.getName() + "'." );
314            }
315        }
316    
317        /**
318         * Checks if the associated <code>User</code> has a certain <code>Right</code> on the given
319         * <code>SecurableObject</code>.
320         * 
321         * @param right
322         * @param object
323         * @throws GeneralSecurityException
324         *             this is a UnauthorizedException if the holder does not have the right
325         */
326        protected void checkForRight( RightType right, SecurableObject object )
327                                throws UnauthorizedException, GeneralSecurityException {
328            if ( !user.hasRight( this, right, object ) ) {
329                throw new UnauthorizedException( "The requested operation requires the right '" + right.getName()
330                                                 + "' on the object '" + object.getName() + "'." );
331            }
332        }
333    }