Commit bd8840dc authored by jdeolive's avatar jdeolive
Browse files

Updates for GeoTools FeatureCollection api changes

parent 06bc9c77
......@@ -167,7 +167,7 @@ public abstract class ExcelOutputFormat extends WFSGetFeatureOutputFormat {
}
}
} finally {
fc.close(i);
i.close();
}
}
......
......@@ -195,9 +195,10 @@ public class HTMLImageMapWriter extends OutputStreamWriter {
} catch (NoSuchElementException ex) {
throw new DataSourceException(ex.getMessage(), ex);
} finally {
if(iter!=null)
//make sure we always close
fColl.close(iter);
if(iter!=null) {
//make sure we always close
iter.close();
}
}
}
......
......@@ -13,6 +13,7 @@ import java.util.List;
import org.geotools.data.DataUtilities;
import org.geotools.data.store.DataFeatureCollection;
import org.geotools.feature.FeatureCollection;
import org.geotools.feature.FeatureIterator;
import org.geotools.geometry.jts.ReferencedEnvelope;
import org.opengis.feature.simple.SimpleFeatureType;
import org.opengis.filter.identity.FeatureId;
......@@ -64,7 +65,7 @@ public class CompositeFeatureCollection extends DataFeatureCollection {
class CompositeIterator implements Iterator {
int index;
Iterator iterator;
FeatureIterator iterator;
public CompositeIterator() {
index = 0;
......@@ -83,11 +84,11 @@ public class CompositeFeatureCollection extends DataFeatureCollection {
while (index < collections.size()) {
//close current before we move to next
if (iterator != null) {
((FeatureCollection) collections.get(index - 1)).close(iterator);
iterator.close();
}
//grap next
iterator = ((FeatureCollection) collections.get(index++)).iterator();
iterator = ((FeatureCollection) collections.get(index++)).features();
if (iterator.hasNext()) {
return true;
......@@ -97,7 +98,7 @@ public class CompositeFeatureCollection extends DataFeatureCollection {
//no more
if (iterator != null) {
//close the last iterator
((FeatureCollection) collections.get(collections.size() - 1)).close(iterator);
iterator.close();
}
return false;
......@@ -108,43 +109,17 @@ public class CompositeFeatureCollection extends DataFeatureCollection {
}
}
public boolean addAll(Collection arg0) {
throw new RuntimeException("Can't add to a composite featurecollection; you need to add to one of the constituent collections direclty.");
}
public boolean removeAll(Collection arg0) {
Iterator it = collections.iterator();
boolean result = false;
while (it.hasNext()){
FeatureCollection col = (FeatureCollection)it.next();
result |= col.removeAll(arg0);
}
return result;
}
public boolean retainAll(Collection arg0) {
boolean result = false;
Iterator it = collections.iterator();
while (it.hasNext()){
FeatureCollection col = (FeatureCollection)it.next();
result |= col.removeAll(arg0);
}
return result;
}
public Object[] toArray(Object[] arg0) {
List list = new ArrayList();
Iterator it = collections.iterator();
while(it.hasNext()){
FeatureCollection col = (FeatureCollection)it.next();
Iterator it2 = col.iterator();
FeatureIterator it2 = col.features();
while (it2.hasNext()){
list.add(it.next());
}
col.close(it2);
it2.close();
}
return list.toArray(arg0);
......
......@@ -120,7 +120,7 @@ public class ReprojectingFeatureCollection extends DecoratingFeatureCollection {
visitor.visit(it.next());
}
} finally {
close(it);
it.close();
}
}
......@@ -132,24 +132,6 @@ public class ReprojectingFeatureCollection extends DecoratingFeatureCollection {
return new ReprojectingFeatureIterator(delegate.features());
}
public Iterator iterator() {
return new ReprojectingIterator(delegate.iterator());
}
public void close(SimpleFeatureIterator iterator) {
if (iterator instanceof ReprojectingFeatureIterator) {
delegate.close(((ReprojectingFeatureIterator) iterator).getDelegate());
}
iterator.close();
}
public void close(Iterator iterator) {
if (iterator instanceof ReprojectingIterator) {
delegate.close(((ReprojectingIterator) iterator).getDelegate());
}
}
public SimpleFeatureType getFeatureType() {
return schema;
}
......@@ -218,7 +200,7 @@ public class ReprojectingFeatureCollection extends DecoratingFeatureCollection {
public ReferencedEnvelope getBounds() {
ReferencedEnvelope bounds = null;
Iterator i = iterator();
SimpleFeatureIterator i = features();
try {
if (!i.hasNext()) {
......@@ -237,7 +219,7 @@ public class ReprojectingFeatureCollection extends DecoratingFeatureCollection {
return bounds;
} finally {
close(i);
i.close();
}
}
......@@ -339,6 +321,7 @@ public class ReprojectingFeatureCollection extends DecoratingFeatureCollection {
}
public void close() {
if (delegate != null) delegate.close();
delegate = null;
}
}
......
......@@ -12,6 +12,7 @@ import org.geotools.data.FeatureReader;
import org.geotools.data.FeatureWriter;
import org.geotools.data.simple.SimpleFeatureCollection;
import org.geotools.data.simple.SimpleFeatureIterator;
import org.geotools.feature.FeatureIterator;
import org.geotools.feature.IllegalAttributeException;
import org.geotools.feature.collection.DelegateSimpleFeatureIterator;
import org.geotools.feature.simple.SimpleFeatureBuilder;
......@@ -40,22 +41,8 @@ public class RetypingFeatureCollection extends DecoratingFeatureCollection {
return target;
}
public Iterator<SimpleFeature> iterator() {
return new RetypingIterator(delegate.iterator(), target);
}
public void close(Iterator<SimpleFeature> iterator) {
RetypingIterator retyping = (RetypingIterator) iterator;
delegate.close(retyping.delegate);
}
public SimpleFeatureIterator features() {
return new DelegateSimpleFeatureIterator(this, iterator());
}
public void close(SimpleFeatureIterator iterator) {
DelegateSimpleFeatureIterator delegate = (DelegateSimpleFeatureIterator) iterator;
delegate.close();
return new RetypingIterator(delegate.features(), target);
}
static SimpleFeature retype(SimpleFeature source, SimpleFeatureBuilder builder)
......@@ -102,11 +89,11 @@ public class RetypingFeatureCollection extends DecoratingFeatureCollection {
return sourceId;
}
public static class RetypingIterator implements Iterator<SimpleFeature> {
public static class RetypingIterator implements SimpleFeatureIterator {
SimpleFeatureBuilder builder;
Iterator<SimpleFeature> delegate;
SimpleFeatureIterator delegate;
public RetypingIterator(Iterator<SimpleFeature> delegate, SimpleFeatureType target) {
public RetypingIterator(SimpleFeatureIterator delegate, SimpleFeatureType target) {
this.delegate = delegate;
this.builder = new SimpleFeatureBuilder(target);
}
......@@ -123,8 +110,9 @@ public class RetypingFeatureCollection extends DecoratingFeatureCollection {
}
}
public void remove() {
delegate.remove();
@Override
public void close() {
delegate.close();
}
}
......
......@@ -43,11 +43,6 @@ class CheckAttributesFeatureCollection extends DecoratingSimpleFeatureCollection
return new CheckAttributesFeatureIterator(delegate.features(), writableAttributes);
}
@Override
public Iterator iterator() {
return new FeatureIteratorIterator<SimpleFeature>(features());
}
public class CheckAttributesFeatureIterator implements SimpleFeatureIterator {
SimpleFeatureIterator delegate;
......
......@@ -49,7 +49,6 @@ public class DefaultSecureDataFactory implements SecuredObjectFactory {
|| FeatureStore.class.isAssignableFrom(clazz)
|| FeatureLocking.class.isAssignableFrom(clazz)
|| FeatureCollection.class.isAssignableFrom(clazz)
|| Iterator.class.isAssignableFrom(clazz)
|| FeatureIterator.class.isAssignableFrom(clazz)
|| AbstractGridCoverage2DReader.class.isAssignableFrom(clazz)
|| AbstractGridFormat.class.isAssignableFrom(clazz)
......@@ -109,8 +108,6 @@ public class DefaultSecureDataFactory implements SecuredObjectFactory {
return new SecuredSimpleFeatureCollection((SimpleFeatureCollection) object, policy);
} else if (FeatureCollection.class.isAssignableFrom(clazz)) {
return new SecuredFeatureCollection((FeatureCollection) object, policy);
} else if (Iterator.class.isAssignableFrom(clazz)) {
return new SecuredIterator((Iterator) object, policy);
} else if (SimpleFeatureIterator.class.isAssignableFrom(clazz)) {
return new SecuredSimpleFeatureIterator((SimpleFeatureIterator) object);
} else if (FeatureIterator.class.isAssignableFrom(clazz)) {
......
......@@ -48,10 +48,6 @@ public class SecuredFeatureCollection<T extends FeatureType, F extends Feature>
this.policy = policy;
}
public Iterator iterator() {
return (Iterator) SecuredObjects.secure(delegate.iterator(), policy);
}
@Override
public org.geotools.feature.FeatureIterator<F> features() {
return (FeatureIterator) SecuredObjects.secure(delegate.features(), policy);
......@@ -73,137 +69,4 @@ public class SecuredFeatureCollection<T extends FeatureType, F extends Feature>
else
return (FeatureCollection) SecuredObjects.secure(fc, policy);
}
@Override
public void close(FeatureIterator<F> close) {
if(close instanceof Wrapper && ((Wrapper) close).isWrapperFor(FeatureIterator.class))
delegate.close(((Wrapper) close).unwrap(FeatureIterator.class));
else
delegate.close(close);
}
@Override
public void close(Iterator<F> close) {
if(close instanceof Wrapper && ((Wrapper) close).isWrapperFor(Iterator.class))
delegate.close(((Wrapper) close).unwrap(Iterator.class));
else
delegate.close(close);
}
// ---------------------------------------------------------------------
// Write related methods
// ---------------------------------------------------------------------
public boolean add(F o) {
Query writeQuery = getWriteQuery(policy);
final Filter filter = writeQuery.getFilter();
if(filter == Filter.EXCLUDE) {
throw unsupportedOperation();
} else {
if(filter.evaluate(o)) {
if(writeQuery.getPropertyNames() == Query.ALL_NAMES) {
return delegate.add(o);
} else {
// TODO: shave off attributes we cannot write
LOGGER.log(Level.SEVERE, "Unfinished implementation, we need to shave off " +
"the attributes one cannot write!");
return add(o);
}
} else {
return false;
}
}
}
public boolean addAll(Collection c) {
Query writeQuery = getWriteQuery(policy);
final Filter filter = writeQuery.getFilter();
if(filter == Filter.EXCLUDE) {
throw unsupportedOperation();
} else {
List filtered = filterCollection(c, writeQuery);
return addAll(filtered);
}
}
/**
* Filters out all features that cannot be modified/removed
* @param collection
* @param writeQuery
* @return
*/
List filterCollection(Collection collection, Query writeQuery) {
// warn about inability to shave off complex features
if(writeQuery.getPropertyNames() != Query.ALL_NAMES) {
LOGGER.log(Level.SEVERE, "Unfinished implementation, we need to shave off " +
"the attributes one cannot write!");
}
// filter out anything we cannot write
final Filter filter = writeQuery.getFilter();
List filtered = new ArrayList();
for (Object feature : collection) {
if(filter.evaluate(feature)) {
filtered.add(feature);
}
}
return filtered;
}
public void clear() {
Query writeQuery = getWriteQuery(policy);
final Filter filter = writeQuery.getFilter();
if(filter == Filter.EXCLUDE) {
throw unsupportedOperation();
} else {
delegate.clear();
}
}
public boolean remove(Object o) {
Query writeQuery = getWriteQuery(policy);
final Filter filter = writeQuery.getFilter();
if(filter == Filter.EXCLUDE) {
throw unsupportedOperation();
} else {
if(filter.evaluate(o)) {
return delegate.remove(o);
} else {
return false;
}
}
}
public boolean removeAll(Collection c) {
Query writeQuery = getWriteQuery(policy);
final Filter filter = writeQuery.getFilter();
if(filter == Filter.EXCLUDE) {
throw unsupportedOperation();
} else {
List filtered = filterCollection(c, writeQuery);
return removeAll(filtered);
}
}
public boolean retainAll(Collection c) {
// way too inefficient and fancy to implement, besides nothing in GS uses it and
// even ContentFeatureCollection does not implement it, so just let it go, we'll
// cross this bridge when necessary
throw new UnsupportedOperationException("Sorry, not even ContentFeatureCollection implements this one");
}
/**
* Notifies the caller the requested operation is not supported, using a plain {@link UnsupportedOperationException}
* in case we have to conceal the fact the data is actually writable, using an Spring security exception otherwise
* to force an authentication from the user
*/
RuntimeException unsupportedOperation() {
String typeName = getID();
if(policy.response == Response.CHALLENGE) {
return SecureCatalogImpl.unauthorizedAccess(typeName);
} else
return new UnsupportedOperationException("Feature type " + typeName + " is read only");
}
}
......@@ -19,6 +19,8 @@ import org.opengis.filter.Filter;
* Applies the write policy to removals
* @author Andrea Aime - GeoSolutions
*
* @deprecated This class is not longer used, {@link SecuredFeatureIterator} and
* {@ SecuredSimpleFeatureIterator} are used instead.
*/
public class SecuredIterator extends AbstractDecorator<Iterator> implements Iterator,FeatureIterator {
WrapperPolicy policy;
......
package org.geoserver.security.decorators;
import java.util.Iterator;
import java.util.NoSuchElementException;
import org.geotools.data.simple.SimpleFeatureIterator;
......@@ -12,7 +13,7 @@ import org.opengis.feature.simple.SimpleFeature;
*
* @author Josh Vote, CSIRO Earth Science and Resource Engineering
*/
public class SecuredSimpleFeatureIterator implements SimpleFeatureIterator {
public class SecuredSimpleFeatureIterator implements SimpleFeatureIterator, Iterator<SimpleFeature> {
SimpleFeatureIterator wrapped;
......@@ -32,4 +33,8 @@ public class SecuredSimpleFeatureIterator implements SimpleFeatureIterator {
return wrapped.next();
}
@Override
public void remove() {
throw new UnsupportedOperationException();
}
}
package org.geoserver.security.decorators;
import static org.easymock.EasyMock.anyObject;
import static org.easymock.EasyMock.createNiceMock;
import static org.easymock.EasyMock.expect;
import static org.easymock.EasyMock.replay;
......@@ -10,102 +11,97 @@ import java.util.Iterator;
import org.geoserver.security.WrapperPolicy;
import org.geoserver.security.impl.SecureObjectsTest;
import org.geotools.data.FeatureStore;
import org.geotools.data.Query;
import org.geotools.feature.DefaultFeatureCollection;
import org.geotools.feature.FeatureCollection;
import org.geotools.feature.FeatureIterator;
import org.geotools.feature.NameImpl;
import org.geotools.filter.text.ecql.ECQL;
import org.junit.Before;
import org.junit.Test;
import org.opengis.feature.Feature;
import org.opengis.feature.simple.SimpleFeature;
import org.opengis.feature.simple.SimpleFeatureType;
import org.opengis.filter.Filter;
import org.opengis.filter.sort.SortBy;
public class SecuredFeatureCollectionTest extends SecureObjectsTest {
private FeatureCollection fc;
private FeatureStore store;
private Feature feature;
private SortBy sort;
private SimpleFeature feature;
@Before
public void setUp() throws Exception {
feature = createNiceMock(Feature.class);
replay(feature);
Iterator it = createNiceMock(Iterator.class);
replay(it);
sort = createNiceMock(SortBy.class);
replay(sort);
SimpleFeatureType schema = createNiceMock(SimpleFeatureType.class);
expect(schema.getTypeName()).andReturn("testSchema").anyTimes();
expect(schema.getName()).andReturn(new NameImpl("testSchema")).anyTimes();
replay(schema);
fc = createNiceMock(FeatureCollection.class);
expect(fc.iterator()).andReturn(it).anyTimes();
feature = createNiceMock(SimpleFeature.class);
expect(feature.getID()).andReturn("testSchema.1").anyTimes();
expect(feature.getType()).andReturn(schema).anyTimes();
expect(feature.getFeatureType()).andReturn(schema).anyTimes();
replay(feature);
DefaultFeatureCollection fc = new DefaultFeatureCollection();
fc.add(feature);
store = createNiceMock(FeatureStore.class);
expect(store.getSchema()).andReturn(schema).anyTimes();
expect(store.getFeatures()).andReturn(fc).anyTimes();
expect(store.getFeatures((Filter)anyObject())).andReturn(fc).anyTimes();
expect(store.getFeatures((Query)anyObject())).andReturn(fc).anyTimes();
replay(store);
/*expect(fc.features()).andReturn(it).anyTimes();
expect(fc.sort(sort)).andReturn(fc).anyTimes();
expect(fc.subCollection(Filter.INCLUDE)).andReturn(fc).anyTimes();
expect(fc.getSchema()).andReturn(schema).anyTimes();
replay(fc);
replay(fc);*/
}
@Test
public void testHide() throws Exception {
SecuredFeatureCollection ro = new SecuredFeatureCollection(fc, WrapperPolicy.hide(null));
SecuredFeatureStore ro = new SecuredFeatureStore(store, WrapperPolicy.hide(null));
DefaultFeatureCollection fc = new DefaultFeatureCollection();
fc.add(feature);
// check the easy ones, those that are not implemented in a read only
// collection
try {
ro.add(feature);
fail("Should have failed with an UnsupportedOperationException");
} catch (UnsupportedOperationException e) {
// ok
}
try {
ro.addAll(new ArrayList());
fail("Should have failed with an UnsupportedOperationException");
} catch (UnsupportedOperationException e) {
// ok
}
try {
ro.clear();
fail("Should have failed with an UnsupportedOperationException");
} catch (UnsupportedOperationException e) {
// ok
}
try {
ro.remove(feature);
fail("Should have failed with an UnsupportedOperationException");
} catch (UnsupportedOperationException e) {
// ok
}
try {
ro.removeAll(new ArrayList());
ro.addFeatures(fc);
fail("Should have failed with an UnsupportedOperationException");
} catch (UnsupportedOperationException e) {
// ok
}
try {
ro.retainAll(new ArrayList());
ro.removeFeatures(Filter.INCLUDE);
fail("Should have failed with an UnsupportedOperationException");
} catch (UnsupportedOperationException e) {
// ok
}
}</