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.components.util;
018    
019    import javax.jbi.JBIException;
020    import javax.jbi.messaging.DeliveryChannel;
021    import javax.jbi.messaging.ExchangeStatus;
022    import javax.jbi.messaging.Fault;
023    import javax.jbi.messaging.InOnly;
024    import javax.jbi.messaging.InOut;
025    import javax.jbi.messaging.MessageExchange;
026    import javax.jbi.messaging.MessageExchangeFactory;
027    import javax.jbi.messaging.MessagingException;
028    import javax.jbi.servicedesc.ServiceEndpoint;
029    import javax.xml.namespace.QName;
030    
031    import org.apache.servicemix.MessageExchangeListener;
032    import org.apache.servicemix.jbi.MissingPropertyException;
033    import org.apache.servicemix.jbi.NoServiceAvailableException;
034    
035    /**
036     * This component acts as an InOnly component which pipelines a request/response (InOut) to a service
037     * then forwards the response onto an InOut component.
038     *
039     * @version $Revision: 564374 $
040     */
041    public class PipelineComponent extends ComponentSupport implements MessageExchangeListener {
042        private ServiceEndpoint requestResponseEndpoint;
043        private ServiceEndpoint outputEndpoint;
044        private QName requestResponseServiceName;
045        private QName outputEndpointServiceName;
046    
047        public PipelineComponent() {
048        }
049    
050        public PipelineComponent(QName service, String endpoint) {
051            super(service, endpoint);
052        }
053    
054        public void start() throws JBIException {
055            super.start();
056    
057            if (requestResponseEndpoint == null) {
058                if (requestResponseServiceName == null) {
059                    throw new MissingPropertyException("requestResponseServiceName");
060                }
061                requestResponseEndpoint = chooseEndpoint(requestResponseServiceName);
062    
063            }
064            if (outputEndpoint == null) {
065                if (outputEndpointServiceName == null) {
066                    throw new MissingPropertyException("outputEndpointServiceName");
067                }
068                outputEndpoint = chooseEndpoint(outputEndpointServiceName);
069            }
070        }
071    
072        public void onMessageExchange(MessageExchange exchange) throws MessagingException {
073            // Skip done exchanges
074            if (exchange.getStatus() == ExchangeStatus.DONE) {
075                return;
076            // Handle error exchanges
077            } else if (exchange.getStatus() == ExchangeStatus.ERROR) {
078                return;
079            }
080    
081            // lets create an endpoint
082            DeliveryChannel deliveryChannel = getDeliveryChannel();
083            MessageExchangeFactory rpcFactory = deliveryChannel.createExchangeFactory(requestResponseEndpoint);
084            InOut rpc = rpcFactory.createInOutExchange();
085            rpc.setInMessage(exchange.getMessage("in"));
086            boolean answer = deliveryChannel.sendSync(rpc);
087    
088            MessageExchangeFactory outputFactory = deliveryChannel.createExchangeFactory(outputEndpoint);
089            InOnly inOnly = outputFactory.createInOnlyExchange();
090    
091            if (answer) {
092                inOnly.setInMessage(rpc.getOutMessage());
093                deliveryChannel.send(inOnly);
094                done(exchange);
095            } else if (!(exchange instanceof InOnly)) {
096                inOnly.setError(rpc.getError());
097                Fault fault = rpc.getFault();
098                fail(exchange, fault);
099            } else {
100                // terminate the exchange
101                done(exchange);
102            }
103            done(rpc);
104        }
105    
106        // Properties
107        //-------------------------------------------------------------------------
108        public ServiceEndpoint getRequestResponseEndpoint() {
109            return requestResponseEndpoint;
110        }
111    
112        public void setRequestResponseEndpoint(ServiceEndpoint requestResponseEndpoint) {
113            this.requestResponseEndpoint = requestResponseEndpoint;
114        }
115    
116        public ServiceEndpoint getOutputEndpoint() {
117            return outputEndpoint;
118        }
119    
120        public void setOutputEndpoint(ServiceEndpoint outputEndpoint) {
121            this.outputEndpoint = outputEndpoint;
122        }
123    
124        public QName getRequestResponseServiceName() {
125            return requestResponseServiceName;
126        }
127    
128        public void setRequestResponseServiceName(QName requestResponseServiceName) {
129            this.requestResponseServiceName = requestResponseServiceName;
130        }
131    
132        public QName getOutputEndpointServiceName() {
133            return outputEndpointServiceName;
134        }
135    
136        public void setOutputEndpointServiceName(QName outputEndpointServiceName) {
137            this.outputEndpointServiceName = outputEndpointServiceName;
138        }
139    
140        // Implementation methods
141        //-------------------------------------------------------------------------
142    
143        /**
144         * Resolves the given service endpoint reference from a serviceName
145         *
146         * @param serviceName is the name of the service
147         * @return the service endpoint
148         * @throws JBIException if the service cannot be resolved
149         */
150        protected ServiceEndpoint chooseEndpoint(QName serviceName) throws JBIException {
151            ServiceEndpoint[] endpoints = getContext().getEndpointsForService(serviceName);
152            if (endpoints == null || endpoints.length == 0) {
153                throw new NoServiceAvailableException(serviceName);
154            }
155            // TODO how should we choose?
156            return endpoints[0];
157        }
158    
159    }