org.codice.ddf.admin.sources.opensearch.OpenSearchSourceUtils.java Source code

Java tutorial

Introduction

Here is the source code for org.codice.ddf.admin.sources.opensearch.OpenSearchSourceUtils.java

Source

/**
 * Copyright (c) Codice Foundation
 * <p>
 * This is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser
 * General Public License as published by the Free Software Foundation, either version 3 of the
 * License, or any later version.
 * <p>
 * This program 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
 * Lesser General Public License for more details. A copy of the GNU Lesser General Public License
 * is distributed along with this program and can be found at
 * <http://www.gnu.org/licenses/lgpl.html>.
 */
package org.codice.ddf.admin.sources.opensearch;

import static java.net.HttpURLConnection.HTTP_OK;
import static org.codice.ddf.admin.api.handler.commons.SourceHandlerCommons.SOURCES_NAMESPACE_CONTEXT;
import static org.codice.ddf.admin.sources.SourcesCommons.closeClientAndResponse;
import static org.codice.ddf.admin.sources.SourcesCommons.getCloseableHttpClient;

import java.util.List;
import java.util.Optional;

import javax.net.ssl.SSLPeerUnverifiedException;
import javax.xml.parsers.DocumentBuilder;
import javax.xml.parsers.DocumentBuilderFactory;
import javax.xml.xpath.XPath;
import javax.xml.xpath.XPathConstants;
import javax.xml.xpath.XPathFactory;

import org.apache.commons.codec.binary.Base64;
import org.apache.http.client.methods.CloseableHttpResponse;
import org.apache.http.client.methods.HttpGet;
import org.apache.http.impl.client.CloseableHttpClient;
import org.codice.ddf.admin.api.config.sources.OpenSearchSourceConfiguration;
import org.codice.ddf.admin.api.handler.commons.UrlAvailability;
import org.w3c.dom.Document;

import com.google.common.collect.ImmutableList;
import com.google.common.net.HttpHeaders;

public class OpenSearchSourceUtils {

    private static final List<String> OPENSEARCH_MIME_TYPES = ImmutableList.of("application/atom+xml");

    private static final List<String> URL_FORMATS = ImmutableList.of("https://%s:%d/services/catalog/query",
            "https://%s:%d/catalog/query", "http://%s:%d/services/catalog/query", "http://%s:%d/catalog/query");

    private static final String SIMPLE_QUERY_PARAMS = "?q=test&mr=1&src=local";

    private static final String TOTAL_RESULTS_XPATH = "//os:totalResults|//opensearch:totalResults";

    //Given a config, returns the correct URL format for the endpoint if one exists
    public UrlAvailability confirmEndpointUrl(OpenSearchSourceConfiguration config) {
        Optional<UrlAvailability> result = URL_FORMATS.stream()
                .map(formatUrl -> String.format(formatUrl, config.sourceHostName(), config.sourcePort()))
                .map(url -> getUrlAvailability(url, config.sourceUserName(), config.sourceUserPassword()))
                .filter(avail -> avail.isAvailable() || avail.isCertError()).findFirst();
        return result.isPresent() ? result.get() : null;
    }

    // Given a configuration with and endpointUrl, determines if that URL is available as an OS source
    public UrlAvailability getUrlAvailability(String url, String un, String pw) {
        UrlAvailability result = new UrlAvailability(url);
        boolean queryResponse;
        int status;
        String contentType;
        HttpGet request = new HttpGet(url + SIMPLE_QUERY_PARAMS);
        CloseableHttpResponse response = null;
        CloseableHttpClient client = null;

        if (url.startsWith("https") && un != null && pw != null) {
            byte[] auth = Base64.encodeBase64((un + ":" + pw).getBytes());
            request.setHeader(HttpHeaders.AUTHORIZATION, "Basic " + new String(auth));
        }
        XPath xpath = XPathFactory.newInstance().newXPath();
        xpath.setNamespaceContext(SOURCES_NAMESPACE_CONTEXT);
        try {
            client = getCloseableHttpClient(false);
            response = client.execute(request);
            DocumentBuilderFactory factory = DocumentBuilderFactory.newInstance();
            factory.setNamespaceAware(true);
            DocumentBuilder builder = factory.newDocumentBuilder();
            Document responseXml = builder.parse(response.getEntity().getContent());
            queryResponse = (Boolean) xpath.compile(TOTAL_RESULTS_XPATH).evaluate(responseXml,
                    XPathConstants.BOOLEAN);
            status = response.getStatusLine().getStatusCode();
            contentType = response.getEntity().getContentType().getValue();
            if (status == HTTP_OK && OPENSEARCH_MIME_TYPES.contains(contentType) && queryResponse) {
                return result.trustedCertAuthority(true).certError(false).available(true);
            } else {
                return result.trustedCertAuthority(true).certError(false).available(false);
            }
        } catch (SSLPeerUnverifiedException e) {
            // This is the hostname != cert name case - if this occurs, the URL's SSL cert configuration
            // is incorrect, or a serious network security issue has occurred.
            return result.trustedCertAuthority(false).certError(true).available(false);
        } catch (Exception e) {
            try {
                closeClientAndResponse(client, response);
                client = getCloseableHttpClient(true);
                response = client.execute(request);
                status = response.getStatusLine().getStatusCode();
                contentType = response.getEntity().getContentType().getValue();
                DocumentBuilderFactory factory = DocumentBuilderFactory.newInstance();
                factory.setNamespaceAware(true);
                DocumentBuilder builder = factory.newDocumentBuilder();
                Document responseXml = builder.parse(response.getEntity().getContent());
                queryResponse = (Boolean) xpath.compile(TOTAL_RESULTS_XPATH).evaluate(responseXml,
                        XPathConstants.BOOLEAN);
                if (status == HTTP_OK && OPENSEARCH_MIME_TYPES.contains(contentType) && queryResponse) {
                    return result.trustedCertAuthority(false).certError(false).available(true);
                }
            } catch (Exception e1) {
                return result.trustedCertAuthority(false).certError(false).available(false);
            }
        } finally {
            closeClientAndResponse(client, response);
        }
        return result;
    }
}