Package com.esri.gpt.server.csw.provider.components

Source Code of com.esri.gpt.server.csw.provider.components.RequestHandler

/* See the NOTICE file distributed with
* this work for additional information regarding copyright ownership.
* Esri Inc. licenses this file to You under the Apache License, Version 2.0
* (the "License"); you may not use this file except in compliance with
* the License.  You may obtain a copy of the License at
*
*     http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.esri.gpt.server.csw.provider.components;
import com.esri.gpt.framework.context.RequestContext;
import com.esri.gpt.framework.security.credentials.UsernameCredential;
import com.esri.gpt.framework.security.identity.NotAuthorizedException;
import com.esri.gpt.framework.security.principal.User;
import com.esri.gpt.framework.util.Val;
import com.esri.gpt.framework.xml.DomUtil;
import com.esri.gpt.framework.xml.XmlIoUtil;
import com.esri.gpt.sdisuite.IntegrationContext;
import com.esri.gpt.sdisuite.IntegrationContextFactory;

import java.io.IOException;
import java.util.logging.Level;
import java.util.logging.Logger;
import javax.servlet.http.HttpServletRequest;
import javax.xml.parsers.ParserConfigurationException;
import javax.xml.xpath.XPath;
import javax.xml.xpath.XPathConstants;
import javax.xml.xpath.XPathExpressionException;
import javax.xml.xpath.XPathFactory;
import org.w3c.dom.Document;
import org.w3c.dom.Node;
import org.w3c.dom.NodeList;
import org.xml.sax.SAXException;

/**
* Request handler.
*/
public class RequestHandler {

  /** class variables ========================================================= */
 
  /** The Logger. */
  private static Logger LOGGER = Logger.getLogger(RequestHandler.class.getName());
 
  /** instance variables ====================================================== */
  private OperationContext operationContext;
  private boolean          wasSoap = false;
  
  /** constructors ============================================================ */
 
  /** Default constructor */
  public RequestHandler() {}
 
  /** properties ============================================================== */
 
  /**
   * Gets the operation context.
   * @return the operation context
   */
  public OperationContext getOperationContext() {
    return this.operationContext;
  }
  /**
   * Sets the operation context.
   * @param context the operation context
   */
  public void setOperationContext(OperationContext context) {
    this.operationContext = context;
  }
 
  /**
   * Gets the flag indicating a SOAP based request.
   * @return <code>true</code> is this was a SOAP based request
   */
  public boolean getWasSoap() {
    return this.wasSoap;
  }
  /**
   * Sets the flag indicating a SOAP based request.
   * @param wasSoap <code>true</code> is this was a SOAP based request
   */
  public void setWasSoap(boolean wasSoap) {
    this.wasSoap = wasSoap;
  }
           
  /** methods ================================================================= */
 
  /**
   * Handles a URL based request (HTTP GET).
   * @param request the HTTP request
   * @throws Exception if a processing exception occurs
   */
  public OperationResponse handleGet(HttpServletRequest request)
    throws Exception {
       
    // initialize
    LOGGER.finer("Handling CSW request URL...");
    OperationContext context = this.getOperationContext();
    IProviderFactory factory = context.getProviderFactory();
    ServiceProperties svcProps = context.getServiceProperties();
    ParseHelper pHelper = new ParseHelper();
    ValidationHelper vHelper = new ValidationHelper();
    String locator;
    String[] parsed;
    ISupportedValues supported;
   
    // determine the operation name and provider
    String opName = null;
    IOperationProvider opProvider = null;
    locator = "request";
    parsed = pHelper.getParameterValues(request,locator);
    supported = svcProps.getSupportedValues(CswConstants.Parameter_OperationName);
    opName = vHelper.validateValue(supported,locator,parsed,true);
    context.setOperationName(opName);
    if (opName != null) {
      opProvider = factory.makeOperationProvider(context,opName);
    }
   
    // ensure a valid operation provider
    if (opProvider == null) {
      if ((opName == null) || (opName.length() == 0)) {
        throw new OwsException(OwsException.OWSCODE_MissingParameterValue,
            "request","The request parameter was missing.");
      } else {
        throw new OwsException(OwsException.OWSCODE_OperationNotSupported,
            "request","Unsupported operation: "+opName);
      }
    }
   
    // parse the service and version
    this.parseServiceAndVersion(context,request);
   
    // parse and execute the operation
    opProvider.handleGet(context,request);
    return context.getOperationResponse();
  
  }
 
  /**
   * Handles an XML based request (normally HTTP POST).
   * @param xml the XML
   * @throws Exception if a processing exception occurs
   */
  public OperationResponse handleXML(String xml) throws Exception {
   
    // initialize
    LOGGER.finer("Handling CSW request XML...");
    OperationContext context = this.getOperationContext();
    IProviderFactory factory = context.getProviderFactory();
    Node root = null;
    String nsSoapUri = null;
    String nsSoapPfx = null;
   
    try {
     
      // load the dom
      context.getRequestOptions().setRequestXml(xml);
      Document dom = this.loadDom(xml);
      context.getRequestOptions().setRequestDom(dom);
     
      // make an XPath for the CSW name space context
      CswNamespaces ns = new CswNamespaces();
      XPath xpath = XPathFactory.newInstance().newXPath();
      xpath.setNamespaceContext(ns.makeNamespaceContext());
     
      // check for a soap request, if so determine the root CSW operation node
      /*
        <?xml version="1.0"?>
        <soap:Envelope xmlns:soap="http://www.w3.org/2001/12/soap-envelope"
              soap:encodingStyle="http://www.w3.org/2001/12/soap-encoding">
          <soap:Body xmlns:m="http://www.example.org/stock">
        
        <soap:Envelope xmlns:soap="http://schemas.xmlsoap.org/soap/envelope/">
          <soap:Body>
       */
      String expr = "/SOAP-ENV:Envelope | /soap:Envelope | /soap_2003_05:Envelope";
      Node ndSoapEnv = (Node)xpath.evaluate(expr,dom,XPathConstants.NODE);
      if (ndSoapEnv != null) {
        this.setWasSoap(true);
        nsSoapUri = ndSoapEnv.getNamespaceURI();
        nsSoapPfx = ndSoapEnv.lookupPrefix(nsSoapUri);
        expr = "//SOAP-ENV:Body | //soap:Body | //soap_2003_05:Body";
        Node ndSoapBody = (Node)xpath.evaluate(expr,ndSoapEnv,XPathConstants.NODE);
        if (ndSoapBody == null) {
          throw new OwsException(OwsException.OWSCODE_MissingParameterValue,
              "Envelope","The SOAP body was missing.");
        } else {
          NodeList nl = ndSoapBody.getChildNodes();
          for (int i=0; i<nl.getLength(); i++) {
            if (nl.item(i).getNodeType() == Node.ELEMENT_NODE){
              root = nl.item(i);
              break;
            }
          }
          if (root == null) {
            throw new OwsException(OwsException.OWSCODE_MissingParameterValue,
                "Body","No CSW operation was located within the soap body.");
          }
        }
       
        // check for an sdi-suite SAML token
        expr = "//tcExt:samlTicket";
        Node ndSaml = (Node)xpath.evaluate(expr,ndSoapEnv,XPathConstants.NODE);
        if (ndSaml != null) {
          String samlToken = ndSaml.getTextContent();
          if (samlToken != null) {
            IntegrationContextFactory icf = new IntegrationContextFactory();
            if (icf.isIntegrationEnabled()) {
              IntegrationContext ic = icf.newIntegrationContext();
              if (ic != null) {
                String samlUsername = ic.getUsernameFromSAMLToken(samlToken);
                RequestContext rc = context.getRequestContext();
                if ((rc != null) && (samlUsername != null)) {
                  User user = rc.getUser();
                  user.reset();
                  user.setCredentials(new UsernameCredential(samlUsername));
                  rc.newIdentityAdapter().authenticate(user);
                  context.getRequestOptions().getTransactionOptions().setPublicationMethod("seditor");

                  expr = "//tcExt:tcSecurity/tcExt:tcSecuredAction[tcExt:status='draft']";
                  Node ndTmp = (Node)xpath.evaluate(expr,ndSoapEnv,XPathConstants.NODE);
                  if (ndTmp != null) {
                    context.getRequestOptions().getTransactionOptions().setApprovalStatus("draft");
                  }
                }
              }
            }
          }
        }
      }
     
      // if this wasn't a SOAP request, determine the root node
      if (!this.getWasSoap()) {
        NodeList nl = dom.getChildNodes();
        for (int i=0; i<nl.getLength(); i++) {
          if (nl.item(i).getNodeType() == Node.ELEMENT_NODE){
            root = nl.item(i);
            break;
          }
        }
      }
         
      // determine the operation name and provider
      String opName = null;
      IOperationProvider opProvider = null;
      String namespace = root.getNamespaceURI();
      opName = root.getLocalName();
      if (CswNamespaces.URI_CSW.equals(namespace)) {
        context.setOperationName(opName);
        if (opName != null) {
          opProvider = factory.makeOperationProvider(context,opName);
        }
      }
     
      // ensure a valid operation provider
      if (opProvider == null) {
        throw new OwsException(OwsException.OWSCODE_OperationNotSupported,
              "root-node","Unsupported operation: "+opName);
      }
     
      // parse the service and version
      this.parseServiceAndVersion(context,root,xpath);
     
      // parse and execute the operation
      opProvider.handleXML(context,root,xpath);
     
    } catch (NotAuthorizedException e) {
      throw e;
    } catch (Exception e) {
      if (this.getWasSoap()) {
        this.generateSoapResponse(context,nsSoapUri,nsSoapPfx,e);
        return context.getOperationResponse();
      } else {
        throw e;
      }
    }
   
    // wrap the SOAP response if required
    if (this.getWasSoap()) {
      this.generateSoapResponse(context,nsSoapUri,nsSoapPfx,null);
    }
    return context.getOperationResponse();
  }
 
  /**
   * Wraps the response within a SOAp envelope.
   * <br/>If the exception argument is null, the operation response is wrapped.
   * <br/>If the exception argument is not null, an OWS exception report is wrapped.
   * <br/>The OperationResponse.responseXml is reset to the SOAP response string.
   * @param context the operation context
   * @param nsSoapUri the SOAP namespace URI
   * @param nsSoapPfx the SOAP namespace prefix
   * @param exception an exception condition that should be wrapped as an OWS exception report
   * @throws Exception Exception if a processing exception occurs
   */
  protected void generateSoapResponse(OperationContext context,
                                      String nsSoapUri,
                                      String nsSoapPfx,
                                      Exception exception)
    throws Exception {
   
    // make the SOAP document
    if (Val.chkStr(nsSoapPfx).length() == 0) {
      nsSoapPfx = "soap";
    }
    Document domSoap = DomUtil.newDocument();
    Node ndSoapEnv = domSoap.createElementNS(nsSoapUri,nsSoapPfx+":Envelope");
    Node ndSoapBody = domSoap.createElementNS(nsSoapUri,nsSoapPfx+":Body");
    domSoap.appendChild(ndSoapEnv);
    ndSoapEnv.appendChild(ndSoapBody);
   
    // check for an exception condition
    OperationResponse opResponse = context.getOperationResponse();
    if (exception != null) {
      if (exception instanceof OwsException) {
        OwsException ows = (OwsException)exception;
        LOGGER.finer("Invalid CSW request: "+exception.getMessage());
        opResponse.setResponseXml(ows.getReport(context));
      } else {
        OwsException ows = new OwsException(exception);
        LOGGER.log(Level.WARNING,exception.toString(),exception);
        opResponse.setResponseXml(ows.getReport(context));
      }
    }
   
    try {

      // wrap the response within the SOAP body
      Document domCsw = DomUtil.makeDomFromString(opResponse.getResponseXml(),true);
      NodeList nl = domCsw.getChildNodes();
      for (int i=0; i<nl.getLength(); i++) {
        if (nl.item(i).getNodeType() == Node.ELEMENT_NODE){
          Node cswRoot = nl.item(i);
          Node ndImported = domSoap.importNode(cswRoot,true);
          ndSoapBody.appendChild(ndImported);
          opResponse.setResponseXml(XmlIoUtil.domToString(domSoap));
          break;
        }
      }
   
    // throw a SOAP fault
    } catch (Exception e) {
      Node ndFault = domSoap.createElementNS(nsSoapUri,nsSoapPfx+":Fault");
      Node ndCode = domSoap.createElement("faultcode");
      Node ndReason = domSoap.createElement("faultstring");
      Node ndDetail = domSoap.createElementNS(nsSoapUri,nsSoapPfx+":Detail");
      Node ndMessage = domSoap.createElement("message");
      ndFault.appendChild(ndCode);
      ndCode.setTextContent("Server");
      ndFault.appendChild(ndReason);
      ndReason.setTextContent("An error occurred while generating the SOAP body.");
      ndFault.appendChild(ndDetail);
      ndDetail.appendChild(ndMessage);
      ndMessage.setTextContent(e.toString());
      ndSoapBody.appendChild(ndFault);
      opResponse.setResponseXml(XmlIoUtil.domToString(domSoap));
    }
  }
 
  /**
   * Loads an XML string into an XML Document.
   * @param xml the document XML string
   * @return the document
   * @throws OwsException if the document fails to load
   */
  protected Document loadDom(String xml) throws OwsException {
    String sErrorMsg = "Unable to parse incoming XML document.";
    try {
      xml = Val.chkStr(xml);
      if (xml.length() == 0) {
        sErrorMsg = "The incoming XML document was empty.";
      }
      return DomUtil.makeDomFromString(xml,true);
    } catch (ParserConfigurationException e) {
      throw new OwsException(sErrorMsg,e);
    } catch (SAXException e) {
      throw new OwsException(sErrorMsg,e);
    } catch (IOException e) {
      throw new OwsException(sErrorMsg,e);
    }
  }
 
  /**
   * Parses the service name and version for a URL based request (HTTP GET).
   * @param context the operation context
   * @param request the HTTP request
   * @throws OwsException if validation fails
   * @throws XPathExpressionException if an XPath related exception occurs
   */
  public void parseServiceAndVersion(OperationContext context, HttpServletRequest request)
    throws OwsException {
   
    // initialize
    LOGGER.finer("Parsing request URL for service and version...");
    ServiceProperties svcProps = context.getServiceProperties();
    ParseHelper pHelper = new ParseHelper();
    ValidationHelper vHelper = new ValidationHelper();
    String locator;
    String[] parsed;
    ISupportedValues supported;
   
    // service name
    locator = "service";
    parsed = pHelper.getParameterValues(request,locator);
    supported = svcProps.getSupportedValues(CswConstants.Parameter_Service);
    String service = vHelper.validateValue(supported,locator,parsed,true);
    svcProps.setServiceName(service);
   
    // service version
    locator = "acceptVersions";
    parsed = pHelper.getParameterValues(request,locator,",");
    supported = svcProps.getSupportedValues(CswConstants.Parameter_Version);
    String version = Val.chkStr(vHelper.negotiateValue(supported,locator,parsed,false));
    if (version.length() > 0) {
      svcProps.setServiceVersion(version);
    } else {
      locator = "version";
      parsed = pHelper.getParameterValues(request,locator);
      supported = svcProps.getSupportedValues(CswConstants.Parameter_Version);
      version = vHelper.validateValue(supported,locator,parsed,false);
      svcProps.setServiceVersion(version);
    }
  }
 
  /**
   * Parses the service name and version an XML based request (normally HTTP POST).
   * @param context the operation context
   * @param root the root node
   * @param xpath an XPath to enable queries (properly configured with name spaces)
   * @throws OwsException if validation fails
   * @throws XPathExpressionException if an XPath related exception occurs
   */
  public void parseServiceAndVersion(OperationContext context, Node root, XPath xpath)
    throws OwsException, XPathExpressionException {
   
    // initialize
    LOGGER.finer("Parsing request XML for service and version...");
    ServiceProperties svcProps = context.getServiceProperties();
    ParseHelper pHelper = new ParseHelper();
    ValidationHelper vHelper = new ValidationHelper();
    String locator;
    String[] parsed;
    ISupportedValues supported;
   
    // service name
    locator = "@service";
    parsed = pHelper.getParameterValues(root,xpath,locator);
    supported = svcProps.getSupportedValues(CswConstants.Parameter_Service);
    String service = vHelper.validateValue(supported,locator,parsed,true);
    svcProps.setServiceName(service);
   
    // service version
    locator = "ows:AcceptVersions/ows:Version";
    parsed = pHelper.getParameterValues(root,xpath,locator);
    supported = svcProps.getSupportedValues(CswConstants.Parameter_Version);
    String version = Val.chkStr(vHelper.negotiateValue(supported,locator,parsed,false));
    if (version.length() > 0) {
      svcProps.setServiceVersion(version);
    } else {
      locator = "@version";
      parsed = pHelper.getParameterValues(root,xpath,locator);
      supported = svcProps.getSupportedValues(CswConstants.Parameter_Version);
      version = vHelper.validateValue(supported,locator,parsed,false);
      svcProps.setServiceVersion(version);
    }
  }
 
}
TOP

Related Classes of com.esri.gpt.server.csw.provider.components.RequestHandler

TOP
Copyright © 2018 www.massapi.com. All rights reserved.
All source code are property of their respective owners. Java is a trademark of Sun Microsystems, Inc and owned by ORACLE Inc. Contact coftware#gmail.com.