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.bean.support;
018    
019    import java.net.URI;
020    
021    import javax.annotation.PostConstruct;
022    import javax.jbi.messaging.ExchangeStatus;
023    import javax.jbi.messaging.Fault;
024    import javax.jbi.messaging.MessageExchange;
025    import javax.jbi.messaging.MessagingException;
026    import javax.jbi.messaging.NormalizedMessage;
027    
028    import org.apache.servicemix.common.JbiConstants;
029    import org.apache.servicemix.common.util.MessageUtil;
030    import org.apache.servicemix.jbi.listener.MessageExchangeListener;
031    import org.apache.servicemix.jbi.transformer.CopyTransformer;
032    import org.apache.servicemix.store.Store;
033    import org.apache.servicemix.store.StoreFactory;
034    import org.apache.servicemix.store.memory.MemoryStoreFactory;
035    
036    /**
037     * A useful base class for a transform component.
038     *
039     * @version $Revision: 62449 $
040     */
041    public abstract class TransformBeanSupport extends BeanSupport implements MessageExchangeListener {
042        
043        private String correlation;
044        
045        private ExchangeTarget target;
046    
047        private boolean copyProperties = true;
048        private boolean copyAttachments = true;
049        private StoreFactory storeFactory;
050        private Store store;
051    
052        protected TransformBeanSupport() {
053        }
054    
055        // Getters / Setters
056        //-------------------------------------------------------------------------
057    
058        public ExchangeTarget getTarget() {
059            return target;
060        }
061    
062        public void setTarget(ExchangeTarget target) {
063            this.target = target;
064        }
065    
066        public boolean isCopyProperties() {
067            return copyProperties;
068        }
069    
070    
071        public void setCopyProperties(boolean copyProperties) {
072            this.copyProperties = copyProperties;
073            if (getMessageTransformer() instanceof CopyTransformer) {
074                ((CopyTransformer) getMessageTransformer()).setCopyProperties(copyProperties);
075            }
076        }
077    
078    
079        public boolean isCopyAttachments() {
080            return copyAttachments;
081        }
082    
083    
084        public void setCopyAttachments(boolean copyAttachments) {
085            this.copyAttachments = copyAttachments;
086            if (getMessageTransformer() instanceof CopyTransformer) {
087                ((CopyTransformer) getMessageTransformer()).setCopyAttachments(copyAttachments);
088            }
089        }
090    
091        public StoreFactory getStoreFactory() {
092            return storeFactory;
093        }
094    
095        public void setStoreFactory(StoreFactory storeFactory) {
096            this.storeFactory = storeFactory;
097        }
098    
099        public Store getStore() {
100            return store;
101        }
102    
103        public void setStore(Store store) {
104            this.store = store;
105        }
106    
107        // Implementation methods
108        //-------------------------------------------------------------------------
109    
110        @PostConstruct
111        public void initialize() throws Exception {
112            if (store == null) {
113                if (storeFactory == null) {
114                    storeFactory = new MemoryStoreFactory();
115                }
116                store = storeFactory.open(getService().toString() + getEndpoint());
117            }
118            correlation = "TransformBeanSupport.Correlation." + getService() + "." + getEndpoint();
119        }
120    
121        public void onMessageExchange(MessageExchange exchange) throws MessagingException {
122            // Handle consumer exchanges && non-active RobustInOnly provider exchanges
123            if (exchange.getRole() == MessageExchange.Role.CONSUMER
124                    || exchange.getProperty(correlation) != null) {
125                processOngoingExchange(exchange);
126            } else {
127                processFirstExchange(exchange);
128            }
129        }
130    
131        protected void processFirstExchange(MessageExchange exchange) {
132            try {
133                MessageExchange outExchange = null;
134                NormalizedMessage in = getInMessage(exchange);
135                NormalizedMessage out;
136                if (isInAndOut(exchange)) {
137                    out = exchange.createMessage();
138                } else {
139                    URI pattern = exchange.getPattern();
140                    if (target == null) {
141                        throw new IllegalStateException("A TransformBean with MEP " + pattern + " has no Target specified");
142                    }
143                    outExchange = getExchangeFactory().createExchange(pattern);
144                    target.configureTarget(outExchange, getContext());
145                    outExchange.setProperty(JbiConstants.SENDER_ENDPOINT, getService() + ":" + getEndpoint());
146                    // Set correlations
147                    outExchange.setProperty(correlation, exchange.getExchangeId());
148                    exchange.setProperty(correlation, outExchange.getExchangeId());
149                    String processCorrelationId = (String)exchange.getProperty(JbiConstants.CORRELATION_ID);
150                    if (processCorrelationId != null) {
151                        outExchange.setProperty(JbiConstants.CORRELATION_ID, processCorrelationId);
152                    }
153                    out = outExchange.createMessage();
154                }
155                boolean txSync = exchange.isTransacted() && Boolean.TRUE.equals(exchange.getProperty(JbiConstants.SEND_SYNC));
156                copyPropertiesAndAttachments(exchange, in, out);
157                if (transform(exchange, in, out)) {
158                    if (isInAndOut(exchange)) {
159                        exchange.setMessage(out, "out");
160                        if (txSync) {
161                            sendSync(exchange);
162                        } else {
163                            send(exchange);
164                        }
165                    } else {
166                        outExchange.setMessage(out, "in");
167                        if (txSync) {
168                            sendSync(outExchange);
169                            if (outExchange.getStatus() == ExchangeStatus.DONE) {
170                                done(exchange);
171                            } else if (outExchange.getStatus() == ExchangeStatus.ERROR) {
172                                fail(exchange, outExchange.getError());
173                            } else if (outExchange.getFault() != null) {
174                                Fault fault = MessageUtil.copyFault(outExchange);
175                                done(outExchange);
176                                MessageUtil.transferToFault(fault, exchange);
177                                sendSync(exchange);
178                            } else {
179                                done(outExchange);
180                                throw new IllegalStateException("Exchange status is " + ExchangeStatus.ACTIVE
181                                        + " but has no Out nor Fault message");
182                            }
183                        } else {
184                            store.store(exchange.getExchangeId(), exchange);
185                            try {
186                                send(outExchange);
187                            } catch (Exception e) {
188                                store.load(exchange.getExchangeId());
189                                throw e;
190                            }
191                        }
192                    }
193                } else {
194                    exchange.setStatus(ExchangeStatus.DONE);
195                    send(exchange);
196                }
197            } catch (Exception e) {
198                try {
199                    fail(exchange, e);
200                } catch (Exception e2) {
201                    logger.warn("Unable to handle error: " + e2, e2);
202                    if (logger.isDebugEnabled()) {
203                        logger.debug("Original error: " + e, e);
204                    }
205                }
206            }
207        }
208    
209        protected void processOngoingExchange(MessageExchange exchange) {
210            MessageExchange original = null;
211            String id = null;
212            try {
213                id = (String) exchange.getProperty(correlation);
214                original = (MessageExchange) store.load(id);
215            } catch (Exception e) {
216                // We can't do, so just return
217                return;
218            }
219            try {
220                if (exchange.getStatus() == ExchangeStatus.DONE) {
221                    done(original);
222                // Reproduce ERROR status to the other side
223                } else if (exchange.getStatus() == ExchangeStatus.ERROR) {
224                    fail(original, exchange.getError());
225                // Reproduce faults to the other side and listeners
226                } else if (exchange.getFault() != null) {
227                    store.store(exchange.getExchangeId(), exchange);
228                    try {
229                        MessageUtil.transferTo(exchange, original, "fault");
230                        send(original);
231                    } catch (Exception e) {
232                        store.load(exchange.getExchangeId());
233                        throw e;
234                    }
235                // Reproduce answers to the other side
236                } else if (exchange.getMessage("out") != null) {
237                    store.store(exchange.getExchangeId(), exchange);
238                    try {
239                        MessageUtil.transferTo(exchange, original, "out");
240                        send(original);
241                    } catch (Exception e) {
242                        store.load(exchange.getExchangeId());
243                        throw e;
244                    }
245                } else {
246                    throw new IllegalStateException("Exchange status is " + ExchangeStatus.ACTIVE
247                            + " but has no Out nor Fault message");
248                }
249            } catch (Exception e) {
250                if (logger.isDebugEnabled()) {
251                    logger.debug("Original error: " + e, e);
252                }
253            }
254        }
255    
256    
257        /**
258         * Transforms the given out message
259         */
260        protected abstract boolean transform(MessageExchange exchange, NormalizedMessage in, NormalizedMessage out) throws Exception;
261    
262    
263        /**
264         * If enabled the properties and attachments are copied to the destination message
265         */
266        protected void copyPropertiesAndAttachments(MessageExchange exchange, NormalizedMessage in, 
267                                                    NormalizedMessage out) throws MessagingException {
268            if (isCopyProperties()) {
269                CopyTransformer.copyProperties(in, out);
270            }
271            if (isCopyAttachments()) {
272                CopyTransformer.copyAttachments(in, out);
273            }
274        }
275    
276    }