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