teichmann@5835: package org.dive4elements.river.client.server; ingo@1417: ingo@1417: import java.io.InputStream; ingo@1417: import java.io.IOException; ingo@1417: import java.net.MalformedURLException; ingo@1417: import java.net.URL; ingo@1417: import java.net.URLConnection; ingo@1417: import java.util.ArrayList; ingo@1417: import java.util.List; ingo@1417: import java.util.regex.Matcher; ingo@1417: import java.util.regex.Pattern; ingo@1417: ingo@1417: import javax.xml.xpath.XPathConstants; ingo@1417: ingo@1417: import org.w3c.dom.Document; ingo@1488: import org.w3c.dom.Element; ingo@1417: import org.w3c.dom.Node; ingo@1417: import org.w3c.dom.NodeList; ingo@1417: ingo@1417: import org.apache.log4j.Logger; ingo@1417: teichmann@5835: import org.dive4elements.artifacts.common.utils.XMLUtils; ingo@1417: teichmann@5835: import org.dive4elements.river.client.shared.exceptions.ServerException; teichmann@5835: import org.dive4elements.river.client.shared.model.Capabilities; teichmann@5835: import org.dive4elements.river.client.shared.model.ContactInformation; teichmann@5835: import org.dive4elements.river.client.shared.model.WMSLayer; ingo@1417: ingo@1417: ingo@1417: public class CapabilitiesParser { ingo@1417: ingo@1417: private static final Logger logger = ingo@1417: Logger.getLogger(CapabilitiesParser.class); ingo@1417: ingo@1417: ingo@1417: public static final String ERR_GC_REQUEST_FAILED = ingo@1417: "error_gc_req_failed"; ingo@1417: ingo@1417: public static final String ERR_GC_DOC_NOT_VALID = ingo@1417: "error_gc_doc_not_valid"; ingo@1417: ingo@1417: public static final String ERR_MALFORMED_URL = ingo@1417: "error_malformed_url"; ingo@1417: ingo@1417: ingo@1417: public static final String XPATH_WMS_CAPS = ingo@1417: "/WMS_Capabilities"; ingo@1417: ingo@1417: public static final String XPATH_WMT_CAPS = ingo@1417: "/WMT_MS_Capabilities"; ingo@1417: ingo@1417: public static final String XPATH_TITLE = ingo@1417: "Service/Title/text()"; ingo@1417: ingo@1417: public static final String XPATH_ONLINE_RESOURCE = ingo@1417: "Service/OnlineResource/@href"; ingo@1417: ingo@1417: public static final String XPATH_CONTACT_INFORMATION = ingo@1417: "Service/ContactInformation"; ingo@1417: ingo@1417: public static final String XPATH_CI_PERSON = ingo@1417: "ContactPersonPrimary/ContactPerson/text()"; ingo@1417: ingo@1417: public static final String XPATH_CI_ORGANIZATION = ingo@1417: "ContactPersonPrimary/ContactOrganization/text()"; ingo@1417: ingo@1417: public static final String XPATH_CI_ADDRESS = ingo@1417: "ContactAddress/Address/text()"; ingo@1417: ingo@1417: public static final String XPATH_CI_CITY = ingo@1417: "ContactAddress/City/text()"; ingo@1417: ingo@1417: public static final String XPATH_CI_POSTCODE = ingo@1417: "ContactAddress/PostCode/text()"; ingo@1417: ingo@1417: public static final String XPATH_CI_PHONE = ingo@1417: "ContactVoiceTelephone/text()"; ingo@1417: ingo@1417: public static final String XPATH_CI_EMAIL = ingo@1417: "ContactElectronicMailAddress/text()"; ingo@1417: ingo@1417: public static final String XPATH_FEES = ingo@1417: "Service/Fees/text()"; ingo@1417: ingo@1417: public static final String XPATH_ACCESS_CONSTRAINTS = ingo@1417: "Service/AccessConstraints/text()"; ingo@1417: ingo@1417: public static final String XPATH_LAYERS = ingo@1417: "Capability/Layer"; ingo@1417: ingo@1417: public static final Pattern SRS_PATTERN = Pattern.compile("(EPSG:\\d+)*"); ingo@1417: ingo@1417: ingo@1417: private CapabilitiesParser() { ingo@1417: } ingo@1417: ingo@1417: ingo@1417: public static void main(String[] args) { ingo@1417: logger.info("Do static Capabilities request/parsing."); ingo@1417: bjoern@3479: String log4jProperties = System.getenv(BaseServletContextListener.LOG4J_PROPERTIES); ingo@1417: LoggingConfigurator.init(log4jProperties); ingo@1417: ingo@1417: try { ingo@1487: Capabilities caps = getCapabilities(System.getProperty("test.wms")); ingo@1487: ingo@1487: logger.debug(caps.toString()); ingo@1417: } ingo@1417: catch (ServerException se) { ingo@1417: se.printStackTrace(); ingo@1417: } ingo@1417: ingo@1417: logger.info("Finished fetching capabiltiies."); ingo@1417: } ingo@1417: ingo@1417: ingo@1417: public static Capabilities getCapabilities(String urlStr) ingo@1417: throws ServerException ingo@1417: { ingo@1417: try { ingo@1417: URL url = new URL(urlStr); ingo@1417: ingo@1417: logger.debug("Open connection to url: " + urlStr); ingo@1417: ingo@1417: URLConnection conn = url.openConnection(); ingo@1417: conn.connect(); ingo@1417: ingo@1417: InputStream is = conn.getInputStream(); ingo@1417: ingo@1417: return parse(is); ingo@1417: } ingo@1417: catch (MalformedURLException mue) { ingo@1417: logger.warn(mue, mue); ingo@1417: throw new ServerException(ERR_MALFORMED_URL); ingo@1417: } ingo@1417: catch (IOException ioe) { ingo@1417: logger.warn(ioe, ioe); ingo@1417: } ingo@1417: ingo@1417: throw new ServerException(ERR_GC_REQUEST_FAILED); ingo@1417: } ingo@1417: ingo@1417: ingo@1417: protected static Capabilities parse(InputStream is) ingo@1417: throws ServerException ingo@1417: { ingo@1417: logger.debug("GCServiceImpl.parseCapabilitiesResponse"); ingo@1417: ingo@1417: Document doc = XMLUtils.parseDocument(is, false); ingo@1417: ingo@1417: if (doc == null) { ingo@1417: throw new ServerException(ERR_GC_DOC_NOT_VALID); ingo@1417: } ingo@1417: ingo@1417: return CapabilitiesParser.parse(doc); ingo@1417: } ingo@1417: ingo@1417: ingo@1417: public static Capabilities parse(Document doc) ingo@1417: throws ServerException ingo@1417: { ingo@1417: Node capabilities = getCapabilitiesNode(doc); ingo@1417: ingo@1417: String title = (String) XMLUtils.xpath( ingo@1417: capabilities, ingo@1417: XPATH_TITLE, ingo@1417: XPathConstants.STRING); ingo@1417: ingo@1417: String onlineResource = (String) XMLUtils.xpath( ingo@1417: capabilities, ingo@1417: XPATH_ONLINE_RESOURCE, ingo@1417: XPathConstants.STRING); ingo@1417: ingo@1417: String fees = (String) XMLUtils.xpath( ingo@1417: capabilities, ingo@1417: XPATH_FEES, ingo@1417: XPathConstants.STRING); ingo@1417: ingo@1417: String accessConstraints = (String) XMLUtils.xpath( ingo@1417: capabilities, ingo@1417: XPATH_ACCESS_CONSTRAINTS, ingo@1417: XPathConstants.STRING); ingo@1417: ingo@1417: Node contactInformation = (Node) XMLUtils.xpath( ingo@1417: capabilities, ingo@1417: XPATH_CONTACT_INFORMATION, ingo@1417: XPathConstants.NODE); ingo@1417: ingo@1417: ContactInformation ci = parseContactInformation(contactInformation); ingo@1417: ingo@1417: logger.debug("Found fees: " + fees); ingo@1417: logger.debug("Found access constraints: " + accessConstraints); ingo@1417: ingo@1417: NodeList layerNodes = (NodeList) XMLUtils.xpath( ingo@1417: capabilities, ingo@1417: XPATH_LAYERS, ingo@1417: XPathConstants.NODESET); ingo@1417: ingo@1417: List layers = parseLayers(layerNodes, onlineResource); ingo@1417: ingo@1417: return new Capabilities( ingo@1417: title, ingo@1417: onlineResource, ingo@1417: ci, ingo@1417: fees, ingo@1417: accessConstraints, ingo@1417: layers); ingo@1417: } ingo@1417: ingo@1417: ingo@1417: protected static Node getCapabilitiesNode(Document doc) ingo@1417: throws ServerException { ingo@1417: Node capabilities = (Node) XMLUtils.xpath( ingo@1417: doc, ingo@1417: XPATH_WMS_CAPS, ingo@1417: XPathConstants.NODE); ingo@1417: ingo@1417: if (capabilities == null) { ingo@1417: logger.info("No '/WMS_Capabilities' node found."); ingo@1417: logger.info("Try to find a '/WMT_MS_Capabilities' node."); ingo@1417: ingo@1417: capabilities = (Node) XMLUtils.xpath( ingo@1417: doc, ingo@1417: XPATH_WMT_CAPS, ingo@1417: XPathConstants.NODE); ingo@1417: } ingo@1417: ingo@1417: if (capabilities == null) { ingo@1417: throw new ServerException(ERR_GC_DOC_NOT_VALID); ingo@1417: } ingo@1417: ingo@1417: return capabilities; ingo@1417: } ingo@1417: ingo@1417: ingo@1417: protected static ContactInformation parseContactInformation(Node node) { ingo@1417: String person = (String) XMLUtils.xpath( ingo@1417: node, ingo@1417: XPATH_CI_PERSON, ingo@1417: XPathConstants.STRING); ingo@1417: ingo@1417: String organization = (String) XMLUtils.xpath( ingo@1417: node, ingo@1417: XPATH_CI_ORGANIZATION, ingo@1417: XPathConstants.STRING); ingo@1417: ingo@1417: String address = (String) XMLUtils.xpath( ingo@1417: node, ingo@1417: XPATH_CI_ADDRESS, ingo@1417: XPathConstants.STRING); ingo@1417: ingo@1417: String postcode = (String) XMLUtils.xpath( ingo@1417: node, ingo@1417: XPATH_CI_POSTCODE, ingo@1417: XPathConstants.STRING); ingo@1417: ingo@1417: String city = (String) XMLUtils.xpath( ingo@1417: node, ingo@1417: XPATH_CI_CITY, ingo@1417: XPathConstants.STRING); ingo@1417: ingo@1417: String phone = (String) XMLUtils.xpath( ingo@1417: node, ingo@1417: XPATH_CI_PHONE, ingo@1417: XPathConstants.STRING); ingo@1417: ingo@1417: String email = (String) XMLUtils.xpath( ingo@1417: node, ingo@1417: XPATH_CI_EMAIL, ingo@1417: XPathConstants.STRING); ingo@1417: ingo@1417: ContactInformation ci = new ContactInformation(); ingo@1417: ci.setPerson(person); ingo@1417: ci.setOrganization(organization); ingo@1417: ci.setAddress(address); ingo@1417: ci.setPostcode(postcode); ingo@1417: ci.setCity(city); ingo@1417: ci.setPhone(phone); ingo@1417: ci.setEmail(email); ingo@1417: ingo@1417: return ci; ingo@1417: } ingo@1417: ingo@1417: ingo@1417: /** ingo@1417: * @param layersNode ingo@1417: * @param onlineResource ingo@1417: * ingo@1417: * @return ingo@1417: */ ingo@1417: protected static List parseLayers( ingo@1417: NodeList layersNode, ingo@1417: String onlineResource ingo@1417: ) { ingo@1417: int len = layersNode != null ? layersNode.getLength() : 0; ingo@1417: ingo@1417: logger.debug("Node has " + len + " layers."); ingo@1417: ingo@1417: List layers = new ArrayList(len); ingo@1417: ingo@1417: for (int i = 0; i < len; i++) { ingo@1417: layers.add(parseLayer(layersNode.item(i), onlineResource)); ingo@1417: } ingo@1417: ingo@1417: return layers; ingo@1417: } ingo@1417: ingo@1417: ingo@1417: protected static WMSLayer parseLayer(Node layerNode, String onlineResource) { ingo@1417: String title = (String) XMLUtils.xpath( ingo@1417: layerNode, ingo@1417: "Title/text()", ingo@1417: XPathConstants.STRING); ingo@1417: ingo@1417: String name = (String) XMLUtils.xpath( ingo@1417: layerNode, ingo@1417: "Name/text()", ingo@1417: XPathConstants.STRING); ingo@1417: ingo@1417: logger.debug("Found layer: " + title + "(" + name + ")"); ingo@1417: ingo@1417: List srs = parseSRS(layerNode); ingo@1417: ingo@1417: NodeList layersNodes = (NodeList) XMLUtils.xpath( ingo@1417: layerNode, ingo@1417: "Layer", ingo@1417: XPathConstants.NODESET); ingo@1417: ingo@1417: List layers = parseLayers(layersNodes, onlineResource); ingo@1417: ingo@1417: return new WMSLayer(onlineResource, title, name, srs, layers); ingo@1417: } ingo@1417: ingo@1417: ingo@1417: protected static List parseSRS(Node layerNode) { ingo@1488: NodeList srsNodes = ((Element) layerNode).getElementsByTagName("SRS"); ingo@1417: ingo@1488: if (srsNodes.getLength() == 0) { ingo@1488: srsNodes = ((Element) layerNode).getElementsByTagName("CRS"); ingo@1488: ingo@1488: if (srsNodes.getLength() == 0) { ingo@1488: logger.debug("No explicit SRS for this layer specified."); ingo@1488: return null; ingo@1488: } ingo@1488: } ingo@1488: ingo@1488: List allSRS = new ArrayList(); ingo@1488: ingo@1488: for (int i = 0, n = srsNodes.getLength(); i < n; i++) { ingo@1488: List srs = parseSRSItem(srsNodes.item(i).getTextContent()); ingo@1488: ingo@1488: if (srs != null && srs.size() > 0) { ingo@1488: allSRS.addAll(srs); ingo@1488: } ingo@1488: } ingo@1488: ingo@1488: return allSRS; ingo@1488: } ingo@1488: ingo@1488: ingo@1488: protected static List parseSRSItem(String srsStr) { ingo@1417: if (srsStr == null || srsStr.length() == 0) { ingo@1417: return null; ingo@1417: } ingo@1417: ingo@1488: List allSRS = new ArrayList(); ingo@1488: ingo@1488: if (srsStr.indexOf(" ") <= 0) { ingo@1488: String srs = getSRSFromString(srsStr); ingo@1488: if (srs != null && srs.length() > 0) { ingo@1488: allSRS.add(srs); ingo@1488: } ingo@1488: ingo@1488: return allSRS; ingo@1488: } ingo@1488: ingo@1417: String[] splittedSrs = srsStr.split(" "); ingo@1417: ingo@1417: for (String singleSrs: splittedSrs) { ingo@1488: String srs = getSRSFromString(singleSrs); ingo@1488: if (srs != null && srs.length() > 0) { ingo@1488: allSRS.add(srs); ingo@1417: } ingo@1417: } ingo@1417: ingo@1488: return allSRS; ingo@1488: } ingo@1488: ingo@1488: ingo@1488: protected static String getSRSFromString(String singleSrs) { ingo@1488: Matcher m = SRS_PATTERN.matcher(singleSrs); ingo@1488: ingo@1488: if (m.matches()) { ingo@1488: logger.debug("Found SRS '" + m.group(1) + "'"); ingo@1488: return m.group(1); ingo@1488: } ingo@1488: ingo@1488: return null; ingo@1417: } ingo@1417: } ingo@1417: // vim:set ts=4 sw=4 si et sta sts=4 fenc=utf8 :