001    //$HeadURL: https://svn.wald.intevation.org/svn/deegree/base/branches/2.3_testing/src/org/deegree/security/drm/model/RightSet.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.model;
037    
038    import java.util.ArrayList;
039    import java.util.HashMap;
040    import java.util.Iterator;
041    import java.util.Map;
042    
043    import org.deegree.model.feature.Feature;
044    import org.deegree.security.GeneralSecurityException;
045    
046    /**
047     * A <code>RightSet</code> encapsulates a number of <code>Right</code> objects. This are grouped
048     * by the <code>SecurableObject</code> for which they apply to support an efficient implementation
049     * of the merge()-operation. The merge()-operation results in a <code>RightSet</code> that
050     * contains the logical rights of boths sets, but only one <code>Right</code> object of each
051     * <code>RightType</code> (and <code>SecurableObject</code>). This is accomplished by merging
052     * the constraints of the <code>Rights</code> of the same type (and object).
053     *
054     * @author <a href="mailto:mschneider@lat-lon.de">Markus Schneider </a>
055     * @version $Revision: 18195 $
056     */
057    public class RightSet {
058    
059        // keys are SecurableObjects (for which the rights are defined), values
060        // are Maps (keys are RightTypes, values are Rights)
061        private Map<SecurableObject, Map<RightType, Right>> secObjects = new HashMap<SecurableObject, Map<RightType, Right>>();
062    
063        RightSet() {
064        }
065    
066        /**
067         * @param rights
068         */
069        public RightSet( Right[] rights ) {
070            for ( int i = 0; i < rights.length; i++ ) {
071                Map<RightType, Right> rightMap = secObjects.get( rights[i].getSecurableObject() );
072                if ( rightMap == null ) {
073                    rightMap = new HashMap<RightType, Right>();
074                }
075                rightMap.put( rights[i].getType(), rights[i] );
076                secObjects.put( rights[i].getSecurableObject(), rightMap );
077            }
078        }
079    
080        /**
081         * Checks if the <code>RightSet</code> contains the permissions for a
082         * <code>SecurableObject</code> and a concrete situation (the situation is represented by the
083         * given <code>Feature</code>).
084         *
085         * @param object
086         * @param type
087         * @param situation
088         * @return true, if the right applies
089         * @throws GeneralSecurityException
090         */
091        public boolean applies( SecurableObject object, RightType type, Feature situation )
092                                throws GeneralSecurityException {
093            boolean applies = false;
094            Map<RightType, Right> rightMap = secObjects.get( object );
095            if ( rightMap != null ) {
096                Right right = rightMap.get( type );
097                if ( right != null ) {
098                    applies = right.applies( object, situation );
099                }
100            }
101            return applies;
102        }
103    
104        /**
105         * Checks if the <code>RightSet</code> contains the (unrestricted) permissions for a
106         * <code>SecurableObject</code> and a certain type of right.
107         *
108         * @param object
109         * @param type
110         * @return true, if the right applies
111         */
112        public boolean applies( SecurableObject object, RightType type ) {
113            boolean applies = false;
114            Map<RightType, Right> rightMap = secObjects.get( object );
115            if ( rightMap != null ) {
116                Right right = rightMap.get( type );
117                if ( right != null ) {
118                    applies = right.applies( object );
119                }
120    
121            }
122            return applies;
123        }
124    
125        /**
126         * @param secObject
127         * @param type
128         * @return the <code>Right</code> of the specified <code>RightType</code> that this
129         * <code>RightSet</code> defines on the specified <code>SecurableObject</code>.
130         */
131        public Right getRight( SecurableObject secObject, RightType type ) {
132            Right right = null;
133            if ( secObjects.get( secObject ) != null ) {
134                right = secObjects.get( secObject ).get( type );
135            }
136            return right;
137        }
138    
139        /**
140         * @param secObject
141         * @return the encapulated <code>Rights</code> (for one <code>SecurableObject</code>) as an
142         * one-dimensional array.
143         */
144        public Right[] toArray( SecurableObject secObject ) {
145            Right[] rights = new Right[0];
146            Map<RightType, Right> rightMap = secObjects.get( secObject );
147            if ( rightMap != null ) {
148                rights = rightMap.values().toArray( new Right[rightMap.size()] );
149            }
150            return rights;
151        }
152    
153        /**
154         * @return the encapulated <code>Rights</code> as a two-dimensional array:
155         * <ul>
156         * <li>first index: runs the different <code>SecurableObjects</code>
157         * <li>second index: runs the different <code>Rights</code>
158         * </ul>
159         */
160        public Right[][] toArray2() {
161            ArrayList<Right[]> secObjectList = new ArrayList<Right[]>();
162            Iterator<Map<RightType, Right>> it = secObjects.values().iterator();
163            while ( it.hasNext() ) {
164                Map<RightType, Right> rightMap = it.next();
165                Right[] rights = rightMap.values().toArray( new Right[rightMap.size()] );
166                secObjectList.add( rights );
167            }
168            return secObjectList.toArray( new Right[secObjectList.size()][] );
169        }
170    
171        /**
172         * Produces the logical disjunction of two <code>RightSets</code>.
173         *
174         * @param that
175         * @return the new right set
176         */
177        public RightSet merge( RightSet that ) {
178    
179            ArrayList<Right> mergedRights = new ArrayList<Right>( 20 );
180            Iterator<SecurableObject> secObjectsIt = this.secObjects.keySet().iterator();
181    
182            // add all rights from 'this' (and merge them with corresponding right
183            // from 'that')
184            while ( secObjectsIt.hasNext() ) {
185                SecurableObject secObject = secObjectsIt.next();
186                Map<RightType, Right> thisRightMap = this.secObjects.get( secObject );
187                Map<RightType, Right> thatRightMap = that.secObjects.get( secObject );
188                Iterator<RightType> rightIt = ( thisRightMap ).keySet().iterator();
189                while ( rightIt.hasNext() ) {
190                    RightType type = rightIt.next();
191                    Right mergedRight = thisRightMap.get( type );
192    
193                    // find corresponding Right (if any) in the other RightSet
194                    if ( thatRightMap != null && thatRightMap.get( type ) != null ) {
195                        try {
196                            mergedRight = mergedRight.merge( thatRightMap.get( type ) );
197                        } catch ( GeneralSecurityException e ) {
198                            e.printStackTrace();
199                        }
200                    }
201                    mergedRights.add( mergedRight );
202                }
203            }
204    
205            // add role rights from 'that'
206            secObjectsIt = that.secObjects.keySet().iterator();
207            while ( secObjectsIt.hasNext() ) {
208                SecurableObject secObject = secObjectsIt.next();
209                Map<RightType, Right> thisRightMap = this.secObjects.get( secObject );
210                Map<RightType, Right> thatRightMap = that.secObjects.get( secObject );
211    
212                Iterator<RightType> it = thatRightMap.keySet().iterator();
213                while ( it.hasNext() ) {
214                    Object o = it.next();
215                    RightType type = (RightType) o;
216                    // find corresponding Right (if none, add)
217                    if ( thisRightMap == null || thisRightMap.get( type ) == null ) {
218                        mergedRights.add( thatRightMap.get( type ) );
219                    }
220                }
221            }
222            return new RightSet( mergedRights.toArray( new Right[mergedRights.size()] ) );
223        }
224    
225        @Override
226        public String toString() {
227            StringBuffer sb = new StringBuffer( "RightSet:" );
228            Iterator<SecurableObject> it = secObjects.keySet().iterator();
229            while ( it.hasNext() ) {
230                SecurableObject secObject = it.next();
231                sb.append( "on SecurableObject " ).append( secObject ).append( "\n" );
232                Map<RightType, Right> rightMap = secObjects.get( secObject );
233                Iterator<RightType> rights = rightMap.keySet().iterator();
234                while ( rights.hasNext() ) {
235                    RightType rightType = rights.next();
236                    sb.append( "- Right " ).append( rightMap.get( rightType ) ).append( "\n" );
237                }
238            }
239            return sb.toString();
240        }
241    
242    }