All Downloads are FREE. Search and download functionalities are using the official Maven repository.

org.mapfish.print.map.readers.ServerInfoCache Maven / Gradle / Ivy

package org.mapfish.print.map.readers;

import com.codahale.metrics.MetricRegistry;
import org.apache.commons.httpclient.methods.GetMethod;
import org.apache.commons.logging.Log;
import org.mapfish.print.RenderingContext;
import org.w3c.dom.Element;
import org.w3c.dom.Node;
import org.w3c.dom.NodeList;
import org.xml.sax.SAXException;

import java.io.IOException;
import java.io.InputStream;
import java.io.UnsupportedEncodingException;
import java.net.HttpURLConnection;
import java.net.MalformedURLException;
import java.net.URI;
import java.net.URISyntaxException;
import java.net.URL;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collections;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.NoSuchElementException;
import javax.xml.parsers.ParserConfigurationException;

/**
 * Contains shared code for loading information from a server and caching it for later use.
 *
 * Created by Jesse on 1/17/14.
 */
public class ServerInfoCache {
    private final Map cache = Collections.synchronizedMap(new HashMap());

    private final ServiceInfoLoader loader;

    public ServerInfoCache(ServiceInfoLoader loader) {
        this.loader = loader;
    }

    public synchronized void clearCache() {
        cache.clear();
    }

    public synchronized final T getInfo(URI uri, RenderingContext context) {
        T result = cache.get(uri);
        if (result == null) {
            try {
                result = requestInfo(uri, context);
            } catch (Exception e) {
                loader.logger().info("Error while getting capabilities for "+uri+". The print module will assume it's a standard WMS.");
                String stackTrace = "";
                for (StackTraceElement el : e.getStackTrace()) {
                    stackTrace += el.toString() +"\n";
                }
                loader.logger().info(stackTrace);
                result = loader.createNewErrorResult();
            }
            if (loader.logger().isDebugEnabled()) {
                loader.logger().debug("GetCapabilities " + uri + ": " + result);
            }
            cache.put(uri, result);
        }
        return result;

    }


    private T requestInfo(URI baseUrl, RenderingContext context) throws IOException, URISyntaxException, ParserConfigurationException, SAXException {
        URL url = loader.createURL(baseUrl, context);

        GetMethod method = null;

        MetricRegistry registry = context.getConfig().getMetricRegistry();
        final com.codahale.metrics.Timer.Context timer = registry.timer("http_" + url.getAuthority()).time();
        try {
            final InputStream stream;

            if ((url.getProtocol().equals("http") || url.getProtocol().equals("https")) &&
                context.getConfig().localHostForwardIsFrom(url.getHost())) {
                String scheme = url.getProtocol();
                final String host = url.getHost();
                if (url.getProtocol().equals("https") &&
                    context.getConfig().localHostForwardIsHttps2http()) {
                    scheme = "http";
                }
                URL localUrl = new URL(scheme, "localhost", url.getPort(),
                        url.getFile());
                HttpURLConnection connexion = (HttpURLConnection)localUrl.openConnection();
                connexion.setRequestProperty("Host", host);
                for (Map.Entry entry : context.getHeaders().entrySet()) {
                    connexion.setRequestProperty(entry.getKey(), entry.getValue());
                }
                stream = connexion.getInputStream();
            }
            else {
                method = new GetMethod(url.toString());
                for (Map.Entry entry : context.getHeaders().entrySet()) {
                    method.setRequestHeader(entry.getKey(), entry.getValue());
                }
                context.getConfig().getHttpClient(baseUrl).executeMethod(method);
                int code = method.getStatusCode();
                if (code < 200 || code >= 300) {
                    throw new IOException("Error " + code + " while reading the Capabilities from " + url + ": " + method.getStatusText());
                }
                stream = method.getResponseBodyAsStream();
            }
            final T result;
            try {
                result = loader.parseInfo(stream);
            } finally {
                stream.close();
            }
            return result;
        } finally {
            timer.stop();
            if (method != null) {
                method.releaseConnection();
            }
        }
    }
    public static abstract class ServiceInfoLoader {

        public abstract Log logger();

        public abstract T createNewErrorResult();

        public abstract URL createURL(URI baseUrl, RenderingContext context) throws UnsupportedEncodingException, URISyntaxException, MalformedURLException;

        public abstract T parseInfo(InputStream stream) throws ParserConfigurationException, IOException, SAXException;


        /**
         * Get the text content of the _child_ element or return default value if element does not exist. An exception is thrown
         * if the child is not found.
         *
         * @param element
         * @param tagName
         */
        public static String getTextContentOfChild(Element element, String tagName) {
            String result = getTextContextFromPath(element, tagName, null);
            if (result == null) {
                throw new NoSuchElementException("No child "+tagName+" was found in element "+element.getNodeName());
            }
            return result;
        }
        /**
         * Get the text content of the _child_ element or return default value if element does not exist. The elements are used for selection but
         * the namespace is ignored.
         *
         * @param element
         * @param tagName
         * @param defaultValue
         */
        public static String getTextContentOfChild(Element element, String tagName, String defaultValue) {
            Element child = getFirstChildElement(element, tagName);
            if (child == null || child.getTextContent().trim().isEmpty()) {
                return defaultValue;
            }
            return child.getTextContent();
        }

        /**
         * Find all the children with the provided tagName and return an array of their non-empty text.
         *
         *
         * @param element parent element of elements to get
         * @param tagName child names
         * @return
         */
        public static ArrayList getTextContentOfChildren(Element element, String tagName) {

            ArrayList text = new ArrayList();
            final NodeList nodeList = element.getChildNodes();
            for (int i = 0; i < nodeList.getLength(); i++) {
                Node node = nodeList.item(i);
                if (node instanceof Element) {
                    Element child = (Element) node;
                    if (getLocalName(child).equals(tagName)) {
                        final String textContent = node.getTextContent();
                        if (!textContent.trim().isEmpty()) {
                            text.add(textContent);
                        }
                    }
                }
            }
            return text;
        }

        /**
         * Find the text at the indicated path (not an XPath just a / separated path of tagnames) or return default value.
         *
         * Assumptions:
         * 
    *
  • Only the first child in each path segment is traversed. If there are multiple then they will be ignored.
  • *
* * @param element * @param path * @param defaultValue * @return */ public static String getTextContextFromPath(Element element, String path, String defaultValue) { return getTextContextFromPath(element, Arrays.asList(path.split("/")), defaultValue); } private static String getTextContextFromPath(Element element, List path, String defaultValue) { final Element child = getFirstChildElement(element, path.get(0)); if (child == null) { return defaultValue; } if (path.size() == 1) { String text = child.getTextContent(); if (text.trim().isEmpty()) { return defaultValue; } else { return text; } } return getTextContextFromPath(child, path.subList(1, path.size()), defaultValue); } private static Element getFirstChildElement(Element element, String tagName) { final NodeList childNodes = element.getChildNodes(); for (int i = 0; i < childNodes.getLength(); i++) { Node elem = childNodes.item(i); if (elem instanceof Element) { if (getLocalName(elem).equals(tagName)) { return (Element) elem; } } } return null; } private static String getLocalName(Node elem) { final String nodeName = elem.getNodeName(); String[] split = nodeName.split(":", 2); return split.length == 2 ? split[1] : split[0]; } } }




© 2015 - 2025 Weber Informatics LLC | Privacy Policy