001 /*
002 * Licensed to the Apache Software Foundation (ASF) under one or more
003 * contributor license agreements. See the NOTICE file distributed with
004 * this work for additional information regarding copyright ownership.
005 * The ASF licenses this file to You under the Apache License, Version 2.0
006 * (the "License"); you may not use this file except in compliance with
007 * the License. You may obtain a copy of the License at
008 *
009 * http://www.apache.org/licenses/LICENSE-2.0
010 *
011 * Unless required by applicable law or agreed to in writing, software
012 * distributed under the License is distributed on an "AS IS" BASIS,
013 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
014 * See the License for the specific language governing permissions and
015 * limitations under the License.
016 */
017 package org.apache.servicemix.soap.interceptors.jbi;
018
019 import java.net.URI;
020 import java.util.HashMap;
021 import java.util.Map;
022
023 import javax.activation.DataHandler;
024 import javax.jbi.JBIException;
025 import javax.jbi.component.ComponentContext;
026 import javax.jbi.messaging.DeliveryChannel;
027 import javax.jbi.messaging.MessageExchange;
028 import javax.jbi.messaging.MessageExchangeFactory;
029 import javax.jbi.messaging.MessagingException;
030 import javax.jbi.messaging.NormalizedMessage;
031 import javax.security.auth.Subject;
032 import javax.xml.namespace.QName;
033 import javax.xml.transform.Source;
034
035 import org.apache.servicemix.soap.api.Fault;
036 import org.apache.servicemix.soap.api.Message;
037 import org.apache.servicemix.soap.api.model.Operation;
038 import org.apache.servicemix.soap.bindings.soap.SoapFault;
039 import org.apache.servicemix.soap.core.AbstractInterceptor;
040 import org.apache.servicemix.soap.util.QNameUtil;
041 import org.w3c.dom.DocumentFragment;
042
043 /**
044 * @author <a href="mailto:gnodet [at] gmail.com">Guillaume Nodet</a>
045 */
046 public class JbiInInterceptor extends AbstractInterceptor {
047
048 public static final String OPERATION_MEP = "MEP";
049
050 private final boolean server;
051
052 public JbiInInterceptor(boolean server) {
053 this.server = server;
054 }
055
056 public void handleMessage(Message message) {
057 try {
058 Operation operation = message.get(Operation.class);
059 MessageExchange exchange;
060 NormalizedMessage nm;
061 // Create message
062 if (server) {
063 exchange = createExchange(message);
064 if (operation != null) {
065 exchange.setOperation(operation.getName());
066 }
067 nm = exchange.createMessage();
068 exchange.setMessage(nm, "in");
069 message.setContent(MessageExchange.class, exchange);
070 } else {
071 exchange = message.getContent(MessageExchange.class);
072 if (exchange == null) {
073 throw new IllegalStateException("Content of type " + MessageExchange.class + " not found on message");
074 }
075 if (message.getContent(Exception.class) == null) {
076 nm = exchange.getMessage("out");
077 if (nm == null) {
078 nm = exchange.createMessage();
079 exchange.setMessage(nm, "out");
080 }
081 } else {
082 exchange.setFault(exchange.createFault());
083 nm = exchange.getFault();
084 }
085 }
086 // Put headers
087 toNMSHeaders(nm, message);
088 // Put attachments
089 toNMSAttachments(nm, message);
090 // Put subject
091 nm.setSecuritySubject(message.get(Subject.class));
092 // Put main source
093 getContent(nm, message);
094 // Register new content
095 message.setContent(NormalizedMessage.class, nm);
096 } catch (JBIException e) {
097 throw new Fault(e);
098 }
099 }
100
101 /**
102 * Create the JBI exchange
103 */
104 private MessageExchange createExchange(Message message) throws JBIException {
105 URI mep;
106 Operation operation = message.get(Operation.class);
107 if (operation != null) {
108 mep = operation.getMep();
109 } else {
110 mep = (URI) message.get(OPERATION_MEP);
111 }
112 if (mep == null) {
113 throw new NullPointerException("MEP not found");
114 }
115 MessageExchangeFactory mef = message.get(MessageExchangeFactory.class);
116 if (mef == null) {
117 DeliveryChannel dv = message.get(DeliveryChannel.class);
118 if (dv == null) {
119 ComponentContext cc = message.get(ComponentContext.class);
120 if (cc == null) {
121 throw new NullPointerException("MessageExchangeFactory or DeliveryChannel or ComponentContext not found");
122 }
123 dv = cc.getDeliveryChannel();
124 }
125 mef = dv.createExchangeFactory();
126 }
127 return mef.createExchange(mep);
128 }
129
130 /**
131 * Convert SoapMessage headers to NormalizedMessage headers
132 */
133 private void toNMSHeaders(NormalizedMessage normalizedMessage, Message soapMessage) {
134 Map<String, Object> headers = new HashMap<String, Object>();
135 for (Map.Entry<QName, DocumentFragment> entry : soapMessage.getSoapHeaders().entrySet()) {
136 headers.put(QNameUtil.toString(entry.getKey()), entry.getValue());
137 }
138 headers.putAll(soapMessage.getTransportHeaders());
139 normalizedMessage.setProperty(JbiConstants.PROTOCOL_HEADERS, headers);
140 }
141
142 /**
143 * Convert SoapMessage attachments to NormalizedMessage attachments
144 */
145 private void toNMSAttachments(NormalizedMessage normalizedMessage, Message soapMessage) throws MessagingException {
146 for (Map.Entry<String, DataHandler> entry : soapMessage.getAttachments().entrySet()) {
147 normalizedMessage.addAttachment(entry.getKey(), entry.getValue());
148 }
149 }
150
151 /**
152 * Extract the content as a jaxp Source
153 */
154 private void getContent(NormalizedMessage nm, Message message) throws MessagingException {
155 Exception e = message.getContent(Exception.class);
156 if (e == null) {
157 nm.setContent(message.getContent(Source.class));
158 } else if (e instanceof SoapFault) {
159 SoapFault fault = (SoapFault) e;
160 nm.setContent(fault.getDetails());
161 nm.setProperty(JbiConstants.SOAP_FAULT_CODE, fault.getCode());
162 nm.setProperty(JbiConstants.SOAP_FAULT_NODE, fault.getNode());
163 nm.setProperty(JbiConstants.SOAP_FAULT_REASON, fault.getReason());
164 nm.setProperty(JbiConstants.SOAP_FAULT_ROLE, fault.getRole());
165 nm.setProperty(JbiConstants.SOAP_FAULT_SUBCODE, fault.getSubcode());
166 }
167 }
168
169 }