package org.geoserver.wfs.response; import java.io.ByteArrayOutputStream; import java.io.IOException; import java.io.StringReader; import java.util.ArrayList; import java.util.List; import net.opengis.wfs.FeatureCollectionType; import net.opengis.wfs.GetFeatureType; import net.opengis.wfs.WfsFactory; import org.geoserver.data.test.MockData; import org.geoserver.platform.Operation; import org.geoserver.wfs.WFSTestSupport; import org.geoserver.wfs.request.FeatureCollectionResponse; import org.geotools.data.FeatureSource; import org.geotools.data.Query; import org.geotools.data.memory.MemoryDataStore; import org.geotools.data.simple.SimpleFeatureSource; import org.geotools.feature.simple.SimpleFeatureBuilder; import org.geotools.feature.simple.SimpleFeatureTypeBuilder; import org.opengis.feature.simple.SimpleFeature; import org.opengis.feature.simple.SimpleFeatureType; import au.com.bytecode.opencsv.CSVReader; import com.mockrunner.mock.web.MockHttpServletResponse; import com.vividsolutions.jts.geom.Coordinate; import com.vividsolutions.jts.geom.GeometryFactory; import com.vividsolutions.jts.geom.Point; public class CSVOutputFormatTest extends WFSTestSupport { public void testFullRequest() throws Exception { MockHttpServletResponse resp = getAsServletResponse("wfs?version=1.1.0&request=GetFeature&typeName=sf:PrimitiveGeoFeature&outputFormat=csv"); FeatureSource fs = getFeatureSource(MockData.PRIMITIVEGEOFEATURE); // System.out.println(resp.getOutputStreamContent()); // check the mime type assertEquals("text/csv", resp.getContentType()); // check the content disposition assertEquals("attachment; filename=PrimitiveGeoFeature.csv", resp.getHeader("Content-Disposition")); // read the response back with a parser that can handle escaping, newlines and what not List<String[]> lines = readLines(resp.getOutputStreamContent()); // we should have one header line and then all the features in that feature type assertEquals(fs.getCount(Query.ALL) + 1, lines.size()); for (String[] line : lines) { // check each line has the expected number of elements (num of att + 1 for the id) assertEquals(fs.getSchema().getDescriptors().size() + 1, line.length); } } public void testEscapes() throws Exception { // build some fake data in memory, the property data store cannot handle newlines in its data SimpleFeatureTypeBuilder builder = new SimpleFeatureTypeBuilder(); builder.add("geom", Point.class); builder.add("label", String.class); builder.setName("funnyLabels"); SimpleFeatureType type = builder.buildFeatureType(); GeometryFactory gf = new GeometryFactory(); SimpleFeature f1 = SimpleFeatureBuilder.build(type, new Object[]{gf.createPoint(new Coordinate(5, 8)), "A label with \"quotes\""}, null); SimpleFeature f2 = SimpleFeatureBuilder.build(type, new Object[]{gf.createPoint(new Coordinate(5, 4)), "A long label\nwith newlines"}, null); MemoryDataStore data = new MemoryDataStore(); data.addFeature(f1); data.addFeature(f2); SimpleFeatureSource fs = data.getFeatureSource("funnyLabels"); // build the request objects and feed the output format GetFeatureType gft = WfsFactory.eINSTANCE.createGetFeatureType(); Operation op = new Operation("GetFeature", getServiceDescriptor10(), null, new Object[] {gft}); ByteArrayOutputStream bos = new ByteArrayOutputStream(); FeatureCollectionResponse fct = FeatureCollectionResponse.adapt(WfsFactory.eINSTANCE.createFeatureCollectionType()); fct.getFeature().add(fs.getFeatures()); // write out the results CSVOutputFormat format = new CSVOutputFormat(getGeoServer()); format.write(fct, bos, op); // read the response back with a parser that can handle escaping, newlines and what not List<String[]> lines = readLines(bos.toString()); // we should have one header line and then all the features in that feature type assertEquals(fs.getCount(Query.ALL) + 1, lines.size()); for (String[] line : lines) { // check each line has the expected number of elements assertEquals(fs.getSchema().getAttributeCount() + 1, line.length); } // check we have the expected values in the string attributes assertEquals(f1.getAttribute("label"), lines.get(1)[2]); assertEquals(f2.getAttribute("label"), lines.get(2)[2]); } /** * Convenience to read the csv content and * @param csvContent * @return * @throws IOException */ private List<String[]> readLines(String csvContent) throws IOException { CSVReader reader = new CSVReader(new StringReader(csvContent)); List<String[]> result = new ArrayList<String[]>(); String [] nextLine; while ((nextLine = reader.readNext()) != null) { result.add(nextLine); } return result; } }