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;
018
019 import java.io.ByteArrayOutputStream;
020 import java.io.IOException;
021 import java.io.InputStream;
022 import java.util.ArrayList;
023 import java.util.List;
024
025 import javax.jbi.messaging.ExchangeStatus;
026 import javax.jbi.messaging.Fault;
027 import javax.jbi.messaging.InOptionalOut;
028 import javax.jbi.messaging.InOut;
029 import javax.jbi.messaging.MessageExchange;
030 import javax.jbi.messaging.MessagingException;
031 import javax.jbi.messaging.NormalizedMessage;
032 import javax.xml.namespace.QName;
033 import javax.xml.transform.Source;
034
035 import org.apache.cxf.binding.soap.SoapMessage;
036 import org.apache.cxf.binding.soap.interceptor.MustUnderstandInterceptor;
037 import org.apache.cxf.binding.soap.interceptor.ReadHeadersInterceptor;
038 import org.apache.cxf.endpoint.Endpoint;
039 import org.apache.cxf.helpers.IOUtils;
040 import org.apache.cxf.interceptor.AttachmentInInterceptor;
041 import org.apache.cxf.interceptor.Interceptor;
042 import org.apache.cxf.interceptor.StaxInInterceptor;
043 import org.apache.cxf.io.CachedOutputStream;
044 import org.apache.cxf.message.Attachment;
045 import org.apache.cxf.message.Exchange;
046 import org.apache.cxf.message.ExchangeImpl;
047 import org.apache.cxf.message.Message;
048 import org.apache.cxf.phase.PhaseChainCache;
049 import org.apache.cxf.phase.PhaseInterceptorChain;
050 import org.apache.cxf.phase.PhaseManager;
051 import org.apache.cxf.service.model.BindingOperationInfo;
052 import org.apache.cxf.service.model.EndpointInfo;
053 import org.apache.cxf.transport.MessageObserver;
054 import org.apache.servicemix.JbiConstants;
055 import org.apache.servicemix.cxfbc.interceptors.JbiInWsdl1Interceptor;
056
057
058
059 public class CxfBcProviderMessageObserver implements MessageObserver {
060 ByteArrayOutputStream response = new ByteArrayOutputStream();
061
062 boolean written;
063
064 String contentType;
065
066 private CxfBcProvider providerEndpoint;
067
068 public CxfBcProviderMessageObserver(CxfBcProvider providerEndpoint) {
069 this.providerEndpoint = providerEndpoint;
070 }
071
072 public ByteArrayOutputStream getResponseStream() throws Exception {
073 synchronized (this) {
074 if (!written) {
075 wait(1000000000);
076 }
077 }
078 return response;
079 }
080
081 public String getResponseContentType() {
082 return contentType;
083 }
084
085 public void onMessage(Message message) {
086 try {
087 MessageExchange messageExchange = message.getExchange().get(MessageExchange.class);
088 if (messageExchange == null) {
089 // probably, that's a WS-RM Response; use the messageObserver defined in exchange
090 MessageObserver messageObserver = message.getExchange().get(MessageObserver.class);
091 if (messageObserver != null) {
092 messageObserver.onMessage(message);
093 }
094 return;
095 }
096 if (messageExchange.getStatus() != ExchangeStatus.ACTIVE) {
097 return;
098 }
099
100 contentType = (String) message.get(Message.CONTENT_TYPE);
101 SoapMessage soapMessage =
102 (SoapMessage) this.providerEndpoint.getCxfEndpoint().getBinding().createMessage(message);
103
104 EndpointInfo ei = this.providerEndpoint.getEndpointInfo();
105 QName opeName = messageExchange.getOperation();
106 BindingOperationInfo boi = null;
107 if (opeName == null) {
108 // if interface only have one operation, may not specify the opeName in MessageExchange
109 if (ei.getBinding().getOperations().size() == 1) {
110 boi = ei.getBinding().getOperations().iterator().next();
111 } else {
112 throw new org.apache.cxf.interceptor.Fault(
113 new Exception("Operation not bound on this MessageExchange"));
114
115 }
116 } else {
117 boi = ei.getBinding().getOperation(messageExchange.getOperation());
118 }
119
120 if (boi.getOperationInfo().isOneWay()) {
121 return;
122 }
123
124 soapMessage
125 .put(org.apache.cxf.message.Message.REQUESTOR_ROLE, true);
126 Exchange cxfExchange = new ExchangeImpl();
127 soapMessage.setExchange(cxfExchange);
128
129 cxfExchange.put(BindingOperationInfo.class, boi);
130 cxfExchange.put(Endpoint.class, providerEndpoint.getCxfEndpoint());
131 // create Interceptor chain
132
133 PhaseChainCache inboundChainCache = new PhaseChainCache();
134 PhaseManager pm = providerEndpoint.getBus().getExtension(
135 PhaseManager.class);
136 List<Interceptor> inList = new ArrayList<Interceptor>();
137 inList.add(new ReadHeadersInterceptor(this.providerEndpoint.getBus()));
138 inList.add(new MustUnderstandInterceptor());
139 inList.add(new StaxInInterceptor());
140 inList.add(new JbiInWsdl1Interceptor(this.providerEndpoint.isUseJBIWrapper(),
141 this.providerEndpoint.isUseSOAPEnvelope()));
142 inList.add(new AttachmentInInterceptor());
143 PhaseInterceptorChain inChain = inboundChainCache.get(pm
144 .getInPhases(), inList);
145 inChain.add(providerEndpoint.getInInterceptors());
146 inChain.add(providerEndpoint.getInFaultInterceptors());
147 inChain.add(this.providerEndpoint.getInInterceptors());
148 inChain.add(this.providerEndpoint.getInFaultInterceptors());
149 soapMessage.setInterceptorChain(inChain);
150 inChain.doIntercept(soapMessage);
151 closeConnectionStream(soapMessage);
152 setMessageStatus(soapMessage, boi, messageExchange);
153 boolean txSync = messageExchange.getStatus() == ExchangeStatus.ACTIVE
154 && messageExchange.isTransacted()
155 && Boolean.TRUE.equals(messageExchange
156 .getProperty(JbiConstants.SEND_SYNC));
157 if (txSync) {
158 providerEndpoint.getContext().getDeliveryChannel().sendSync(
159 messageExchange);
160 } else {
161 providerEndpoint.getContext().getDeliveryChannel().send(
162 messageExchange);
163 }
164
165 } catch (Exception e) {
166 e.printStackTrace();
167 } finally {
168 synchronized (this) {
169 written = true;
170 notifyAll();
171 }
172 }
173 }
174
175 private void closeConnectionStream(SoapMessage soapMessage) throws IOException {
176 InputStream is = soapMessage.getContent(InputStream.class);
177 if (is != null) {
178 CachedOutputStream bos = new CachedOutputStream();
179 IOUtils.copy(is, bos);
180
181 bos.flush();
182 is.close();
183
184 soapMessage.setContent(InputStream.class, bos.getInputStream());
185
186 bos.close();
187 }
188
189 }
190
191 private void setMessageStatus(SoapMessage soapMessage, BindingOperationInfo boi, MessageExchange messageExchange)
192 throws MessagingException {
193 if (boi.getOperationInfo().isOneWay()) {
194 messageExchange.setStatus(ExchangeStatus.DONE);
195 } else if (soapMessage.get("jbiFault") != null
196 && soapMessage.get("jbiFault").equals(true)) {
197 Fault fault = messageExchange.createFault();
198 fault.setContent(soapMessage.getContent(Source.class));
199 messageExchange.setFault(fault);
200 if (soapMessage.get("faultstring") != null) {
201 messageExchange.setProperty("faultstring", soapMessage.get("faultstring"));
202 }
203 if (soapMessage.get("faultcode") != null) {
204 messageExchange.setProperty("faultcode", soapMessage.get("faultcode"));
205 }
206 if (soapMessage.get("hasdetail") != null) {
207 messageExchange.setProperty("hasdetail", soapMessage.get("hasdetail"));
208 }
209 } else if (messageExchange instanceof InOut) {
210 NormalizedMessage msg = messageExchange.createMessage();
211 msg.setContent(soapMessage.getContent(Source.class));
212 toNMSAttachments(msg, soapMessage);
213 messageExchange.setMessage(msg, "out");
214 } else if (messageExchange instanceof InOptionalOut) {
215 if (soapMessage.getContent(Source.class) != null) {
216 NormalizedMessage msg = messageExchange.createMessage();
217 msg.setContent(soapMessage.getContent(Source.class));
218 toNMSAttachments(msg, soapMessage);
219 messageExchange.setMessage(msg, "out");
220 } else {
221 messageExchange.setStatus(ExchangeStatus.DONE);
222 }
223 } else {
224 messageExchange.setStatus(ExchangeStatus.DONE);
225
226 }
227 }
228
229 private void toNMSAttachments(NormalizedMessage normalizedMessage,
230 Message soapMessage) throws MessagingException {
231 if (soapMessage.getAttachments() != null) {
232 for (Attachment att : soapMessage.getAttachments()) {
233 normalizedMessage.addAttachment(att.getId(), att
234 .getDataHandler());
235 }
236 }
237 }
238
239 }