/* (c) 2014 Open Source Geospatial Foundation - all rights reserved
* This code is licensed under the GPL 2.0 license, available at the root
* application directory.
*/
package org.geoserver.wps.executor;
import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method;
import java.lang.reflect.Proxy;
import org.geoserver.wps.ProcessDismissedException;
import org.geotools.data.simple.SimpleFeatureCollection;
import org.geotools.data.simple.SimpleFeatureIterator;
import org.geotools.feature.FeatureCollection;
import org.geotools.feature.FeatureIterator;
import org.opengis.util.ProgressListener;
/**
* Helper class that builds a intercepting proxy around feature collections, the proxy will start
* throwing exceptions as soon as the ProgressListener is cancelled
*
* @author Andrea Aime - GeoSolutions
*/
class CancellingFeatureCollectionBuilder {
public static SimpleFeatureCollection wrap(final FeatureCollection delegate,
final ProgressListener listener) {
InvocationHandler cancellingInvocationHandler = new CancellingInvocationHandler(listener,
delegate);
Class[] interfaces;
if (delegate instanceof SimpleFeatureCollection) {
interfaces = new Class[] { SimpleFeatureCollection.class };
} else {
interfaces = new Class[] { FeatureCollection.class };
}
SimpleFeatureCollection proxy = (SimpleFeatureCollection) Proxy.newProxyInstance(
CancellingFeatureCollectionBuilder.class.getClassLoader(), interfaces,
cancellingInvocationHandler);
return proxy;
}
private static class CancellingInvocationHandler implements InvocationHandler {
ProgressListener listener;
Object delegate;
public CancellingInvocationHandler(ProgressListener listener, Object delegate) {
this.listener = listener;
this.delegate = delegate;
}
@Override
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
if (listener.isCanceled()) {
throw new ProcessDismissedException(listener);
}
Object result = method.invoke(delegate, args);
// wrap feature iterators into cancelling bits too
if (result instanceof FeatureIterator<?>) {
Class[] interfaces;
if (result instanceof SimpleFeatureIterator) {
interfaces = new Class[] { SimpleFeatureIterator.class };
} else {
interfaces = new Class[] { FeatureIterator.class };
}
result = Proxy.newProxyInstance(CancellingFeatureCollectionBuilder.class.getClassLoader(),
interfaces, new CancellingInvocationHandler(listener, result));
}
return result;
}
}
}