org.codice.ddf.ui.Query.java Source code

Java tutorial

Introduction

Here is the source code for org.codice.ddf.ui.Query.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.ui;

import java.io.IOException;
import java.io.PrintWriter;
import java.io.StringReader;
import java.io.StringWriter;
import java.util.List;

import javax.servlet.ServletException;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import javax.xml.transform.Source;
import javax.xml.transform.stream.StreamSource;

import org.apache.commons.io.IOUtils;
import org.apache.commons.lang.StringUtils;
import org.codice.ddf.platform.util.XMLUtils;
import org.jasig.cas.client.authentication.AttributePrincipal;
import org.opengis.filter.Filter;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import ddf.catalog.CatalogFramework;
import ddf.catalog.data.BinaryContent;
import ddf.catalog.data.Metacard;
import ddf.catalog.data.Result;
import ddf.catalog.federation.FederationException;
import ddf.catalog.filter.FilterBuilder;
import ddf.catalog.operation.QueryRequest;
import ddf.catalog.operation.QueryResponse;
import ddf.catalog.operation.impl.QueryImpl;
import ddf.catalog.operation.impl.QueryRequestImpl;
import ddf.catalog.source.SourceUnavailableException;
import ddf.catalog.source.UnsupportedQueryException;
import ddf.catalog.transform.CatalogTransformerException;
import ddf.security.SecurityConstants;
import ddf.security.Subject;
import ddf.security.service.SecurityManager;
import ddf.security.service.SecurityServiceException;
import ddf.security.service.impl.cas.CasAuthenticationToken;

/**
 * This a a very simple example of a servlet protected by CAS that can be used to query for
 * metacards using metacard ids.
 * <p>
 * The query page that displays a metacard in xml format.
 */
public class Query extends HttpServlet {
    private static final long serialVersionUID = 1L;

    private static final Logger LOGGER = LoggerFactory.getLogger(Query.class);

    private static final String QUERY_FORM_SERVLET = "/ddf/query/QueryForm";

    private static final String QUERY_REQUEST_PARAM = "query";

    private static final String PROXY_TICKET_REQUEST_PARAM = "proxyticket";

    private static final String STS_SERVICE_URL = "https://localhost:8993/services/SecurityTokenService";

    private transient CatalogFramework catalogFramework;

    private transient SecurityManager securityManager;

    private transient FilterBuilder filterBuilder;

    public void setCatalogFramework(CatalogFramework catalogFramework) {
        this.catalogFramework = catalogFramework;
    }

    public void setSecurityManager(SecurityManager securityManager) {
        LOGGER.debug("Got a security manager");
        this.securityManager = securityManager;
    }

    public void setFilterBuilder(FilterBuilder filterBuilder) {
        this.filterBuilder = filterBuilder;
    }

    @Override
    protected void doGet(HttpServletRequest request, HttpServletResponse response)
            throws ServletException, IOException {
        doPost(request, response);
    }

    @Override
    protected void doPost(HttpServletRequest request, HttpServletResponse response)
            throws ServletException, IOException {
        response.setContentType("text/html");
        PrintWriter writer = response.getWriter();
        LOGGER.debug("serviceticket request parameter: {}", request.getParameter(PROXY_TICKET_REQUEST_PARAM));
        LOGGER.debug("query request parameter: {}", request.getParameter(QUERY_REQUEST_PARAM));
        String html = createPage(request);
        writer.println(html);
    }

    /**
     * @param request The Http servlet request.
     * @return Returns the html representation of the query page which includes the xml
     * representation of the metacard.
     */
    private String createPage(HttpServletRequest request) {
        StringBuilder sb = new StringBuilder();
        sb.append("<?xml version=\"1.0\" encoding=\"UTF-8\"?>");
        sb.append("<!DOCTYPE html PUBLIC \"-//W3C//DTD XHTML 1.0 Strict//EN\" \"DTD/xhtml1-strict.dtd\">");
        sb.append("<html xmlns=\"http://www.w3.org/1999/xhtml\" xml:lang=\"en\" lang=\"en\">");
        sb.append("<head>");
        sb.append("<title>");
        sb.append("Query Result");
        sb.append("</title>");
        sb.append("</head>");
        sb.append("<body>");
        sb.append("<h1>");
        sb.append("Query Request:");
        sb.append("</h1>");
        sb.append("<p>");
        String metacardId = request.getParameter(QUERY_REQUEST_PARAM);
        sb.append(metacardId);
        sb.append("</p>");
        sb.append("<h1>");
        sb.append("Query Result:");
        sb.append("</h1>");
        sb.append("<p>");
        sb.append("<textarea name=\"queryresult\" id=\"queryresult\" rows=\"40\" cols=\"80\">");
        sb.append(getMetacardForId(metacardId, getProxyTicket(request)));
        sb.append("</textarea>");
        sb.append("</p>");
        sb.append("<p>");
        sb.append("<form method=\"post\" action=\"" + QUERY_FORM_SERVLET + "\">");
        sb.append("<input type=\"submit\" value=\"New Query\" />");
        sb.append("</form>");
        sb.append("</p>");
        sb.append("</body>");
        sb.append("</html>");

        StringBuilder message = new StringBuilder();
        message.append("\n########################################################################\n");
        message.append(" Query result html:\n");
        message.append(sb.toString());
        message.append("\n########################################################################\n");
        LOGGER.debug(message.toString());

        return sb.toString();
    }

    /**
     * @param searchPhrase The search phrase used to query for the metacard.
     * @param proxyTicket  The CAS proxy ticket that will be used by the STS to get a SAML assertion.
     * @return
     */
    private String getMetacardForId(String searchPhrase, String proxyTicket) {

        Filter filter = filterBuilder.attribute(Metacard.ANY_TEXT).is().like().text(searchPhrase);
        LOGGER.info("Query filter: {}", filter.toString());
        String queryError = "Unable to perform query " + filter.toString() + ".";
        QueryRequest request = new QueryRequestImpl(new QueryImpl(filter), true);
        StringBuilder responseString = new StringBuilder();

        try {
            Subject subject = securityManager.getSubject(new CasAuthenticationToken(proxyTicket));
            LOGGER.info("Adding {} property with value {} to request", SecurityConstants.SECURITY_SUBJECT, subject);
            request.getProperties().put(SecurityConstants.SECURITY_SUBJECT, subject);
        } catch (SecurityServiceException se) {
            LOGGER.error("Could not retrieve subject from securitymanager.", se);
            return queryError;
        }

        try {
            LOGGER.debug("About to query the catalog framework with query {}", filter.toString());
            QueryResponse queryResponse = catalogFramework.query(request, null);
            LOGGER.debug("Got query response from catalog framework for query {}", filter.toString());
            List<Result> results = queryResponse.getResults();
            if (results != null) {
                String message = "The query for " + filter.toString() + " returned " + results.size() + " results.";
                responseString.append(message);
                LOGGER.debug(message);
                for (Result curResult : results) {
                    Metacard metacard = curResult.getMetacard();
                    LOGGER.debug("Transforming the metacard with id [{}] to xml.", metacard.getId());
                    BinaryContent content = catalogFramework.transform(metacard, "xml", null);
                    StringWriter writer = new StringWriter();
                    IOUtils.copy(content.getInputStream(), writer, "UTF8");
                    LOGGER.debug("Formatting xml for metacard with id [{}].", metacard.getId());
                    responseString.append(format(writer.toString()));
                }
            } else {
                String message = "The query for " + filter.toString() + " returned a null result.";
                responseString.append(message);
                LOGGER.warn(message);
            }
        } catch (SourceUnavailableException e) {
            LOGGER.error(queryError, e);
        } catch (UnsupportedQueryException e) {
            LOGGER.error(queryError, e);
        } catch (FederationException e) {
            LOGGER.error(queryError, e);
        } catch (CatalogTransformerException e) {
            LOGGER.error(queryError, e);
        } catch (IOException e) {
            LOGGER.error(queryError, e);
        }

        return responseString.toString();
    }

    /**
     * Gets the CAS proxy ticket that will be used by the STS to get a SAML assertion.
     *
     * @param request The Http servlet request.
     * @return Returns the CAS proxy ticket that will be used by the STS to get a SAML assertion.
     */
    private String getProxyTicket(HttpServletRequest request) {
        AttributePrincipal attributePrincipal = (AttributePrincipal) request.getUserPrincipal();
        String proxyTicket = null;

        if (attributePrincipal != null) {
            // proxyTicket = attributePrincipal.getProxyTicketFor(
            // "https://server:8993/ddf/query/sts" );
            LOGGER.debug("Getting proxy ticket for {}", STS_SERVICE_URL);
            proxyTicket = attributePrincipal.getProxyTicketFor(STS_SERVICE_URL);
            LOGGER.info("proxy ticket: {}", proxyTicket);
        } else {
            LOGGER.error("attribute principal is null!");
        }

        return proxyTicket;
    }

    /**
     * @param unformattedXml Unformatted xml.
     * @return Returns formatted xml.
     */
    private String format(String unformattedXml) {
        Source xmlInput = new StreamSource(new StringReader(unformattedXml));
        String formattedXml;

        formattedXml = XMLUtils.prettyFormat(xmlInput);

        LOGGER.debug("Formatted xml:\n{}", formattedXml);

        if (StringUtils.isBlank(formattedXml)) {
            // Did not format so return unformatted xml
            formattedXml = unformattedXml;
        }
        return formattedXml;
    }

}