package org.gcube.portlets.user.geoportaldataviewer.server.gis; import java.util.ArrayList; import java.util.HashMap; import java.util.List; import java.util.Map; import org.gcube.spatial.data.geoutility.GeoWmsServiceUtility; import org.gcube.spatial.data.geoutility.bean.WmsParameters; import org.gcube.spatial.data.geoutility.util.HttpRequestUtil; import org.gcube.spatial.data.geoutility.wms.WmsUrlValidator; import org.slf4j.Logger; import org.slf4j.LoggerFactory; /** * The Class GisViewerWMSUrlValidator. * * @author Francesco Mangiacrapa francesco.mangiacrapa@isti.cnr.it Jan 28, 2016 */ public class WMSUrlValidator { public static final String GEOSERVER = "/geoserver"; private static final String WMS = "wms"; private static final String OWS = "ows"; private HashMap parametersValue = new HashMap(); private String wmsRequestURI; private String wmsServiceHost; private String layerName; private String wmsNoStandardParameters = ""; private Map mapWmsNoStandardParams; private WmsUrlValidator urlValidator; private static final Logger LOG = LoggerFactory.getLogger(WMSUrlValidator.class); /** * Instantiates a new WMS url validator. * * @param wmsRequest the wms request * @param inputLayerName the input layer name * @throws Exception the exception */ public WMSUrlValidator(String wmsRequest, String inputLayerName) throws Exception { LOG.debug("WMSURLValidator wmsRequest: " + wmsRequest); LOG.debug("WMSURLValidator layerName: " + inputLayerName); if (wmsRequest == null || wmsRequest.isEmpty()) throw new Exception("WMS request is null or empty"); this.wmsRequestURI = wmsRequest.trim(); boolean isOwsService = GeoWmsServiceUtility.isOWSSerice(this.wmsRequestURI); WebMapServerHost webMapServerHost; // IS WMS? if (GeoWmsServiceUtility.isWMSService(wmsRequestURI)) { LOG.trace("found " + GeoWmsServiceUtility.SERVICE_WMS + " in wms request: " + wmsRequestURI); webMapServerHost = getWebMapServerHost(wmsRequestURI); } else throw new Exception("WMS service not found for layer: " + inputLayerName); // VALIDATION WMS String baseWmsService = webMapServerHost.getHost(); // IS OWS OR WMS? this.wmsServiceHost = appendWmsServiceToBaseUrl(wmsRequest.substring(0, wmsRequest.indexOf("?")), isOwsService); this.layerName = inputLayerName; try { // VALIDATE WMS SERVICE FOR WEB MAP SERVER if (!HttpRequestUtil.urlExists(this.wmsServiceHost, true)) { LOG.info("baseWmsServiceUrl: " + wmsServiceHost + " is not a geoserver, setting as input base wms server: " + baseWmsService); this.wmsServiceHost = baseWmsService; } } catch (Exception e) { LOG.error("error on validating geoserver wms service: " + e); LOG.info("setting baseWmsService as input base wms server: " + baseWmsService); this.wmsServiceHost = baseWmsService; } // VALIDATION FOR THREDDS - FIND LAYER NAME INTO WMS PATH if (this.layerName == null || this.layerName.isEmpty()) { this.layerName = WmsUrlValidator.getValueOfParameter(WmsParameters.LAYERS, wmsRequest); if (this.layerName == null || this.layerName.isEmpty()) throw new Exception("Layer name is null or empty"); } parametersValue.put(WmsParameters.LAYERS.getParameter(), this.layerName); } /** * Append wms service to base url. * * @param url the url * @param isOwsServer the is ows server * @return the string */ public String appendWmsServiceToBaseUrl(String url, boolean isOwsServer) { if (url.contains("/" + WMS) || url.contains("/" + OWS)) return url; if (url.lastIndexOf("/") != url.length()) { url += "/"; } if (isOwsServer) return url += OWS; else return url += WMS; } /** * Method: getFullWmsUrlRequest Create a correct wms url request Returns: * {String}. * * @param returnEmptyParameter if true the wms url returned contains also * wms parameter with empty value, none * otherwise. and mandatory wms parameters * that does not found are filled with empty * values * @param fillEmptyParameterAsDefault the fill empty parameter as default * @return a correct wms url request in formatted string like this: * "wmsserver?key1=value1&key2=value2&key3=value3" */ public String parseWMSRequest(boolean returnEmptyParameter, boolean fillEmptyParameterAsDefault) { urlValidator = new org.gcube.spatial.data.geoutility.wms.WmsUrlValidator(wmsRequestURI); String fullWmsUrlBuilded; try { fullWmsUrlBuilded = urlValidator.parseWmsRequest(returnEmptyParameter, fillEmptyParameterAsDefault); parametersValue.putAll(urlValidator.getMapWmsParameters()); String ln = parametersValue.get(WmsParameters.LAYERS.name()); LOG.debug("Comparing layer name from Wms request: " + ln + ", with OnLineResource layerName: " + this.layerName); if (ln == null || ln.isEmpty() || ln.compareTo(this.layerName) != 0) { LOG.info( "Layer name into wms request is different to OnLineResource layers name, replacing layer name: " + this.layerName); parametersValue.put(WmsParameters.LAYERS.getParameter(), this.layerName); urlValidator.getMapWmsParameters().put( org.gcube.spatial.data.geoutility.bean.WmsParameters.LAYERS.getParameter(), this.layerName); fullWmsUrlBuilded = org.gcube.spatial.data.geoutility.wms.WmsUrlValidator.setValueOfParameter( org.gcube.spatial.data.geoutility.bean.WmsParameters.LAYERS, fullWmsUrlBuilded, this.layerName, true); } // logger.trace("parametersValue: "+parametersValue); mapWmsNoStandardParams = new HashMap(urlValidator.getMapWmsNoStandardParams().size()); mapWmsNoStandardParams.putAll(urlValidator.getMapWmsNoStandardParams()); wmsNoStandardParameters = urlValidator.getWmsNoStandardParameters(); } catch (Exception e) { LOG.error("An error occurred during wms uri build, returning uri: " + wmsRequestURI, e); fullWmsUrlBuilded = wmsRequestURI; } LOG.trace("GisViewerWMSUrlValidator parseWMSRequest returning full wms url: " + fullWmsUrlBuilded); return fullWmsUrlBuilded; } /** * Gets the web map server host. * * @param wmsRequest the wms request * @return the web map server host, (geoserver URI or the wmsRequest substring * from start to index of '?' char (if exists)) */ public WebMapServerHost getWebMapServerHost(String wmsRequest) { WebMapServerHost webMapServerHost = new WebMapServerHost(); if (wmsRequest == null) return webMapServerHost; // uri is empty int end = wmsRequest.toLowerCase().lastIndexOf("?"); if (end == -1) { LOG.trace("char ? not found in geoserver uri, return: " + wmsRequest); return webMapServerHost; // uri is empty } String webMapServerBaseURL = wmsRequest.substring(0, wmsRequest.toLowerCase().lastIndexOf("?")); int index = webMapServerBaseURL.lastIndexOf(GEOSERVER); if (index > -1) { // FOUND the string GEOSERVER into URL LOG.trace("found geoserver string: " + GEOSERVER + " in " + webMapServerBaseURL); // THERE IS SCOPE? int lastSlash = webMapServerBaseURL.lastIndexOf("/"); int includeGeoserverString = index + GEOSERVER.length(); int endUrl = lastSlash > includeGeoserverString ? lastSlash : includeGeoserverString; LOG.trace("indexs - lastSlash: [" + lastSlash + "], includeGeoserverString: [" + includeGeoserverString + "], endUrl: [" + endUrl + "]"); int startScope = includeGeoserverString + 1 < endUrl ? includeGeoserverString + 1 : endUrl; // INCLUDE SLASH String scope = webMapServerBaseURL.substring(startScope, endUrl); LOG.trace("geoserver url include scope: " + webMapServerBaseURL.substring(includeGeoserverString, endUrl)); webMapServerHost.setHost(webMapServerBaseURL.substring(0, endUrl)); webMapServerHost.setScope(scope); return webMapServerHost; } else { LOG.trace("the string 'geoserver' not found in " + webMapServerBaseURL); // GET LAST INDEX OF '/' AND CONCATENATE GEOSERVER String urlConn = webMapServerBaseURL.substring(0, webMapServerBaseURL.lastIndexOf("/")) + GEOSERVER; LOG.trace("tentative concatenating string 'geoserver' at http url " + urlConn); try { if (HttpRequestUtil.urlExists(urlConn, false)) { LOG.trace("url: " + urlConn + " - open a connection, return " + urlConn); webMapServerHost.setHost(urlConn); return webMapServerHost; } else LOG.trace("url: " + urlConn + " - not open a connection"); } catch (Exception e) { LOG.error("url connection is wrong at :" + urlConn); } String uriWithoutParameters = wmsRequest.substring(0, end); LOG.trace("url connection, returned: " + uriWithoutParameters); webMapServerHost.setHost(uriWithoutParameters); return webMapServerHost; } } /** * Gets the wms service host. * * @return the wms service host */ public String getWmsServiceHost() { return wmsServiceHost; } /** * Gets the url validator. * * @return the urlValidator */ public org.gcube.spatial.data.geoutility.wms.WmsUrlValidator getUrlValidator() { return urlValidator; } /** * Gets the wms no standard parameters. * * @return the wms no standard parameters */ public String getWmsNoStandardParameters() { return wmsNoStandardParameters; } /** * Gets the value of parsed wms parameter. * * @param parameter the parameter * @return the value of parsed wms parameter parsed from wms request. */ public String getValueOfParsedWMSParameter(WmsParameters parameter) { return parametersValue.get(parameter.getParameter()); } /** * Gets the value of parameter. * * @param wmsParam the wms param * @param wmsUrlParameters the wms url parameters * @return the value of parameter */ public static String getValueOfParameter(WmsParameters wmsParam, String wmsUrlParameters) { return WmsUrlValidator.getValueOfParameter(wmsParam, wmsUrlParameters); } /** * Sets the value of parameter. * * @param wmsParam the wms param * @param wmsUrlParameters the wms url parameters * @param newValue the new value * @param addIfNotExists the add if not exists * @return the string */ public static String setValueOfParameter(WmsParameters wmsParam, String wmsUrlParameters, String newValue, boolean addIfNotExists) { return WmsUrlValidator.setValueOfParameter(wmsParam, wmsUrlParameters, newValue, addIfNotExists); } /** * Gets the layer name. * * @return the layer name */ public String getLayerName() { return layerName; } /** * Gets the styles as list. * * @return the styles as list */ public List getStylesAsList() { List listStyles = new ArrayList(); String styles = getValueOfParsedWMSParameter(WmsParameters.STYLES); if (styles != null && !styles.isEmpty()) { String[] arrayStyle = styles.split(","); for (String style : arrayStyle) { if (style != null && !style.isEmpty()) listStyles.add(style); } } return listStyles; } /** * Gets the map wms no standard params. * * @return the map wms no standard params */ public Map getMapWmsNoStandardParams() { return mapWmsNoStandardParams; } }