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 }