Mercurial > dive4elements > river
view flys-client/src/main/java/de/intevation/flys/client/server/CapabilitiesParser.java @ 5779:ebec12def170
Datacage: Add a pool of builders to make it multi threadable.
XML DOM is not thread safe. Therefore the old implementation only allowed one thread
to use the builder at a time. As the complexity of the configuration
has increased over time this has become a bottleneck of the whole application
because it took quiet some time to build a result. Furthermore the builder code path
is visited very frequent. So many concurrent requests were piled up
resulting in long waits for the users.
To mitigate this problem a round robin pool of builders is used now.
Each of the pooled builders has an independent copy of the XML template
and can be run in parallel.
The number of builders is determined by the system property
'flys.datacage.pool.size'. It defaults to 4.
author | Sascha L. Teichmann <teichmann@intevation.de> |
---|---|
date | Sun, 21 Apr 2013 12:48:09 +0200 |
parents | 40d02fbf414d |
children |
line wrap: on
line source
package de.intevation.flys.client.server; import java.io.InputStream; import java.io.IOException; import java.net.MalformedURLException; import java.net.URL; import java.net.URLConnection; import java.util.ArrayList; import java.util.List; import java.util.regex.Matcher; import java.util.regex.Pattern; import javax.xml.xpath.XPathConstants; import org.w3c.dom.Document; import org.w3c.dom.Element; import org.w3c.dom.Node; import org.w3c.dom.NodeList; import org.apache.log4j.Logger; import de.intevation.artifacts.common.utils.XMLUtils; import de.intevation.flys.client.shared.exceptions.ServerException; import de.intevation.flys.client.shared.model.Capabilities; import de.intevation.flys.client.shared.model.ContactInformation; import de.intevation.flys.client.shared.model.WMSLayer; public class CapabilitiesParser { private static final Logger logger = Logger.getLogger(CapabilitiesParser.class); public static final String ERR_GC_REQUEST_FAILED = "error_gc_req_failed"; public static final String ERR_GC_DOC_NOT_VALID = "error_gc_doc_not_valid"; public static final String ERR_MALFORMED_URL = "error_malformed_url"; public static final String XPATH_WMS_CAPS = "/WMS_Capabilities"; public static final String XPATH_WMT_CAPS = "/WMT_MS_Capabilities"; public static final String XPATH_TITLE = "Service/Title/text()"; public static final String XPATH_ONLINE_RESOURCE = "Service/OnlineResource/@href"; public static final String XPATH_CONTACT_INFORMATION = "Service/ContactInformation"; public static final String XPATH_CI_PERSON = "ContactPersonPrimary/ContactPerson/text()"; public static final String XPATH_CI_ORGANIZATION = "ContactPersonPrimary/ContactOrganization/text()"; public static final String XPATH_CI_ADDRESS = "ContactAddress/Address/text()"; public static final String XPATH_CI_CITY = "ContactAddress/City/text()"; public static final String XPATH_CI_POSTCODE = "ContactAddress/PostCode/text()"; public static final String XPATH_CI_PHONE = "ContactVoiceTelephone/text()"; public static final String XPATH_CI_EMAIL = "ContactElectronicMailAddress/text()"; public static final String XPATH_FEES = "Service/Fees/text()"; public static final String XPATH_ACCESS_CONSTRAINTS = "Service/AccessConstraints/text()"; public static final String XPATH_LAYERS = "Capability/Layer"; public static final Pattern SRS_PATTERN = Pattern.compile("(EPSG:\\d+)*"); private CapabilitiesParser() { } public static void main(String[] args) { logger.info("Do static Capabilities request/parsing."); String log4jProperties = System.getenv(BaseServletContextListener.LOG4J_PROPERTIES); LoggingConfigurator.init(log4jProperties); try { Capabilities caps = getCapabilities(System.getProperty("test.wms")); logger.debug(caps.toString()); } catch (ServerException se) { se.printStackTrace(); } logger.info("Finished fetching capabiltiies."); } public static Capabilities getCapabilities(String urlStr) throws ServerException { try { URL url = new URL(urlStr); logger.debug("Open connection to url: " + urlStr); URLConnection conn = url.openConnection(); conn.connect(); InputStream is = conn.getInputStream(); return parse(is); } catch (MalformedURLException mue) { logger.warn(mue, mue); throw new ServerException(ERR_MALFORMED_URL); } catch (IOException ioe) { logger.warn(ioe, ioe); } throw new ServerException(ERR_GC_REQUEST_FAILED); } protected static Capabilities parse(InputStream is) throws ServerException { logger.debug("GCServiceImpl.parseCapabilitiesResponse"); Document doc = XMLUtils.parseDocument(is, false); if (doc == null) { throw new ServerException(ERR_GC_DOC_NOT_VALID); } return CapabilitiesParser.parse(doc); } public static Capabilities parse(Document doc) throws ServerException { Node capabilities = getCapabilitiesNode(doc); String title = (String) XMLUtils.xpath( capabilities, XPATH_TITLE, XPathConstants.STRING); String onlineResource = (String) XMLUtils.xpath( capabilities, XPATH_ONLINE_RESOURCE, XPathConstants.STRING); String fees = (String) XMLUtils.xpath( capabilities, XPATH_FEES, XPathConstants.STRING); String accessConstraints = (String) XMLUtils.xpath( capabilities, XPATH_ACCESS_CONSTRAINTS, XPathConstants.STRING); Node contactInformation = (Node) XMLUtils.xpath( capabilities, XPATH_CONTACT_INFORMATION, XPathConstants.NODE); ContactInformation ci = parseContactInformation(contactInformation); logger.debug("Found fees: " + fees); logger.debug("Found access constraints: " + accessConstraints); NodeList layerNodes = (NodeList) XMLUtils.xpath( capabilities, XPATH_LAYERS, XPathConstants.NODESET); List<WMSLayer> layers = parseLayers(layerNodes, onlineResource); return new Capabilities( title, onlineResource, ci, fees, accessConstraints, layers); } protected static Node getCapabilitiesNode(Document doc) throws ServerException { Node capabilities = (Node) XMLUtils.xpath( doc, XPATH_WMS_CAPS, XPathConstants.NODE); if (capabilities == null) { logger.info("No '/WMS_Capabilities' node found."); logger.info("Try to find a '/WMT_MS_Capabilities' node."); capabilities = (Node) XMLUtils.xpath( doc, XPATH_WMT_CAPS, XPathConstants.NODE); } if (capabilities == null) { throw new ServerException(ERR_GC_DOC_NOT_VALID); } return capabilities; } protected static ContactInformation parseContactInformation(Node node) { String person = (String) XMLUtils.xpath( node, XPATH_CI_PERSON, XPathConstants.STRING); String organization = (String) XMLUtils.xpath( node, XPATH_CI_ORGANIZATION, XPathConstants.STRING); String address = (String) XMLUtils.xpath( node, XPATH_CI_ADDRESS, XPathConstants.STRING); String postcode = (String) XMLUtils.xpath( node, XPATH_CI_POSTCODE, XPathConstants.STRING); String city = (String) XMLUtils.xpath( node, XPATH_CI_CITY, XPathConstants.STRING); String phone = (String) XMLUtils.xpath( node, XPATH_CI_PHONE, XPathConstants.STRING); String email = (String) XMLUtils.xpath( node, XPATH_CI_EMAIL, XPathConstants.STRING); ContactInformation ci = new ContactInformation(); ci.setPerson(person); ci.setOrganization(organization); ci.setAddress(address); ci.setPostcode(postcode); ci.setCity(city); ci.setPhone(phone); ci.setEmail(email); return ci; } /** * @param layersNode * @param onlineResource * * @return */ protected static List<WMSLayer> parseLayers( NodeList layersNode, String onlineResource ) { int len = layersNode != null ? layersNode.getLength() : 0; logger.debug("Node has " + len + " layers."); List<WMSLayer> layers = new ArrayList<WMSLayer>(len); for (int i = 0; i < len; i++) { layers.add(parseLayer(layersNode.item(i), onlineResource)); } return layers; } protected static WMSLayer parseLayer(Node layerNode, String onlineResource) { String title = (String) XMLUtils.xpath( layerNode, "Title/text()", XPathConstants.STRING); String name = (String) XMLUtils.xpath( layerNode, "Name/text()", XPathConstants.STRING); logger.debug("Found layer: " + title + "(" + name + ")"); List<String> srs = parseSRS(layerNode); NodeList layersNodes = (NodeList) XMLUtils.xpath( layerNode, "Layer", XPathConstants.NODESET); List<WMSLayer> layers = parseLayers(layersNodes, onlineResource); return new WMSLayer(onlineResource, title, name, srs, layers); } protected static List<String> parseSRS(Node layerNode) { NodeList srsNodes = ((Element) layerNode).getElementsByTagName("SRS"); if (srsNodes.getLength() == 0) { srsNodes = ((Element) layerNode).getElementsByTagName("CRS"); if (srsNodes.getLength() == 0) { logger.debug("No explicit SRS for this layer specified."); return null; } } List<String> allSRS = new ArrayList<String>(); for (int i = 0, n = srsNodes.getLength(); i < n; i++) { List<String> srs = parseSRSItem(srsNodes.item(i).getTextContent()); if (srs != null && srs.size() > 0) { allSRS.addAll(srs); } } return allSRS; } protected static List<String> parseSRSItem(String srsStr) { if (srsStr == null || srsStr.length() == 0) { return null; } List<String> allSRS = new ArrayList<String>(); if (srsStr.indexOf(" ") <= 0) { String srs = getSRSFromString(srsStr); if (srs != null && srs.length() > 0) { allSRS.add(srs); } return allSRS; } String[] splittedSrs = srsStr.split(" "); for (String singleSrs: splittedSrs) { String srs = getSRSFromString(singleSrs); if (srs != null && srs.length() > 0) { allSRS.add(srs); } } return allSRS; } protected static String getSRSFromString(String singleSrs) { Matcher m = SRS_PATTERN.matcher(singleSrs); if (m.matches()) { logger.debug("Found SRS '" + m.group(1) + "'"); return m.group(1); } return null; } } // vim:set ts=4 sw=4 si et sta sts=4 fenc=utf8 :