Package org.fcrepo.server.security.xacml.pep.ws.operations

Source Code of org.fcrepo.server.security.xacml.pep.ws.operations.AbstractOperationHandler

/*
* File: AbstractOperationHandler.java
*
* Copyright 2007 Macquarie E-Learning Centre Of Excellence
*
* Licensed 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 org.fcrepo.server.security.xacml.pep.ws.operations;

import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.net.URI;
import java.net.URISyntaxException;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Set;

import javax.servlet.http.HttpServletRequest;
import javax.xml.bind.JAXBContext;
import javax.xml.bind.JAXBException;
import javax.xml.bind.Marshaller;
import javax.xml.bind.Unmarshaller;
import javax.xml.namespace.QName;
import javax.xml.soap.SOAPBody;
import javax.xml.soap.SOAPElement;
import javax.xml.soap.SOAPException;
import javax.xml.soap.SOAPMessage;
import javax.xml.ws.handler.soap.SOAPMessageContext;

import org.apache.cxf.binding.soap.SoapFault;
import org.fcrepo.common.Constants;
import org.fcrepo.server.security.xacml.pep.ContextHandler;
import org.fcrepo.server.security.xacml.pep.PEPException;
import org.fcrepo.server.security.xacml.pep.ResourceAttributes;
import org.fcrepo.server.utilities.CXFUtility;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import com.sun.xacml.attr.AnyURIAttribute;
import com.sun.xacml.attr.AttributeValue;
import com.sun.xacml.attr.StringAttribute;

/**
* This is the AbstractHandler class which provides generic functionality for
* all operation handlers. All operation handlers should extend this class.
*
* @author nishen@melcoe.mq.edu.au
*/
public abstract class AbstractOperationHandler
        implements OperationHandler {

    private static final Logger logger = LoggerFactory
            .getLogger(AbstractOperationHandler.class);

    protected static final JAXBContext JAXB_CONTEXT = getJAXBContext();

    private final ContextHandler m_contextHandler;

    /**
     * Default constructor that obtains an instance of the ContextHandler.
     *
     * @throws PEPException
     */
    public AbstractOperationHandler(ContextHandler contextHandler)
            throws PEPException {
        m_contextHandler = contextHandler;
    }

    /**
     * Extracts the request as object from the context.
     *
     * @param context
     *        the message context.
     * @return Object
     * @throws SoapFault
     */
    protected Object getSOAPRequestObjects(SOAPMessageContext context) {
        // Obtain the operation details and message type
        // Extract the SOAP Message
        SOAPElement requestNode = getSOAPRequestNode(context);
        return unmarshall(requestNode);
    }

    private SOAPElement getSOAPNode(SOAPMessageContext context, QName operation) {
        SOAPMessage message = context.getMessage();
        SOAPBody body;
        try {
            body = message.getSOAPBody();
        } catch (SOAPException e) {
            throw CXFUtility.getFault(e);
        }
        SOAPElement bodyElement = body;
        if (bodyElement.getNamespaceURI().equals("http://schemas.xmlsoap.org/soap/envelope/")
                && bodyElement.getLocalName().equals("Body")){
            bodyElement = (SOAPElement)bodyElement.getElementsByTagNameNS(operation.getNamespaceURI(), operation.getLocalPart()).item(0);
        }
        if (logger.isDebugEnabled() && bodyElement != null) {
            logger.debug("Operation: {} {}", operation.getNamespaceURI(), operation.getLocalPart());
        }
        return bodyElement;
    }

    protected SOAPElement getSOAPRequestNode(SOAPMessageContext context) {
        QName operation =
                (QName) context.get(SOAPMessageContext.WSDL_OPERATION);
        SOAPElement bodyElement = getSOAPNode(context, operation);
        if (bodyElement == null){
            logger.error("Could not obtain " + operation.toString() + " Object from SOAP Request");
            logger.error(context.getMessage().toString());
            throw CXFUtility
                    .getFault(new Exception("Could not obtain Object from SOAP Request"));
        }
        return bodyElement;
    }

    protected SOAPElement getSOAPResponseNode(SOAPMessageContext context) {
        QName operation =
                (QName) context.get(SOAPMessageContext.WSDL_OPERATION);
        operation = new QName(operation.getNamespaceURI(),operation.getLocalPart() + "Response");
        SOAPElement bodyElement = getSOAPNode(context, operation);
        if (bodyElement == null){
            logger.error("Could not obtain " + operation.toString() + " Object from SOAP Response");
            logger.error(context.getMessage().toString());
            throw CXFUtility
                    .getFault(new Exception("Could not obtain Object from SOAP Response"));
        }
        return bodyElement;
    }

    protected Object getSOAPResponseObject(SOAPMessageContext context) {
        // Obtain the operation details and message type
        // Extract the SOAP Message
        SOAPElement responseNode = getSOAPResponseNode(context);
        return unmarshall(responseNode);
    }

    /**
     * Extracts the return object from the context.
     * @param <T>
     * @param <T>
     *
     * @param context
     *        the message context.
     * @return the return object for the message.
     * @throws SoapFault
     */
    protected <T> List<T>  getSOAPResponseObject(SOAPMessageContext context, Class<T> clazz) {
        // return result

        Object responseObject = getSOAPResponseObject(context);
        ArrayList<T> resultList = new ArrayList<T>();
        for (Method m:responseObject.getClass().getDeclaredMethods()){
            if (m.getReturnType() == clazz) {
                try {
                    resultList.add((T)m.invoke(responseObject, null));
                } catch (Exception e) {
                    logger.error(e.toString(),e);
                    throw CXFUtility.getFault(e);
                }
            }
        }

        return resultList;
    }

    /**
     * Sets the request parameters for a request.
     *
     * @param context
     *        the message context
     * @param params
     *        list of parameters to set in order
     * @throws SoapFault
     */
    protected void setSOAPRequestObjects(SOAPMessageContext context,
                                         List<SOAPElement> params) {
        // Extract the SOAP Message
        SOAPMessage message = context.getMessage();

        // Get the envelope body
        SOAPBody body;
        try {
            body = message.getSOAPBody();
        } catch (SOAPException e) {
            throw CXFUtility.getFault(e);
        }

        try {
            body.removeContents();
            for (SOAPElement p : params) {
                body.addChildElement(p);
            }
        } catch (Exception e) {
            logger.error("Problem changing SOAP message contents", e);
            throw CXFUtility.getFault(e);
        }
    }

    /**
     * Sets the return object for a response as the param.
     *
     * @param context
     *        the message context
     * @param param
     *        the object to set as the return object
     * @throws SoapFault
     */
    protected void setSOAPResponseObject(SOAPMessageContext context,
                                         Object newResponse) {
        if (newResponse == null) {
            return;
        }
        // Extract the SOAP Message
        SOAPMessage message = context.getMessage();

        // Get the envelope body
        SOAPElement body;
        try {
            body = message.getSOAPBody();
            SOAPElement response = getSOAPResponseNode(context);
            body.removeChild(response);
            marshall(newResponse, body);
        } catch (SOAPException e) {
            logger.error("Problem changing SOAP message contents", e);
            throw CXFUtility.getFault(e);
        }
    }

    /**
     * Extracts the list of Subjects from the given context.
     *
     * @param context
     *        the message context
     * @return a list of Subjects
     * @throws SoapFault
     */
    protected List<Map<URI, List<AttributeValue>>> getSubjects(SOAPMessageContext context) {
        // setup the id and value for the requesting subject
        List<Map<URI, List<AttributeValue>>> subjects =
                new ArrayList<Map<URI, List<AttributeValue>>>();

        if (getUser(context) == null
                || "".equals(getUser(context).trim())) {
            return subjects;
        }

        String[] fedoraRole = getUserRoles(context);

        Map<URI, List<AttributeValue>> subAttr = null;
        List<AttributeValue> attrList = null;

        subAttr = new HashMap<URI, List<AttributeValue>>();
        attrList = new ArrayList<AttributeValue>();
        attrList.add(new StringAttribute(getUser(context)));
        subAttr.put(Constants.SUBJECT.LOGIN_ID.getURI(), attrList);
        if (fedoraRole != null && fedoraRole.length > 0) {
            attrList = new ArrayList<AttributeValue>();
            for (String r : fedoraRole) {
                attrList.add(new StringAttribute(r));
            }
            subAttr.put(Constants.SUBJECT.ROLE.getURI(), attrList);
        }
        subjects.add(subAttr);

        subAttr = new HashMap<URI, List<AttributeValue>>();
        attrList = new ArrayList<AttributeValue>();
        attrList.add(new StringAttribute(getUser(context)));
        subAttr.put(Constants.SUBJECT.USER_REPRESENTED.getURI(), attrList);
        if (fedoraRole != null && fedoraRole.length > 0) {
            attrList = new ArrayList<AttributeValue>();
            for (String r : fedoraRole) {
                attrList.add(new StringAttribute(r));
            }
            subAttr.put(Constants.SUBJECT.ROLE.getURI(), attrList);
        }
        subjects.add(subAttr);

        subAttr = new HashMap<URI, List<AttributeValue>>();
        attrList = new ArrayList<AttributeValue>();
        attrList.add(new StringAttribute(getUser(context)));
        subAttr.put(Constants.XACML1_SUBJECT.ID.getURI(), attrList);
        if (fedoraRole != null && fedoraRole.length > 0) {
            attrList = new ArrayList<AttributeValue>();
            for (String r : fedoraRole) {
                attrList.add(new StringAttribute(r));
            }
            subAttr.put(Constants.SUBJECT.ROLE.getURI(), attrList);
        }
        subjects.add(subAttr);

        return subjects;
    }

    /**
     * Obtains a map of environment Attributes.
     *
     * @param context
     *        the message context
     * @return map of environment Attributes
     */
    protected Map<URI, AttributeValue> getEnvironment(SOAPMessageContext context) {
        Map<URI, AttributeValue> envAttr = new HashMap<URI, AttributeValue>();

        HttpServletRequest request =
                (HttpServletRequest) context
                        .get(SOAPMessageContext.SERVLET_REQUEST);
        String ip = request.getRemoteAddr();

        if (ip != null && !"".equals(ip)) {
            envAttr.put(Constants.HTTP_REQUEST.CLIENT_IP_ADDRESS.getURI(),
                        new StringAttribute(ip));
        }

        return envAttr;
    }
   
    /**
     * Obtains a map of resource Attributes.
     *
     * @param context
     *        the message context
     * @return map of resource Attributes
     * @throws OperationHandlerException
     * @throws URISyntaxException
     */
    protected Map<URI, AttributeValue> getResources(SOAPMessageContext context) throws OperationHandlerException, URISyntaxException {
        Object oMap = null;

        String pid = null;
        try {
            oMap = getSOAPRequestObjects(context);
            logger.debug("Retrieved SOAP Request Objects");
        } catch (SoapFault af) {
            logger.error("Error obtaining SOAP Request Objects", af);
            throw new OperationHandlerException("Error obtaining SOAP Request Objects",
                                                af);
        }

        try {
            pid = (String) callGetter("getPid",oMap);
        } catch (Exception e) {
            logger.error("Error obtaining parameters", e);
            throw new OperationHandlerException("Error obtaining parameters.",
                                                e);
        }
        Map<URI, AttributeValue> resAttr = ResourceAttributes.getResources(pid);
        logger.debug("Extracted SOAP Request Objects");
        return resAttr;
    }
    /**
     * @return the Context Handler
     */
    protected ContextHandler getContextHandler() {
        return m_contextHandler;
    }

    /**
     * Returns the roles that the user has.
     *
     * @param context
     *        the message context
     * @return a String array of roles
     */
    @SuppressWarnings("unchecked")
    protected String[] getUserRoles(SOAPMessageContext context) {
        HttpServletRequest request =
                (HttpServletRequest) context
                        .get(SOAPMessageContext.SERVLET_REQUEST);

        Map<String, Set<String>> reqAttr = null;
        reqAttr =
                (Map<String, Set<String>>) request
                        .getAttribute("FEDORA_AUX_SUBJECT_ATTRIBUTES");

        if (reqAttr == null) {
            return null;
        }

        Set<String> fedoraRoles = reqAttr.get("fedoraRole");
        if (fedoraRoles == null || fedoraRoles.size() == 0) {
            return null;
        }

        String[] fedoraRole =
                fedoraRoles.toArray(new String[fedoraRoles.size()]);

        return fedoraRole;
    }

    protected String getUser(SOAPMessageContext context){
//        String username = (String) context.get("Username");
        HttpServletRequest request =
            (HttpServletRequest) context
                    .get(SOAPMessageContext.SERVLET_REQUEST);
        return request.getRemoteUser();
    }

    protected Object callGetter(String mname, Object context) throws SecurityException, NoSuchMethodException, IllegalArgumentException, IllegalAccessException, InvocationTargetException {
        Class klass = context.getClass();
        Method getter = klass.getDeclaredMethod(mname, null);
        return getter.invoke(context);
    }

    private static JAXBContext getJAXBContext(){
        try {
            return JAXBContext.newInstance("org.fcrepo.server.types.gen:org.fcrepo.server.types.mtom.gen");
        } catch (JAXBException e) {
            logger.error(e.toString(),e);
            return null;
        }

    }

    protected static Object unmarshall(SOAPElement node) {
        if (node == null) return node;
        Unmarshaller um = null;
        try {
            um = JAXB_CONTEXT.createUnmarshaller();
        } catch (JAXBException e) {
            logger.error(e.toString(),e);
            throw CXFUtility.getFault(e);
        }
        Object result = null;
        try {
            result = um.unmarshal(node);
        } catch (Exception e) {
            logger.error("Problem obtaining params", e);
            throw CXFUtility.getFault(e);
        }
        return result;
    }

    protected static void marshall(Object unmarshalled, SOAPElement parent) {
        if (unmarshalled == null) return;
        Marshaller m = null;
        try {
            m = JAXB_CONTEXT.createMarshaller();
        } catch (Exception e) {
            logger.error(e.toString(),e);
            throw CXFUtility.getFault(e);
        }
        try {
            m.marshal(unmarshalled, parent);
        } catch (JAXBException e) {
            logger.error("Problem serializing params", e);
            throw CXFUtility.getFault(e);
        }
    }

}
TOP

Related Classes of org.fcrepo.server.security.xacml.pep.ws.operations.AbstractOperationHandler

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.