Java tutorial
/* * B3P Kaartenbalie is a OGC WMS/WFS proxy that adds functionality * for authentication/authorization, pricing and usage reporting. * * Copyright 2006, 2007, 2008 B3Partners BV * * This file is part of B3P Kaartenbalie. * * B3P Kaartenbalie 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. * * B3P Kaartenbalie 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 B3P Kaartenbalie. If not, see <http://www.gnu.org/licenses/>. */ package nl.b3p.kaartenbalie.service.requesthandler; import java.awt.image.BufferedImage; import java.io.ByteArrayOutputStream; import java.io.IOException; import java.io.InputStream; import java.io.UnsupportedEncodingException; import java.math.BigDecimal; import java.net.HttpURLConnection; import java.net.URL; import java.net.URLEncoder; import java.util.*; import javax.persistence.EntityManager; import javax.persistence.NoResultException; import javax.xml.parsers.DocumentBuilder; import javax.xml.parsers.DocumentBuilderFactory; import nl.b3p.commons.xml.IgnoreEntityResolver; import nl.b3p.commons.services.B3PCredentials; import nl.b3p.commons.services.HttpClientConfigured; import nl.b3p.kaartenbalie.core.server.Organization; import nl.b3p.kaartenbalie.core.server.User; import nl.b3p.kaartenbalie.core.server.accounting.ExtLayerCalculator; import nl.b3p.kaartenbalie.core.server.accounting.entity.LayerPriceComposition; import nl.b3p.kaartenbalie.core.server.accounting.entity.LayerPricing; import nl.b3p.kaartenbalie.core.server.b3pLayering.ConfigLayer; import nl.b3p.kaartenbalie.core.server.monitoring.DataMonitoring; import nl.b3p.kaartenbalie.core.server.monitoring.Operation; import nl.b3p.kaartenbalie.core.server.monitoring.ServiceProviderRequest; import nl.b3p.kaartenbalie.core.server.persistence.MyEMFDatabase; import nl.b3p.kaartenbalie.core.server.persistence.WFSProviderDAO; import nl.b3p.kaartenbalie.service.ImageManager; import nl.b3p.kaartenbalie.service.KBImageTool; import nl.b3p.kaartenbalie.service.LayerValidator; import nl.b3p.kaartenbalie.service.ServiceProviderValidator; import nl.b3p.kaartenbalie.service.servlet.CallWMSServlet; import nl.b3p.kaartenbalie.service.servlet.ProxySLDServlet; import nl.b3p.ogc.utils.KBConfiguration; import nl.b3p.ogc.utils.LayerSummary; import nl.b3p.ogc.utils.OGCCommunication; import nl.b3p.ogc.utils.OGCConstants; import nl.b3p.ogc.utils.OGCRequest; import nl.b3p.ogc.utils.SpLayerSummary; import nl.b3p.wms.capabilities.*; import org.apache.commons.logging.Log; import org.apache.commons.logging.LogFactory; import org.apache.http.Header; import org.apache.http.HttpEntity; import org.apache.http.HttpResponse; import org.apache.http.client.methods.HttpGet; import org.apache.xml.serialize.OutputFormat; import org.apache.xml.serialize.XMLSerializer; import org.geotools.data.ows.HTTPResponse; import org.geotools.data.ows.LayerDescription; import org.geotools.data.ows.SimpleHttpClient.SimpleHTTPResponse; import org.geotools.data.wms.response.DescribeLayerResponse; import org.geotools.ows.ServiceException; import org.w3c.dom.*; import org.xml.sax.Attributes; import org.xml.sax.InputSource; import org.xml.sax.SAXException; import org.xml.sax.XMLReader; public abstract class WMSRequestHandler extends OGCRequestHandler { private static final Log log = LogFactory.getLog(WMSRequestHandler.class); private XMLReader parser; private static Stack stack = new Stack(); private Switcher s; public WMSRequestHandler() { } public boolean mayDirectWrite() { return false; } /** * @return the maxResponseTime */ public int getMaxResponseTime() { if (maxResponseTime <= 0) { try { maxResponseTime = new Integer(KBConfiguration.WMS_RESPONSE_TIME_LIMIT); } catch (NumberFormatException nfe) { maxResponseTime = 11111; } } return maxResponseTime; } protected Set getValidLayers(User user, EntityManager em, boolean isAdmin, String spAbbrUrl) throws Exception { Set organizationLayers = new HashSet(); List layerlist = null; if (isAdmin) { if (spAbbrUrl == null) { layerlist = em.createQuery("from Layer l").getResultList(); } else { layerlist = em.createQuery("from Layer l where l.serviceProvider.abbr = :spAbbr") .setParameter("spAbbr", spAbbrUrl).getResultList(); } } else { Set orgs = user.getAllOrganizations(); if (spAbbrUrl == null) { layerlist = em .createQuery("from Layer l where " + "l in (select ol from Organization o join o.layers ol where o in (:orgs)) ") .setParameter("orgs", orgs).getResultList(); } else { layerlist = em .createQuery("from Layer l where l.serviceProvider.abbr = :spAbbr and " + "l in (select ol from Organization o join o.layers ol where o in (:orgs)) ") .setParameter("spAbbr", spAbbrUrl).setParameter("orgs", orgs).getResultList(); } } organizationLayers.addAll(layerlist); return organizationLayers; } public Set getServiceProviders(boolean isAdmin, String spAbbrUrl) throws Exception { log.debug("Getting entity manager ......"); EntityManager em = MyEMFDatabase.getEntityManager(MyEMFDatabase.MAIN_EM); User dbUser = null; try { dbUser = (User) em.createQuery("from User u where " + "u.id = :userid") .setParameter("userid", user.getId()).getSingleResult(); } catch (NoResultException nre) { log.error("No serviceprovider for user found."); throw new Exception("No serviceprovider for user found."); } Set organizationLayers = getValidLayers(dbUser, em, isAdmin, spAbbrUrl); Set serviceproviders = null; if (organizationLayers != null && !organizationLayers.isEmpty()) { serviceproviders = new HashSet(); Iterator it = organizationLayers.iterator(); while (it.hasNext()) { Layer layer = (Layer) it.next(); ServiceProvider sp = layer.getServiceProvider(); if (!serviceproviders.contains(sp)) { serviceproviders.add(sp); } } } return serviceproviders; } public ServiceProvider getServiceProvider(boolean isAdmin, String spAbbrUrl) throws Exception { log.debug("Getting entity manager ......"); EntityManager em = MyEMFDatabase.getEntityManager(MyEMFDatabase.MAIN_EM); User dbUser = null; try { dbUser = (User) em.createQuery("from User u where " + "u.id = :userid") .setParameter("userid", user.getId()).getSingleResult(); } catch (NoResultException nre) { log.error("User not found in database."); throw new Exception("User not found in database."); } Set organizationLayers = getValidLayers(dbUser, em, isAdmin, spAbbrUrl); Set serviceproviders = null; Layer kaartenbalieTopLayer = null; Set<TileSet> tileSets = null; if (organizationLayers != null && !organizationLayers.isEmpty()) { serviceproviders = new HashSet(); Set topLayers = new HashSet(); Set orgLayerIds = new HashSet(); Iterator it = organizationLayers.iterator(); while (it.hasNext()) { Layer layer = (Layer) it.next(); orgLayerIds.add(layer.getId()); Layer topLayer = layer.getTopLayer(); ServiceProvider sp = layer.getServiceProvider(); sp.setUrlServiceProvideCode(spAbbrUrl); if (!serviceproviders.contains(sp)) { serviceproviders.add(sp); if (!topLayers.contains(topLayer)) { topLayers.add(topLayer); } } } Iterator spIt = serviceproviders.iterator(); while (spIt.hasNext()) { ServiceProvider sp = (ServiceProvider) spIt.next(); if (sp.getTileSets() != null) { Iterator<TileSet> tileSetIt = sp.getTileSets().iterator(); while (tileSetIt.hasNext()) { TileSet ts = tileSetIt.next(); if (ts.getLayers() != null) { Iterator<Layer> layerIt = ts.getLayers().iterator(); boolean hasRight = false; while (layerIt.hasNext()) { Layer l = layerIt.next(); if (!organizationLayers.contains(l)) { hasRight = false; break; } else { hasRight = true; } } if (hasRight) { if (tileSets == null) { tileSets = new HashSet<TileSet>(); } tileSets.add(ts); } } } } } if (!topLayers.isEmpty()) { kaartenbalieTopLayer = new Layer(); kaartenbalieTopLayer.setTitle(KBConfiguration.TOPLAYERNAME); LayerValidator lv = new LayerValidator(organizationLayers); kaartenbalieTopLayer.addSrsbb(lv.validateLatLonBoundingBox()); Iterator tlId = topLayers.iterator(); /* To prevent multiple topLayers as a child of the kaartenbalieTopLayer * with duplicate name, title and cascaded properties (but not * service provider abbr!), keep count of how many duplicates * there are and a duplicate number after the layer title in braces. * * NOTE: theoretically a duplicate can only occur when name is * null, otherwise a unique abbreviation prefix has been added * to the name */ /* Map of as keys layer identity tuples maps; see Layer.getIdentityMap() * and as value an Integer of the duplicate count. No map entry means a * count of 0, naturally. */ Map topLayerDuplicateCounts = new HashMap(); while (tlId.hasNext()) { Layer layer = (Layer) tlId.next(); Layer layerCloned = (Layer) layer.clone(); Set authSubLayers = layerCloned.getAuthSubLayersClone(orgLayerIds); // niet toevoegen indien deze layer en alle sublayers niet toegankelijk boolean layerAuthorized = orgLayerIds.contains(layer.getId()); if (!layerAuthorized && (authSubLayers == null || authSubLayers.isEmpty())) { continue; } layerCloned.setLayers(authSubLayers); // layer alleen als placeholder indien niet toegankelijk maar wel toegankelijke sublayers heeft if (!layerAuthorized) { layerCloned.setName(null); } if (authSubLayers == null) { authSubLayers = new HashSet(); } Map topLayerIdentity = layerCloned.getIdentityMap(false); Integer duplicateCount = (Integer) topLayerDuplicateCounts.get(topLayerIdentity); if (duplicateCount == null) { /* First time this identity combo has been encountered... Do not add * a counter to the title */ topLayerDuplicateCounts.put(topLayerIdentity, new Integer(1)); } else { /* Add a counter to the title */ int count = duplicateCount.intValue() + 1; layerCloned.setTitle(layerCloned.getTitle().trim() + " (" + count + ")"); topLayerDuplicateCounts.put(topLayerIdentity, new Integer(count)); } kaartenbalieTopLayer.addLayer(layerCloned); } // Valideer SRS van toplayers lv = new LayerValidator(kaartenbalieTopLayer.getLayers()); String[] supportedSRS = lv.validateSRS(); for (int i = 0; i < supportedSRS.length; i++) { SrsBoundingBox srsbb = new SrsBoundingBox(); srsbb.setSrs(supportedSRS[i]); kaartenbalieTopLayer.addSrsbb(srsbb); } } } //controleer of een organisatie een bepaalde startpostitie heeft voor de BBOX //indien dit het geval is, voeg deze bbox toe aan de toplayer. if (kaartenbalieTopLayer != null) { SrsBoundingBox srsbb = calcSrsBoundingBox(dbUser); if (srsbb != null) { kaartenbalieTopLayer.addSrsbb(srsbb); } } // Creeer geldige service provider ServiceProviderValidator spv = new ServiceProviderValidator(serviceproviders); ServiceProvider validServiceProvider = spv.getValidServiceProvider(); validServiceProvider.setTopLayer(kaartenbalieTopLayer); if (spAbbrUrl != null && !spAbbrUrl.equals("")) { validServiceProvider.setUrlServiceProvideCode(spAbbrUrl); } /* * B3Partners Configuration Layers.. */ boolean allowAccountingLayers = false; Set orgs = dbUser.getAllOrganizations(); Iterator it = orgs.iterator(); while (it.hasNext()) { Organization org = (Organization) it.next(); if (org.getAllowAccountingLayers()) { allowAccountingLayers = true; break; } } /* *Only adds AllowTransaction layer and creditInfo layer if the user has the rights to see these layers. */ if (allowAccountingLayers == true && kaartenbalieTopLayer != null) { Map configLayers = ConfigLayer.getConfigLayers(); Iterator iterLayerKeys = configLayers.keySet().iterator(); while (iterLayerKeys.hasNext()) { Layer configLayer = ConfigLayer.forName((String) iterLayerKeys.next()); configLayer.setServiceProvider(validServiceProvider); kaartenbalieTopLayer.addLayer(configLayer); } } Set roles = dbUser.getRoles(); if (roles != null) { Iterator roleIt = roles.iterator(); while (roleIt.hasNext()) { Roles role = (Roles) roleIt.next(); validServiceProvider.addRole(role); } } //if tileSets then add! if (tileSets != null) { validServiceProvider.setTileSets(tileSets); } return validServiceProvider; } private SrsBoundingBox calcSrsBoundingBox(User user) { SrsBoundingBox srsbb = new SrsBoundingBox(); String orgBbox = user.getMainOrganization().getBbox(); if (orgBbox != null) { String[] values = orgBbox.split(","); srsbb.setSrs("EPSG:28992"); srsbb.setMinx(values[0]); srsbb.setMiny(values[1]); srsbb.setMaxx(values[2]); srsbb.setMaxy(values[3]); } return srsbb; } /** * Gets the data from a specific set of URL's and converts the information * to the format usefull to the REQUEST_TYPE. Once the information is * collected and converted the method calls for a write in the DataWrapper, * which will sent the data to the client requested for this information. * * @param dw DataWrapper object containing the clients request information * @param urls StringBuffer with the urls where kaartenbalie should connect * to to recieve the requested data. * @param overlay A boolean setting the overlay to true or false. If false * is chosen the images are placed under eachother. * * @return byte[] * * @throws Exception */ protected void getOnlineData(DataWrapper dw, ArrayList urlWrapper, boolean overlay, String REQUEST_TYPE) throws Exception { ByteArrayOutputStream baos = new ByteArrayOutputStream(); BufferedImage[] bi = null; //The list is given in the opposit ranking. Therefore we first need to swap the list. int size = urlWrapper.size(); ArrayList swaplist = new ArrayList(size); for (int i = size - 1; i >= 0; i--) { swaplist.add(urlWrapper.get(i)); log.debug("Outgoing url: " + ((ServiceProviderRequest) urlWrapper.get(i)).getProviderRequestURI()); } urlWrapper = swaplist; /* To save time, this method checks first if the ArrayList contains more then one url * If it contains only one url then the method doesn't have to load the image into the G2D * environment, which saves a lot of time and capacity because it doesn't have to decode * and recode the image. */ long startprocestime = System.currentTimeMillis(); DataMonitoring rr = dw.getRequestReporting(); if (urlWrapper.size() > 1) { if (REQUEST_TYPE.equalsIgnoreCase(OGCConstants.WMS_REQUEST_GetMap)) { /* * Log the time in ms from the start of the clientrequest.. (Reporting) */ Operation o = new Operation(); o.setType(Operation.SERVER_TRANSFER); o.setMsSinceRequestStart(new Long(rr.getMSSinceStart())); ImageManager imagemanager = new ImageManager(urlWrapper, dw); imagemanager.process(); long endprocestime = System.currentTimeMillis(); Long time = new Long(endprocestime - startprocestime); dw.setHeader("X-Kaartenbalie-ImageServerResponseTime", time.toString()); o.setDuration(time); rr.addRequestOperation(o); imagemanager.sendCombinedImages(dw); } else if (REQUEST_TYPE.equalsIgnoreCase(OGCConstants.WMS_REQUEST_GetFeatureInfo)) { /* * Create a DOM document and copy all the information of the several GetFeatureInfo * responses into one document. This document has the same layout as the received * documents and will hold all the information of the specified objects. * After combining these documents, the new document will be sent onto the request. */ DocumentBuilderFactory dbf = DocumentBuilderFactory.newInstance(); dbf.setValidating(false); dbf.setNamespaceAware(true); dbf.setIgnoringElementContentWhitespace(true); DocumentBuilder builder = dbf.newDocumentBuilder(); Document destination = builder.newDocument(); Element rootElement = destination.createElement("msGMLOutput"); destination.appendChild(rootElement); rootElement.setAttribute("xmlns:gml", "http://www.opengis.net/gml"); rootElement.setAttribute("xmlns:xlink", "http://www.w3.org/1999/xlink"); rootElement.setAttribute("xmlns:xsi", "http://www.w3.org/2001/XMLSchema-instance"); Document source = null; for (int i = 0; i < urlWrapper.size(); i++) { ServiceProviderRequest wmsRequest = (ServiceProviderRequest) urlWrapper.get(i); String url = wmsRequest.getProviderRequestURI(); // code below could be used to get bytes received //InputStream is = new URL(url).openStream(); //CountingInputStream cis = new CountingInputStream(is); //source = builder.parse(cis); source = builder.parse(url); //what if url points to non MapServer service? copyElements(source, destination); wmsRequest.setBytesSent(new Long(url.getBytes().length)); wmsRequest.setProviderRequestURI(url); wmsRequest.setMsSinceRequestStart(new Long(rr.getMSSinceStart())); wmsRequest.setBytesReceived(new Long(-1)); //wmsRequest.setBytesReceived(new Long(cis.getByteCount())); wmsRequest.setResponseStatus(new Integer(-1)); rr.addServiceProviderRequest(wmsRequest); } OutputFormat format = new OutputFormat(destination); format.setIndenting(true); XMLSerializer serializer = new XMLSerializer(baos, format); serializer.serialize(destination); dw.write(baos); } else if (REQUEST_TYPE.equalsIgnoreCase(OGCConstants.WMS_REQUEST_DescribeLayer)) { //TODO: implement and refactor so there is less code duplication with getFeatureInfo /* DocumentBuilderFactory dbf = DocumentBuilderFactory.newInstance(); dbf.setValidating(false); dbf.setNamespaceAware(true); dbf.setIgnoringElementContentWhitespace(true); DocumentBuilder builder = dbf.newDocumentBuilder(); Document destination = builder.newDocument(); //root element is different Element rootElement = destination.createElement("WMS_DescribeLayerResponse"); destination.appendChild(rootElement); //set version attribute Document source = null; for (int i = 0; i < urlWrapper.size(); i++) { ServiceProviderRequest dlRequest = (ServiceProviderRequest) urlWrapper.get(i); String url = dlRequest.getProviderRequestURI(); source = builder.parse(url); copyElements(source,destination); }*/ throw new Exception(REQUEST_TYPE + " request with more then one service url is not supported yet!"); } } else { //urlWrapper not > 1, so only 1 url or zero urls if (!urlWrapper.isEmpty()) { getOnlineData(dw, (ServiceProviderRequest) urlWrapper.get(0), REQUEST_TYPE); } else { if (REQUEST_TYPE.equalsIgnoreCase(OGCConstants.WMS_REQUEST_GetFeatureInfo)) { log.error(KBConfiguration.FEATUREINFO_EXCEPTION); throw new Exception(KBConfiguration.FEATUREINFO_EXCEPTION); } else if (REQUEST_TYPE.equalsIgnoreCase(OGCConstants.WMS_REQUEST_GetLegendGraphic)) { log.error(KBConfiguration.LEGENDGRAPHIC_EXCEPTION); throw new Exception(KBConfiguration.LEGENDGRAPHIC_EXCEPTION); } } } } /** * Private method getOnlineData which handels the throughput of information * when it is only about one URL. This is a slightly different method, * because no checks have to be done or information has to be stored. * Everything can be directly send through the open connection. * * @param dw DataWrapper object which handles sending the information over * the request. * @param url String object which has the specific url where the information * should come from. * * @throws Exception */ private void getOnlineData(DataWrapper dw, ServiceProviderRequest wmsRequest, String REQUEST_TYPE) throws Exception { /* * Because only one url is defined, the images don't have to be loaded into a * BufferedImage. The data received from the url can be directly transported to the client. */ String url = wmsRequest.getProviderRequestURI(); DataMonitoring rr = dw.getRequestReporting(); wmsRequest.setBytesSent(new Long(url.getBytes().length)); long startTime = System.currentTimeMillis(); try { if (REQUEST_TYPE.equalsIgnoreCase(OGCConstants.WMS_REQUEST_GetMap) && url.startsWith(KBConfiguration.SERVICEPROVIDER_BASE_HTTP)) { //B3PLayering... long time = System.currentTimeMillis() - startTime; try { /* Test for avoiding scrambled png images on some platforms */ //ImageUtilities.allowNativeCodec("png", ImageReaderSpi.class, false); BufferedImage[] bi = new BufferedImage[] { ConfigLayer.handleRequest(url, dw.getLayeringParameterMap()) }; KBImageTool.writeImage(bi, "image/png", dw); wmsRequest.setBytesReceived(new Long(dw.getContentLength())); wmsRequest.setResponseStatus(new Integer(200)); } catch (Exception e) { wmsRequest.setResponseStatus(new Integer(404)); throw e; } wmsRequest.setRequestResponseTime(new Long(time)); } else { // TODO: Wel goed doen url = url.replaceAll(" ", "%20"); url = url.replaceAll("\\\\+", "/"); log.debug("Outgoing URL: " + url); B3PCredentials credentials = wmsRequest.getCredentials(); if (credentials != null) { credentials.setUrl(url); } HttpClientConfigured hcc = new HttpClientConfigured(credentials); HttpGet httpget = new HttpGet(url); String rhValue = ""; InputStream instream = null; HttpResponse response = hcc.execute(httpget); try { int statusCode = response.getStatusLine().getStatusCode(); long time = System.currentTimeMillis() - startTime; dw.setHeader("X-Kaartenbalie-ImageServerResponseTime", String.valueOf(time)); wmsRequest.setResponseStatus(new Integer(statusCode)); wmsRequest.setRequestResponseTime(new Long(time)); HttpEntity entity = response.getEntity(); if (statusCode != 200 || entity == null) { log.debug("Error connecting to server. Status code: " + statusCode); throw new Exception("Error connecting to server. Status code: " + statusCode); } instream = entity.getContent(); Header h1 = response.getFirstHeader("Content-Type"); if (h1 != null && !h1.equals("")) { rhValue = h1.getValue(); } if (rhValue.equalsIgnoreCase(OGCConstants.WMS_PARAM_EXCEPTION_XML)) { log.error("xml error response for request: " + dw.getOgcrequest().toString()); InputStream is = instream; //method.getResponseBodyAsStream(); String body = getServiceException(is); log.debug("error xml body: " + body); throw new Exception(body); } dw.setContentType(rhValue); if (REQUEST_TYPE.equalsIgnoreCase(OGCConstants.WMS_REQUEST_GetFeatureInfo)) { dw.write(instream); wmsRequest.setBytesReceived(new Long(dw.getContentLength())); } else if (REQUEST_TYPE.equalsIgnoreCase(OGCConstants.WMS_REQUEST_DescribeLayer)) { /* Old Geotools 2.5 way to get reponse */ //DescribeLayerResponse wmsResponse = new DescribeLayerResponse(rhValue, instream); /* New Geotools 8 way to get reponse */ DescribeLayerResponse wmsResponse = createGeotools8DescribeLayerResponse(url); DescribeLayerData data = new DescribeLayerData(wmsRequest.getServiceProviderAbbreviation(), wmsResponse); List<DescribeLayerData> dataList = new ArrayList<DescribeLayerData>(); dataList.add(data); Document newResponse = createKBDescribeLayerResponse(dw, dataList); OutputFormat format = new OutputFormat(newResponse, KBConfiguration.CHARSET, true); format.setIndenting(true); ByteArrayOutputStream baos = new ByteArrayOutputStream(); XMLSerializer serializer = new XMLSerializer(baos, format); serializer.serialize(newResponse); dw.write(baos); wmsRequest.setBytesReceived(new Long(dw.getContentLength())); } else { Header cacheControl = (Header) response.getFirstHeader("Cache-Control"); Header expires = (Header) response.getFirstHeader("Expires"); Header pragma = (Header) response.getFirstHeader("Pragma"); if (cacheControl != null) { dw.setHeader(cacheControl.getName(), cacheControl.getValue()); } if (expires != null) { dw.setHeader(expires.getName(), expires.getValue()); } if (pragma != null) { dw.setHeader(pragma.getName(), pragma.getValue()); } dw.setHeader("Keep-Alive", "timeout=15, max=100"); dw.setHeader("Connection", "Keep-Alive"); dw.write(instream); wmsRequest.setBytesReceived(new Long(dw.getContentLength())); } } finally { if (instream != null) { instream.close(); } hcc.close(response); hcc.close(); } } } catch (Exception e) { wmsRequest.setExceptionMessage(e.getMessage()); wmsRequest.setExceptionClass(e.getClass()); throw e; } finally { rr.addServiceProviderRequest(wmsRequest); } } protected StringBuffer createOnlineUrl(SpLayerSummary spInfo, OGCRequest ogc, String serviceUrl) throws UnsupportedEncodingException { StringBuffer returnValue = new StringBuffer(); List<String> newSldParams = new ArrayList<String>(); List<Integer> sldStyleIds = new ArrayList<Integer>(); String layersString = spInfo.getLayersAsString(); String kbProxySldUrl = serviceUrl.replace("/services/", "/proxysld/"); log.debug("Kb proxy url: " + kbProxySldUrl); List<LayerSummary> layersList = spInfo.getLayers(); returnValue.append(spInfo.getSpUrl()); if (returnValue.indexOf("?") != returnValue.length() - 1 && returnValue.indexOf("&") != returnValue.length() - 1) { if (returnValue.indexOf("?") >= 0) { returnValue.append("&"); } else { returnValue.append("?"); } } String[] params = ogc.getParametersArray(); for (int i = 0; i < params.length; i++) { //In SLD_BODY zitten = tekens. Dus niet splitten String[] keyValuePair = new String[2]; int indexOfIs = params[i].indexOf("="); if (indexOfIs == -1) continue; keyValuePair[0] = params[i].substring(0, indexOfIs); if (indexOfIs + 1 < params[i].length()) keyValuePair[1] = params[i].substring(indexOfIs + 1); else keyValuePair[1] = ""; if (keyValuePair[0].equalsIgnoreCase(OGCConstants.WMS_PARAM_LAYERS)) { returnValue.append(OGCConstants.WMS_PARAM_LAYERS); returnValue.append("="); returnValue.append(layersString); } else if (keyValuePair[0].equalsIgnoreCase(OGCConstants.WMS_PARAM_STYLES)) { returnValue.append(OGCConstants.WMS_PARAM_STYLES); returnValue.append("="); //maak alleen de styles goed als er geen sld= of sld_body= parameter aanwezig is. try { if (layersList != null && layersList.size() > 0) { String stylesParameter = ogc.getParameter(OGCConstants.WMS_PARAM_STYLES); if (stylesParameter != null && stylesParameter.length() > 0) { //splitten werkt niet. Een lege string (tussen 2 komma's) wordt dan niet gezien als waarde //String[] stylesArray = stylesParameter.split(","); String tempStyles = "" + stylesParameter; List<String> styles = new ArrayList<String>(); while (tempStyles != null) { if (tempStyles.length() == 0) { styles.add(""); tempStyles = null; break; } int kommaIndex = tempStyles.indexOf(","); if (kommaIndex < 0) { kommaIndex = tempStyles.length(); styles.add(tempStyles.substring(0)); tempStyles = null; break; } else { styles.add(tempStyles.substring(0, kommaIndex)); tempStyles = tempStyles.substring(kommaIndex + 1, tempStyles.length()); } } String layersParameter = ogc.getParameter(OGCConstants.WMS_PARAM_LAYERS); if (layersParameter != null && layersParameter.length() > 0) { String[] layersArray = layersParameter.split(","); if (styles.size() == layersArray.length) { //StringBuffer stylesString = new StringBuffer(); List<String> providerStyles = new ArrayList<String>(); for (int j = 0; j < layersArray.length; j++) { Iterator it = layersList.iterator(); while (it.hasNext()) { LayerSummary ls = (LayerSummary) it.next(); String completeName = OGCCommunication.buildFullLayerName(ls); //TODO: Moet het toegevoegd worden als Style= of als sld if (completeName.equals(layersArray[j])) { String style = styles.get(j); //als er een style is gekozen met een SLDpart //niet de style meenemen maar een sld bouwen Style s = spInfo.getStyle( OGCCommunication.buildLayerNameWithoutSp(ls), style); if (s != null && s.getSldPart() != null) { providerStyles.add(""); sldStyleIds.add(s.getId()); } else { providerStyles.add(style); } break; } } } String stylesString = ""; for (int p = 0; p < providerStyles.size(); p++) { if (p != 0) stylesString += ","; stylesString += providerStyles.get(p); } returnValue.append(stylesString); if (sldStyleIds.size() > 0) { String styleIdParam = ""; for (Integer sldStyleId : sldStyleIds) { if (styleIdParam.length() > 0) styleIdParam += ","; styleIdParam += sldStyleId; } StringBuffer sldUrl = new StringBuffer(); sldUrl.append(ProxySLDServlet.PARAM_STYLES); sldUrl.append("="); sldUrl.append(styleIdParam); newSldParams.add(sldUrl.toString()); } } } } } } catch (Exception e) { // so no styles param log.debug(e); } } else if (keyValuePair[0].equalsIgnoreCase(OGCConstants.WMS_PARAM_SLD) || keyValuePair[0].equalsIgnoreCase(OGCConstants.WMS_PARAM_SLD_BODY)) { //als SLD= dan url alvast cachen. if (keyValuePair[0].equalsIgnoreCase(OGCConstants.WMS_PARAM_SLD)) ProxySLDServlet.addSLDToCache(keyValuePair[1]); //SLD of SLD Body StringBuffer sldParam = new StringBuffer(); if (keyValuePair[0].equalsIgnoreCase(OGCConstants.WMS_PARAM_SLD)) { sldParam.append(ProxySLDServlet.PARAM_ORIGINAL_SLD_URL); } else { sldParam.append(ProxySLDServlet.PARAM_ORIGINAL_SLD_BODY); } sldParam.append("="); sldParam.append(URLEncoder.encode(keyValuePair[1], "utf-8")); newSldParams.add(sldParam.toString()); //service provider ID StringBuffer serviceProviderIds = new StringBuffer(); serviceProviderIds.append(ProxySLDServlet.PARAM_SERVICEPROVIDER_ID); serviceProviderIds.append("="); serviceProviderIds.append(spInfo.getServiceproviderId()); newSldParams.add(serviceProviderIds.toString()); } else { returnValue.append(params[i]); } returnValue.append("&"); } if (newSldParams.size() > 0) { //make a new SLD url to the proxySldServlet. StringBuffer sldUrl = new StringBuffer(); sldUrl.append(kbProxySldUrl); sldUrl.append(sldUrl.indexOf("?") > 0 ? "&" : "?"); for (String param : newSldParams) { sldUrl.append(param); sldUrl.append(sldUrl.indexOf("?") > 0 ? "&" : "?"); } //altijd een sld=. Ook sld_body zodat we kunnen opsplitsen returnValue.append(OGCConstants.WMS_PARAM_SLD); returnValue.append("="); returnValue.append(URLEncoder.encode(sldUrl.toString(), "utf-8")); returnValue.append("&"); } return returnValue; } private DescribeLayerResponse createGeotools8DescribeLayerResponse(String wmsUrl) throws Exception { DescribeLayerResponse response = null; try { URL tempUrl = new URL(wmsUrl); HttpURLConnection conn = (HttpURLConnection) tempUrl.openConnection(); HTTPResponse httpResponse = (HTTPResponse) new SimpleHTTPResponse(conn); response = new DescribeLayerResponse(httpResponse); } catch (IOException iox) { log.error("Error getting describe layer response.", iox); throw new Exception("Error getting describe layer response."); } catch (ServiceException svx) { log.error("Error getting describe layer response.", svx); throw new Exception("Service error getting describe layer response."); } return response; } private Document createKBDescribeLayerResponse(DataWrapper dw, List<DescribeLayerData> describeLayerData) throws Exception { DocumentBuilderFactory dbf = DocumentBuilderFactory.newInstance(); dbf.setValidating(false); dbf.setNamespaceAware(true); DocumentBuilder db = dbf.newDocumentBuilder(); DOMImplementation di = db.getDOMImplementation(); // <!DOCTYPE WMS_DescribeLayerResponse SYSTEM "http://schemas.opengis.net/wms/1.1.1/WMS_DescribeLayerResponse.dtd"> // [ <WMS_DescribeLayerResponse version="1.1.1" > (...) </WMS_DescribeLayerResponse>] DocumentType dt = di.createDocumentType("WMS_DescribeLayerResponse", null, CallWMSServlet.DESCRIBELAYER_DTD); Document dom = di.createDocument(null, "WMS_DescribeLayerResponse", dt); Element rootElement = dom.getDocumentElement(); rootElement.setAttribute("version", "1.1.1"); //describeLayer version in kbconfig? String spAbbrUrl = dw.getOgcrequest().getServiceProviderName(); String personalUrl = this.user.getPersonalURL(dw.getRequest(), spAbbrUrl); Integer[] orgIds = this.user.getOrganizationIds(); WFSProviderDAO wfsProviderDao = new WFSProviderDAO(); String[] validLayerNames = wfsProviderDao.getAuthorizedFeatureTypeNames(orgIds, null, false); //it is not possible to use getSeviceProviderURLS because that will call getValidObjects implementation of WMSRequestHandler //therefore build spInfo here in loop //also, B3PLayering is not relevant here, because describeLayer should not be subject to pricing List spInfo = new ArrayList(); for (String name : validLayerNames) { SpLayerSummary layerInfo = wfsProviderDao.getAuthorizedFeatureTypeSummary(name, orgIds, false); if (layerInfo == null) { continue; } spInfo.add(layerInfo); } for (DescribeLayerData resp : describeLayerData) { for (LayerDescription descr : resp.getDescribeLayerResponse().getLayerDescs()) { Element layerDescriptionElement = dom.createElement("LayerDescription"); if (spAbbrUrl != null && !spAbbrUrl.equals("")) { layerDescriptionElement.setAttribute("name", descr.getName()); } else { layerDescriptionElement.setAttribute("name", OGCCommunication.attachSp(resp.getWmsPrefix(), descr.getName())); } descr.getOwsURL(); //additional info should only be returned for WMS layer that has corresponding WFS type that is served by Kaartenbalie String wfsPrefix = getAuthorizedWFSPrefix(spInfo, descr); if (wfsPrefix != null) { layerDescriptionElement.setAttribute("wfs", personalUrl); layerDescriptionElement.setAttribute("owsType", descr.getOwsType()); layerDescriptionElement.setAttribute("owsURL", personalUrl); Element queryElement = dom.createElement("Query"); queryElement.setAttribute("typeName", OGCCommunication.attachSp(wfsPrefix, descr.getName())); layerDescriptionElement.appendChild(queryElement); } rootElement.appendChild(layerDescriptionElement); } } return dom; } private String getAuthorizedWFSPrefix(List spLayerSummaries, LayerDescription descr) { String wfsPrefix = null; Iterator it = spLayerSummaries.iterator(); while (it.hasNext()) { SpLayerSummary spLayerSummary = (SpLayerSummary) it.next(); String spUrl = spLayerSummary.getSpUrl(); //will KB remove '?' char? if (spUrl.endsWith("?")) { spUrl = spUrl.substring(0, (spUrl.length() - 1)); } String owsUrl = descr.getOwsURL().toString(); if (owsUrl.endsWith("?")) { owsUrl = owsUrl.substring(0, (owsUrl.length() - 1)); } if (spUrl.equals(owsUrl) && descr.getName().equalsIgnoreCase(spLayerSummary.getLayerName())) { wfsPrefix = spLayerSummary.getSpAbbr(); } } return wfsPrefix; } protected LayerPriceComposition calculateLayerPriceComposition(DataWrapper dw, ExtLayerCalculator lc, String spAbbr, String layerName) throws Exception { String operation = dw.getOperation(); if (operation == null) { log.error("Operation can not be null"); throw new Exception("Operation can not be null"); } else if (operation.equalsIgnoreCase(OGCConstants.WMS_REQUEST_GetLegendGraphic)) { log.debug("Never pricing for GetLegendGraphic."); return null; } String projection = dw.getOgcrequest().getParameter(OGCConstants.WMS_PARAM_SRS); BigDecimal scale = (new BigDecimal(dw.getOgcrequest().calcScale())).setScale(2, BigDecimal.ROUND_HALF_UP); int planType = LayerPricing.PAY_PER_REQUEST; String service = OGCConstants.WMS_SERVICE_WMS; return lc.calculateLayerComplete(spAbbr, layerName, new Date(), projection, scale, new BigDecimal("1"), planType, service, operation); } protected SpLayerSummary getValidLayerObjects(EntityManager em, LayerSummary m, Integer[] orgIds, boolean b3pLayering) throws Exception { String query = "select distinct new " + "nl.b3p.ogc.utils.SpLayerSummary(l, l.queryable,sp) " + "from Layer l, Organization o, ServiceProvider sp join o.layers ol " + "where l = ol and " + "l.serviceProvider = sp and " + "o.id in (:orgIds) and " + "l.name = :layerName and " + "sp.abbr = :layerCode and " + "sp.allowed = true"; return getValidLayerObjects(em, query, m, orgIds, b3pLayering); } /** * * @param byteStream InputStream object in which the serviceexception is * stored. * * @ return String with the given exception * * @throws IOException, SAXException */ private static String getServiceException(InputStream byteStream) throws IOException, SAXException { Switcher s = new Switcher(); s.setElementHandler("ServiceException", new ServiceExceptionHandler()); XMLReader reader = org.xml.sax.helpers.XMLReaderFactory.createXMLReader(); IgnoreEntityResolver r = new IgnoreEntityResolver(); reader.setEntityResolver(r); reader.setContentHandler(s); InputSource is = new InputSource(byteStream); is.setEncoding(KBConfiguration.CHARSET); reader.parse(is); return (String) stack.pop(); } /** * Below is the Handler defined which reads the Exception from a * ServiceException recieved when an error occurs. */ private static class ServiceExceptionHandler extends ElementHandler { StringBuffer sb; @Override public void startElement(String uri, String localName, String qName, Attributes atts) { sb = new StringBuffer(); } @Override public void characters(char[] chars, int start, int len) { sb.append(chars, start, len); } @Override public void endElement(String uri, String localName, String qName) { stack.push(sb.toString()); } } private class DescribeLayerData { String prefix; DescribeLayerResponse resp; DescribeLayerData(String wmsPrefix, DescribeLayerResponse wmsResponse) { this.prefix = wmsPrefix; this.resp = wmsResponse; } String getWmsPrefix() { return this.prefix; } DescribeLayerResponse getDescribeLayerResponse() { return this.resp; } } /** * Method which copies information from one XML document to another * document. It adds information to an document and with this method it's * possible to create one document from several other documents as used to * create an GetFeatureInfo document. * * @param source Document object * @param destination Document object */ private static void copyElements(Document source, Document destination) { Element root_source = source.getDocumentElement(); NodeList nodelist_source = root_source.getChildNodes(); int size_source = nodelist_source.getLength(); for (int i = 0; i < size_source; i++) { Node node_source = nodelist_source.item(i); if (node_source instanceof Element) { Element element_source = (Element) node_source; String tagName = element_source.getTagName(); if (!tagName.equalsIgnoreCase("ServiceException")) { Node importedNode = destination.importNode(element_source, true); Element root_destination = destination.getDocumentElement(); root_destination.appendChild(importedNode); } } } } /* Voor GetFeatureInfo de _layer en _feature prefixen met serviceprovider abbr Kijken welke degree Elementen een prefix moeten krijgen */ private static void prefixElements(Document source, Document destination, String spAbbr) { Element root_source = source.getDocumentElement(); NodeList nodelist_source = root_source.getChildNodes(); int size_source = nodelist_source.getLength(); for (int i = 0; i < size_source; i++) { Node node_source = nodelist_source.item(i); if (node_source instanceof Element) { Element element_source = (Element) node_source; String tagName = element_source.getTagName(); if (!tagName.equalsIgnoreCase("ServiceException")) { Node importedNode = destination.importNode(element_source, true); Node newNode = destination.renameNode(importedNode, importedNode.getNamespaceURI(), OGCCommunication.attachSp(spAbbr, tagName)); Element root_destination = destination.getDocumentElement(); root_destination.appendChild(newNode); } } } } }