1 /* 2 * $Id: DefaultMuleEventContext.java 11433 2008-03-20 03:43:57Z dirk.olmes $ 3 * -------------------------------------------------------------------------------------- 4 * Copyright (c) MuleSource, Inc. All rights reserved. http://www.mulesource.com 5 * 6 * The software in this package is published under the terms of the CPAL v1.0 7 * license, a copy of which has been included with this distribution in the 8 * LICENSE.txt file. 9 */ 10 11 package org.mule; 12 13 import org.mule.api.FutureMessageResult; 14 import org.mule.api.MuleContext; 15 import org.mule.api.MuleEvent; 16 import org.mule.api.MuleEventContext; 17 import org.mule.api.MuleException; 18 import org.mule.api.MuleMessage; 19 import org.mule.api.MuleSession; 20 import org.mule.api.config.MuleProperties; 21 import org.mule.api.endpoint.EndpointURI; 22 import org.mule.api.endpoint.InboundEndpoint; 23 import org.mule.api.endpoint.OutboundEndpoint; 24 import org.mule.api.service.Service; 25 import org.mule.api.transaction.Transaction; 26 import org.mule.api.transaction.TransactionException; 27 import org.mule.api.transformer.TransformerException; 28 import org.mule.config.i18n.CoreMessages; 29 import org.mule.transaction.TransactionCoordination; 30 31 import java.io.OutputStream; 32 33 import edu.emory.mathcs.backport.java.util.concurrent.Callable; 34 35 import org.apache.commons.logging.Log; 36 import org.apache.commons.logging.LogFactory; 37 38 /** 39 * <code>DefaultMuleEventContext</code> is the context object for the current request. 40 * Using the context, developers can send/dispatch/receive events programmatically as 41 * well as manage transactions. 42 */ 43 public class DefaultMuleEventContext implements MuleEventContext 44 { 45 /** 46 * logger used by this class 47 */ 48 protected static final Log logger = LogFactory.getLog(DefaultMuleEventContext.class); 49 50 private final MuleEvent event; 51 private final MuleSession session; 52 53 public DefaultMuleEventContext(MuleEvent event) 54 { 55 this.event = event; 56 this.session = event.getSession(); 57 } 58 59 /** 60 * Returns the message payload for this event 61 * 62 * @return the message payload for this event 63 */ 64 public MuleMessage getMessage() 65 { 66 return event.getMessage(); 67 } 68 69 /** 70 * Reterns the conents of the message as a byte array. 71 * 72 * @return the conents of the message as a byte array 73 * @throws org.mule.api.MuleException if the message cannot be converted into an 74 * array of bytes 75 */ 76 public byte[] getMessageAsBytes() throws MuleException 77 { 78 return event.getMessageAsBytes(); 79 } 80 81 /** 82 * Returns the message transformed into it's recognised or expected format. The 83 * transformer used is the one configured on the endpoint through which this 84 * event was received. 85 * 86 * @return the message transformed into it's recognised or expected format. 87 * @throws org.mule.api.transformer.TransformerException if a failure occurs in 88 * the transformer 89 * @see org.mule.api.transformer.Transformer 90 */ 91 public Object transformMessage() throws TransformerException 92 { 93 return event.transformMessage(); 94 } 95 96 /** 97 * Returns the message transformed into its recognised or expected format. The 98 * transformer used is the one configured on the endpoint through which this 99 * event was received. 100 * 101 * @param expectedType The class type required for the return object. This param 102 * just provides a convienient way to manage type casting of 103 * transformed objects 104 * @return the message transformed into it's recognised or expected format. 105 * @throws org.mule.api.transformer.TransformerException if a failure occurs or 106 * if the return type is not the same as the expected type in the 107 * transformer 108 * @see org.mule.api.transformer.Transformer 109 */ 110 public Object transformMessage(Class expectedType) throws TransformerException 111 { 112 return event.transformMessage(expectedType); 113 } 114 115 /** 116 * Returns the message transformed into it's recognised or expected format and 117 * then into an array of bytes. The transformer used is the one configured on the 118 * endpoint through which this event was received. 119 * 120 * @return the message transformed into it's recognised or expected format as an 121 * array of bytes. 122 * @throws org.mule.api.transformer.TransformerException if a failure occurs in 123 * the transformer 124 * @see org.mule.api.transformer.Transformer 125 */ 126 public byte[] transformMessageToBytes() throws TransformerException 127 { 128 return event.transformMessageToBytes(); 129 } 130 131 /** 132 * Returns the message contents as a string 133 * 134 * @return the message contents as a string 135 * @throws org.mule.api.MuleException if the message cannot be converted into a 136 * string 137 */ 138 public String getMessageAsString(String encoding) throws MuleException 139 { 140 return event.getMessageAsString(encoding); 141 } 142 143 /** 144 * Returns the message transformed into it's recognised or expected format and 145 * then into a String. The transformer used is the one configured on the endpoint 146 * through which this event was received. This method will use the default 147 * encoding on the event 148 * 149 * @return the message transformed into it's recognised or expected format as a 150 * Strings. 151 * @throws org.mule.api.transformer.TransformerException if a failure occurs in 152 * the transformer 153 * @see org.mule.api.transformer.Transformer 154 */ 155 public String transformMessageToString() throws TransformerException 156 { 157 return event.transformMessageToString(); 158 } 159 160 /** 161 * Returns the message contents as a string This method will use the default 162 * encoding on the event 163 * 164 * @return the message contents as a string 165 * @throws org.mule.api.MuleException if the message cannot be converted into a 166 * string 167 */ 168 public String getMessageAsString() throws MuleException 169 { 170 return event.getMessageAsString(); 171 } 172 173 /** 174 * Returns the current transaction (if any) for the session 175 * 176 * @return the current transaction for the session or null if there is no 177 * transaction in progress 178 */ 179 public Transaction getCurrentTransaction() 180 { 181 return TransactionCoordination.getInstance().getTransaction(); 182 } 183 184 public void markTransactionForRollback() throws TransactionException 185 { 186 if (getCurrentTransaction() != null) 187 { 188 getCurrentTransaction().setRollbackOnly(); 189 } 190 } 191 192 /** 193 * This will send an event via the configured outbound router on the service 194 * 195 * @param message the message to send 196 * @return the result of the send if any 197 * @throws org.mule.api.MuleException if there is no outbound endpoint configured 198 * on the service or the events fails during dispatch 199 */ 200 public MuleMessage sendEvent(Object message) throws MuleException 201 { 202 return sendEvent(new DefaultMuleMessage(message, event.getMessage())); 203 } 204 205 /** 206 * Depending on the session state this methods either Passes an event 207 * synchronously to the next available Mule UMO in the pool or via the endpoint 208 * configured for the event 209 * 210 * @param message the event message payload to send 211 * @param endpoint The endpoint to disptch the event through. 212 * @return the return Message from the call or null if there was no result 213 * @throws org.mule.api.MuleException if the event fails to be processed by the 214 * service or the transport for the endpoint 215 */ 216 public MuleMessage sendEvent(MuleMessage message, OutboundEndpoint endpoint) throws MuleException 217 { 218 // If synchronous receive has not been explicitly set, default it to true 219 setRemoteSync(message, endpoint); 220 return session.sendEvent(message, endpoint); 221 } 222 223 /** 224 * Depending on the session state this methods either Passes an event 225 * synchronously to the next available Mule UMO in the pool or via the endpoint 226 * configured for the event 227 * 228 * @param message the message payload to send 229 * @return the return Message from the call or null if there was no result 230 * @throws org.mule.api.MuleException if the event fails to be processed by the 231 * service or the transport for the endpoint 232 */ 233 public MuleMessage sendEvent(MuleMessage message) throws MuleException 234 { 235 // If synchronous receive has not been explicitly set, default it to 236 // true 237 setRemoteSync(message, (OutboundEndpoint) event.getEndpoint()); 238 return session.sendEvent(message); 239 } 240 241 /** 242 * Depending on the session state this methods either Passes an event 243 * synchronously to the next available Mule UMO in the pool or via the 244 * endpointUri configured for the event 245 * 246 * @param message the event message payload to send 247 * @param endpointUri The endpointUri to disptch the event through 248 * @return the return Message from the call or null if there was no result 249 * @throws org.mule.api.MuleException if the event fails to be processed by the 250 * service or the transport for the endpointUri 251 */ 252 public MuleMessage sendEvent(MuleMessage message, EndpointURI endpointUri) throws MuleException 253 { 254 OutboundEndpoint endpoint = 255 getMuleContext().getRegistry().lookupEndpointFactory().getOutboundEndpoint(endpointUri); 256 257 // If synchronous receive has not been explicitly set, default it to 258 // true 259 setRemoteSync(message, endpoint); 260 return session.sendEvent(message, endpoint); 261 } 262 263 /** 264 * sends an event request via the configured outbound router for this service. 265 * This method return immediately, but the result of the event invocation 266 * available from the returned a Future result that can be accessed later by the 267 * the returned FutureMessageResult. the Future messageResult can be queried at 268 * any time to check that the invocation has completed. A timeout is associated 269 * with the invocation, which is the maximum time in milli-seconds that the 270 * invocation should take to complete 271 * 272 * @param message the object that is the payload of the event 273 * @param timeout how long to block in milliseconds waiting for a result 274 * @return the result message if any of the invocation 275 * @throws org.mule.api.MuleException if the dispatch fails or the components or 276 * transfromers cannot be found 277 * @see org.mule.api.FutureMessageResult 278 */ 279 public FutureMessageResult sendEventAsync(final Object message, final int timeout) throws MuleException 280 { 281 Callable callable = new Callable() 282 { 283 public Object call() throws Exception 284 { 285 MuleMessage umoMessage = new DefaultMuleMessage(message, event.getMessage()); 286 umoMessage.setBooleanProperty(MuleProperties.MULE_REMOTE_SYNC_PROPERTY, true); 287 umoMessage.setIntProperty(MuleProperties.MULE_EVENT_TIMEOUT_PROPERTY, timeout); 288 return sendEvent(umoMessage); 289 } 290 }; 291 292 FutureMessageResult result = new FutureMessageResult(callable); 293 // TODO MULE-732: use injected ExecutorService 294 result.execute(); 295 return result; 296 } 297 298 /** 299 * sends an event request via the configured outbound router for this service. 300 * This method return immediately, but the result of the event invocation 301 * available from the returned a Future result that can be accessed later by the 302 * the returned FutureMessageResult. the Future messageResult can be queried at 303 * any time to check that the invocation has completed. A timeout is associated 304 * with the invocation, which is the maximum time in milli-seconds that the 305 * invocation should take to complete 306 * 307 * @param message the MuleMessage of the event 308 * @param timeout how long to block in milliseconds waiting for a result 309 * @return the result message if any of the invocation 310 * @throws org.mule.api.MuleException if the dispatch fails or the components or 311 * transfromers cannot be found 312 * @see org.mule.api.FutureMessageResult 313 */ 314 public FutureMessageResult sendEventAsync(final MuleMessage message, final int timeout) 315 throws MuleException 316 { 317 Callable callable = new Callable() 318 { 319 public Object call() throws Exception 320 { 321 message.setBooleanProperty(MuleProperties.MULE_REMOTE_SYNC_PROPERTY, true); 322 message.setIntProperty(MuleProperties.MULE_EVENT_TIMEOUT_PROPERTY, timeout); 323 return sendEvent(message); 324 } 325 }; 326 327 FutureMessageResult result = new FutureMessageResult(callable); 328 // TODO MULE-732: use injected ExecutorService 329 result.execute(); 330 return result; 331 } 332 333 /** 334 * sends an event request via the configured outbound router for this service. 335 * This method return immediately, but the result of the event invocation 336 * available from the returned a Future result that can be accessed later by the 337 * the returned FutureMessageResult. the Future messageResult can be queried at 338 * any time to check that the invocation has completed. A timeout is associated 339 * with the invocation, which is the maximum time in milli-seconds that the 340 * invocation should take to complete 341 * 342 * @param message the MuleMessage of the event 343 * @param endpointUri the endpointUri to dispatch to 344 * @param timeout how long to block in milliseconds waiting for a result 345 * @return the result message if any of the invocation 346 * @throws org.mule.api.MuleException if the dispatch fails or the components or 347 * transfromers cannot be found 348 * @see org.mule.api.FutureMessageResult 349 */ 350 public FutureMessageResult sendEventAsync(final MuleMessage message, 351 final EndpointURI endpointUri, 352 final int timeout) throws MuleException 353 { 354 Callable callable = new Callable() 355 { 356 public Object call() throws Exception 357 { 358 message.setBooleanProperty(MuleProperties.MULE_REMOTE_SYNC_PROPERTY, true); 359 message.setIntProperty(MuleProperties.MULE_EVENT_TIMEOUT_PROPERTY, timeout); 360 return sendEvent(message, endpointUri); 361 } 362 }; 363 364 FutureMessageResult result = new FutureMessageResult(callable); 365 // TODO MULE-732: use injected ExecutorService 366 result.execute(); 367 return result; 368 } 369 370 /** 371 * sends an event request via the configured outbound router for this service. 372 * This method return immediately, but the result of the event invocation 373 * available from the returned a Future result that can be accessed later by the 374 * the returned FutureMessageResult. the Future messageResult can be queried at 375 * any time to check that the invocation has completed. A timeout is associated 376 * with the invocation, which is the maximum time in milli-seconds that the 377 * invocation should take to complete 378 * 379 * @param message the MuleMessage of the event 380 * @param endpointName The endpoint name to disptch the event through. This will 381 * be looked up first on the service configuration and then on the 382 * mule manager configuration 383 * @param timeout how long to block in milliseconds waiting for a result 384 * @return the result message if any of the invocation 385 * @throws org.mule.api.MuleException if the dispatch fails or the components or 386 * transfromers cannot be found 387 * @see org.mule.api.FutureMessageResult 388 */ 389 public FutureMessageResult sendEventAsync(final MuleMessage message, 390 final String endpointName, 391 final int timeout) throws MuleException 392 { 393 Callable callable = new Callable() 394 { 395 public Object call() throws Exception 396 { 397 message.setBooleanProperty(MuleProperties.MULE_REMOTE_SYNC_PROPERTY, true); 398 message.setIntProperty(MuleProperties.MULE_EVENT_TIMEOUT_PROPERTY, timeout); 399 return sendEvent(message, endpointName); 400 } 401 }; 402 403 FutureMessageResult result = new FutureMessageResult(callable); 404 // TODO MULE-732: use injected ExecutorService 405 result.execute(); 406 return result; 407 } 408 409 /** 410 * Depending on the session state this methods either Passes an event 411 * synchronously to the next available Mule UMO in the pool or via the endpoint 412 * configured for the event 413 * 414 * @param message the event message payload to send 415 * @param endpointName The endpoint name to disptch the event through. This will 416 * be looked up first on the service configuration and then on the 417 * mule manager configuration 418 * @return the return Message from the call or null if there was no result 419 * @throws org.mule.api.MuleException if the event fails to be processed by the 420 * service or the transport for the endpoint 421 */ 422 public MuleMessage sendEvent(MuleMessage message, String endpointName) throws MuleException 423 { 424 OutboundEndpoint endpoint = RegistryContext.getRegistry().lookupEndpointFactory().getOutboundEndpoint(endpointName); 425 setRemoteSync(message, endpoint); 426 return session.sendEvent(message, endpoint); 427 } 428 429 /** 430 * This will dispatch an event asynchronously via the configured outbound 431 * endpoint on the service for this session 432 * 433 * @param message payload to dispatch 434 * @throws org.mule.api.MuleException if there is no outbound endpoint configured 435 * on the service or the events fails during dispatch 436 */ 437 public void dispatchEvent(Object message) throws MuleException 438 { 439 session.dispatchEvent(new DefaultMuleMessage(message, event.getMessage())); 440 } 441 442 /** 443 * This will dispatch an event asynchronously via the configured outbound 444 * endpoint on the service for this session 445 * 446 * @param message the message to send 447 * @throws org.mule.api.MuleException if there is no outbound endpoint configured 448 * on the service or the events fails during dispatch 449 */ 450 public void dispatchEvent(MuleMessage message) throws MuleException 451 { 452 session.dispatchEvent(message); 453 } 454 455 /** 456 * Depending on the session state this methods either Passes an event 457 * asynchronously to the next available Mule UMO in the pool or via the 458 * endpointUri configured for the event 459 * 460 * @param message the event message payload to send 461 * @param endpointUri the endpointUri to dispatc the event to first on the 462 * service configuration and then on the mule manager configuration 463 * @throws org.mule.api.MuleException if the event fails to be processed by the 464 * service or the transport for the endpointUri 465 */ 466 public void dispatchEvent(MuleMessage message, EndpointURI endpointUri) throws MuleException 467 { 468 OutboundEndpoint endpoint = 469 getMuleContext().getRegistry().lookupEndpointFactory().getOutboundEndpoint(endpointUri); 470 session.dispatchEvent(message, endpoint); 471 } 472 473 /** 474 * Depending on the session state this methods either Passes an event 475 * asynchronously to the next available Mule UMO in the pool or via the endpoint 476 * configured for the event 477 * 478 * @param message the event message payload to send 479 * @param endpointName The endpoint name to disptch the event through. This will 480 * be looked up first on the service configuration and then on the 481 * mule manager configuration 482 * @throws org.mule.api.MuleException if the event fails to be processed by the 483 * service or the transport for the endpoint 484 */ 485 public void dispatchEvent(MuleMessage message, String endpointName) throws MuleException 486 { 487 session.dispatchEvent(message, endpointName); 488 } 489 490 /** 491 * Depending on the session state this methods either Passes an event 492 * asynchronously to the next available Mule UMO in the pool or via the endpoint 493 * configured for the event 494 * 495 * @param message the event message payload to send 496 * @param endpoint The endpoint name to disptch the event through. 497 * @throws org.mule.api.MuleException if the event fails to be processed by the 498 * service or the transport for the endpoint 499 */ 500 public void dispatchEvent(MuleMessage message, OutboundEndpoint endpoint) throws MuleException 501 { 502 session.dispatchEvent(message, endpoint); 503 } 504 505 /** 506 * Requests a synchronous receive of an event on the service 507 * 508 * @param endpoint the endpoint identifing the endpointUri on ewhich the event 509 * will be received 510 * @param timeout time in milliseconds before the request timesout 511 * @return The requested event or null if the request times out 512 * @throws org.mule.api.MuleException if the request operation fails 513 */ 514 public MuleMessage requestEvent(InboundEndpoint endpoint, long timeout) throws MuleException 515 { 516 return session.requestEvent(endpoint, timeout); 517 } 518 519 /** 520 * Requests a synchronous receive of an event on the service 521 * 522 * @param endpointName the endpoint identifing the endpointUri on ewhich the 523 * event will be received 524 * @param timeout time in milliseconds before the request timesout 525 * @return The requested event or null if the request times out 526 * @throws org.mule.api.MuleException if the request operation fails 527 */ 528 public MuleMessage requestEvent(String endpointName, long timeout) throws MuleException 529 { 530 return session.requestEvent(endpointName, timeout); 531 } 532 533 /** 534 * Requests a synchronous receive of an event on the service 535 * 536 * @param endpointUri the endpointUri on which the event will be received 537 * @param timeout time in milliseconds before the request timesout 538 * @return The requested event or null if the request times out 539 * @throws org.mule.api.MuleException if the request operation fails 540 */ 541 public MuleMessage requestEvent(EndpointURI endpointUri, long timeout) throws MuleException 542 { 543 InboundEndpoint endpoint = 544 getMuleContext().getRegistry().lookupEndpointFactory().getInboundEndpoint(endpointUri); 545 return session.requestEvent(endpoint, timeout); 546 } 547 548 /** 549 * @return the service descriptor of the service that received this event 550 */ 551 public Service getService() 552 { 553 return event.getService(); 554 } 555 556 /** 557 * Determines whether the default processing for this event will be executed. By 558 * default, the Mule server will route events according to a components 559 * configuration. The user can override this behaviour by obtaining a reference 560 * to the MuleEvent context, either by implementing 561 * <code>org.mule.api.lifecycle.Callable</code> or calling 562 * <code>RequestContext.getEventContext</code> to obtain the MuleEventContext for 563 * the current thread. The user can programmatically control how events are 564 * dispatched. 565 * 566 * @return Returns true is the user has set stopFurtherProcessing. 567 * @see org.mule.api.MuleEventContext 568 * @see org.mule.api.lifecycle.Callable 569 */ 570 public boolean isStopFurtherProcessing() 571 { 572 return RequestContext.getEvent().isStopFurtherProcessing(); 573 } 574 575 /** 576 * Determines whether the default processing for this event will be executed. By 577 * default, the Mule server will route events according to a components 578 * configuration. The user can override this behaviour by obtaining a reference 579 * to the MuleEvent context, either by implementing 580 * <code>org.mule.api.lifecycle.Callable</code> or calling 581 * <code>UMOManager.getEventContext</code> to obtain the MuleEventContext for 582 * the current thread. The user can programmatically control how events are 583 * dispached. 584 * 585 * @param stopFurtherProcessing the value to set. 586 */ 587 public void setStopFurtherProcessing(boolean stopFurtherProcessing) 588 { 589 event.setStopFurtherProcessing(stopFurtherProcessing); 590 } 591 592 /** 593 * An outputstream the can optionally be used write response data to an incoming 594 * message. 595 * 596 * @return an output stream if one has been made available by the message receiver 597 * that received the message 598 */ 599 public OutputStream getOutputStream() 600 { 601 return event.getOutputStream(); 602 } 603 604 /** 605 * Determines whether the was sent synchrounously or not 606 * 607 * @return true if the event is synchronous 608 */ 609 public boolean isSynchronous() 610 { 611 return event.isSynchronous(); 612 } 613 614 public EndpointURI getEndpointURI() 615 { 616 return event.getEndpoint().getEndpointURI(); 617 } 618 619 /** 620 * Returns the transaction for the current event or null if there is no 621 * transaction in progresss 622 * 623 * @return the transaction for the current event or null if there is no 624 * transaction in progresss 625 */ 626 public Transaction getTransaction() 627 { 628 return TransactionCoordination.getInstance().getTransaction(); 629 } 630 631 /** 632 * Get the timeout value associated with the event 633 * 634 * @return the timeout for the event 635 */ 636 public int getTimeout() 637 { 638 return event.getTimeout(); 639 } 640 641 private void setRemoteSync(MuleMessage message, OutboundEndpoint endpoint) 642 { 643 if (endpoint.isRemoteSync()) 644 { 645 if (getTransaction() == null) 646 { 647 message.setBooleanProperty(MuleProperties.MULE_REMOTE_SYNC_PROPERTY, true); 648 } 649 else 650 { 651 throw new IllegalStateException( 652 CoreMessages.cannotUseTxAndRemoteSync().getMessage()); 653 } 654 } 655 } 656 657 /** 658 * Gets the encoding for the current message. For potocols that send encoding 659 * Information with the message, this method should be overriden to expose the 660 * transport encoding, otherwise the default encoding in the Mule configuration 661 * will be used 662 * 663 * @return the encoding for this message. This method must never return null 664 */ 665 public String getEncoding() 666 { 667 return event.getEncoding(); 668 } 669 670 public MuleSession getSession() 671 { 672 return event.getSession(); 673 } 674 675 public String toString() 676 { 677 return event.toString(); 678 } 679 680 public MuleContext getMuleContext() 681 { 682 return event.getMuleContext(); 683 } 684 685 }