/*---------------- FILE HEADER ------------------------------------------ This file is part of deegree. Copyright (C) 2001-2006 by: EXSE, Department of Geography, University of Bonn http://www.giub.uni-bonn.de/deegree/ lat/lon GmbH http://www.lat-lon.de This library is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. This library is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public License along with this library; if not, write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA Contact: Andreas Poth lat/lon GmbH Aennchenstr. 19 53177 Bonn Germany E-Mail: poth@lat-lon.de Prof. Dr. Klaus Greve Department of Geography University of Bonn Meckenheimer Allee 166 53115 Bonn Germany E-Mail: greve@giub.uni-bonn.de ---------------------------------------------------------------------------*/ package org.deegree.security.owsrequestvalidator.csw; import java.net.URI; import java.util.ArrayList; import java.util.List; import org.deegree.datatypes.QualifiedName; import org.deegree.datatypes.Types; import org.deegree.framework.util.StringTools; import org.deegree.model.feature.Feature; import org.deegree.model.feature.FeatureFactory; import org.deegree.model.feature.FeatureProperty; import org.deegree.model.feature.schema.FeatureType; import org.deegree.model.feature.schema.PropertyType; import org.deegree.ogcwebservices.InvalidParameterValueException; import org.deegree.ogcwebservices.OGCWebServiceRequest; import org.deegree.ogcwebservices.csw.manager.Delete; import org.deegree.ogcwebservices.csw.manager.Insert; import org.deegree.ogcwebservices.csw.manager.Operation; import org.deegree.ogcwebservices.csw.manager.Transaction; import org.deegree.ogcwebservices.csw.manager.Update; import org.deegree.portal.standard.security.control.ClientHelper; import org.deegree.security.UnauthorizedException; import org.deegree.security.drm.model.RightType; import org.deegree.security.drm.model.User; import org.deegree.security.owsproxy.Condition; import org.deegree.security.owsproxy.OperationParameter; import org.deegree.security.owsproxy.Request; import org.deegree.security.owsrequestvalidator.Messages; import org.deegree.security.owsrequestvalidator.Policy; import org.w3c.dom.Element; /** * Validator for OGC CSW Transaction requests. It will validated values of:<br> * <ul> * <li>service version</li> * <li>operation</li> * <li>type names</li> * <li>metadata standard</li> * </ul> * * @version $Revision: 1.5 $ * @author <a href="mailto:poth@lat-lon.de">Andreas Poth</a> * @author last edited by: $Author: poth $ * * @version 1.0. $Revision: 1.5 $, $Date: 2006/08/14 13:39:02 $ * * @since 2.0 */ public class TransactionValidator extends AbstractCSWRequestValidator { private final static String METADATAFORMAT = "metadataFormat"; private final static String TYPENAME = "typeName"; private static FeatureType insertFT = null; private static FeatureType updateFT = null; private static FeatureType deleteFT = null; static { if ( insertFT == null ) { insertFT = TransactionValidator.createInsertFeatureType(); } if ( updateFT == null ) { updateFT = TransactionValidator.createUpdateFeatureType(); } if ( deleteFT == null ) { deleteFT = TransactionValidator.createDeleteFeatureType(); } } /** * * @param policy */ public TransactionValidator( Policy policy ) { super( policy ); } @Override public void validateRequest( OGCWebServiceRequest request, User user ) throws InvalidParameterValueException, UnauthorizedException { userCoupled = false; Transaction cswreq = (Transaction) request; List<Operation> ops = cswreq.getOperations(); for ( int i = 0; i < ops.size(); i++ ) { userCoupled = false; if ( ops.get( i ) instanceof Insert ) { Request req = policy.getRequest( "CSW", "CSW_Insert" ); if ( !req.isAny() ) { Condition condition = req.getPreConditions(); validateOperation( condition, (Insert) ops.get( i ) ); } if ( userCoupled ) { validateAgainstRightsDB( (Insert) ops.get( i ), user ); } } else if ( ops.get( i ) instanceof Update ) { Request req = policy.getRequest( "CSW", "CSW_Update" ); if ( !req.isAny() ) { Condition condition = req.getPreConditions(); validateOperation( condition, (Update) ops.get( i ) ); } if ( userCoupled ) { validateAgainstRightsDB( (Update) ops.get( i ), user ); } } else if ( ops.get( i ) instanceof Delete ) { Request req = policy.getRequest( "CSW", "CSW_Delete" ); if ( !req.isAny() ) { Condition condition = req.getPreConditions(); validateOperation( condition, (Delete) ops.get( i ) ); } if ( userCoupled ) { validateAgainstRightsDB( (Delete) ops.get( i ), user ); } } } } /** * * @param condition * @param insert * @throws InvalidParameterValueException */ private void validateOperation( Condition condition, Insert insert ) throws InvalidParameterValueException { OperationParameter op = condition.getOperationParameter( METADATAFORMAT ); // version is valid because no restrictions are made if ( op.isAny() ) { return; } List vals = op.getValues(); List<Element> records = insert.getRecords(); for ( int i = 0; i < records.size(); i++ ) { String name = records.get( i ).getLocalName(); String ns = records.get( i ).getNamespaceURI(); String qn = StringTools.concat( 200, '{', ns, "}:", name ); if ( !vals.contains( qn ) ) { if ( !op.isUserCoupled() ) { String s = Messages.format( "CSWTransactionValidator.INVALIDMETADATAFORMAT", qn ); throw new InvalidParameterValueException( s ); } userCoupled = true; break; } } } /** * * @param condition * @param delete * @throws InvalidParameterValueException */ private void validateOperation( Condition condition, Delete delete ) throws InvalidParameterValueException { OperationParameter op = condition.getOperationParameter( TYPENAME ); // version is valid because no restrictions are made if ( op.isAny() ) return; URI typeName = delete.getTypeName(); if ( typeName == null ) { String s = Messages.getString( "CSWTransactionValidator.INVALIDDELETETYPENAME1" ); throw new InvalidParameterValueException( s ); } List vals = op.getValues(); if ( !vals.contains( typeName.toASCIIString() ) ) { if ( !op.isUserCoupled() ) { String s = Messages.format( "CSWTransactionValidator.INVALIDDELETETYPENAME2", typeName ); throw new InvalidParameterValueException( s ); } userCoupled = true; } } /** * * @param condition * @param update * @throws InvalidParameterValueException */ private void validateOperation( Condition condition, Update update ) throws InvalidParameterValueException { URI typeName = update.getTypeName(); Element record = update.getRecord(); if ( typeName == null && record == null ) { String s = Messages.getString( "CSWTransactionValidator.INVALIDUPDATETYPENAME1" ); throw new InvalidParameterValueException( s ); } OperationParameter op = condition.getOperationParameter( TYPENAME ); List vals = op.getValues(); if ( typeName != null && !vals.contains( typeName.toASCIIString() ) ) { // version is valid because no restrictions are made if ( op.isAny() ) { return; } if ( !op.isUserCoupled() ) { String s = Messages.format( "CSWTransactionValidator.INVALIDUPDATETYPENAME2", typeName ); throw new InvalidParameterValueException( s ); } userCoupled = true; } else { op = condition.getOperationParameter( METADATAFORMAT ); // version is valid because no restrictions are made if ( op.isAny() ) { return; } vals = op.getValues(); String name = record.getLocalName(); String ns = record.getNamespaceURI(); String qn = StringTools.concat( 200, '{', ns, "}:", name ); if ( !vals.contains( qn ) ) { if ( !op.isUserCoupled() ) { String s = Messages.format( "CSWTransactionValidator.INVALIDMETADATAFORMAT", qn ); throw new InvalidParameterValueException( s ); } userCoupled = true; } } } /** * validates a Transcation.Delete request against the underlying users and * rights management system * @param delete * @param version * @param user * @throws InvalidParameterValueException * @throws UnauthorizedException */ private void validateAgainstRightsDB( Delete delete, User user ) throws InvalidParameterValueException, UnauthorizedException { if ( user == null ) { throw new UnauthorizedException( Messages.getString( "RequestValidator.NOACCESS" ) ); } // create a feature instance from the parameters of the GetRecords request // to enable comparsion with a filter encoding expression stored in the // assigned rights management system List<FeatureProperty> fps = new ArrayList<FeatureProperty>(); URI typeName = delete.getTypeName(); String tn = null; if ( typeName != null ) { tn = typeName.toASCIIString(); } FeatureProperty fp = FeatureFactory.createFeatureProperty( "typeName", tn ); fps.add( fp ); Feature feature = FeatureFactory.createFeature( "id", insertFT, fps ); handleUserCoupledRules( user, //the user who posted the request feature, //This is the Database feature //the name the metadataFormat to be deleted "{http://www.opengis.net/cat/csw}:profil", ClientHelper.TYPE_METADATASCHEMA, //a primary key in the db. RightType.DELETE );//We're requesting a featuretype. } /** * validates a Transcation.Update request against the underlying users and * rights management system * @param update * @param user */ private void validateAgainstRightsDB( Update update, User user ) { throw new NoSuchMethodError( getClass().getName() + ".validateAgainstRightsDB not implemented yet" ); } /** * validates the passed insert operation against the deegree user/rights * management system * * @param insert * @param version * @param user * @throws InvalidParameterValueException * @throws UnauthorizedException */ private void validateAgainstRightsDB( Insert insert, User user ) throws InvalidParameterValueException, UnauthorizedException { if ( user == null ) { throw new UnauthorizedException( Messages.getString( "RequestValidator.NOACCESS" ) ); } // create a feature instance from the parameters of the GetRecords request // to enable comparsion with a filter encoding expression stored in the // assigned rights management system List<FeatureProperty> fps = new ArrayList<FeatureProperty>(); FeatureProperty fp = null; fps.add( fp ); Feature feature = FeatureFactory.createFeature( "id", insertFT, fps ); List<Element> records = insert.getRecords(); for ( int i = 0; i < records.size(); i++ ) { String name = records.get( i ).getLocalName(); String ns = records.get( i ).getNamespaceURI(); String qn = StringTools.concat( 200, '{', ns, "}:", name ); handleUserCoupledRules( user, //the user who posted the request feature, //This is the Database feature qn, //the Qualified name of the users Featurerequest ClientHelper.TYPE_METADATASCHEMA, //a primary key in the db. RightType.INSERT );//We're requesting a featuretype. } } /** * creates a feature type that matches the parameters of a Insert operation * * @return created <tt>FeatureType</tt> */ private static FeatureType createInsertFeatureType() { PropertyType[] ftps = new PropertyType[1]; ftps[0] = FeatureFactory.createSimplePropertyType( new QualifiedName( "metadataFormat" ), Types.VARCHAR, false ); return FeatureFactory.createFeatureType( "CSW_Insert", false, ftps ); } /** * creates a feature type that matches the parameters of a Update operation * * @return created <tt>FeatureType</tt> */ private static FeatureType createUpdateFeatureType() { PropertyType[] ftps = new PropertyType[2]; ftps[0] = FeatureFactory.createSimplePropertyType( new QualifiedName( "metadataFormat" ), Types.VARCHAR, false ); ftps[1] = FeatureFactory.createSimplePropertyType( new QualifiedName( "typeName" ), Types.VARCHAR, false ); return FeatureFactory.createFeatureType( "CSW_Update", false, ftps ); } /** * creates a feature type that matches the parameters of a Delete operation * * @return created <tt>FeatureType</tt> */ private static FeatureType createDeleteFeatureType() { PropertyType[] ftps = new PropertyType[1]; ftps[0] = FeatureFactory.createSimplePropertyType( new QualifiedName( "typeName" ), Types.VARCHAR, false ); return FeatureFactory.createFeatureType( "CSW_Delete", false, ftps ); } } /* ******************************************************************** Changes to this class. What the people have been up to: $Log: TransactionValidator.java,v $ Revision 1.5 2006/08/14 13:39:02 poth bug fix - removing version from tested parameters / corrected reading of policy parameter lists Revision 1.4 2006/08/10 07:17:52 poth bug fix - removing Arrays.asList calls for transforming op.geValues because accoring to refactoring this method it already returns a list Revision 1.3 2006/08/03 16:40:36 poth code formated Revision 1.2 2006/08/03 08:04:07 poth support for validating delete requests against user and rights managemend system Revision 1.1 2006/07/23 08:44:53 poth refactoring - moved validators assigned to OWS into specialized packages ********************************************************************** */