/* * 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 melcoe.fedora.pep.ws.operations; 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 melcoe.fedora.pep.ContextHandler; import melcoe.fedora.pep.ContextHandlerImpl; import melcoe.fedora.pep.PEPException; import org.apache.axis.AxisFault; import org.apache.axis.Message; import org.apache.axis.MessageContext; import org.apache.axis.description.OperationDesc; import org.apache.axis.message.RPCElement; import org.apache.axis.message.RPCParam; import org.apache.axis.message.SOAPBodyElement; import org.apache.axis.message.SOAPEnvelope; import org.apache.log4j.Logger; import com.sun.xacml.attr.AttributeValue; import com.sun.xacml.attr.StringAttribute; import fedora.common.Constants; /** * 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 Logger log = Logger.getLogger(AbstractOperationHandler.class.getName()); protected static final String XACML_RESOURCE_ID = "urn:oasis:names:tc:xacml:1.0:resource:resource-id"; protected static final String SUBJECT_ID = "urn:oasis:names:tc:xacml:1.0:subject:subject-id"; protected static final String FEDORA_ROLE = "urn:fedora:names:fedora:2.1:subject:role"; private static ContextHandler contextHandlerImpl; /** * Default constructor that obtains an instance of the ContextHandler. * * @throws PEPException */ public AbstractOperationHandler() throws PEPException { contextHandlerImpl = ContextHandlerImpl.getInstance(); } /** * Extracts the request parameters as objects from the context. * * @param context * the message context. * @return list of Objects * @throws AxisFault */ protected List<Object> getSOAPRequestObjects(MessageContext context) throws AxisFault { // return result List<Object> result = new ArrayList<Object>(); // Obtain the operation details and message type OperationDesc operation = context.getOperation(); // Extract the SOAP Message Message message = context.getRequestMessage(); // Extract the SOAP Envelope from the Message SOAPEnvelope envelope = message.getSOAPEnvelope(); // Get the envelope body SOAPBodyElement body = envelope.getFirstBody(); // Make sure that the body element is an RPCElement. if (body instanceof RPCElement) { // Get all the parameters from the Body Element. List params = null; try { params = ((RPCElement) body).getParams(); log.debug("Number of params: " + params.size()); } catch (Exception e) { log.error("Problem obtaining params", e); throw AxisFault.makeFault(e); } if (params.size() > 0) { log.info("Operation returnType: " + operation.getReturnType().getNamespaceURI() + " " + operation.getReturnType().getLocalPart()); for (int x = 0; x < params.size(); x++) { RPCParam param = (RPCParam) params.get(x); result.add(param.getObjectValue()); log.info("Obtained object: (" + x + ") " + param.getQName().toString()); } } } return result; } /** * Extracts the return object from the context. * * @param context * the message context. * @return the return object for the message. * @throws AxisFault */ protected Object getSOAPResponseObject(MessageContext context) throws AxisFault { // return result Object result = null; // Obtain the operation details and message type OperationDesc operation = context.getOperation(); // Extract the SOAP Message Message message = context.getPastPivot() ? context.getResponseMessage() : context .getRequestMessage(); // Extract the SOAP Envelope from the Message SOAPEnvelope envelope = message.getSOAPEnvelope(); // Get the envelope body SOAPBodyElement body = envelope.getFirstBody(); // Make sure that the body element is an RPCElement. if (body instanceof RPCElement) { // Get all the parameters from the Body Element. List params = null; try { params = ((RPCElement) body).getParams(); if (log.isDebugEnabled()) { log.debug("Number of params: " + params.size()); } } catch (Exception e) { log.error("Problem obtaining params", e); throw AxisFault.makeFault(e); } if (params != null && params.size() > 0) { log.info("Operation returnType: " + operation.getReturnType().getNamespaceURI() + " " + operation.getReturnType().getLocalPart()); for (int x = 0; result == null && x < params.size(); x++) { RPCParam param = (RPCParam) params.get(x); if (param.getQName().equals(operation.getReturnQName())) { log.info("Obtained object: (" + x + ") " + param.getQName().toString()); result = param.getObjectValue(); } } } } if (result == null) { throw AxisFault .makeFault(new Exception("Could not obtain Object from SOAP Response")); } return result; } /** * Sets the request parameters for a request. * * @param context * the message context * @param params * list of parameters to set in order * @throws AxisFault */ protected void setSOAPRequestObjects(MessageContext context, List<RPCParam> params) throws AxisFault { // Extract the SOAP Message Message message = context.getPastPivot() ? context.getResponseMessage() : context .getRequestMessage(); // Extract the SOAP Envelope from the Message SOAPEnvelope envelope = message.getSOAPEnvelope(); // Get the envelope body SOAPBodyElement body = envelope.getFirstBody(); try { body.removeContents(); for (RPCParam p : params) { body.addChild(p); } } catch (Exception e) { log.fatal("Problem changing SOAP message contents", e); throw AxisFault.makeFault(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 AxisFault */ protected void setSOAPResponseObject(MessageContext context, RPCParam param) throws AxisFault { // Extract the SOAP Message Message message = context.getPastPivot() ? context.getResponseMessage() : context .getRequestMessage(); // Extract the SOAP Envelope from the Message SOAPEnvelope envelope = message.getSOAPEnvelope(); // Get the envelope body SOAPBodyElement body = envelope.getFirstBody(); try { body.removeContents(); body.addChild(param); } catch (Exception e) { log.fatal("Problem changing SOAP message contents", e); throw AxisFault.makeFault(e); } } /** * Sets the return object for a response as a sequence of params. * * @param context * the message context * @param param * the object to set as the return object * @throws AxisFault */ protected void setSOAPResponseObject(MessageContext context, RPCParam[] params) throws AxisFault { // Extract the SOAP Message Message message = context.getPastPivot() ? context.getResponseMessage() : context .getRequestMessage(); // Extract the SOAP Envelope from the Message SOAPEnvelope envelope = message.getSOAPEnvelope(); // Get the envelope body SOAPBodyElement body = envelope.getFirstBody(); try { body.removeContents(); if (params != null) { for (RPCParam param : params) { body.addChild(param); } } } catch (Exception e) { log.fatal("Problem changing SOAP message contents", e); throw AxisFault.makeFault(e); } } /** * Extracts the list of Subjects from the given context. * * @param context * the message context * @return a list of Subjects * @throws AxisFault */ protected List<Map<URI, List<AttributeValue>>> getSubjects(MessageContext context) throws AxisFault { // setup the id and value for the requesting subject List<Map<URI, List<AttributeValue>>> subjects = new ArrayList<Map<URI, List<AttributeValue>>>(); if (context.getUsername() == null || "".equals(context.getUsername().trim())) { return subjects; } String[] fedoraRole = getUserRoles(context); Map<URI, List<AttributeValue>> subAttr = null; List<AttributeValue> attrList = null; try { subAttr = new HashMap<URI, List<AttributeValue>>(); attrList = new ArrayList<AttributeValue>(); attrList.add(new StringAttribute(context.getUsername())); 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(new URI(FEDORA_ROLE), attrList); } subjects.add(subAttr); subAttr = new HashMap<URI, List<AttributeValue>>(); attrList = new ArrayList<AttributeValue>(); attrList.add(new StringAttribute(context.getUsername())); 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(new URI(FEDORA_ROLE), attrList); } subjects.add(subAttr); subAttr = new HashMap<URI, List<AttributeValue>>(); attrList = new ArrayList<AttributeValue>(); attrList.add(new StringAttribute(context.getUsername())); subAttr.put(new URI(SUBJECT_ID), attrList); if (fedoraRole != null && fedoraRole.length > 0) { attrList = new ArrayList<AttributeValue>(); for (String r : fedoraRole) { attrList.add(new StringAttribute(r)); } subAttr.put(new URI(FEDORA_ROLE), attrList); } subjects.add(subAttr); } catch (URISyntaxException use) { log.error(use.getMessage(), use); throw AxisFault.makeFault(use); } return subjects; } /** * Obtains a list of environment Attributes. * * @param context * the message context * @return list of environment Attributes */ protected Map<URI, AttributeValue> getEnvironment(MessageContext context) { Map<URI, AttributeValue> envAttr = new HashMap<URI, AttributeValue>(); String ip = (String) context.getProperty("remoteaddr"); if (ip != null && !"".equals(ip)) { envAttr.put(Constants.HTTP_REQUEST.CLIENT_IP_ADDRESS.getURI(), new StringAttribute(ip)); } return envAttr; } /** * @return the Context Handler */ protected ContextHandler getContextHandler() { return contextHandlerImpl; } /** * Returns the roles that the user has. * * @param context * the message context * @return a String array of roles */ @SuppressWarnings("unchecked") protected String[] getUserRoles(MessageContext context) { HttpServletRequest request = (HttpServletRequest) context .getProperty("transport.http.servletRequest"); 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; } }