Java tutorial
/* Copyright (c) 2001 - 2007 TOPP - www.openplans.org. All rights reserved. * This code is licensed under the GPL 2.0 license, availible at the root * application directory. */ package org.geoserver.wms.featureinfo; import java.io.IOException; import java.io.OutputStream; import java.io.OutputStreamWriter; import java.net.URI; import java.net.URISyntaxException; import java.util.Collections; import java.util.Map; import javax.xml.namespace.QName; import net.opengis.wfs.FeatureCollectionType; import net.opengis.wfs.GetFeatureType; import net.opengis.wfs.QueryType; import net.opengis.wfs.WfsFactory; import org.apache.commons.io.IOUtils; import org.geoserver.config.GeoServer; import org.geoserver.ows.Dispatcher; import org.geoserver.ows.Request; import org.geoserver.platform.Operation; import org.geoserver.platform.Service; import org.geoserver.platform.ServiceException; import org.geoserver.wfs.json.JSONType; import org.geoserver.wfs.response.GeoJSONOutputFormat; import org.geoserver.wms.GetFeatureInfoRequest; import org.geoserver.wms.WMS; import org.geotools.feature.FeatureCollection; import org.geotools.gml2.bindings.GML2EncodingUtils; import org.opengis.feature.type.Name; /** * A GetFeatureInfo response handler specialized in producing Json and JsonP data for a * GetFeatureInfo request. * * <p> * This class does not deals directly with GML encoding. Instead, it works by taking the * FeatureResults produced in <code>execute()</code> and constructs a <code>GetFeaturesResult</code> * wich is passed to a <code>GML2FeatureResponseDelegate</code>, as if it where the result of a * GetFeature WFS request. * </p> * * @author Simone Giannecchini, GeoSolutions */ public class GeoJSONFeatureInfoOutputFormat extends GetFeatureInfoOutputFormat { protected final WMS wms; /** * @param wms * @param outputFormat * @throws Exception if outputFormat is not a valid json mime type */ public GeoJSONFeatureInfoOutputFormat(final WMS wms, final String outputFormat) throws Exception { super(outputFormat); if (JSONType.getJSONType(outputFormat) == null) throw new Exception("Illegal json mime type"); this.wms = wms; } /** * Takes the <code>FeatureResult</code>s generated by the <code>execute</code> method in the * superclass and constructs a <code>GetFeaturesResult</code> wich is passed to a * <code>GML2FeatureResponseDelegate</code>. * * @see AbstractFeatureInfoResponse#writeTo(OutputStream) */ @SuppressWarnings({ "rawtypes", "unchecked" }) @Override public void write(FeatureCollectionType results, GetFeatureInfoRequest fInfoReq, OutputStream out) throws ServiceException, IOException { // the 'response' object we'll pass to our OutputFormat FeatureCollectionType features = WfsFactory.eINSTANCE.createFeatureCollectionType(); // the 'request' object we'll pass to our OutputFormat GetFeatureType gfreq = WfsFactory.eINSTANCE.createGetFeatureType(); gfreq.setBaseUrl(fInfoReq.getBaseUrl()); final int size = results.getFeature().size(); for (int i = 0; i < size; i++) { FeatureCollection fc = (FeatureCollection) results.getFeature().get(i); Name name = FeatureCollectionDecorator.getName(fc); QName qname = new QName(name.getNamespaceURI(), name.getLocalPart()); features.getFeature().add(fc); QueryType qt = WfsFactory.eINSTANCE.createQueryType(); qt.setTypeName(Collections.singletonList(qname)); String crs = GML2EncodingUtils.epsgCode(fc.getSchema().getCoordinateReferenceSystem()); if (crs != null) { final String srsName = "EPSG:" + crs; try { qt.setSrsName(new URI(srsName)); } catch (URISyntaxException e) { throw new ServiceException("Unable to determite coordinate system for featureType " + fc.getSchema().getName().getLocalPart() + ". Schema told us '" + srsName + "'", e); } } gfreq.getQuery().add(qt); } // this is a dummy wrapper around our 'request' object so that the new Dispatcher will // accept it. Service serviceDesc = new Service("wms", null, null, Collections.EMPTY_LIST); Operation opDescriptor = new Operation("", serviceDesc, null, new Object[] { gfreq }); final GeoServer gs = wms.getGeoServer(); GeoJSONOutputFormat format = new GeoJSONOutputFormat(gs); if (JSONType.isJsonMimeType(getContentType())) { writeJSON(out, features, opDescriptor, format); } else { writeJSONP(out, features, opDescriptor, format); } } private void writeJSONP(OutputStream out, FeatureCollectionType features, Operation opDescriptor, GeoJSONOutputFormat format) throws IOException { OutputStreamWriter outWriter = null; try { outWriter = new OutputStreamWriter(out, wms.getGeoServer().getSettings().getCharset()); // preamble outWriter.write(getCallbackFunction() + "("); outWriter.flush(); // call regular format format.write(features, out, opDescriptor); // postamble outWriter.write(")"); outWriter.flush(); } finally { IOUtils.closeQuietly(outWriter); } } private static void writeJSON(OutputStream out, FeatureCollectionType features, Operation opDescriptor, GeoJSONOutputFormat format) throws IOException { format.write(features, out, opDescriptor); } private String getCallbackFunction() { Request request = Dispatcher.REQUEST.get(); if (request == null) { return JSONType.CALLBACK_FUNCTION; } else if (!(request.getKvp().get("FORMAT_OPTIONS") instanceof Map)) { return JSONType.CALLBACK_FUNCTION; } return JSONType.getCallbackFunction(request.getKvp()); } }