/* * This is part of Geomajas, a GIS framework, http://www.geomajas.org/. * * Copyright 2008-2015 Geosparc nv, http://www.geosparc.com/, Belgium. * * The program is available in open source according to the GNU Affero * General Public License. All contributions in this program are covered * by the Geomajas Contributors License Agreement. For full licensing * details, see LICENSE.txt in the project root. */ package org.geomajas.gwt2.plugin.wms.server.command; import java.io.IOException; import java.net.URL; import java.util.ArrayList; import java.util.List; import javax.xml.parsers.ParserConfigurationException; import org.apache.http.HttpResponse; import org.apache.http.client.HttpClient; import org.apache.http.client.methods.HttpGet; import org.apache.http.util.EntityUtils; import org.geomajas.command.CommandHasRequest; import org.geomajas.gwt2.plugin.wfs.server.command.converter.FeatureConverter; import org.geomajas.gwt2.plugin.wms.client.service.WmsService.GetFeatureInfoFormat; import org.geomajas.gwt2.plugin.wms.server.command.dto.WmsGetFeatureInfoRequest; import org.geomajas.gwt2.plugin.wms.server.command.dto.WmsGetFeatureInfoResponse; import org.geomajas.gwt2.plugin.wms.server.command.factory.WmsHttpClientFactory; import org.geomajas.gwt2.plugin.wms.server.command.factory.impl.DefaultWmsHttpClientFactory; import org.geomajas.layer.feature.Feature; import org.geotools.GML; import org.geotools.GML.Version; import org.geotools.feature.FeatureCollection; import org.geotools.feature.FeatureIterator; import org.geotools.geojson.feature.FeatureJSON; import org.opengis.feature.simple.SimpleFeature; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import org.springframework.stereotype.Component; import org.xml.sax.SAXException; /** * Command that executes a WMS GetFeatureInfo request. * <p/> * This command is not part of the API and shouldn't be used directly. * * @author Pieter De Graef * @author An Buyle * @author Jan De Moerloose */ @Component public class WmsGetFeatureInfoCommand implements CommandHasRequest<WmsGetFeatureInfoRequest, WmsGetFeatureInfoResponse> { private final Logger log = LoggerFactory.getLogger(WmsGetFeatureInfoCommand.class); private static final String PARAM_FORMAT = "info_format"; private WmsHttpClientFactory httpClientFactory = new DefaultWmsHttpClientFactory(); @Override public void execute(WmsGetFeatureInfoRequest request, WmsGetFeatureInfoResponse response) throws Exception { HttpClient client = httpClientFactory.create(request.getUrl()); URL url = httpClientFactory.getTargetUrl(request.getUrl()); GML gml; GetFeatureInfoFormat format = getFormatFromUrl(request.getUrl()); switch (format) { case GML2: gml = new GML(Version.GML2); response.setFeatures(getFeaturesFromUrl(client, url, gml, request.getMaxCoordsPerFeature())); break; case GML3: gml = new GML(Version.GML3); response.setFeatures(getFeaturesFromUrl(client, url, gml, request.getMaxCoordsPerFeature())); break; case JSON: response.setFeatures(getFeaturesFromJson(client, request, url, request.getMaxCoordsPerFeature())); break; default: String content = readUrl(client, url); response.setWmsResponse(content); } } public WmsHttpClientFactory getHttpClientFactory() { return httpClientFactory; } public void setHttpClientFactory(WmsHttpClientFactory httpClientFactory) { this.httpClientFactory = httpClientFactory; } @Override public WmsGetFeatureInfoRequest getEmptyCommandRequest() { return new WmsGetFeatureInfoRequest(); } @Override public WmsGetFeatureInfoResponse getEmptyCommandResponse() { return new WmsGetFeatureInfoResponse(); } private List<Feature> getFeaturesFromJson(HttpClient client, WmsGetFeatureInfoRequest request, URL url, int maxCoordsPerFeature) throws IOException { FeatureConverter converter = new FeatureConverter(); List<Feature> dtoFeatures = new ArrayList<Feature>(); HttpGet get = new HttpGet(url.toExternalForm()); HttpResponse response = client.execute(get); if (200 != response.getStatusLine().getStatusCode()) { get.releaseConnection(); throw new IOException("Server returned " + response.getStatusLine() + " for URL " + url.toExternalForm()); } FeatureIterator<SimpleFeature> it = new FeatureJSON() .streamFeatureCollection(response.getEntity().getContent()); while (it.hasNext()) { SimpleFeature feature = it.next(); try { dtoFeatures.add(converter.toDto(feature, maxCoordsPerFeature)); } catch (Exception e) { log.error("Error parsing Feature information: " + e.getMessage()); } } it.close(); return dtoFeatures; } private List<Feature> getFeaturesFromUrl(HttpClient client, URL url, GML gml, int maxCoordsPerFeature) throws IOException, SAXException, ParserConfigurationException { HttpGet get = new HttpGet(url.toExternalForm()); HttpResponse response = client.execute(get); if (200 != response.getStatusLine().getStatusCode()) { get.releaseConnection(); throw new IOException("Server returned " + response.getStatusLine() + " for URL " + url.toExternalForm()); } FeatureCollection<?, SimpleFeature> collection = gml.decodeFeatureCollection(response.getEntity().getContent()); List<Feature> dtoFeatures = new ArrayList<Feature>(); if (null == collection) { return dtoFeatures; // empty list } FeatureConverter converter = new FeatureConverter(); FeatureIterator<SimpleFeature> it = collection.features(); if (it.hasNext()) { SimpleFeature feature = it.next(); try { dtoFeatures.add(converter.toDto(feature, maxCoordsPerFeature)); } catch (Exception e) { log.error("Error parsing Feature information: " + e.getMessage()); } } while (it.hasNext()) { SimpleFeature feature = it.next(); try { dtoFeatures.add(converter.toDto(feature, maxCoordsPerFeature)); } catch (Exception e) { // Do nothing... } } return dtoFeatures; } private GetFeatureInfoFormat getFormatFromUrl(String url) { try { int index = url.toLowerCase().indexOf(PARAM_FORMAT) + PARAM_FORMAT.length() + 1; String format = url.substring(index); index = format.indexOf('&'); if (index > 0) { format = format.substring(0, index); } for (GetFeatureInfoFormat enumValue : GetFeatureInfoFormat.values()) { if (enumValue.toString().equalsIgnoreCase(format)) { return enumValue; } } } catch (Exception e) { log.error("WMS GetFeatureInfo - Cannot understand which format to request... " + "We'll take HTML format as a fallback." + e.getMessage()); } return GetFeatureInfoFormat.HTML; } private String readUrl(HttpClient client, URL url) throws Exception { HttpGet get = new HttpGet(url.toExternalForm()); HttpResponse response = client.execute(get); if (200 != response.getStatusLine().getStatusCode()) { get.releaseConnection(); throw new IOException("Server returned " + response.getStatusLine() + " for URL " + url.toExternalForm()); } return EntityUtils.toString(response.getEntity()); } }