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    }