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.interceptors;
018    
019    import javax.xml.namespace.QName;
020    import javax.xml.stream.XMLStreamReader;
021    
022    import org.apache.cxf.attachment.LazyAttachmentCollection;
023    import org.apache.cxf.binding.soap.model.SoapBindingInfo;
024    import org.apache.cxf.binding.soap.model.SoapBodyInfo;
025    import org.apache.cxf.endpoint.Endpoint;
026    import org.apache.cxf.interceptor.Fault;
027    import org.apache.cxf.interceptor.URIMappingInterceptor;
028    import org.apache.cxf.message.Message;
029    import org.apache.cxf.phase.AbstractPhaseInterceptor;
030    import org.apache.cxf.phase.Phase;
031    import org.apache.cxf.service.model.BindingMessageInfo;
032    import org.apache.cxf.service.model.BindingOperationInfo;
033    import org.apache.cxf.service.model.OperationInfo;
034    import org.apache.cxf.service.model.ServiceModelUtil;
035    import org.apache.cxf.staxutils.DepthXMLStreamReader;
036    import org.apache.cxf.staxutils.StaxUtils;
037    
038    
039    public class JbiOperationInterceptor extends AbstractPhaseInterceptor<Message> {
040    
041            
042        public JbiOperationInterceptor() {
043            super(Phase.UNMARSHAL);
044            addAfter(URIMappingInterceptor.class.getName());
045        }
046    
047        public void handleMessage(Message message) {
048            loadAttachments(message);
049            if (isGET(message)) {
050                return;
051            }
052            if (message.getExchange().get(BindingOperationInfo.class) != null) {
053                return;
054            }
055            
056            DepthXMLStreamReader xmlReader = getXMLStreamReader(message);
057            
058            BindingOperationInfo operation = null;
059            if (!StaxUtils.toNextElement(xmlReader)) {
060                message.setContent(Exception.class, new RuntimeException(
061                        "There must be a method name element."));
062            }
063            String opName = xmlReader.getLocalName();
064            if (isRequestor(message) && opName.endsWith("Response")) {
065                opName = opName.substring(0, opName.length() - 8);
066            }
067            QName opQName = new QName(xmlReader.getNamespaceURI(), opName);
068            SoapBindingInfo binding = (SoapBindingInfo) message.getExchange().get(
069                    Endpoint.class).getEndpointInfo().getBinding();
070            for (BindingOperationInfo op : binding.getOperations()) {
071                String style = binding.getStyle(op.getOperationInfo());
072                if (style == null) {
073                    style = binding.getStyle();
074                }
075                if ("document".equals(style)) {
076                    BindingMessageInfo msg = !isRequestor(message) ? op.getInput()
077                            : op.getOutput();
078                    if (msg.getExtensor(SoapBodyInfo.class)
079                                .getParts().get(0).getElementQName().equals(opQName)) {
080                        operation = op;
081                        break;
082                    }
083                } else {
084                    if (opQName.equals(op.getName())) {
085                        operation = op;
086                        break;
087                    }
088                }
089            }
090            if (operation != null) {
091                message.getExchange().put(BindingOperationInfo.class, operation);
092                message.getExchange().put(OperationInfo.class,
093                        operation.getOperationInfo());
094                message.getExchange().setOneWay(operation.getOperationInfo().isOneWay());
095            }
096        }
097    
098        private void loadAttachments(Message message) {
099            //get chance to cache the attachments
100            if (message.getAttachments() != null) {
101                LazyAttachmentCollection attachments = (LazyAttachmentCollection) message.getAttachments();
102                attachments.size();
103            }
104        }
105    
106        protected DepthXMLStreamReader getXMLStreamReader(Message message) {
107            
108            XMLStreamReader xr = message.getContent(XMLStreamReader.class);
109            if (xr instanceof DepthXMLStreamReader) {
110                return (DepthXMLStreamReader) xr;
111            }
112            DepthXMLStreamReader dr = new DepthXMLStreamReader(xr);
113            message.setContent(XMLStreamReader.class, dr);
114            return dr;
115        }
116    
117        protected BindingOperationInfo getOperation(Message message, QName opName) {
118            BindingOperationInfo op = ServiceModelUtil.getOperation(message
119                    .getExchange(), opName);
120            if (op == null) {
121                throw new Fault(new Exception("Unrecognized operation"));
122            }
123            return op;
124        }
125    
126        protected boolean isRequestor(Message message) {
127            return Boolean.TRUE.equals(message.get(Message.REQUESTOR_ROLE));
128        }
129    
130    }