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.soap.interceptors.jbi;
018    
019    import java.net.URI;
020    import java.util.HashMap;
021    import java.util.Map;
022    
023    import javax.activation.DataHandler;
024    import javax.jbi.JBIException;
025    import javax.jbi.component.ComponentContext;
026    import javax.jbi.messaging.DeliveryChannel;
027    import javax.jbi.messaging.MessageExchange;
028    import javax.jbi.messaging.MessageExchangeFactory;
029    import javax.jbi.messaging.MessagingException;
030    import javax.jbi.messaging.NormalizedMessage;
031    import javax.security.auth.Subject;
032    import javax.xml.namespace.QName;
033    import javax.xml.transform.Source;
034    
035    import org.apache.servicemix.soap.api.Fault;
036    import org.apache.servicemix.soap.api.Message;
037    import org.apache.servicemix.soap.api.model.Operation;
038    import org.apache.servicemix.soap.bindings.soap.SoapFault;
039    import org.apache.servicemix.soap.core.AbstractInterceptor;
040    import org.apache.servicemix.soap.util.QNameUtil;
041    import org.w3c.dom.DocumentFragment;
042    
043    /**
044     * @author <a href="mailto:gnodet [at] gmail.com">Guillaume Nodet</a>
045     */
046    public class JbiInInterceptor extends AbstractInterceptor {
047    
048        public static final String OPERATION_MEP = "MEP";
049        
050        private final boolean server;
051        
052        public JbiInInterceptor(boolean server) {
053            this.server = server;
054        }
055        
056        public void handleMessage(Message message) {
057            try {
058                Operation operation = message.get(Operation.class);
059                MessageExchange exchange;
060                NormalizedMessage nm;
061                // Create message
062                if (server) {
063                    exchange = createExchange(message);
064                    if (operation != null) {
065                        exchange.setOperation(operation.getName());
066                    }
067                    nm = exchange.createMessage();
068                    exchange.setMessage(nm, "in");
069                    message.setContent(MessageExchange.class, exchange);
070                } else {
071                    exchange = message.getContent(MessageExchange.class);
072                    if (exchange == null) {
073                        throw new IllegalStateException("Content of type " + MessageExchange.class + " not found on message");
074                    }
075                    if (message.getContent(Exception.class) == null) {
076                        nm = exchange.getMessage("out");
077                        if (nm == null) {
078                            nm = exchange.createMessage();
079                            exchange.setMessage(nm, "out");
080                        }
081                    } else {
082                        exchange.setFault(exchange.createFault());
083                        nm = exchange.getFault();
084                    }
085                }
086                // Put headers
087                toNMSHeaders(nm, message);
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            Operation operation = message.get(Operation.class);
107            if (operation != null) {
108                mep = operation.getMep();
109            } else {
110                mep = (URI) message.get(OPERATION_MEP);
111            }
112            if (mep == null) {
113                throw new NullPointerException("MEP not found");
114            }
115            MessageExchangeFactory mef = message.get(MessageExchangeFactory.class);
116            if (mef == null) {
117                DeliveryChannel dv = message.get(DeliveryChannel.class);
118                if (dv == null) {
119                    ComponentContext cc = message.get(ComponentContext.class);
120                    if (cc == null) {
121                        throw new NullPointerException("MessageExchangeFactory or DeliveryChannel or ComponentContext not found");
122                    }
123                    dv = cc.getDeliveryChannel();
124                }
125                mef = dv.createExchangeFactory();
126            }
127            return mef.createExchange(mep);
128        }
129    
130        /**
131         * Convert SoapMessage headers to NormalizedMessage headers
132         */
133        private void toNMSHeaders(NormalizedMessage normalizedMessage, Message soapMessage) {
134            Map<String, Object> headers = new HashMap<String, Object>();
135            for (Map.Entry<QName, DocumentFragment> entry : soapMessage.getSoapHeaders().entrySet()) {
136                headers.put(QNameUtil.toString(entry.getKey()), entry.getValue());
137            }
138            headers.putAll(soapMessage.getTransportHeaders());
139            normalizedMessage.setProperty(JbiConstants.PROTOCOL_HEADERS, headers);
140        }
141    
142        /**
143         * Convert SoapMessage attachments to NormalizedMessage attachments
144         */
145        private void toNMSAttachments(NormalizedMessage normalizedMessage, Message soapMessage) throws MessagingException {
146            for (Map.Entry<String, DataHandler> entry : soapMessage.getAttachments().entrySet()) {
147                normalizedMessage.addAttachment(entry.getKey(), entry.getValue());
148            }
149        }
150    
151        /**
152         * Extract the content as a jaxp Source
153         */
154        private void getContent(NormalizedMessage nm, Message message) throws MessagingException {
155            Exception e = message.getContent(Exception.class);
156            if (e == null) {
157                nm.setContent(message.getContent(Source.class));
158            } else if (e instanceof SoapFault) {
159                SoapFault fault = (SoapFault) e;
160                nm.setContent(fault.getDetails());
161                nm.setProperty(JbiConstants.SOAP_FAULT_CODE, fault.getCode());
162                nm.setProperty(JbiConstants.SOAP_FAULT_NODE, fault.getNode());
163                nm.setProperty(JbiConstants.SOAP_FAULT_REASON, fault.getReason());
164                nm.setProperty(JbiConstants.SOAP_FAULT_ROLE, fault.getRole());
165                nm.setProperty(JbiConstants.SOAP_FAULT_SUBCODE, fault.getSubcode());
166            }
167        }
168    
169    }