/** * OrbisGIS is a java GIS application dedicated to research in GIScience. * OrbisGIS is developed by the GIS group of the DECIDE team of the * Lab-STICC CNRS laboratory, see <http://www.lab-sticc.fr/>. * * The GIS group of the DECIDE team is located at : * * Laboratoire Lab-STICC – CNRS UMR 6285 * Equipe DECIDE * UNIVERSITÉ DE BRETAGNE-SUD * Institut Universitaire de Technologie de Vannes * 8, Rue Montaigne - BP 561 56017 Vannes Cedex * * OrbisGIS is distributed under GPL 3 license. * * Copyright (C) 2007-2014 CNRS (IRSTV FR CNRS 2488) * Copyright (C) 2015-2017 CNRS (Lab-STICC UMR CNRS 6285) * * This file is part of OrbisGIS. * * OrbisGIS is free software: you can redistribute it and/or modify it under the * terms of the GNU General Public License as published by the Free Software * Foundation, either version 3 of the License, or (at your option) any later * version. * * OrbisGIS is distributed in the hope that it will be useful, but WITHOUT ANY * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR * A PARTICULAR PURPOSE. See the GNU General Public License for more details. * * You should have received a copy of the GNU General Public License along with * OrbisGIS. If not, see <http://www.gnu.org/licenses/>. * * For more information, please consult: <http://www.orbisgis.org/> * or contact directly: * info_at_ orbisgis.org */ package org.orbisgis.coremap.stream; import org.h2gis.utilities.URIUtilities; import java.io.Serializable; import java.io.UnsupportedEncodingException; import java.net.MalformedURLException; import java.net.URI; import java.net.URISyntaxException; import java.util.Collections; import java.util.HashMap; import java.util.HashSet; import java.util.Map; import java.util.Set; /** * Contains the information to identify a stream. We retain only the needed * information gathered from the input URI. Consequently, some WMS request * parameters are useless and forgotten : * <ul> * <li>TIME</li> * <li>WIDTH</li> * <li>HEIGHT</li> * <li>BBOX</li> * <li>TRANSPARENT</li> * <li>BGCOLOR</li> * <li>ELEVATION</li> * <li>EXCEPTIONS</li> * </ul> * * <p>All the other keys are kept. They are put in two distinct maps. The first * one is dedicated to WMS keys. The second map is dedicated to the keys that * are not described in the WMS specifications. They are kept in order to * preserve our ability to give mandatory information to some WMS server * implementations.</p> * <p>This strategy makes this source quite resistant to user input. Indeed, * we can accept about any valid GetMap request as an input and obtain a valid * WMSStreamSource. * * @author Antoine Gourlay * @author Vincent Dépériers * @author Alexis Guéganno */ public final class WMSStreamSource implements Serializable { /** * Default HTTP port : 80 */ public static final int DEFAULT_PORT = 80; private static final long serialVersionUID = 144456789L; public static final String SERVICE_NAME = "wms"; /** Layers name */ public static final String LAYER_PARAMETER = "layers"; /** Image type ex:image/png */ public static final String OUTPUTFORMAT_PARAMETER = "format"; /** CRS replace SRS from this version */ public static final WMSVersion CRS_BEGINNING_VERSION = WMSVersion.fromString("1.3.0"); /** Coordinate reference system ex:EPSG:27572 Version >= 1.3.0 */ public static final String CRS_PARAMETER = "crs"; // Version >= 1.3.0 /** Spatial reference system ex:EPSG:27572 Version < 1.3.0 */ public static final String SRS_PARAMETER = "srs"; // Version < 1.3.0 /** SERVICE, must be WMS */ public static final String SERVICE_PARAMETER = "service"; /** WMS server version */ public static final String VERSION_PARAMETER = "version"; /** * WMS keys that we want to ignore */ public static final String TIME_PARAMETER = "time"; public static final String WIDTH_PARAMETER = "width"; public static final String HEIGHT_PARAMETER = "height"; public static final String BBOX_PARAMETER = "bbox"; public static final String TRANSPARENT_PARAMETER = "TRANSPARENT"; public static final String BGCOLOR_PARAMETER = "BGCOLOR"; public static final String ELEVATION_PARAMETER = "elevation"; public static final String EXCEPTIONS_PARAMETER = "exceptions"; public static final String REQUEST_PARAMETER = "request"; public static final Set<String> WMS_KEYS; public static final Set<String> IGNORED_WMS_KEYS; static { HashSet<String> keys = new HashSet<String>(); keys.add(LAYER_PARAMETER); keys.add(OUTPUTFORMAT_PARAMETER); keys.add(CRS_PARAMETER); keys.add(SRS_PARAMETER); keys.add(SERVICE_PARAMETER); keys.add(VERSION_PARAMETER); WMS_KEYS = Collections.unmodifiableSet(keys); HashSet<String> ignored = new HashSet<String>(); ignored.add(TIME_PARAMETER); ignored.add(WIDTH_PARAMETER); ignored.add(HEIGHT_PARAMETER); ignored.add(BBOX_PARAMETER); ignored.add(TRANSPARENT_PARAMETER); ignored.add(BGCOLOR_PARAMETER); ignored.add(ELEVATION_PARAMETER); ignored.add(EXCEPTIONS_PARAMETER); ignored.add(REQUEST_PARAMETER); IGNORED_WMS_KEYS = Collections.unmodifiableSet(ignored); } private String scheme="http"; private String host; private int port; private String path=""; private WMSVersion version; private Map<String,String> wmsParameters = new HashMap<String, String>(); private Map<String,String> otherParameters = new HashMap<String, String>(); /** * Short constructor, imageFormat is "image/png", crs is "EPSG:4326", version 1.3.0 * @param scheme Protocol ex:http * @param host Host name or IP, ex: services.orbisgis.org * @param port Service port, -1 for default * @param path URL path * @param layerName Layers, separated by a comma character * @param service Service (ex: WMS) */ @Deprecated public WMSStreamSource(String scheme, String host, int port, String path, String layerName, String service) { this(scheme,host, port, path, layerName, service, "image/png", "EPSG:4326", "1.3.0"); } /** * Complete constructor. * @param scheme Protocol ex:http * @param host Host name or IP, ex: services.orbisgis.org * @param port Service port, -1 for default * @param path URL path * @param layerName Layers, separated by a comma character * @param service Service (ex: WMS) * @param imageFormat Output format of the service ex:image/png * @param crs Spatial reference system ex: * @param version Wms server version ex: 1.3.0 */ @Deprecated public WMSStreamSource(String scheme, String host, int port, String path, String layerName, String service, String imageFormat, String crs, String version) { this.scheme = scheme; this.host = host; this.path = path; setVersion(version); if(port<=0) { //invalid port try { this.port = URI.create(scheme+"://dummy.org").toURL().getDefaultPort(); } catch (MalformedURLException ex) { this.port = DEFAULT_PORT; } } wmsParameters.put(LAYER_PARAMETER,layerName); wmsParameters.put(SERVICE_PARAMETER,service); wmsParameters.put(OUTPUTFORMAT_PARAMETER,imageFormat); if(this.version.equals(WMSVersion.VERSION_1_3_0)) { wmsParameters.put(SRS_PARAMETER,crs); } else { wmsParameters.put(CRS_PARAMETER,crs); } } /** * Set the service version * @param version Service version "x.y.z" */ public void setVersion(String version) { wmsParameters.put(VERSION_PARAMETER,version); this.version = WMSVersion.fromString(version); } /** * @return The stream version x.y.z */ public String getVersion() { return wmsParameters.get(VERSION_PARAMETER); } /** * Construct the stream source from an URI * @param uri Stream uri * @throws IllegalArgumentException If the URI does not contain a required query, fragment * @throws UnsupportedEncodingException If the URI contains non-utf8 characters */ public WMSStreamSource(URI uri) throws IllegalArgumentException, UnsupportedEncodingException { host = uri.getHost(); port = uri.getPort(); scheme = uri.getScheme(); path = uri.getPath(); if(port==-1) { try { port = uri.toURL().getDefaultPort(); } catch (MalformedURLException ex) { // Not a url port = DEFAULT_PORT; } } feedParameters(URIUtilities.getQueryKeyValuePairs(uri)); // If version is not set in the URI, find the appropriate one by using the projection system variable String vers = wmsParameters.get(VERSION_PARAMETER); if(vers==null) { String srs = wmsParameters.get(SRS_PARAMETER); String crs = wmsParameters.get(CRS_PARAMETER); if(crs!=null || srs==null) { setVersion("1.3.0"); } else { setVersion("1.1.1"); } } else { setVersion(vers); } if(wmsParameters.get(SERVICE_PARAMETER) == null){ wmsParameters.put(SERVICE_PARAMETER, SERVICE_NAME); } } private void feedParameters(Map<String,String> keyValues){ for(Map.Entry<String,String> entry : keyValues.entrySet()){ String key = entry.getKey(); if(!IGNORED_WMS_KEYS.contains(key)){ if(WMS_KEYS.contains(key)){ wmsParameters.put(key, entry.getValue()); } else { otherParameters.put(key, entry.getValue()); } } } } /** * Gets a String that gathers all the HTTP parameters not related to the * WMS query. * @return */ private String getOtherParameters(){ Set<String> keys = otherParameters.keySet(); String[] toArray = keys.toArray(new String[keys.size()]); return URIUtilities.getConcatenatedParameters( otherParameters, toArray); } /** * Gets a String gathering all the HTTP parameters linked to the WMS * query. * @return */ private String getQuery() { if(version.equals(WMSVersion.VERSION_1_3_0)) { return URIUtilities.getConcatenatedParameters( wmsParameters, SERVICE_PARAMETER, LAYER_PARAMETER, CRS_PARAMETER, VERSION_PARAMETER, OUTPUTFORMAT_PARAMETER); } else { return URIUtilities.getConcatenatedParameters( wmsParameters, SERVICE_PARAMETER, LAYER_PARAMETER, SRS_PARAMETER, VERSION_PARAMETER, OUTPUTFORMAT_PARAMETER); } } public URI toServerURI(){ try { return new URI(scheme,null,host,port,path,getQuery(),null); } catch (URISyntaxException ex) { return null; } } /** * @return URI equivalent of this request */ public URI toURI() { try { StringBuilder sb = new StringBuilder(); String o = getOtherParameters(); if(o!=null && !o.isEmpty()){ sb.append(o).append("&"); } sb.append(getQuery()); return new URI(scheme,null,host,port,path,sb.toString(),null); } catch (URISyntaxException ex) { return null; } } /** * @return the host of the source. */ public String getHost() { return this.host; } /** * * @return URI query as a map of key, values. We only have pairs not related * to the WMS query here. */ public Map<String,String> getOthersQueryMap(){ return Collections.unmodifiableMap(otherParameters); } /** * @return URI query as a map of key, values. We only have pairs related * to the WMS query here. */ public Map<String,String> getQueryMap() { return Collections.unmodifiableMap(wmsParameters); } /** * @return The path of the service */ public String getPath() { return path; } /** * @return The protocol of the stream (ex: http) */ public String getScheme() { return scheme; } /** * Sets the host of the source. * * @param host a new host */ public void setHost(String host) { this.host = host; } /** * @return the port of the source */ public int getPort() { return port; } /** * Sets the port of the source. * * @param port a new port number */ public void setPort(int port) { this.port = port; } /** * @return the name of the layer of the source */ public String getLayerName() { return wmsParameters.get(LAYER_PARAMETER); } /** * Sets the name of the layer of the source. * * @param layerName a new layer name */ public void setLayerName(String layerName) { wmsParameters.put(LAYER_PARAMETER,layerName); } /** * @return the format of the image, as a MIME type */ public String getImageFormat() { return wmsParameters.get(OUTPUTFORMAT_PARAMETER); } /** * Sets the format (MIME type) of the image. * * @param imageFormat a MIME format string. */ public void setImageFormat(String imageFormat) { wmsParameters.put(OUTPUTFORMAT_PARAMETER,imageFormat); } /** * Sets the srs of the source. * If version < 1.3.0 * @param srs a new SRS String */ public void setSRS(String srs) { wmsParameters.put(SRS_PARAMETER,srs); } /** * @return the srs of the source */ public String getSRS() { return getReferenceSystem(); } private String getReferenceSystem() { if(version.equals(WMSVersion.VERSION_1_3_0)) { return wmsParameters.get(CRS_PARAMETER); } else { return wmsParameters.get(SRS_PARAMETER); } } /** * @return the crs of the source */ public String getCRS() { return getReferenceSystem(); } /** * Sets the crs of the source. * If version >= 1.3.0 * @param crs a new CRS String */ public void setCRS(String crs) { wmsParameters.put(CRS_PARAMETER,crs); } @Override public String toString() { return toURI().toString(); } /** * @return the prefix of the source */ public String getStreamType() { return wmsParameters.get(SERVICE_PARAMETER); } /** * Sets the prefix of the source. * * @param type a new prefix */ public void setStreamType(String type) { wmsParameters.put(SERVICE_PARAMETER,type); } @Override public boolean equals(Object obj) { if (obj instanceof WMSStreamSource) { final WMSStreamSource other = (WMSStreamSource) obj; if ((this.host == null) ? (other.host != null) : !this.host.equals(other.host)) { return false; } if((this.path == null) ? (other.path != null) : !this.path.equals(other.path)) { return false; } if (this.port != other.port) { return false; } // Compare query for(Map.Entry<String,String> entry : other.getQueryMap().entrySet()) { String value = wmsParameters.get(entry.getKey()); if((value==null && entry.getValue()!=null) || !(value!=null && value.equals(entry.getValue()))) { return false; } } return true; } else { return false; } } @Override public int hashCode() { int result = scheme.hashCode(); result = 31 * result + host.hashCode(); result = 31 * result + port; result = 31 * result + (path != null ? path.hashCode() : 0); result = 31 * result + wmsParameters.hashCode(); return result; } }