/* Copyright (c) 2001 - 2013 OpenPlans - www.openplans.org. All rights reserved.
* This code is licensed under the GPL 2.0 license, available at the root
* application directory.
*/
package org.geoserver.wps;
import static junit.framework.Assert.assertEquals;
import static junit.framework.Assert.assertNotNull;
import static junit.framework.Assert.assertTrue;
import static org.custommonkey.xmlunit.XMLAssert.assertXpathEvaluatesTo;
import static org.custommonkey.xmlunit.XMLAssert.assertXpathExists;
import static org.geoserver.data.test.MockData.PRIMITIVEGEOFEATURE;
import java.io.ByteArrayInputStream;
import java.io.IOException;
import java.io.InputStream;
import java.net.URL;
import java.net.URLEncoder;
import java.util.HashMap;
import java.util.HashSet;
import java.util.Iterator;
import java.util.Set;
import java.util.zip.ZipEntry;
import java.util.zip.ZipInputStream;
import javax.xml.namespace.QName;
import net.opengis.ows11.BoundingBoxType;
import org.custommonkey.xmlunit.XMLUnit;
import org.custommonkey.xmlunit.XpathEngine;
import org.custommonkey.xmlunit.exceptions.XpathException;
import org.geoserver.data.test.MockData;
import org.geoserver.data.test.SystemTestData;
import org.geoserver.data.test.SystemTestData.LayerProperty;
import org.geoserver.test.RemoteOWSTestSupport;
import org.geotools.data.collection.ListFeatureCollection;
import org.geotools.data.simple.SimpleFeatureIterator;
import org.geotools.feature.FeatureCollection;
import org.geotools.feature.simple.SimpleFeatureTypeBuilder;
import org.geotools.geojson.feature.FeatureJSON;
import org.geotools.geometry.jts.ReferencedEnvelope;
import org.geotools.gml3.GMLConfiguration;
import org.geotools.ows.v1_1.OWSConfiguration;
import org.geotools.process.ProcessException;
import org.geotools.referencing.CRS;
import org.geotools.referencing.crs.DefaultGeographicCRS;
import org.geotools.xml.Parser;
import org.junit.Before;
import org.junit.Test;
import org.opengis.feature.simple.SimpleFeatureType;
import org.w3c.dom.Document;
import com.mockrunner.mock.web.MockHttpServletResponse;
import com.vividsolutions.jts.geom.Geometry;
import com.vividsolutions.jts.geom.Point;
import com.vividsolutions.jts.geom.Polygon;
import com.vividsolutions.jts.io.WKTReader;
public class ExecuteTest extends WPSTestSupport {
@Override
protected void onSetUp(SystemTestData testData) throws Exception {
super.onSetUp(testData);
testData.addVectorLayer(SystemTestData.PRIMITIVEGEOFEATURE, getCatalog());
String pgf = PRIMITIVEGEOFEATURE.getLocalPart();
testData.addVectorLayer(new QName("http://foo.org", pgf, "foo" ), new HashMap<LayerProperty,Object>(), pgf + ".properties", MockData.class, getCatalog());
}
@Before
public void oneTimeSetUp() throws Exception {
WPSInfo wps = getGeoServer().getService(WPSInfo.class);
// want at least two asynchronous processes to test concurrency
wps.setMaxAsynchronousProcesses(Math.max(2, wps.getMaxAsynchronousProcesses()));
getGeoServer().save(wps);
}
@Before
public void setUpInternal() throws Exception {
// make extra sure we don't have anything else going
MonkeyProcess.clearCommands();
}
/* TODO GET requests A.4.4.1 */
@Test
public void testDataInline() throws Exception { // Standard Test A.4.4.2, A.4.4.4
String xml =
"<wps:Execute service='WPS' version='1.0.0' xmlns:wps='http://www.opengis.net/wps/1.0.0' " +
"xmlns:ows='http://www.opengis.net/ows/1.1'>" +
"<ows:Identifier>JTS:buffer</ows:Identifier>" +
"<wps:DataInputs>" +
"<wps:Input>" +
"<ows:Identifier>distance</ows:Identifier>" +
"<wps:Data>" +
"<wps:LiteralData>1</wps:LiteralData>" +
"</wps:Data>" +
"</wps:Input>" +
"<wps:Input>" +
"<ows:Identifier>geom</ows:Identifier>" +
"<wps:Data>" +
"<wps:ComplexData>" +
"<gml:Polygon xmlns:gml='http://www.opengis.net/gml'>" +
"<gml:exterior>" +
"<gml:LinearRing>" +
"<gml:coordinates>1 1 2 1 2 2 1 2 1 1</gml:coordinates>" +
"</gml:LinearRing>" +
"</gml:exterior>" +
"</gml:Polygon>" +
"</wps:ComplexData>" +
"</wps:Data>" +
"</wps:Input>" +
"</wps:DataInputs>" +
"<wps:ResponseForm>" +
"<wps:ResponseDocument storeExecuteResponse='false'>" +
"<wps:Output>" +
"<ows:Identifier>result</ows:Identifier>" +
"</wps:Output>" +
"</wps:ResponseDocument>" +
"</wps:ResponseForm>" +
"</wps:Execute>";
// System.out.println(xml);
Document d = postAsDOM( "wps", xml );
checkValidationErrors(d);
assertEquals( "wps:ExecuteResponse", d.getDocumentElement().getNodeName() );
assertXpathExists( "/wps:ExecuteResponse/wps:Status/wps:ProcessSucceeded", d);
assertXpathExists(
"/wps:ExecuteResponse/wps:ProcessOutputs/wps:Output/wps:Data/wps:ComplexData/gml:Polygon", d);
}
@Test
public void testDataInlineRawOutput() throws Exception { // Standard Test A.4.4.3
String xml =
"<wps:Execute service='WPS' version='1.0.0' xmlns:wps='http://www.opengis.net/wps/1.0.0' " +
"xmlns:ows='http://www.opengis.net/ows/1.1'>" +
"<ows:Identifier>JTS:buffer</ows:Identifier>" +
"<wps:DataInputs>" +
"<wps:Input>" +
"<ows:Identifier>distance</ows:Identifier>" +
"<wps:Data>" +
"<wps:LiteralData>1</wps:LiteralData>" +
"</wps:Data>" +
"</wps:Input>" +
"<wps:Input>" +
"<ows:Identifier>geom</ows:Identifier>" +
"<wps:Data>" +
"<wps:ComplexData>" +
"<gml:Polygon xmlns:gml='http://www.opengis.net/gml'>" +
"<gml:exterior>" +
"<gml:LinearRing>" +
"<gml:coordinates>1 1 2 1 2 2 1 2 1 1</gml:coordinates>" +
"</gml:LinearRing>" +
"</gml:exterior>" +
"</gml:Polygon>" +
"</wps:ComplexData>" +
"</wps:Data>" +
"</wps:Input>" +
"</wps:DataInputs>" +
"<wps:ResponseForm>" +
" <wps:RawDataOutput>" +
" <ows:Identifier>result</ows:Identifier>" +
" </wps:RawDataOutput>" +
" </wps:ResponseForm>" +
"</wps:Execute>";
Document d = postAsDOM( "wps", xml );
// print(d);
checkValidationErrors(d, new GMLConfiguration());
assertEquals( "gml:Polygon", d.getDocumentElement().getNodeName() );
}
@Test
public void testWKTInlineRawOutput() throws Exception { // Standard Test A.4.4.3
String xml =
"<wps:Execute service='WPS' version='1.0.0' xmlns:wps='http://www.opengis.net/wps/1.0.0' " +
"xmlns:ows='http://www.opengis.net/ows/1.1'>" +
"<ows:Identifier>JTS:buffer</ows:Identifier>" +
"<wps:DataInputs>" +
"<wps:Input>" +
"<ows:Identifier>distance</ows:Identifier>" +
"<wps:Data>" +
"<wps:LiteralData>1</wps:LiteralData>" +
"</wps:Data>" +
"</wps:Input>" +
"<wps:Input>" +
"<ows:Identifier>geom</ows:Identifier>" +
"<wps:Data>" +
"<wps:ComplexData mimeType=\"application/wkt\">" +
"<![CDATA[POLYGON((1 1, 2 1, 2 2, 1 2, 1 1))]]>" +
"</wps:ComplexData>" +
"</wps:Data>" +
"</wps:Input>" +
"</wps:DataInputs>" +
"<wps:ResponseForm>" +
" <wps:RawDataOutput mimeType=\"application/wkt\">" +
" <ows:Identifier>result</ows:Identifier>" +
" </wps:RawDataOutput>" +
" </wps:ResponseForm>" +
"</wps:Execute>";
// print(dom(new StringInputStream("<?xml version=\"1.0\" encoding=\"UTF-16\"?>\n" + xml)));
MockHttpServletResponse response = postAsServletResponse( "wps", xml );
System.out.println(response.getOutputStreamContent());
assertEquals("application/wkt", response.getContentType());
Geometry g = new WKTReader().read(response.getOutputStreamContent());
assertTrue(g instanceof Polygon);
}
@Test
public void testWKTInlineKVPRawOutput() throws Exception {
String request = "wps?service=WPS&version=1.0.0&request=Execute&Identifier=JTS:buffer" +
"&DataInputs=" + urlEncode("geom=POLYGON((1 1, 2 1, 2 2, 1 2, 1 1))@mimetype=application/wkt;distance=1") +
"&RawDataOutput=" + urlEncode("result=@mimetype=application/wkt");
MockHttpServletResponse response = getAsServletResponse(request);
// System.out.println(response.getOutputStreamContent());
assertEquals("application/wkt", response.getContentType());
Geometry g = new WKTReader().read(response.getOutputStreamContent());
assertTrue(g instanceof Polygon);
}
@Test
public void testFeatureCollectionInline() throws Exception { // Standard Test A.4.4.2, A.4.4.4
String xml = "<wps:Execute service='WPS' version='1.0.0' xmlns:wps='http://www.opengis.net/wps/1.0.0' " +
"xmlns:ows='http://www.opengis.net/ows/1.1'>" +
"<ows:Identifier>gs:BufferFeatureCollection</ows:Identifier>" +
"<wps:DataInputs>" +
"<wps:Input>" +
"<ows:Identifier>features</ows:Identifier>" +
"<wps:Data>" +
"<wps:ComplexData>" +
readFileIntoString("states-FeatureCollection.xml") +
"</wps:ComplexData>" +
"</wps:Data>" +
"</wps:Input>" +
"<wps:Input>" +
"<ows:Identifier>distance</ows:Identifier>" +
"<wps:Data>" +
"<wps:LiteralData>10</wps:LiteralData>" +
"</wps:Data>" +
"</wps:Input>" +
"<wps:Input>" +
"<ows:Identifier>attributeName</ows:Identifier>" +
"<wps:Data>" +
"<wps:LiteralData></wps:LiteralData>" +
"</wps:Data>" +
"</wps:Input>" +
"</wps:DataInputs>" +
"<wps:ResponseForm>" +
"<wps:ResponseDocument storeExecuteResponse='false'>" +
"<wps:Output>" +
"<ows:Identifier>result</ows:Identifier>" +
"</wps:Output>" +
"</wps:ResponseDocument>" +
"</wps:ResponseForm>" +
"</wps:Execute>";
Document d = postAsDOM( "wps", xml );
// print(d);
checkValidationErrors(d);
assertEquals( "wps:ExecuteResponse", d.getDocumentElement().getNodeName() );
assertXpathExists( "/wps:ExecuteResponse/wps:Status/wps:ProcessSucceeded", d);
assertXpathExists(
"/wps:ExecuteResponse/wps:ProcessOutputs/wps:Output/wps:Data/wps:ComplexData/wfs:FeatureCollection", d);
}
@Test
public void testFeatureCollectionInlineBoundedBy() throws Exception { // Standard Test A.4.4.2, A.4.4.4
String xml = "<wps:Execute service='WPS' version='1.0.0' xmlns:wps='http://www.opengis.net/wps/1.0.0' " +
"xmlns:ows='http://www.opengis.net/ows/1.1'>" +
"<ows:Identifier>gs:BufferFeatureCollection</ows:Identifier>" +
"<wps:DataInputs>" +
"<wps:Input>" +
"<ows:Identifier>features</ows:Identifier>" +
"<wps:Data>" +
"<wps:ComplexData mimeType=\"text/xml; subtype=wfs-collection/1.0\">" +
readFileIntoString("restricted-FeatureCollection.xml") +
"</wps:ComplexData>" +
"</wps:Data>" +
"</wps:Input>" +
"<wps:Input>" +
"<ows:Identifier>distance</ows:Identifier>" +
"<wps:Data>" +
"<wps:LiteralData>1000</wps:LiteralData>" +
"</wps:Data>" +
"</wps:Input>" +
"</wps:DataInputs>" +
"<wps:ResponseForm>" +
"<wps:ResponseDocument storeExecuteResponse='false'>" +
"<wps:Output>" +
"<ows:Identifier>result</ows:Identifier>" +
"</wps:Output>" +
"</wps:ResponseDocument>" +
"</wps:ResponseForm>" +
"</wps:Execute>";
Document d = postAsDOM( "wps", xml );
// print(d);
checkValidationErrors(d);
assertEquals( "wps:ExecuteResponse", d.getDocumentElement().getNodeName() );
assertXpathExists( "/wps:ExecuteResponse/wps:Status/wps:ProcessSucceeded", d);
assertXpathExists(
"/wps:ExecuteResponse/wps:ProcessOutputs/wps:Output/wps:Data/wps:ComplexData/wfs:FeatureCollection", d);
assertXpathEvaluatesTo("0", "count(//feature:boundedBy)", d);
}
@Test
public void testFeatureCollectionInlineKVP() throws Exception {
String request = "wps?service=WPS&version=1.0.0&request=Execute&Identifier=gs:BufferFeatureCollection" +
"&DataInputs=" + urlEncode("features=" + readFileIntoString("states-FeatureCollection.xml") + "@mimetype=application/wfs-collection-1.1;distance=10") +
"&ResponseDocument=" + urlEncode("result");
Document d = getAsDOM(request);
// print(d);
checkValidationErrors(d);
assertEquals( "wps:ExecuteResponse", d.getDocumentElement().getNodeName() );
assertXpathExists( "/wps:ExecuteResponse/wps:Status/wps:ProcessSucceeded", d);
assertXpathExists(
"/wps:ExecuteResponse/wps:ProcessOutputs/wps:Output/wps:Data/wps:ComplexData/wfs:FeatureCollection", d);
}
@Test
public void testReferenceOutputXML() throws Exception { // Standard Test A.4.4.2, A.4.4.4
String xml = "<wps:Execute service='WPS' version='1.0.0' xmlns:wps='http://www.opengis.net/wps/1.0.0' " +
"xmlns:ows='http://www.opengis.net/ows/1.1'>" +
"<ows:Identifier>gs:BufferFeatureCollection</ows:Identifier>" +
"<wps:DataInputs>" +
"<wps:Input>" +
"<ows:Identifier>features</ows:Identifier>" +
"<wps:Data>" +
"<wps:ComplexData mimeType=\"text/xml; subtype=wfs-collection/1.0\">" +
readFileIntoString("restricted-FeatureCollection.xml") +
"</wps:ComplexData>" +
"</wps:Data>" +
"</wps:Input>" +
"<wps:Input>" +
"<ows:Identifier>distance</ows:Identifier>" +
"<wps:Data>" +
"<wps:LiteralData>1000</wps:LiteralData>" +
"</wps:Data>" +
"</wps:Input>" +
"</wps:DataInputs>" +
"<wps:ResponseForm>" +
"<wps:ResponseDocument storeExecuteResponse='false'>" +
"<wps:Output asReference=\"true\">" +
"<ows:Identifier>result</ows:Identifier>" +
"</wps:Output>" +
"</wps:ResponseDocument>" +
"</wps:ResponseForm>" +
"</wps:Execute>";
Document d = postAsDOM( "wps", xml );
// check we got a valid response with the document as a reference
checkValidationErrors(d);
assertEquals( "wps:ExecuteResponse", d.getDocumentElement().getNodeName() );
assertXpathExists("/wps:ExecuteResponse/wps:Status/wps:ProcessSucceeded", d);
assertXpathExists("/wps:ExecuteResponse/wps:ProcessOutputs/wps:Output/wps:Reference", d);
XpathEngine xpath = XMLUnit.newXpathEngine();
String fullLocation = xpath.evaluate("/wps:ExecuteResponse/wps:ProcessOutputs/wps:Output/wps:Reference/@href", d);
String resourceLocation = fullLocation.substring(fullLocation.indexOf('?') - 3);
d = getAsDOM(resourceLocation);
assertXpathExists("wfs:FeatureCollection", d);
}
@Test
public void testReferenceOutputKVP() throws Exception {
String request = "wps?service=WPS&version=1.0.0&request=Execute&Identifier=gs:BufferFeatureCollection" +
"&DataInputs=" + urlEncode("features=" + readFileIntoString("states-FeatureCollection.xml") +
"@mimetype=application/wfs-collection-1.1;distance=10") +
"&ResponseDocument=" + urlEncode("result=@asReference=true");
Document d = getAsDOM(request);
// print(d);
// check we got a valid response with the document as a reference
checkValidationErrors(d);
assertEquals( "wps:ExecuteResponse", d.getDocumentElement().getNodeName() );
assertXpathExists("/wps:ExecuteResponse/wps:Status/wps:ProcessSucceeded", d);
assertXpathExists("/wps:ExecuteResponse/wps:ProcessOutputs/wps:Output/wps:Reference", d);
XpathEngine xpath = XMLUnit.newXpathEngine();
String fullLocation = xpath.evaluate("/wps:ExecuteResponse/wps:ProcessOutputs/wps:Output/wps:Reference/@href", d);
String resourceLocation = fullLocation.substring(fullLocation.indexOf('?') - 3);
MockHttpServletResponse response = getAsServletResponse(resourceLocation);
assertEquals("text/xml; subtype=wfs-collection/1.0", response.getContentType());
d = dom(new ByteArrayInputStream( response.getOutputStreamContent().getBytes()));
assertXpathExists("wfs:FeatureCollection", d);
}
@Test
public void testFeatureCollectionFileReference() throws Exception { // Standard Test A.4.4.2, A.4.4.4
URL collectionURL = getClass().getResource("states-FeatureCollection.xml");
String xml = "<wps:Execute service='WPS' version='1.0.0' xmlns:wps='http://www.opengis.net/wps/1.0.0' xmlns:xlink=\"http://www.w3.org/1999/xlink\" " +
"xmlns:ows='http://www.opengis.net/ows/1.1'>" +
"<ows:Identifier>gs:BufferFeatureCollection</ows:Identifier>" +
"<wps:DataInputs>" +
"<wps:Input>" +
"<ows:Identifier>features</ows:Identifier>" +
" <wps:Reference mimeType=\"text/xml; subtype=wfs-collection/1.1\" " +
"xlink:href=\"" + collectionURL.toExternalForm() + "\"/>\n" +
"</wps:Input>" +
"<wps:Input>" +
"<ows:Identifier>distance</ows:Identifier>" +
"<wps:Data>" +
"<wps:LiteralData>10</wps:LiteralData>" +
"</wps:Data>" +
"</wps:Input>" +
"</wps:DataInputs>" +
"<wps:ResponseForm>" +
"<wps:ResponseDocument storeExecuteResponse='false'>" +
"<wps:Output>" +
"<ows:Identifier>result</ows:Identifier>" +
"</wps:Output>" +
"</wps:ResponseDocument>" +
"</wps:ResponseForm>" +
"</wps:Execute>";
Document d = postAsDOM( "wps", xml );
// print(d);
checkValidationErrors(d);
assertEquals( "wps:ExecuteResponse", d.getDocumentElement().getNodeName() );
assertXpathExists( "/wps:ExecuteResponse/wps:Status/wps:ProcessSucceeded", d);
assertXpathExists(
"/wps:ExecuteResponse/wps:ProcessOutputs/wps:Output/wps:Data/wps:ComplexData/wfs:FeatureCollection", d);
}
@Test
public void testFeatureCollectionFileReferenceKVP() throws Exception {
URL collectionURL = getClass().getResource("states-FeatureCollection.xml");
String request = "wps?service=WPS&version=1.0.0&request=Execute&Identifier=gs:BufferFeatureCollection" +
"&DataInputs=" + urlEncode("features=@mimetype=application/wfs-collection-1.1@xlink:href="
+ collectionURL.toExternalForm() + ";distance=10") + "&ResponseDocument=" + urlEncode("result");
Document d = getAsDOM(request);
// print(d);
checkValidationErrors(d);
assertEquals( "wps:ExecuteResponse", d.getDocumentElement().getNodeName() );
assertXpathExists( "/wps:ExecuteResponse/wps:Status/wps:ProcessSucceeded", d);
assertXpathExists(
"/wps:ExecuteResponse/wps:ProcessOutputs/wps:Output/wps:Data/wps:ComplexData/wfs:FeatureCollection", d);
}
@Test
public void testInlineGeoJSON() throws Exception {
String xml = "<wps:Execute service='WPS' version='1.0.0' xmlns:wps='http://www.opengis.net/wps/1.0.0' " +
"xmlns:ows='http://www.opengis.net/ows/1.1'>" +
"<ows:Identifier>gs:BufferFeatureCollection</ows:Identifier>" +
"<wps:DataInputs>" +
"<wps:Input>" +
"<ows:Identifier>features</ows:Identifier>" +
"<wps:Data>" +
"<wps:ComplexData mimeType=\"application/json\"><![CDATA[" +
readFileIntoString("states-FeatureCollection.json") +
"]]></wps:ComplexData>" +
"</wps:Data>" +
"</wps:Input>" +
"<wps:Input>" +
"<ows:Identifier>distance</ows:Identifier>" +
"<wps:Data>" +
"<wps:LiteralData>10</wps:LiteralData>" +
"</wps:Data>" +
"</wps:Input>" +
"</wps:DataInputs>" +
"<wps:ResponseForm>" +
"<wps:RawDataOutput mimeType=\"application/json\">" +
"<ows:Identifier>result</ows:Identifier>" +
"</wps:RawDataOutput>" +
"</wps:ResponseForm>" +
"</wps:Execute>";
MockHttpServletResponse r = postAsServletResponse("wps", xml);
assertEquals("application/json", r.getContentType());
// System.out.println(r.getOutputStreamContent());
FeatureCollection fc = new FeatureJSON().readFeatureCollection(r.getOutputStreamContent());
assertEquals(2, fc.size());
}
@Test
public void testShapeZip() throws Exception {
String xml = "<wps:Execute service='WPS' version='1.0.0' xmlns:xlink=\"http://www.w3.org/1999/xlink\" " +
"xmlns:wps='http://www.opengis.net/wps/1.0.0' xmlns:wfs='http://www.opengis.net/wfs' " +
"xmlns:ows='http://www.opengis.net/ows/1.1'>" +
"<ows:Identifier>gs:BufferFeatureCollection</ows:Identifier>" +
"<wps:DataInputs>" +
" <wps:Input>\n" +
"<ows:Identifier>features</ows:Identifier>" +
"<wps:Data>" +
"<wps:ComplexData>" +
readFileIntoString("states-FeatureCollection.xml") +
"</wps:ComplexData>" +
"</wps:Data>" +
"</wps:Input>" +
"<wps:Input>" +
"<ows:Identifier>distance</ows:Identifier>" +
"<wps:Data>" +
"<wps:LiteralData>10</wps:LiteralData>" +
"</wps:Data>" +
"</wps:Input>" +
"</wps:DataInputs>" +
"<wps:ResponseForm>" +
"<wps:RawDataOutput mimeType=\"application/zip\">" +
"<ows:Identifier>result</ows:Identifier>" +
"</wps:RawDataOutput>" +
"</wps:ResponseForm>" +
"</wps:Execute>";
MockHttpServletResponse r = postAsServletResponse("wps", xml);
assertEquals("application/zip", r.getContentType());
checkShapefileIntegrity(new String[] {"states"}, getBinaryInputStream(r));
}
/**
* Tests a process execution with a BoudingBox as the output and check internal layer
* request handling as well
*/
@Test
public void testBoundsPost() throws Exception {
String request = "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n" +
"<wps:Execute version=\"1.0.0\" service=\"WPS\" xmlns:xsi=\"http://www.w3.org/2001/XMLSchema-instance\" xmlns=\"http://www.opengis.net/wps/1.0.0\" xmlns:wfs=\"http://www.opengis.net/wfs\" xmlns:wps=\"http://www.opengis.net/wps/1.0.0\" xmlns:ows=\"http://www.opengis.net/ows/1.1\" xmlns:gml=\"http://www.opengis.net/gml\" xmlns:ogc=\"http://www.opengis.net/ogc\" xmlns:wcs=\"http://www.opengis.net/wcs/1.1.1\" xmlns:xlink=\"http://www.w3.org/1999/xlink\" xsi:schemaLocation=\"http://www.opengis.net/wps/1.0.0 http://schemas.opengis.net/wps/1.0.0/wpsAll.xsd\">\n" +
" <ows:Identifier>gs:Bounds</ows:Identifier>\n" +
" <wps:DataInputs>\n" +
" <wps:Input>\n" +
" <ows:Identifier>features</ows:Identifier>\n" +
" <wps:Reference mimeType=\"text/xml; subtype=wfs-collection/1.0\" xlink:href=\"http://geoserver/wfs\" method=\"POST\">\n" +
" <wps:Body>\n" +
" <wfs:GetFeature service=\"WFS\" version=\"1.0.0\">\n" +
" <wfs:Query typeName=\"cite:Streams\"/>\n" +
" </wfs:GetFeature>\n" +
" </wps:Body>\n" +
" </wps:Reference>\n" +
" </wps:Input>\n" +
" </wps:DataInputs>\n" +
" <wps:ResponseForm>\n" +
" <wps:RawDataOutput>\n" +
" <ows:Identifier>bounds</ows:Identifier>\n" +
" </wps:RawDataOutput>\n" +
" </wps:ResponseForm>\n" +
"</wps:Execute>";
Document dom = postAsDOM(root(), request);
// print(dom);
assertXpathEvaluatesTo("-4.0E-4 -0.0024", "/ows:BoundingBox/ows:LowerCorner", dom);
assertXpathEvaluatesTo("0.0036 0.0024", "/ows:BoundingBox/ows:UpperCorner", dom);
}
/**
* Tests a process execution with a BoudingBox as the output and check internal layer
* request handling as well
*/
@Test
public void testBoundsGet() throws Exception {
String request = "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n" +
"<wps:Execute version=\"1.0.0\" service=\"WPS\" xmlns:xsi=\"http://www.w3.org/2001/XMLSchema-instance\" xmlns=\"http://www.opengis.net/wps/1.0.0\" xmlns:wfs=\"http://www.opengis.net/wfs\" xmlns:wps=\"http://www.opengis.net/wps/1.0.0\" xmlns:ows=\"http://www.opengis.net/ows/1.1\" xmlns:gml=\"http://www.opengis.net/gml\" xmlns:ogc=\"http://www.opengis.net/ogc\" xmlns:wcs=\"http://www.opengis.net/wcs/1.1.1\" xmlns:xlink=\"http://www.w3.org/1999/xlink\" xsi:schemaLocation=\"http://www.opengis.net/wps/1.0.0 http://schemas.opengis.net/wps/1.0.0/wpsAll.xsd\">\n" +
" <ows:Identifier>gs:Bounds</ows:Identifier>\n" +
" <wps:DataInputs>\n" +
" <wps:Input>\n" +
" <ows:Identifier>features</ows:Identifier>\n" +
" <wps:Reference mimeType=\"text/xml; subtype=wfs-collection/1.0\" xlink:href=\"http://geoserver/wfs?service=WFS&request=GetFeature&typename=cite:Streams\" method=\"GET\"/>\n" +
" </wps:Input>\n" +
" </wps:DataInputs>\n" +
" <wps:ResponseForm>\n" +
" <wps:RawDataOutput>\n" +
" <ows:Identifier>bounds</ows:Identifier>\n" +
" </wps:RawDataOutput>\n" +
" </wps:ResponseForm>\n" +
"</wps:Execute>";
Document dom = postAsDOM(root(), request);
// print(dom);
assertXpathEvaluatesTo("-4.0E-4 -0.0024", "/ows:BoundingBox/ows:LowerCorner", dom);
assertXpathEvaluatesTo("0.0036 0.0024", "/ows:BoundingBox/ows:UpperCorner", dom);
}
/**
* Tests a process grabbing a remote layer
*/
@Test
public void testRemoteGetWFS10Layer() throws Exception {
String request = "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n" +
"<wps:Execute version=\"1.0.0\" service=\"WPS\" xmlns:xsi=\"http://www.w3.org/2001/XMLSchema-instance\" xmlns=\"http://www.opengis.net/wps/1.0.0\" xmlns:wfs=\"http://www.opengis.net/wfs\" xmlns:wps=\"http://www.opengis.net/wps/1.0.0\" xmlns:ows=\"http://www.opengis.net/ows/1.1\" xmlns:gml=\"http://www.opengis.net/gml\" xmlns:ogc=\"http://www.opengis.net/ogc\" xmlns:wcs=\"http://www.opengis.net/wcs/1.1.1\" xmlns:xlink=\"http://www.w3.org/1999/xlink\" xsi:schemaLocation=\"http://www.opengis.net/wps/1.0.0 http://schemas.opengis.net/wps/1.0.0/wpsAll.xsd\">\n" +
" <ows:Identifier>gs:Bounds</ows:Identifier>\n" +
" <wps:DataInputs>\n" +
" <wps:Input>\n" +
" <ows:Identifier>features</ows:Identifier>\n" +
" <wps:Reference mimeType=\"text/xml; subtype=wfs-collection/1.0\" " +
" xlink:href=\"http://demo.opengeo.org/geoserver/wfs?request=GetFeature&service=wfs&version=1.0.0&typeName=topp:states&featureid=states.1\" />\n" +
" </wps:Input>\n" +
" </wps:DataInputs>\n" +
" <wps:ResponseForm>\n" +
" <wps:RawDataOutput>\n" +
" <ows:Identifier>bounds</ows:Identifier>\n" +
" </wps:RawDataOutput>\n" +
" </wps:ResponseForm>\n" +
"</wps:Execute>";
executeState1BoundsTest(request, "GET WFS 1.0");
}
/**
* Tests a process grabbing a remote layer
*/
@Test
public void testRemotePostWFS10Layer() throws Exception {
String request = "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n" +
"<wps:Execute version=\"1.0.0\" service=\"WPS\" xmlns:xsi=\"http://www.w3.org/2001/XMLSchema-instance\" xmlns=\"http://www.opengis.net/wps/1.0.0\" xmlns:wfs=\"http://www.opengis.net/wfs\" xmlns:wps=\"http://www.opengis.net/wps/1.0.0\" xmlns:ows=\"http://www.opengis.net/ows/1.1\" xmlns:gml=\"http://www.opengis.net/gml\" xmlns:ogc=\"http://www.opengis.net/ogc\" xmlns:wcs=\"http://www.opengis.net/wcs/1.1.1\" xmlns:xlink=\"http://www.w3.org/1999/xlink\" xsi:schemaLocation=\"http://www.opengis.net/wps/1.0.0 http://schemas.opengis.net/wps/1.0.0/wpsAll.xsd\">\n" +
" <ows:Identifier>gs:Bounds</ows:Identifier>\n" +
" <wps:DataInputs>\n" +
" <wps:Input>\n" +
" <ows:Identifier>features</ows:Identifier>\n" +
" <wps:Reference mimeType=\"text/xml; subtype=wfs-collection/1.0\" " +
" xlink:href=\"http://demo.opengeo.org/geoserver/wfs\" method=\"POST\">\n" +
" <wps:Body>\n" +
"<![CDATA[<wfs:GetFeature service=\"WFS\" version=\"1.0.0\"\n" +
" outputFormat=\"GML2\"\n" +
" xmlns:topp=\"http://www.openplans.org/topp\"\n" +
" xmlns:wfs=\"http://www.opengis.net/wfs\"\n" +
" xmlns:ogc=\"http://www.opengis.net/ogc\"\n" +
" xmlns:xsi=\"http://www.w3.org/2001/XMLSchema-instance\"\n" +
" xsi:schemaLocation=\"http://www.opengis.net/wfs\n" +
" http://schemas.opengis.net/wfs/1.0.0/WFS-basic.xsd\">\n" +
" <wfs:Query typeName=\"topp:states\">\n" +
" <ogc:Filter>\n" +
" <ogc:FeatureId fid=\"states.1\"/>\n" +
" </ogc:Filter>\n" +
" </wfs:Query>\n" +
"</wfs:GetFeature>]]>" +
" </wps:Body>\n" +
" </wps:Reference>\n" +
" </wps:Input>\n" +
" </wps:DataInputs>\n" +
" <wps:ResponseForm>\n" +
" <wps:RawDataOutput>\n" +
" <ows:Identifier>bounds</ows:Identifier>\n" +
" </wps:RawDataOutput>\n" +
" </wps:ResponseForm>\n" +
"</wps:Execute>";
executeState1BoundsTest(request, "POST WFS 1.0");
}
/**
* Tests a process grabbing a remote layer
*/
@Test
public void testRemoteBodyReferencePostWFS10Layer() throws Exception {
URL getFeatureURL = getClass().getResource("getFeature.xml");
String request = "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n" +
"<wps:Execute version=\"1.0.0\" service=\"WPS\" xmlns:xsi=\"http://www.w3.org/2001/XMLSchema-instance\" xmlns=\"http://www.opengis.net/wps/1.0.0\" xmlns:wfs=\"http://www.opengis.net/wfs\" xmlns:wps=\"http://www.opengis.net/wps/1.0.0\" xmlns:ows=\"http://www.opengis.net/ows/1.1\" xmlns:gml=\"http://www.opengis.net/gml\" xmlns:ogc=\"http://www.opengis.net/ogc\" xmlns:wcs=\"http://www.opengis.net/wcs/1.1.1\" xmlns:xlink=\"http://www.w3.org/1999/xlink\" xsi:schemaLocation=\"http://www.opengis.net/wps/1.0.0 http://schemas.opengis.net/wps/1.0.0/wpsAll.xsd\">\n" +
" <ows:Identifier>gs:Bounds</ows:Identifier>\n" +
" <wps:DataInputs>\n" +
" <wps:Input>\n" +
" <ows:Identifier>features</ows:Identifier>\n" +
" <wps:Reference mimeType=\"text/xml; subtype=wfs-collection/1.0\" " +
" xlink:href=\"http://demo.opengeo.org/geoserver/wfs\" method=\"POST\">\n" +
" <wps:BodyReference xlink:href=\"" + getFeatureURL.toExternalForm() + "\"/>\n" +
" </wps:Reference>\n" +
" </wps:Input>\n" +
" </wps:DataInputs>\n" +
" <wps:ResponseForm>\n" +
" <wps:RawDataOutput>\n" +
" <ows:Identifier>bounds</ows:Identifier>\n" +
" </wps:RawDataOutput>\n" +
" </wps:ResponseForm>\n" +
"</wps:Execute>";
executeState1BoundsTest(request, "POST WFS 1.0");
}
/**
* Tests a process grabbing a remote layer
*/
@Test
public void testRemoteGetWFS11Layer() throws Exception {
String request = "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n" +
"<wps:Execute version=\"1.0.0\" service=\"WPS\" xmlns:xsi=\"http://www.w3.org/2001/XMLSchema-instance\" xmlns=\"http://www.opengis.net/wps/1.0.0\" xmlns:wfs=\"http://www.opengis.net/wfs\" xmlns:wps=\"http://www.opengis.net/wps/1.0.0\" xmlns:ows=\"http://www.opengis.net/ows/1.1\" xmlns:gml=\"http://www.opengis.net/gml\" xmlns:ogc=\"http://www.opengis.net/ogc\" xmlns:wcs=\"http://www.opengis.net/wcs/1.1.1\" xmlns:xlink=\"http://www.w3.org/1999/xlink\" xsi:schemaLocation=\"http://www.opengis.net/wps/1.0.0 http://schemas.opengis.net/wps/1.0.0/wpsAll.xsd\">\n" +
" <ows:Identifier>gs:Bounds</ows:Identifier>\n" +
" <wps:DataInputs>\n" +
" <wps:Input>\n" +
" <ows:Identifier>features</ows:Identifier>\n" +
" <wps:Reference mimeType=\"text/xml; subtype=wfs-collection/1.1\" " +
" xlink:href=\"http://demo.opengeo.org/geoserver/wfs?request=GetFeature&service=wfs&version=1.1&typeName=topp:states&featureid=states.1\" />\n" +
" </wps:Input>\n" +
" </wps:DataInputs>\n" +
" <wps:ResponseForm>\n" +
" <wps:RawDataOutput>\n" +
" <ows:Identifier>bounds</ows:Identifier>\n" +
" </wps:RawDataOutput>\n" +
" </wps:ResponseForm>\n" +
"</wps:Execute>";
// System.out.println(request);
executeState1BoundsTest(request, "GET WFS 1.1");
}
/**
* Tests a process grabbing a remote layer
*/
@Test
public void testRemotePostWFS11Layer() throws Exception {
String request = "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n" +
"<wps:Execute version=\"1.0.0\" service=\"WPS\" xmlns:xsi=\"http://www.w3.org/2001/XMLSchema-instance\" xmlns=\"http://www.opengis.net/wps/1.0.0\" xmlns:wfs=\"http://www.opengis.net/wfs\" xmlns:wps=\"http://www.opengis.net/wps/1.0.0\" xmlns:ows=\"http://www.opengis.net/ows/1.1\" xmlns:gml=\"http://www.opengis.net/gml\" xmlns:ogc=\"http://www.opengis.net/ogc\" xmlns:wcs=\"http://www.opengis.net/wcs/1.1.1\" xmlns:xlink=\"http://www.w3.org/1999/xlink\" xsi:schemaLocation=\"http://www.opengis.net/wps/1.0.0 http://schemas.opengis.net/wps/1.0.0/wpsAll.xsd\">\n" +
" <ows:Identifier>gs:Bounds</ows:Identifier>\n" +
" <wps:DataInputs>\n" +
" <wps:Input>\n" +
" <ows:Identifier>features</ows:Identifier>\n" +
" <wps:Reference mimeType=\"text/xml; subtype=wfs-collection/1.1\" " +
" xlink:href=\"http://demo.opengeo.org/geoserver/wfs\" method=\"POST\">\n" +
" <wps:Body>\n" +
"<![CDATA[<wfs:GetFeature service=\"WFS\" version=\"1.1.0\"\n" +
" xmlns:topp=\"http://www.openplans.org/topp\"\n" +
" xmlns:wfs=\"http://www.opengis.net/wfs\"\n" +
" xmlns:ogc=\"http://www.opengis.net/ogc\"\n" +
" xmlns:xsi=\"http://www.w3.org/2001/XMLSchema-instance\"\n" +
" xsi:schemaLocation=\"http://www.opengis.net/wfs\n" +
" http://schemas.opengis.net/wfs/1.1.0/wfs.xsd\">\n" +
" <wfs:Query typeName=\"topp:states\">\n" +
" <ogc:Filter>\n" +
" <ogc:FeatureId fid=\"states.1\"/>\n" +
" </ogc:Filter>\n" +
" </wfs:Query>\n" +
"</wfs:GetFeature>]]>" +
" </wps:Body>\n" +
" </wps:Reference>\n" +
" </wps:Input>\n" +
" </wps:DataInputs>\n" +
" <wps:ResponseForm>\n" +
" <wps:RawDataOutput>\n" +
" <ows:Identifier>bounds</ows:Identifier>\n" +
" </wps:RawDataOutput>\n" +
" </wps:ResponseForm>\n" +
"</wps:Execute>";
executeState1BoundsTest(request, "POST WFS 1.1");
}
@Test
public void testProcessChaining() throws Exception {
// chain two JTS processes
String xml = "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n" +
"<wps:Execute version=\"1.0.0\" service=\"WPS\" xmlns:xsi=\"http://www.w3.org/2001/XMLSchema-instance\" xmlns=\"http://www.opengis.net/wps/1.0.0\" xmlns:wfs=\"http://www.opengis.net/wfs\" xmlns:wps=\"http://www.opengis.net/wps/1.0.0\" xmlns:ows=\"http://www.opengis.net/ows/1.1\" xmlns:gml=\"http://www.opengis.net/gml\" xmlns:ogc=\"http://www.opengis.net/ogc\" xmlns:wcs=\"http://www.opengis.net/wcs/1.1.1\" xmlns:xlink=\"http://www.w3.org/1999/xlink\" xsi:schemaLocation=\"http://www.opengis.net/wps/1.0.0 http://schemas.opengis.net/wps/1.0.0/wpsAll.xsd\">\n" +
" <ows:Identifier>JTS:area</ows:Identifier>\n" +
" <wps:DataInputs>\n" +
" <wps:Input>\n" +
" <ows:Identifier>geom</ows:Identifier>\n" +
" <wps:Reference mimeType=\"text/xml; subtype=gml/3.1.1\" xlink:href=\"http://geoserver/wps\" method=\"POST\">\n" +
" <wps:Execute>\n" +
" <ows:Identifier>JTS:buffer</ows:Identifier>\n" +
" <wps:DataInputs>\n" +
" <wps:Input>\n" +
" <ows:Identifier>geom</ows:Identifier>\n" +
" <wps:Data>\n" +
" <wps:ComplexData mimeType=\"application/wkt\"><![CDATA[POINT(0 0)]]></wps:ComplexData>\n" +
" </wps:Data>\n" +
" </wps:Input>\n" +
" <wps:Input>\n" +
" <ows:Identifier>distance</ows:Identifier>\n" +
" <wps:Data>\n" +
" <wps:LiteralData>10</wps:LiteralData>\n" +
" </wps:Data>\n" +
" </wps:Input>\n" +
" </wps:DataInputs>\n" +
" <wps:ResponseForm>\n" +
" <wps:RawDataOutput mimeType=\"text/xml; subtype=gml/3.1.1\">\n" +
" <ows:Identifier>result</ows:Identifier>\n" +
" </wps:RawDataOutput>\n" +
" </wps:ResponseForm>\n" +
" </wps:Execute>\n" +
" </wps:Reference>\n" +
" </wps:Input>\n" +
" </wps:DataInputs>\n" +
" <wps:ResponseForm>\n" +
" <wps:RawDataOutput>\n" +
" <ows:Identifier>result</ows:Identifier>\n" +
" </wps:RawDataOutput>\n" +
" </wps:ResponseForm>\n" +
"</wps:Execute>";
MockHttpServletResponse resp = postAsServletResponse(root(), xml);
assertEquals("text/plain", resp.getContentType());
// the result is inaccurate since the buffer is just a poor approximation of a circle
assertTrue(resp.getOutputStreamContent().matches("312\\..*"));
}
@Test
public void testProcessChainingKVP() throws Exception {
String nested = "http://geoserver/wps?service=WPS&version=1.0.0&request=Execute&Identifier=JTS:buffer" +
"&DataInputs=" + urlEncode("geom=POINT(0 0)@mimetype=application/wkt;distance=10") + "&RawDataOutput=result";
String request = "wps?service=WPS&version=1.0.0&request=Execute&Identifier=JTS:area" +
"&DataInputs=" + urlEncode("geom=@href=" + nested) + "&RawDataOutput=result";
MockHttpServletResponse resp = getAsServletResponse(request);
assertEquals("text/plain", resp.getContentType());
// the result is inaccurate since the buffer is just a poor approximation of a circle
assertTrue(resp.getOutputStreamContent().matches("312\\..*"));
}
@Test
public void testProcessFailure() throws Exception {
// have the monkey throw an exception
MonkeyProcess.exception("x1", new ProcessException("Sorry dude, things went pear shaped..."), false);
String request = "wps?service=WPS&version=1.0.0&request=Execute&Identifier=gs:Monkey&DataInputs=" + urlEncode("id=x1");
Document dom = getAsDOM(request);
checkValidationErrors(dom);
assertXpathExists("//wps:ProcessFailed", dom);
assertXpathEvaluatesTo("Process failed during execution\nSorry dude, things went pear shaped...",
"//wps:ProcessFailed/ows:ExceptionReport/ows:Exception/ows:ExceptionText", dom);
}
@Test
public void testStoredNoStatus() throws Exception {
// submit asynch request with no updates
String request = "wps?service=WPS&version=1.0.0&request=Execute&Identifier=gs:Monkey&storeExecuteResponse=true&DataInputs=" + urlEncode("id=x2");
Document dom = getAsDOM(request);
assertXpathExists("//wps:ProcessAccepted", dom);
XpathEngine xpath = XMLUnit.newXpathEngine();
String fullStatusLocation = xpath.evaluate("//wps:ExecuteResponse/@statusLocation", dom);
String statusLocation = fullStatusLocation.substring(fullStatusLocation.indexOf('?') - 3);
// we move the clock forward, but we asked no status, nothing should change
MonkeyProcess.progress("x2", 50f, true);
dom = getAsDOM(statusLocation);
// print(dom);
assertXpathExists("//wps:ProcessAccepted", dom);
// now schedule the exit and wait for it to exit
ListFeatureCollection fc = collectionOfThings();
MonkeyProcess.exit("x2", fc, true);
dom = waitForProcessEnd(statusLocation, 60);
assertXpathExists("//wps:ProcessSucceeded", dom);
}
private ListFeatureCollection collectionOfThings() {
SimpleFeatureTypeBuilder tb = new SimpleFeatureTypeBuilder();
tb.add("name", String.class);
tb.add("location", Point.class, DefaultGeographicCRS.WGS84);
tb.setName("thing");
SimpleFeatureType featureType = tb.buildFeatureType();
ListFeatureCollection fc = new ListFeatureCollection(featureType);
return fc;
}
@Test
public void testStoredWithStatus() throws Exception {
// submit asynch request with no updates
String statusLocation = submitMonkey("x3");
// we move the clock forward, but we asked no status, nothing should change
MonkeyProcess.progress("x3", 10f, true);
Document dom = getAsDOM(statusLocation);
print(dom);
assertXpathExists("//wps:ProcessStarted", dom);
assertXpathEvaluatesTo("" + Math.round(0.66 * 10), "//wps:ProcessStarted/@percentCompleted", dom);
// we move the clock forward, but we asked no status, nothing should change
MonkeyProcess.progress("x3", 50f, true);
dom = getAsDOM(statusLocation);
print(dom);
assertXpathExists("//wps:ProcessStarted", dom);
assertXpathEvaluatesTo("" + Math.round(0.66 * 50), "//wps:ProcessStarted/@percentCompleted", dom);
assertXpathEvaluatesTo("Currently at 50.0", "//wps:ProcessStarted", dom);
// now schedule the exit and wait for it to exit
MonkeyProcess.exit("x3", collectionOfThings(), true);
dom = waitForProcessEnd(statusLocation, 60);
// print(dom);
assertXpathExists("//wps:ProcessSucceeded", dom);
}
/**
* http://jira.codehaus.org/browse/GEOS-5208
* @throws Exception
*/
@Test
public void testChainedProgress() throws Exception {
String request = "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n" +
"<wps:Execute version=\"1.0.0\" service=\"WPS\" xmlns:xsi=\"http://www.w3.org/2001/XMLSchema-instance\" xmlns=\"http://www.opengis.net/wps/1.0.0\" xmlns:wfs=\"http://www.opengis.net/wfs\" xmlns:wps=\"http://www.opengis.net/wps/1.0.0\" xmlns:ows=\"http://www.opengis.net/ows/1.1\" xmlns:gml=\"http://www.opengis.net/gml\" xmlns:ogc=\"http://www.opengis.net/ogc\" xmlns:wcs=\"http://www.opengis.net/wcs/1.1.1\" xmlns:xlink=\"http://www.w3.org/1999/xlink\" xsi:schemaLocation=\"http://www.opengis.net/wps/1.0.0 http://schemas.opengis.net/wps/1.0.0/wpsAll.xsd\">\n" +
" <ows:Identifier>gs:CollectGeometries</ows:Identifier>\n" +
" <wps:DataInputs>\n" +
" <wps:Input>\n" +
" <ows:Identifier>features</ows:Identifier>\n" +
" <wps:Reference mimeType=\"text/xml; subtype=wfs-collection/1.0\" xlink:href=\"http://geoserver/wps\" method=\"POST\">\n" +
" <wps:Body>\n" +
" <wps:Execute version=\"1.0.0\" service=\"WPS\">\n" +
" <ows:Identifier>gs:Monkey</ows:Identifier>\n" +
" <wps:DataInputs>\n" +
" <wps:Input>\n" +
" <ows:Identifier>id</ows:Identifier>\n" +
" <wps:Data>\n" +
" <wps:LiteralData>chained-monkey</wps:LiteralData>\n" +
" </wps:Data>\n" +
" </wps:Input>\n" +
" </wps:DataInputs>\n" +
" <wps:ResponseForm>\n" +
" <wps:RawDataOutput mimeType=\"text/xml; subtype=gml/3.1.1\">\n" +
" <ows:Identifier>result</ows:Identifier>\n" +
" </wps:RawDataOutput>\n" +
" </wps:ResponseForm>\n" +
" </wps:Execute>\n" +
" </wps:Body>\n" +
" </wps:Reference>\n" +
" </wps:Input>\n" +
" </wps:DataInputs>\n" +
" <wps:ResponseForm>\n" +
" <wps:RawDataOutput mimeType=\"application/wkt\">\n" +
" <ows:Identifier>result</ows:Identifier>\n" +
" </wps:RawDataOutput>\n" +
" </wps:ResponseForm>\n" +
"</wps:Execute>";
MonkeyProcess.progress("chained-monkey", 10f, false);
MonkeyProcess.exit("chained-monkey", collectionOfThings(), false);
MockHttpServletResponse response = postAsServletResponse("wfs", request);
assertEquals("application/wkt", response.getContentType());
assertEquals("GEOMETRYCOLLECTION EMPTY", response.getOutputStreamContent());
}
@Test
public void testAsynchFailEncode() throws Exception {
// submit asynch request with no updates
String statusLocation = submitMonkey("x5");
// now schedule the exit and wait for it to exit
MonkeyProcess.exit("x5", bombOutCollection(), true);
Document dom = waitForProcessEnd(statusLocation, 60);
// print(dom);
assertXpathExists("//wps:ProcessFailed", dom);
}
@Test
public void testConcurrentRequests() throws Exception {
// submit first
String statusLocation1 = submitMonkey("one");
String statusLocation2 = submitMonkey("two");
// make the report progress
MonkeyProcess.progress("one", 10f, true);
MonkeyProcess.progress("two", 10f, true);
// make sure both were started and are running (the
assertProgress(statusLocation1, "7");
assertProgress(statusLocation2, "7");
// now schedule the exit and wait for it to exit
MonkeyProcess.exit("one", collectionOfThings(), true);
MonkeyProcess.exit("two", collectionOfThings(), true);
Document dom = waitForProcessEnd(statusLocation1, 60);
// print(dom);
assertXpathExists("//wps:ProcessSucceeded", dom);
dom = waitForProcessEnd(statusLocation2, 60);
assertXpathExists("//wps:ProcessSucceeded", dom);
}
@Test
public void testInlineGetFeatureNameClash() throws Exception {
assertNotNull(getCatalog().getLayerByName("foo:PrimitiveGeoFeature"));
assertNotNull(getCatalog().getLayerByName("sf:PrimitiveGeoFeature"));
String request = "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n" +
"<wps:Execute version=\"1.0.0\" service=\"WPS\" xmlns:xsi=\"http://www.w3.org/2001/XMLSchema-instance\" xmlns=\"http://www.opengis.net/wps/1.0.0\" xmlns:wfs=\"http://www.opengis.net/wfs\" xmlns:wps=\"http://www.opengis.net/wps/1.0.0\" xmlns:ows=\"http://www.opengis.net/ows/1.1\" xmlns:gml=\"http://www.opengis.net/gml\" xmlns:ogc=\"http://www.opengis.net/ogc\" xmlns:wcs=\"http://www.opengis.net/wcs/1.1.1\" xmlns:xlink=\"http://www.w3.org/1999/xlink\" xsi:schemaLocation=\"http://www.opengis.net/wps/1.0.0 http://schemas.opengis.net/wps/1.0.0/wpsAll.xsd\">\n" +
" <ows:Identifier>gs:Bounds</ows:Identifier>\n" +
" <wps:DataInputs>\n" +
" <wps:Input>\n" +
" <ows:Identifier>features</ows:Identifier>\n" +
" <wps:Reference mimeType=\"text/xml; subtype=wfs-collection/1.0\" xlink:href=\"http://geoserver/wfs\" method=\"POST\">\n" +
" <wps:Body>\n" +
" <wfs:GetFeature service=\"WFS\" version=\"1.0.0\" xmlns:foo='http://foo.org'>\n" +
" <wfs:Query typeName=\"foo:PrimitiveGeoFeature\"/>\n" +
" </wfs:GetFeature>\n" +
" </wps:Body>\n" +
" </wps:Reference>\n" +
" </wps:Input>\n" +
" </wps:DataInputs>\n" +
" <wps:ResponseForm>\n" +
" <wps:RawDataOutput>\n" +
" <ows:Identifier>bounds</ows:Identifier>\n" +
" </wps:RawDataOutput>\n" +
" </wps:ResponseForm>\n" +
"</wps:Execute>";
Document dom = postAsDOM(root(), request);
assertEquals("ows:BoundingBox", dom.getDocumentElement().getNodeName());
}
private void assertProgress(String statusLocation, String progress) throws Exception {
Document dom = getAsDOM(statusLocation);
// print(dom);
assertXpathExists("//wps:ProcessStarted", dom);
assertXpathEvaluatesTo(progress, "//wps:ProcessStarted/@percentCompleted", dom);
}
private String submitMonkey(String id) throws Exception, XpathException {
String request = "wps?service=WPS&version=1.0.0&request=Execute&Identifier=gs:Monkey&storeExecuteResponse=true&status=true&DataInputs=" + urlEncode("id=" + id);
Document dom = getAsDOM(request);
assertXpathExists("//wps:ProcessAccepted", dom);
XpathEngine xpath = XMLUnit.newXpathEngine();
String fullStatusLocation = xpath.evaluate("//wps:ExecuteResponse/@statusLocation", dom);
String statusLocation = fullStatusLocation.substring(fullStatusLocation.indexOf('?') - 3);
return statusLocation;
}
private ListFeatureCollection bombOutCollection() {
SimpleFeatureTypeBuilder tb = new SimpleFeatureTypeBuilder();
tb.add("name", String.class);
tb.add("location", Point.class, DefaultGeographicCRS.WGS84);
tb.setName("bomb");
SimpleFeatureType featureType = tb.buildFeatureType();
ListFeatureCollection fc = new ListFeatureCollection(featureType) {
@Override
public SimpleFeatureIterator features() {
throw new RuntimeException("Toasted!");
}
@Override
protected Iterator openIterator() {
throw new RuntimeException("Toasted!");
}
};
return fc;
}
private Document waitForProcessEnd(String statusLocation, long maxWaitSeconds) throws Exception {
XpathEngine xpath = XMLUnit.newXpathEngine();
Document dom = null;
long start = System.currentTimeMillis();
while(((System.currentTimeMillis() - start) / 1000 < maxWaitSeconds)) {
dom = getAsDOM(statusLocation);
// print(dom);
// are we still waiting for termination?
if(xpath.getMatchingNodes("//wps:Status/wps:ProcessAccepted", dom).getLength() > 0 ||
xpath.getMatchingNodes("//wps:Status/wps:ProcessStarted", dom).getLength() > 0 ||
xpath.getMatchingNodes("//wps:Status/wps:ProcessQueued", dom).getLength() > 0
) {
Thread.sleep(100);
} else {
return dom;
}
}
throw new Exception("Waited for the process to complete more than " + maxWaitSeconds);
}
/**
* Checks the bounds process returned the expected envelope
* @param request
* @param id
* @throws Exception
*/
void executeState1BoundsTest(String request, String id) throws Exception {
if (!RemoteOWSTestSupport.isRemoteWMSStatesAvailable(LOGGER)) {
LOGGER.warning("Remote OWS tests disabled, skipping test with " + id + " reference source");
return;
}
MockHttpServletResponse resp = postAsServletResponse(root(), request);
ReferencedEnvelope re = toEnvelope(resp.getOutputStreamContent());
assertEquals(-91.516129, re.getMinX(), 0.001);
assertEquals(36.986771, re.getMinY(), 0.001);
assertEquals(-87.507889, re.getMaxX(), 0.001);
assertEquals(42.509361, re.getMaxY(), 0.001);
}
ReferencedEnvelope toEnvelope(String xml) throws Exception {
Parser p = new Parser(new OWSConfiguration());
Object parsed = p.parse(new ByteArrayInputStream(xml.getBytes()));
assertTrue(parsed instanceof BoundingBoxType);
BoundingBoxType box = (BoundingBoxType) parsed;
ReferencedEnvelope re;
if(box.getCrs() != null) {
re = new ReferencedEnvelope(CRS.decode(box.getCrs()));
} else {
re = new ReferencedEnvelope();
}
re.expandToInclude((Double) box.getLowerCorner().get(0), (Double) box.getLowerCorner().get(1));
re.expandToInclude((Double) box.getUpperCorner().get(0), (Double) box.getUpperCorner().get(1));
return re;
}
String urlEncode(String string) throws Exception {
return URLEncoder.encode(string, "ASCII");
}
private void checkShapefileIntegrity(String[] typeNames, final InputStream in) throws IOException {
ZipInputStream zis = new ZipInputStream(in);
ZipEntry entry = null;
final String[] extensions = new String[] {".shp", ".shx", ".dbf", ".prj", ".cst"};
Set names = new HashSet();
for (String name : typeNames) {
for (String extension : extensions) {
names.add(name + extension);
}
}
while((entry = zis.getNextEntry()) != null) {
final String name = entry.getName();
assertTrue("Missing " + name, names.contains(name));
names.remove(name);
zis.closeEntry();
}
zis.close();
}
/* TODO Updating of Response requests A.4.4.5 */
/* TODO Language selection requests A.4.4.6 */
}