/* * Copyright (c) 2005-2014, WSO2 Inc. (http://www.wso2.org) All Rights Reserved. * * WSO2 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 org.wso2.carbon.inbound.endpoint.ext.wsrm.interceptor; import org.apache.axiom.om.OMElement; import org.apache.axiom.soap.SOAPEnvelope; import org.apache.axiom.soap.SOAPHeader; import org.apache.axiom.soap.SOAPHeaderBlock; import org.apache.cxf.binding.soap.interceptor.SoapPreProtocolOutInterceptor; import org.apache.cxf.helpers.IOUtils; import org.apache.cxf.interceptor.Fault; import org.apache.cxf.io.CachedOutputStream; import org.apache.cxf.message.Message; import org.apache.cxf.phase.AbstractPhaseInterceptor; import org.apache.cxf.phase.Phase; import org.apache.log4j.Logger; import org.apache.synapse.util.PayloadHelper; import org.wso2.carbon.inbound.endpoint.ext.wsrm.utils.RMConstants; import org.wso2.carbon.inbound.endpoint.ext.wsrm.utils.SOAPEnvelopeCreator; import javax.xml.namespace.QName; import java.io.IOException; import java.io.InputStream; import java.io.OutputStream; import java.util.Iterator; /** * Intercepts the outbound message and sets the SOAPBody and some of the SOAPHeaders */ public class ResponseInterceptor extends AbstractPhaseInterceptor<Message> { private static final Logger logger = Logger.getLogger(ResponseInterceptor.class); public ResponseInterceptor() { super(Phase.PRE_STREAM); addBefore(SoapPreProtocolOutInterceptor.class.getName()); } /** * Handles the outbound response to the client * * @param message Response message * @throws org.apache.cxf.interceptor.Fault */ public void handleMessage(Message message) throws Fault { boolean isOutbound; isOutbound = message == message.getExchange().getOutMessage() || message == message.getExchange().getOutFaultMessage(); //If the response came through Synapse, it is handled here if (Boolean.TRUE.equals(message.get(RMConstants.CXF_RM_SYNAPSE_MEDIATED)) && isOutbound) { OutputStream os = message.getContent(OutputStream.class); CachedOutputStream cs = new CachedOutputStream(); message.setContent(OutputStream.class, cs); /* * Executes the interceptors in the interceptor chain following this interceptor, * and then returns to this. */ message.getInterceptorChain().doIntercept(message); CachedOutputStream cashedOutputStream = null; InputStream replaceInStream = null; try { cs.flush(); cashedOutputStream = (CachedOutputStream) message.getContent(OutputStream.class); //Create the SOAPEnvelope of the response generated by CXF SOAPEnvelope cxfOutEnvelope = SOAPEnvelopeCreator.getSOAPEnvelopeFromStream(cashedOutputStream.getInputStream()); cashedOutputStream.flush(); //Merge the CXF generated response and the response from the backend service SOAPEnvelope result = changeOutboundMessage(cxfOutEnvelope, message); replaceInStream = org.apache.commons.io.IOUtils.toInputStream(result.toString(), "UTF-8"); IOUtils.copy(replaceInStream, os); os.flush(); message.setContent(OutputStream.class, os); } catch (IOException ioe) { logger.error("Error while processing the response message through the response interceptor", ioe); throw new Fault(new Exception("Error while processing the response")); } finally { org.apache.commons.io.IOUtils.closeQuietly(cs); org.apache.commons.io.IOUtils.closeQuietly(cashedOutputStream); org.apache.commons.io.IOUtils.closeQuietly(os); org.apache.commons.io.IOUtils.closeQuietly(replaceInStream); } } } /** * Sets the SOAPBody of the SOAPEnvelope that comes from the endpoint (originalEnvelope) to * the SOAPBody of the * SOAPEnvelope created by CXF. Then adds the headers from the originalEnvelope to the * SOAPEnvelope created by CXF * * @param cxfOutEnvelope SOAPEnvelope created by CXF * @param message CXF out message * @return The modified SOAPEnvelope */ private SOAPEnvelope changeOutboundMessage(SOAPEnvelope cxfOutEnvelope, Message message) { SOAPEnvelope originalEnvelope = (SOAPEnvelope) message.get(RMConstants.SOAP_ENVELOPE); SOAPHeader soapHeader = originalEnvelope.getHeader(); if (soapHeader != null) { Iterator it = soapHeader.examineAllHeaderBlocks(); //Add the SOAPHeaders of the originalEnvelope to the cxfOutEnvelope if (it != null) { while (it.hasNext()) { SOAPHeaderBlock block = (SOAPHeaderBlock) it.next(); QName name = block.getQName(); /* * If the cxfOutEnvelope already has those headers, they will be replaced */ OMElement existingHeader = cxfOutEnvelope.getHeader().getFirstChildWithName(name); if (existingHeader != null) { existingHeader.detach(); } cxfOutEnvelope.getHeader().addChild(block); } } } try { OMElement originalResponseBody = originalEnvelope.getBody().getFirstElement(); if (originalResponseBody != null) { PayloadHelper.setXMLPayload(cxfOutEnvelope, originalResponseBody); } } catch (Exception e) { logger.error( "Could not merge the CXF generated response body and response body sent from the back end service", e); } return cxfOutEnvelope; } }