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 javax.annotation.Resource;
020 import javax.jbi.component.ComponentContext;
021 import javax.jbi.messaging.DeliveryChannel;
022 import javax.jbi.messaging.ExchangeStatus;
023 import javax.jbi.messaging.Fault;
024 import javax.jbi.messaging.InOnly;
025 import javax.jbi.messaging.InOptionalOut;
026 import javax.jbi.messaging.InOut;
027 import javax.jbi.messaging.MessageExchange;
028 import javax.jbi.messaging.MessageExchangeFactory;
029 import javax.jbi.messaging.MessagingException;
030 import javax.jbi.messaging.NormalizedMessage;
031 import javax.jbi.messaging.RobustInOnly;
032 import javax.jbi.servicedesc.ServiceEndpoint;
033 import javax.management.ObjectName;
034 import javax.xml.namespace.QName;
035
036 import org.apache.commons.logging.Log;
037 import org.apache.commons.logging.LogFactory;
038 import org.apache.servicemix.JbiConstants;
039 import org.apache.servicemix.components.util.CopyTransformer;
040 import org.apache.servicemix.components.util.MessageHelper;
041 import org.apache.servicemix.components.util.MessageTransformer;
042 import org.apache.servicemix.jbi.FaultException;
043 import org.apache.servicemix.jbi.NoInMessageAvailableException;
044
045 /**
046 * A useful base class for servicemix-bean POJOs
047 *
048 * @version $$
049 */
050 public abstract class BeanSupport {
051
052 protected Log logger = LogFactory.getLog(getClass());
053
054 @Resource
055 private ComponentContext context;
056
057 @Resource
058 private DeliveryChannel channel;
059
060 @Resource
061 private ServiceEndpoint serviceEndpoint;
062
063 private ObjectName extensionMBeanName;
064 private MessageExchangeFactory exchangeFactory;
065 private MessageTransformer messageTransformer = CopyTransformer.getInstance();
066
067 protected BeanSupport() {
068 }
069
070 // Helper methods
071 //-------------------------------------------------------------------------
072
073 /**
074 * A helper method to return the body of the message as a POJO which could be a
075 * bean or some DOMish model of the body.
076 *
077 * @param message the message on which to extract the body
078 * @return the body of the message as a POJO or DOM object
079 * @throws MessagingException
080 */
081 public Object getBody(NormalizedMessage message) throws MessagingException {
082 return MessageHelper.getBody(message);
083 }
084
085 /**
086 * Sets the body of the message as a POJO
087 *
088 * @param message the message on which to set the body
089 * @param body the POJO or DOMish model to set
090 * @throws MessagingException
091 */
092 public void setBody(NormalizedMessage message, Object body) throws MessagingException {
093 MessageHelper.setBody(message, body);
094 }
095
096
097 // Properties
098 //-------------------------------------------------------------------------
099 public ObjectName getExtensionMBeanName() {
100 return extensionMBeanName;
101 }
102
103 public void setExtensionMBeanName(ObjectName extensionMBeanName) {
104 this.extensionMBeanName = extensionMBeanName;
105 }
106
107 public ComponentContext getContext() {
108 return context;
109 }
110
111 public void setContext(ComponentContext context) {
112 this.context = context;
113 }
114
115 public ServiceEndpoint getServiceEndpoint() {
116 return serviceEndpoint;
117 }
118
119 public void setServiceEndpoint(ServiceEndpoint serviceEndpoint) {
120 this.serviceEndpoint = serviceEndpoint;
121 }
122
123 /**
124 * Provide access to the default message exchange exchangeFactory, lazily creating one.
125 */
126 public MessageExchangeFactory getExchangeFactory() throws MessagingException {
127 if (exchangeFactory == null && context != null) {
128 exchangeFactory = getDeliveryChannel().createExchangeFactory();
129 }
130 return exchangeFactory;
131 }
132
133 public DeliveryChannel getDeliveryChannel() throws MessagingException {
134 if (channel == null) {
135 channel = context.getDeliveryChannel();
136 }
137 return channel;
138 }
139
140 /**
141 * A helper method to indicate that the message exchange is complete
142 * which will set the status to {@link ExchangeStatus#DONE} and send the message
143 * on the delivery channel.
144 *
145 * @param exchange
146 * @throws MessagingException
147 */
148 public void done(MessageExchange exchange) throws MessagingException {
149 exchange.setStatus(ExchangeStatus.DONE);
150 getDeliveryChannel().send(exchange);
151 }
152
153 public void send(MessageExchange exchange) throws MessagingException {
154 getDeliveryChannel().send(exchange);
155 }
156
157 public boolean sendSync(MessageExchange exchange) throws MessagingException {
158 return getDeliveryChannel().sendSync(exchange);
159 }
160
161 public boolean sendSync(MessageExchange exchange, long timeMillis) throws MessagingException {
162 return getDeliveryChannel().sendSync(exchange, timeMillis);
163 }
164
165 /**
166 * A helper method to indicate that the message exchange should be
167 * continued with the given response and send the message
168 * on the delivery channel.
169 *
170 * @param exchange
171 * @throws MessagingException
172 */
173 public void answer(MessageExchange exchange, NormalizedMessage answer) throws MessagingException {
174 exchange.setMessage(answer, "out");
175 getDeliveryChannel().send(exchange);
176 }
177
178 /**
179 * A helper method which fails and completes the given exchange with the specified fault
180 */
181 public void fail(MessageExchange exchange, Fault fault) throws MessagingException {
182 if (exchange instanceof InOnly || fault == null) {
183 exchange.setError(new FaultException("Fault occured for in-only exchange", exchange, fault));
184 } else {
185 exchange.setFault(fault);
186 }
187 getDeliveryChannel().send(exchange);
188 }
189
190 /**
191 * A helper method which fails and completes the given exchange with the specified error
192 * @throws MessagingException
193 */
194 public void fail(MessageExchange exchange, Exception error) throws MessagingException {
195 if (exchange instanceof InOnly || !(error instanceof FaultException)) {
196 exchange.setError(error);
197 } else {
198 FaultException faultException = (FaultException) error;
199 exchange.setFault(faultException.getFault());
200 }
201 getDeliveryChannel().send(exchange);
202 }
203
204
205 /**
206 * A helper method which will return true if the exchange is capable of both In and Out such as InOut,
207 * InOptionalOut etc.
208 *
209 * @param exchange
210 * @return true if the exchange can handle both input and output
211 */
212 protected boolean isInAndOut(MessageExchange exchange) {
213 return exchange instanceof InOut || exchange instanceof InOptionalOut;
214 }
215
216 /**
217 * Returns the in message or throws an exception if there is no in message.
218 */
219 protected NormalizedMessage getInMessage(MessageExchange exchange) throws NoInMessageAvailableException {
220 NormalizedMessage message = exchange.getMessage("in");
221 if (message == null) {
222 throw new NoInMessageAvailableException(exchange);
223 }
224 return message;
225 }
226
227 public MessageTransformer getMessageTransformer() {
228 return messageTransformer;
229 }
230
231 public void setMessageTransformer(MessageTransformer transformer) {
232 this.messageTransformer = transformer;
233 }
234
235 /**
236 * Performs an invocation where the service, operation or interface name could be specified
237 *
238 * @param exchange
239 * @param in
240 * @param service
241 * @param interfaceName
242 * @param operation
243 */
244 public void invoke(MessageExchange exchange, NormalizedMessage in,
245 QName service, QName interfaceName, QName operation) throws MessagingException {
246 InOnly outExchange = createInOnlyExchange(service, interfaceName, operation);
247 forwardToExchange(exchange, outExchange, in, operation);
248 }
249
250 /**
251 * Creates a new InOnly exchange for the given service, interface and/or operation (any of which can be null).
252 */
253 public InOnly createInOnlyExchange(QName service, QName interfaceName, QName operation) throws MessagingException {
254 MessageExchangeFactory factory = null;
255 if (service != null) {
256 factory = getDeliveryChannel().createExchangeFactoryForService(service);
257 } else if (interfaceName != null) {
258 factory = getDeliveryChannel().createExchangeFactory(interfaceName);
259 } else {
260 factory = getExchangeFactory();
261 }
262 InOnly outExchange = factory.createInOnlyExchange();
263 if (service != null) {
264 outExchange.setService(service);
265 }
266 if (interfaceName != null) {
267 outExchange.setInterfaceName(interfaceName);
268 }
269 if (operation != null) {
270 outExchange.setOperation(operation);
271 }
272 return outExchange;
273 }
274
275 public InOnly createInOnlyExchange(QName service, QName interfaceName,
276 QName operation, MessageExchange beforeExchange) throws MessagingException {
277 InOnly inOnly = createInOnlyExchange(service, interfaceName, operation);
278 propagateCorrelationId(beforeExchange, inOnly);
279 return inOnly;
280 }
281
282 /**
283 * Creates a new InOut exchange for the given service, interface and/or operation (any of which can be null).
284 */
285 public InOut createInOutExchange(QName service, QName interfaceName, QName operation) throws MessagingException {
286 MessageExchangeFactory factory = null;
287 if (service != null) {
288 factory = getDeliveryChannel().createExchangeFactoryForService(service);
289 } else if (interfaceName != null) {
290 factory = getDeliveryChannel().createExchangeFactory(interfaceName);
291 } else {
292 factory = getExchangeFactory();
293 }
294 InOut outExchange = factory.createInOutExchange();
295 if (service != null) {
296 outExchange.setService(service);
297 }
298 if (interfaceName != null) {
299 outExchange.setInterfaceName(interfaceName);
300 }
301 if (operation != null) {
302 outExchange.setOperation(operation);
303 }
304 return outExchange;
305 }
306
307 public InOut createInOutExchange(QName service, QName interfaceName,
308 QName operation, MessageExchange srcExchange) throws MessagingException {
309 InOut inOut = createInOutExchange(service, interfaceName, operation);
310 propagateCorrelationId(srcExchange, inOut);
311 return inOut;
312 }
313
314 /**
315 * Creates an InOnly exchange and propagates the correlation id from the given exchange
316 * to the newly created exchange
317 * @param srcExchange
318 * @return InOnly
319 * @throws MessagingException
320 */
321 public InOnly createInOnlyExchange(MessageExchange srcExchange) throws MessagingException {
322 MessageExchangeFactory factory = getExchangeFactory();
323 InOnly inOnly = factory.createInOnlyExchange();
324
325 propagateCorrelationId(srcExchange, inOnly);
326
327 return inOnly;
328 }
329
330 /**
331 * Creates an InOptionalOut exchange and propagates the correlation id from the given exchange
332 * to the newly created exchange
333 * @param srcExchange
334 * @return InOptionalOut
335 * @throws MessagingException
336 */
337 public InOptionalOut createInOptionalOutExchange(MessageExchange srcExchange) throws MessagingException {
338 MessageExchangeFactory factory = getExchangeFactory();
339 InOptionalOut inOptionalOut = factory.createInOptionalOutExchange();
340
341 propagateCorrelationId(srcExchange, inOptionalOut);
342
343 return inOptionalOut;
344 }
345
346 /**
347 * Creates an InOut exchange and propagates the correlation id from the given exchange
348 * to the newly created exchange
349 * @param srcExchange
350 * @return InOut
351 * @throws MessagingException
352 */
353 public InOut createInOutExchange(MessageExchange srcExchange) throws MessagingException {
354 MessageExchangeFactory factory = getExchangeFactory();
355 InOut inOut = factory.createInOutExchange();
356
357 propagateCorrelationId(srcExchange, inOut);
358
359 return inOut;
360 }
361
362 /**
363 * Creates an RobustInOnly exchange and propagates the correlation id from the given exchange
364 * to the newly created exchange
365 * @param srcExchange
366 * @return RobustInOnly the created exchange
367 * @throws MessagingException
368 */
369 public RobustInOnly createRobustInOnlyExchange(MessageExchange srcExchange) throws MessagingException {
370 MessageExchangeFactory factory = getExchangeFactory();
371 RobustInOnly robustInOnly = factory.createRobustInOnlyExchange();
372
373 propagateCorrelationId(srcExchange, robustInOnly);
374
375 return robustInOnly;
376 }
377
378 /**
379 * Propagates the correlation id from an exchange to a newly created exchange
380 * @param source Exchange which already exists
381 * @param dest Newly created exchange which should get the correlation id
382 */
383 public void propagateCorrelationId(MessageExchange source, MessageExchange dest) {
384 if (source == null || dest == null) {
385 return;
386 }
387 String correlationId = (String) source.getProperty(JbiConstants.CORRELATION_ID);
388 if (correlationId != null) {
389 dest.setProperty(JbiConstants.CORRELATION_ID, correlationId);
390 } else {
391 dest.setProperty(JbiConstants.CORRELATION_ID, source.getExchangeId());
392 }
393 }
394
395 protected void forwardToExchange(MessageExchange exchange, InOnly outExchange,
396 NormalizedMessage in, QName operationName) throws MessagingException {
397 if (operationName != null) {
398 exchange.setOperation(operationName);
399 }
400 forwardToExchange(exchange, outExchange, in);
401 }
402
403 protected void forwardToExchange(MessageExchange exchange, InOnly outExchange, NormalizedMessage in) throws MessagingException {
404 NormalizedMessage out = outExchange.createMessage();
405 outExchange.setInMessage(out);
406 getMessageTransformer().transform(exchange, in, out);
407 getDeliveryChannel().send(outExchange);
408 }
409
410 protected QName getService() {
411 QName service = null;
412 if (serviceEndpoint != null) {
413 service = serviceEndpoint.getServiceName();
414 }
415 return service;
416 }
417
418 protected String getEndpoint() {
419 String endpoint = null;
420 if (serviceEndpoint != null) {
421 endpoint = serviceEndpoint.getEndpointName();
422 }
423 return endpoint;
424 }
425
426 }