001    //$HeadURL: svn+ssh://rbezema@svn.wald.intevation.org/deegree/base/branches/2.2_testing/src/org/deegree/security/drm/model/Right.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.model;
044    
045    import org.deegree.framework.log.ILogger;
046    import org.deegree.framework.log.LoggerFactory;
047    import org.deegree.model.feature.Feature;
048    import org.deegree.model.filterencoding.ComplexFilter;
049    import org.deegree.model.filterencoding.Filter;
050    import org.deegree.model.filterencoding.FilterEvaluationException;
051    import org.deegree.model.filterencoding.OperationDefines;
052    import org.deegree.security.GeneralSecurityException;
053    
054    /**
055     * A <code>Right</code> instance encapsulates a <code>SecurableObject</code>, a
056     * <code>RightType</code> and optional constraints which restrict it's applicability.
057     * <p>
058     * For example, one instance of a <code>RightSet</code> may be the 'access'-Right to a geographic
059     * dataset restricted to a certain area and weekdays. The situation (requested area and current
060     * time) is coded as a <code>Feature</code> object.
061     * 
062     * @author <a href="mailto:mschneider@lat-lon.de">Markus Schneider </a>
063     * @version $Revision: 9346 $
064     */
065    
066    public class Right {
067        
068        private ILogger LOG = LoggerFactory.getLogger( Right.class );
069    
070        private SecurableObject object;
071    
072        private RightType type;
073    
074        private Filter constraints;
075    
076        /**
077         * Creates a new <code>Right</code> -instance (with no constraints).
078         * 
079         * @param object
080         * @param type
081         */
082        public Right( SecurableObject object, RightType type ) {
083            this.object = object;
084            this.type = type;
085        }
086    
087        /**
088         * Creates a new <code>Right</code> -instance.
089         * 
090         * @param object
091         * @param type
092         * @param constraints
093         *            null means that no constraints are defined
094         */
095        public Right( SecurableObject object, RightType type, Filter constraints ) {
096            this( object, type );
097            this.constraints = constraints;
098        }
099    
100        /**
101         * Returns the associated <code>SecurableObject</code>.
102         */
103        public SecurableObject getSecurableObject() {
104            return object;
105        }
106    
107        /**
108         * Returns the associated <code>RightType</code>.
109         * 
110         */
111        public RightType getType() {
112            return type;
113        }
114    
115        /**
116         * Returns the restrictions (the parameters) of this <code>Right</code>.
117         * 
118         * @return null, if no constraints are defined
119         * 
120         */
121        public Filter getConstraints() {
122            return constraints;
123        }
124    
125        /**
126         * Generates the disjunctive combination of the instance and the submitted <code>Right</code>,
127         * so that the new <code>Right</code> has the permissions of both instances.
128         * 
129         * @param that
130         */
131        public Right merge( Right that )
132                                throws GeneralSecurityException {
133            Right combinedRight = null;
134    
135            if ( !this.object.equals( that.object ) ) {
136                throw new GeneralSecurityException( "Trying to merge right on securable object '" + this.object.id
137                                                    + "' and on object '" + that.object.id
138                                                    + "', but only rights on the same object may be merged." );
139            }
140            if ( this.type.getID() != that.type.getID() ) {
141                throw new GeneralSecurityException( "Trying to merge right of type '" + this.type.getName()
142                                                    + "' and right of type '" + that.type.getName()
143                                                    + "', but only rights of the same type may be merged." );
144            }
145    
146            // check if any of the rights has no constraints
147            if ( this.constraints == null && that.constraints == null ) {
148                combinedRight = new Right( object, type, null );
149            } else if ( this.constraints == null && that.constraints != null ) {
150                combinedRight = new Right( object, type, that.constraints );
151            } else if ( this.constraints != null && that.constraints == null ) {
152                combinedRight = new Right( object, type, this.constraints );
153            } else if ( that.constraints == null ) {
154                combinedRight = that;
155            } else {
156                Filter combinedConstraints = new ComplexFilter( (ComplexFilter) this.constraints,
157                                                                (ComplexFilter) that.constraints, OperationDefines.OR );
158                combinedRight = new Right( object, type, combinedConstraints );
159    
160            }
161            return combinedRight;
162        }
163    
164        /**
165         * Checks if the <code>Right</code> applies on the given <code>SecurableObject</code> and in
166         * a concrete situation (the situation is represented by the given <code>Feature</code>).
167         * 
168         * @param object
169         * @param situation
170         * @throws GeneralSecurityException
171         */
172        public boolean applies( SecurableObject object, Feature situation )
173                                throws GeneralSecurityException {
174            boolean applies = false;
175            if ( object.equals( this.object ) ) {
176                try {
177                    if ( constraints != null ) {
178                        if ( LOG.getLevel() == ILogger.LOG_DEBUG ) {
179                            LOG.logDebug( "constraints: ", constraints.toXML() );
180                        }
181                        applies = constraints.evaluate( situation );
182                    } else {
183                        LOG.logDebug( "no constraints" );
184                        applies = true;
185                    }
186                } catch ( FilterEvaluationException e ) {
187                    LOG.logError( e.getMessage(), e );
188                    throw new GeneralSecurityException( "Error evaluating parameters (filter expression): "
189                                                        + e.getMessage() );
190                }
191            }
192            return applies;
193        }
194    
195        /**
196         * Checks if the <code>Right</code> applies on the given <code>SecurableObject</code> and in
197         * unrestricted manner (w/o constraints).
198         * 
199         * @param object
200         * @throws GeneralSecurityException
201         */
202        public boolean applies( SecurableObject object ) {
203            boolean applies = false;
204            if ( object.equals( this.object ) ) {
205                if ( constraints == null ) {
206                    applies = true;
207                }
208            }
209            return applies;
210        }
211    
212        /**
213         * Returns a <code>String</code> representation of this object.
214         */
215        public String toString() {
216            StringBuffer sb = new StringBuffer( "Id: " ).append( type.getID() ).append( ", Name: " ).append( type.getName() ).append(
217                                                                                                                                      ", " );
218            if ( constraints != null ) {
219                sb.append( "Constraints: " + constraints.toXML() );
220            } else {
221                sb.append( "Constraints: none" );
222            }
223            return sb.toString();
224        }
225    }