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