/* * 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; import org.apache.axiom.soap.SOAPEnvelope; import org.apache.axiom.util.UIDGenerator; import org.apache.axis2.AxisFault; import org.apache.axis2.Constants; import org.apache.axis2.context.ConfigurationContext; import org.apache.axis2.context.OperationContext; import org.apache.axis2.context.ServiceContext; import org.apache.axis2.description.InOutAxisOperation; import org.apache.axis2.transport.TransportUtils; import org.apache.cxf.continuations.Continuation; import org.apache.cxf.message.Exchange; import org.apache.cxf.message.Message; import org.apache.cxf.transport.http.AbstractHTTPDestination; import org.apache.log4j.Logger; import org.apache.synapse.MessageContext; import org.apache.synapse.SynapseConstants; import org.apache.synapse.core.axis2.MessageContextCreatorForAxis2; import org.apache.synapse.inbound.InboundEndpointConstants; import org.apache.synapse.mediators.MediatorFaultHandler; import org.apache.synapse.mediators.base.SequenceMediator; import org.eclipse.jetty.http.HttpURI; import org.eclipse.jetty.server.Request; import org.wso2.carbon.core.multitenancy.utils.TenantAxisUtils; import org.wso2.carbon.inbound.endpoint.osgi.service.ServiceReferenceHolder; import org.wso2.carbon.inbound.endpoint.ext.wsrm.utils.RMConstants; import org.wso2.carbon.utils.multitenancy.MultitenantConstants; import org.wso2.carbon.utils.multitenancy.MultitenantUtils; import javax.xml.stream.XMLStreamException; import java.io.ByteArrayInputStream; import java.util.Enumeration; import java.util.HashMap; import java.util.Map; import java.util.concurrent.Callable; /** * Extracts the message from the CXF Exchange */ public class RMRequestCallable implements Callable<Boolean> { private static final Logger logger = Logger.getLogger(RMRequestCallable.class); private Exchange exchange; private Continuation continuation; private String injectingSequence; private String onErrorSequence; private Map<String, String> httpHeaders; private String receiver; private InboundRMResponseSender inboundRMResponseSender; public RMRequestCallable(Exchange exchange, Continuation continuation, String injectingSequence, String onErrorSequence, InboundRMResponseSender inboundRMResponseSender) { this.setExchange(exchange); this.setContinuation(continuation); this.setInjectingSequence(injectingSequence); this.setOnErrorSequence(onErrorSequence); this.inboundRMResponseSender = inboundRMResponseSender; this.httpHeaders = new HashMap<String, String>(); } @Override public Boolean call() throws Exception { Message message = getExchange().getInMessage(); //Extract the HttpServletRequest from the message Request request = (Request) message.get(AbstractHTTPDestination.HTTP_REQUEST); Enumeration headerNames = request.getHeaderNames(); //Extract the HTTP headers while (headerNames.hasMoreElements()) { String headerName = (String) headerNames.nextElement(); String headerValue = request.getHeader(headerName); getHttpHeaders().put(headerName, headerValue); } setReceiver(request.getRequestURL().toString()); byte[] bytes = (byte[]) message.get(RMConstants.CXF_RM_MESSAGE_PAYLOAD); return injectToSynapse(request, bytes); } /** * Creates the SynapseMessageContext and injects the message in to Synapse for mediation * @param request The HttpServletRequest * @param bytes Request in bytes * @return success * @throws org.apache.axis2.AxisFault */ private boolean injectToSynapse(Request request, byte[] bytes) throws AxisFault { String contentType = request.getContentType(); MessageContext msgCtx = createMessageContext(request.getUri()); org.apache.axis2.context.MessageContext axis2MsgCtx = ((org.apache.synapse.core.axis2.Axis2MessageContext) msgCtx).getAxis2MessageContext(); boolean isSuccess; try { msgCtx.setWSAAction(getHttpHeaders().get(RMConstants.SOAP_ACTION)); setMessageContextProperties(contentType, request.getCharacterEncoding() , msgCtx); SOAPEnvelope soapEnvelope = TransportUtils.createSOAPMessage(axis2MsgCtx, new ByteArrayInputStream(bytes), contentType); msgCtx.setEnvelope(soapEnvelope); msgCtx.getConfiguration(); if (getInjectingSequence() == null || "".equals(getInjectingSequence())) { logger.error("Sequence name not specified. Sequence : " + getInjectingSequence()); isSuccess = false; } else { SequenceMediator seq = (SequenceMediator) msgCtx.getSequence(getInjectingSequence()); if (seq != null) { SequenceMediator faultSequence = (SequenceMediator) msgCtx.getSequence(getOnErrorSequence()); MediatorFaultHandler mediatorFaultHandler = new MediatorFaultHandler(faultSequence); msgCtx.pushFaultHandler(mediatorFaultHandler); if (logger.isDebugEnabled()) { logger.debug("injecting message to sequence : " + getInjectingSequence()); } msgCtx.getEnvironment().injectMessage(msgCtx, seq); isSuccess = true; } else { logger.error("Sequence: " + getInjectingSequence() + " not found"); isSuccess = false; } } return isSuccess; } catch (AxisFault axisFault) { logger.error("Error occurred when injecting the incoming request to Synapse", axisFault); return false; } catch (XMLStreamException e) { logger.error("Error occurred when extracting the SOAPEnvelope from the request", e); return false; } } /** * Sets properties in the MessageContext * * @param contentType request content type * @param characterEncoding character encoding of the request * @param msgCtx MessageContext */ private void setMessageContextProperties(String contentType, String characterEncoding, MessageContext msgCtx) { msgCtx.setProperty(Constants.Configuration.CONTENT_TYPE, contentType); msgCtx.setProperty(Constants.Configuration.CHARACTER_SET_ENCODING, characterEncoding); msgCtx.setProperty(SynapseConstants.IS_CXF_WS_RM, Boolean.TRUE); msgCtx.setProperty(RMConstants.CXF_CONTINUATION, getContinuation()); msgCtx.setProperty(RMConstants.CXF_EXCHANGE, getExchange()); msgCtx.setProperty(SynapseConstants.IS_INBOUND, Boolean.TRUE); msgCtx.setProperty(InboundEndpointConstants.INBOUND_ENDPOINT_RESPONSE_WORKER, inboundRMResponseSender); } /** * Creates a Synapse MessageContext from the request details * * @return Synapse MessageContext * @param uri the uri, the request was sent to */ private MessageContext createMessageContext(HttpURI uri) throws AxisFault { String tenantDomain = getTenantDomain(uri.toString()); // Create super tenant message context org.apache.axis2.context.MessageContext axis2MsgCtx = createAxis2MessageContext(); ServiceContext svcCtx = new ServiceContext(); OperationContext opCtx = new OperationContext(new InOutAxisOperation(), svcCtx); axis2MsgCtx.setServiceContext(svcCtx); axis2MsgCtx.setOperationContext(opCtx); // If not super tenant, assign tenant configuration context if (!tenantDomain.equals(MultitenantConstants.SUPER_TENANT_DOMAIN_NAME)) { ConfigurationContext tenantConfigCtx = TenantAxisUtils.getTenantConfigurationContext(tenantDomain, axis2MsgCtx.getConfigurationContext()); axis2MsgCtx.setConfigurationContext(tenantConfigCtx); axis2MsgCtx.setProperty(MultitenantConstants.TENANT_DOMAIN, tenantDomain); } return MessageContextCreatorForAxis2.getSynapseMessageContext(axis2MsgCtx); } /** * Creates an Axis2 MessageContext instance * @return Axis2 Message Context */ private static org.apache.axis2.context.MessageContext createAxis2MessageContext() { org.apache.axis2.context.MessageContext axis2MsgCtx = new org.apache.axis2.context.MessageContext(); axis2MsgCtx.setMessageID(UIDGenerator.generateURNString()); axis2MsgCtx.setConfigurationContext(ServiceReferenceHolder.getInstance().getConfigurationContextService() .getServerConfigContext()); // Axis2 spawns a new thread to send a message if this is TRUE axis2MsgCtx.setProperty(org.apache.axis2.context.MessageContext.CLIENT_API_NON_BLOCKING, Boolean.FALSE); axis2MsgCtx.setServerSide(true); return axis2MsgCtx; } /** * * @param uri uri of the request * @return the tenant domain from the uri */ private String getTenantDomain(String uri) { String tenant = MultitenantUtils.getTenantDomainFromUrl(uri); if (tenant.equals(uri)) { return MultitenantConstants.SUPER_TENANT_DOMAIN_NAME; } return tenant; } public Exchange getExchange() { return exchange; } public final void setExchange(Exchange exchange) { this.exchange = exchange; } public Continuation getContinuation() { return continuation; } public final void setContinuation(Continuation continuation) { this.continuation = continuation; } public String getInjectingSequence() { return injectingSequence; } public final void setInjectingSequence(String injectingSequence) { this.injectingSequence = injectingSequence; } public String getOnErrorSequence() { return onErrorSequence; } public final void setOnErrorSequence(String onErrorSequence) { this.onErrorSequence = onErrorSequence; } public Map<String, String> getHttpHeaders() { return httpHeaders; } public String getReceiver() { return receiver; } public final void setReceiver(String receiver) { this.receiver = receiver; } }