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.cxfbc.interceptors;
018
019 import java.net.URI;
020 import java.util.HashMap;
021 import java.util.Map;
022
023 import javax.jbi.JBIException;
024 import javax.jbi.component.ComponentContext;
025 import javax.jbi.messaging.DeliveryChannel;
026 import javax.jbi.messaging.MessageExchange;
027 import javax.jbi.messaging.MessageExchangeFactory;
028 import javax.jbi.messaging.MessagingException;
029 import javax.jbi.messaging.NormalizedMessage;
030 import javax.security.auth.Subject;
031 import javax.xml.namespace.QName;
032 import javax.xml.transform.Source;
033
034 import org.apache.cxf.binding.soap.SoapMessage;
035 import org.apache.cxf.headers.Header;
036 import org.apache.cxf.interceptor.Fault;
037 import org.apache.cxf.message.Attachment;
038 import org.apache.cxf.message.Message;
039 import org.apache.cxf.phase.AbstractPhaseInterceptor;
040 import org.apache.cxf.phase.Phase;
041 import org.apache.cxf.service.model.BindingOperationInfo;
042 import org.apache.cxf.ws.addressing.AddressingProperties;
043 import org.apache.servicemix.cxfbc.WSAUtils;
044 import org.apache.servicemix.jbi.messaging.MessageExchangeSupport;
045 import org.apache.servicemix.soap.util.QNameUtil;
046
047 /**
048 * @author <a href="mailto:gnodet [at] gmail.com">Guillaume Nodet</a>
049 */
050 public class JbiInInterceptor extends AbstractPhaseInterceptor<Message> {
051
052 public static final String OPERATION_MEP = "MEP";
053
054 public JbiInInterceptor() {
055 super(Phase.PRE_INVOKE);
056 }
057
058 public void handleMessage(Message message) {
059 try {
060 MessageExchange exchange;
061 NormalizedMessage nm;
062 // Create message
063 if (!isRequestor(message)) {
064 exchange = createExchange(message);
065 nm = exchange.createMessage();
066 exchange.setMessage(nm, "in");
067 message.setContent(MessageExchange.class, exchange);
068 } else {
069 exchange = message.getContent(MessageExchange.class);
070 if (exchange == null) {
071 throw new IllegalStateException("Content of type "
072 + MessageExchange.class + " not found on message");
073 }
074 if (message.getContent(Exception.class) == null) {
075 nm = exchange.createMessage();
076 exchange.setMessage(nm, "out");
077 } else {
078 exchange.setFault(exchange.createFault());
079 nm = exchange.getFault();
080 }
081 }
082 // Put headers
083 toNMSHeaders(nm, message);
084
085 // copy wsa headers if present
086 toNMSWSAHeaders(nm, message);
087
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 BindingOperationInfo operation = message.getExchange().get(
107 BindingOperationInfo.class);
108 if (operation != null) {
109 if (operation.getOutput() == null) {
110 mep = MessageExchangeSupport.IN_ONLY;
111 } else {
112 mep = MessageExchangeSupport.IN_OUT;
113 }
114 } else {
115 mep = (URI) message.get(OPERATION_MEP);
116 }
117 if (mep == null) {
118 throw new NullPointerException("MEP not found");
119 }
120 MessageExchangeFactory mef = message.getExchange().get(
121 MessageExchangeFactory.class);
122 if (mef == null) {
123 DeliveryChannel dv = message.getExchange().get(
124 DeliveryChannel.class);
125 if (dv == null) {
126 ComponentContext cc = message.getExchange().get(
127 ComponentContext.class);
128 if (cc == null) {
129 throw new NullPointerException(
130 "MessageExchangeFactory or DeliveryChannel or ComponentContext not found");
131 }
132 dv = cc.getDeliveryChannel();
133 }
134 mef = dv.createExchangeFactory();
135 }
136 MessageExchange me = mef.createExchange(mep);
137 me.setOperation(operation.getName());
138 return me;
139 }
140
141 private void toNMSWSAHeaders(NormalizedMessage normalizedMessage,
142 Message soapMessage) {
143 SoapMessage message = null;
144 if (!(soapMessage instanceof SoapMessage)) {
145 return;
146 } else {
147 message = (SoapMessage) soapMessage;
148 }
149
150 if (message.get(WSAUtils.WSA_HEADERS_INBOUND) != null) {
151 normalizedMessage.setProperty(WSAUtils.WSA_HEADERS_INBOUND,
152 WSAUtils.getAsMap((AddressingProperties) message
153 .get(WSAUtils.WSA_HEADERS_INBOUND)));
154 }
155
156 }
157
158 /**
159 * Convert SoapMessage headers to NormalizedMessage headers
160 */
161 private void toNMSHeaders(NormalizedMessage normalizedMessage,
162 Message soapMessage) {
163 SoapMessage message = null;
164 if (!(soapMessage instanceof SoapMessage)) {
165 return;
166 } else {
167 message = (SoapMessage) soapMessage;
168 }
169 Map<String, Object> headers = new HashMap<String, Object>();
170 QName excludeName = new QName(
171 "http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-secext-1.0.xsd",
172 "Security");
173 for (Header header : message.getHeaders()) {
174 if (!header.getName().equals(excludeName)) {
175 // We must exclude this security header since in Sun's SAAJ impl, the ElementImpl
176 // has a field which doesn't implement Serializable interface, which will cause
177 //java.io.NotSerializableException when we try to serialize the JBI message.
178 // And this security header isn't necessary inside jbi container since we have already
179 // delegate the AA to JAAS at this stage.
180 // SM-1696 track this issue
181 headers.put(QNameUtil.toString(header.getName()), header
182 .getObject());
183 }
184 }
185
186 normalizedMessage.setProperty(JbiConstants.PROTOCOL_HEADERS, headers);
187
188 }
189
190 /**
191 * Convert SoapMessage attachments to NormalizedMessage attachments
192 */
193 private void toNMSAttachments(NormalizedMessage normalizedMessage,
194 Message soapMessage) throws MessagingException {
195 if (soapMessage.getAttachments() != null) {
196 for (Attachment att : soapMessage.getAttachments()) {
197 normalizedMessage.addAttachment(att.getId(), att
198 .getDataHandler());
199 }
200 }
201 }
202
203 /**
204 * Extract the content as a jaxp Source
205 */
206 private void getContent(NormalizedMessage nm, Message message)
207 throws MessagingException {
208 Exception e = message.getContent(Exception.class);
209 if (e == null) {
210 nm.setContent(message.getContent(Source.class));
211 /*
212 * } else if (e instanceof SoapFault) { SoapFault fault =
213 * (SoapFault) e; nm.setContent(fault.getDetails());
214 * nm.setProperty(JbiConstants.SOAP_FAULT_CODE, fault.getCode());
215 * nm.setProperty(JbiConstants.SOAP_FAULT_NODE, fault.getNode());
216 * nm.setProperty(JbiConstants.SOAP_FAULT_REASON,
217 * fault.getReason()); nm.setProperty(JbiConstants.SOAP_FAULT_ROLE,
218 * fault.getRole()); nm.setProperty(JbiConstants.SOAP_FAULT_SUBCODE,
219 * fault.getSubcode());
220 */
221 }
222 }
223
224 protected boolean isRequestor(Message message) {
225 return Boolean.TRUE.equals(message.get(Message.REQUESTOR_ROLE));
226 }
227
228 }