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