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 java.util.Iterator;
020    import java.util.Set;
021    
022    import javax.jbi.messaging.ExchangeStatus;
023    import javax.jbi.messaging.InOut;
024    import javax.jbi.messaging.MessageExchange;
025    import javax.jbi.messaging.MessagingException;
026    import javax.jbi.messaging.NormalizedMessage;
027    import javax.xml.namespace.QName;
028    
029    import org.apache.servicemix.jbi.FaultException;
030    
031    /**
032     * This class allows a series of componeents to be chained together. It will
033     * invoke the first service, then take the output of that first service as the
034     * input to the next service, and return the overall results when finished.
035     * 
036     * All properties and attachments are maintained.
037     * 
038     * @author birchfieldj
039     * @deprecated use the StaticRoutingSlip pattern from the EIP component instead
040     * 
041     */
042    public class ChainedComponent extends TransformComponentSupport {
043    
044        private QName[] services = new QName[0];
045    
046        protected boolean transform(MessageExchange exchange, 
047                                    NormalizedMessage in,
048                                    NormalizedMessage out) throws MessagingException {
049            NormalizedMessage curIn = in;
050            MessageExchange curExchange = exchange;
051            for (int i = 0; i < services.length; i++) {
052                InOut mexchange = this.getDeliveryChannel()
053                        .createExchangeFactoryForService(services[i])
054                        .createInOutExchange();
055                copyProperties(curExchange, mexchange);
056                curIn = invokeService(mexchange, curIn, services[i]);
057                curExchange = mexchange;
058            }
059            getMessageTransformer().transform(exchange, curIn, out);
060            copyProperties(curExchange, exchange);
061            return true;
062        }
063    
064        /**
065         * Invokes the service with the given message, and returns the output
066         * 
067         * @param exchange
068         * @param in
069         * @param service
070         * @return the out message of the invoked service
071         * @throws MessagingException
072         */
073        private NormalizedMessage invokeService(InOut exchange,
074                                                NormalizedMessage in, 
075                                                QName service) throws MessagingException {
076            NormalizedMessage msg = exchange.createMessage();
077            getMessageTransformer().transform(exchange, in, msg);
078            exchange.setMessage(msg, "in");
079            boolean result = this.getDeliveryChannel().sendSync(exchange);
080            if (result) {
081                if (exchange.getStatus() == ExchangeStatus.ERROR) {
082                    exchange.setStatus(ExchangeStatus.DONE);
083                    getDeliveryChannel().send(exchange);
084                    if (exchange.getError() != null) {
085                        throw new MessagingException("Received error", exchange.getError());
086                    } else if (exchange.getFault() != null) {
087                        throw new FaultException("Received fault", exchange, exchange.getFault());
088                    } else {
089                        throw new MessagingException("Received unknown error");
090                    }
091                } else {
092                    NormalizedMessage out = exchange.getOutMessage();
093                    exchange.setStatus(ExchangeStatus.DONE);
094                    getDeliveryChannel().send(exchange);
095                    return out; 
096                }
097            }
098            throw new MessagingException("Could not invoke service: " + service);
099        }
100    
101        /**
102         * 
103         * @param in
104         *            echange to copy from
105         * @param out
106         *            excahnge to copy to
107         */
108        private void copyProperties(MessageExchange in, MessageExchange out) {
109            Set propertyNames = in.getPropertyNames();
110            for (Iterator iter = propertyNames.iterator(); iter.hasNext();) {
111                String name = (String) iter.next();
112                out.setProperty(name, in.getProperty(name));
113            }
114        }
115    
116        /**
117         * Allows the services to be set
118         * 
119         * @param services
120         *            a collection of QNAmes representing the services to be
121         *            invoked.
122         */
123        public void setServices(QName[] services) {
124            this.services = services;
125        }
126    
127    }