/* * GeoTools - The Open Source Java GIS Toolkit * http://geotools.org * * (C) 2008, Open Source Geospatial Foundation (OSGeo) * * 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; * version 2.1 of the License. * * 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. */ package org.geotools.jdbc; import java.util.Collections; import org.geotools.data.DefaultQuery; import org.geotools.data.DefaultTransaction; import org.geotools.data.FeatureLock; import org.geotools.data.FeatureLockException; import org.geotools.data.FeatureLockFactory; import org.geotools.data.FeatureReader; import org.geotools.data.FeatureWriter; import org.geotools.data.Transaction; import org.opengis.feature.simple.SimpleFeature; import org.opengis.feature.simple.SimpleFeatureType; import org.opengis.feature.type.AttributeDescriptor; import org.opengis.filter.Filter; import org.opengis.filter.FilterFactory; import org.opengis.filter.PropertyIsEqualTo; public abstract class JDBCFeatureLockingTest extends JDBCTestSupport { JDBCFeatureStore store; protected void connect() throws Exception { super.connect(); store = (JDBCFeatureStore) dataStore.getFeatureSource(tname("ft1")); store.setFeatureLock(FeatureLock.TRANSACTION); } public void testLockFeatures() throws Exception { FeatureLock lock = FeatureLockFactory.generate(tname("ft1"), 60 * 60 * 1000); Transaction tx = new DefaultTransaction(); store.setTransaction( tx ); store.setFeatureLock(lock); //lock features int locked = store.lockFeatures(); assertTrue( locked > 0 ); //grabbing a reader should be no problem DefaultQuery query = new DefaultQuery( tname("ft1") ); FeatureReader<SimpleFeatureType, SimpleFeature> reader = dataStore.getFeatureReader(query,tx); int count = 0; while( reader.hasNext() ) { count++; reader.next(); } assertTrue( count > 0 ); reader.close(); //grab a writer FeatureWriter<SimpleFeatureType, SimpleFeature> writer = dataStore.getFeatureWriter(tname("ft1"), tx ); assertTrue( writer.hasNext() ); SimpleFeature feature = writer.next(); feature.setAttribute(aname("intProperty"), new Integer(100) ); try { writer.write(); fail( "should have thrown feature lock exception" ); } catch( FeatureLockException e ) { //good } finally { writer.close(); } tx.addAuthorization(lock.getAuthorization()); writer = dataStore.getFeatureWriter(tname("ft1"), tx); assertTrue( writer.hasNext() ); feature = writer.next(); feature.setAttribute(aname("intProperty"), new Integer(100) ); writer.write(); writer.close(); tx.close(); } public void testLockFeaturesWithFilter() throws Exception { FeatureLock lock = FeatureLockFactory.generate(tname("ft1"), 60 * 60 * 1000); Transaction tx = new DefaultTransaction(); store.setTransaction( tx ); store.setFeatureLock(lock); //lock features FilterFactory ff = dataStore.getFilterFactory(); PropertyIsEqualTo f = ff.equals(ff.property(aname("intProperty")), ff.literal(1)); int locked = store.lockFeatures( f ); assertEquals( 1, locked ); //grabbing a reader should be no problem FeatureWriter<SimpleFeatureType, SimpleFeature> writer = dataStore.getFeatureWriter(tname("ft1"), tx); boolean failure = false; while( writer.hasNext() ) { SimpleFeature feature = (SimpleFeature) writer.next(); Number old = (Number) feature.getAttribute(aname("intProperty")); feature.setAttribute(aname("intProperty"), new Integer(100)); if ( new Integer(1).equals( old.intValue() ) ) { try { writer.write(); fail( "writer should have thrown exception for locked feature"); } catch( FeatureLockException e ) { failure = true; } } else { writer.write(); } } writer.close(); assertTrue( failure ); tx.close(); } public void testLockFeaturesWithInvalidFilter() throws Exception { FeatureLock lock = FeatureLockFactory.generate(tname("ft1"), 60 * 60 * 1000); Transaction tx = new DefaultTransaction(); store.setTransaction( tx ); store.setFeatureLock(lock); //lock features FilterFactory ff = dataStore.getFilterFactory(); PropertyIsEqualTo f = ff.equals(ff.property(aname("invalidProperty")), ff.literal(1)); try { store.lockFeatures( f ); fail("Should have failed with an exception, the filter is not valid"); } catch(Exception e) { // fine } tx.close(); } public void testLockFeaturesWithInvalidQuery() throws Exception { FeatureLock lock = FeatureLockFactory.generate(tname("ft1"), 60 * 60 * 1000); Transaction tx = new DefaultTransaction(); store.setTransaction( tx ); store.setFeatureLock(lock); //lock features FilterFactory ff = dataStore.getFilterFactory(); PropertyIsEqualTo f = ff.equals(ff.property(aname("invalidProperty")), ff.literal(1)); try { store.lockFeatures( new DefaultQuery(store.getSchema().getTypeName(), f) ); fail("Should have failed with an exception, the filter is not valid"); } catch(Exception e) { // fine } tx.close(); } public void testUnlockFeatures() throws Exception { FeatureLock lock = FeatureLockFactory.generate(tname("ft1"), 60 * 60 * 1000); Transaction tx = new DefaultTransaction(); store.setTransaction( tx ); store.setFeatureLock(lock); store.lockFeatures(); FeatureWriter<SimpleFeatureType, SimpleFeature> writer = dataStore.getFeatureWriter(tname("ft1"), tx ); assertTrue( writer.hasNext() ); SimpleFeature feature = writer.next(); feature.setAttribute( aname("intProperty"), new Integer(100) ); try { writer.write(); fail( "write should have thrown exception"); } catch( FeatureLockException e) { } finally { writer.close(); } try { store.unLockFeatures(); fail( "unlock should have thrown an exception"); } catch( FeatureLockException e ) {} tx.addAuthorization(lock.getAuthorization()); store.unLockFeatures(); writer = dataStore.getFeatureWriter(tname("ft1"), tx ); assertTrue( writer.hasNext() ); feature = writer.next(); feature.setAttribute( aname("intProperty"), new Integer(100) ); writer.write(); writer.close(); tx.close(); } public void testUnlockFeaturesInvalidFilter() throws Exception { FeatureLock lock = FeatureLockFactory.generate(tname("ft1"), 60 * 60 * 1000); Transaction tx = new DefaultTransaction(); store.setTransaction( tx ); store.setFeatureLock(lock); tx.addAuthorization(lock.getAuthorization()); store.lockFeatures(); // uhnlock features FilterFactory ff = dataStore.getFilterFactory(); PropertyIsEqualTo f = ff.equals(ff.property(aname("invalidProperty")), ff.literal(1)); try { store.unLockFeatures(new DefaultQuery(store.getSchema().getTypeName(), f) ); fail("Should have failed with an exception, the filter is not valid"); } catch(Exception e) { // fine } store.unLockFeatures(); tx.close(); } public void testDeleteLockedFeatures() throws Exception { FeatureLock lock = FeatureLockFactory.generate(tname("ft1"), 60 * 60 * 1000); Transaction tx = new DefaultTransaction(); store.setTransaction( tx ); store.setFeatureLock(lock); tx.addAuthorization(lock.getAuthorization()); FilterFactory ff = dataStore.getFilterFactory(); Filter f1 = ff.id( Collections.singleton( ff.featureId( tname("ft1")+".1"))); assertEquals( 1, store.lockFeatures(f1) ); Transaction tx1 = new DefaultTransaction(); store.setTransaction( tx1 ); try { store.removeFeatures( f1 ); fail( "Locked feature should not be deleted."); } catch( FeatureLockException e ) {} tx1.close(); store.setTransaction( tx ); store.removeFeatures( f1 ); tx.commit(); tx.close(); } public void testModifyLockedFeatures() throws Exception { FilterFactory ff = dataStore.getFilterFactory(); Filter f0 = ff.equal( ff.property( aname("intProperty" ) ), ff.literal(1000), true); assertEquals( 0 , store.getCount( new DefaultQuery( tname("ft1"), f0 ) )); FeatureLock lock = FeatureLockFactory.generate(tname("ft1"), 60 * 60 * 1000); Transaction tx = new DefaultTransaction(); store.setTransaction( tx ); store.setFeatureLock(lock); tx.addAuthorization(lock.getAuthorization()); Filter f1 = ff.id( Collections.singleton( ff.featureId( tname("ft1")+".1"))); store.lockFeatures(f1); Transaction tx1 = new DefaultTransaction(); store.setTransaction( tx1 ); AttributeDescriptor ad = store.getSchema().getDescriptor( aname( "intProperty") ); Integer v = new Integer(1000); try { store.modifyFeatures(ad, v, f1 ); fail( "Locked feature should not be modified."); } catch( FeatureLockException e ) {} tx1.close(); store.setTransaction( tx ); store.modifyFeatures(ad, v, f1 ); tx.commit(); assertEquals( 1 , store.getCount( new DefaultQuery( tname("ft1"), f0 ) )); tx.close(); } }