0001: /*
0002: * $Id: MuleClient.java 11371 2008-03-15 03:12:09Z tcarlson $
0003: * --------------------------------------------------------------------------------------
0004: * Copyright (c) MuleSource, Inc. All rights reserved. http://www.mulesource.com
0005: *
0006: * The software in this package is published under the terms of the CPAL v1.0
0007: * license, a copy of which has been included with this distribution in the
0008: * LICENSE.txt file.
0009: */
0010:
0011: package org.mule.module.client;
0012:
0013: import org.mule.DefaultMuleEvent;
0014: import org.mule.DefaultMuleMessage;
0015: import org.mule.DefaultMuleSession;
0016: import org.mule.MuleServer;
0017: import org.mule.api.FutureMessageResult;
0018: import org.mule.api.MessagingException;
0019: import org.mule.api.MuleContext;
0020: import org.mule.api.MuleEvent;
0021: import org.mule.api.MuleException;
0022: import org.mule.api.MuleMessage;
0023: import org.mule.api.MuleSession;
0024: import org.mule.api.config.ConfigurationBuilder;
0025: import org.mule.api.config.ConfigurationException;
0026: import org.mule.api.config.MuleConfiguration;
0027: import org.mule.api.config.MuleProperties;
0028: import org.mule.api.context.MuleContextBuilder;
0029: import org.mule.api.endpoint.EndpointBuilder;
0030: import org.mule.api.endpoint.EndpointURI;
0031: import org.mule.api.endpoint.ImmutableEndpoint;
0032: import org.mule.api.endpoint.InboundEndpoint;
0033: import org.mule.api.endpoint.OutboundEndpoint;
0034: import org.mule.api.lifecycle.Disposable;
0035: import org.mule.api.lifecycle.InitialisationException;
0036: import org.mule.api.registry.RegistrationException;
0037: import org.mule.api.service.Service;
0038: import org.mule.api.transport.DispatchException;
0039: import org.mule.api.transport.ReceiveException;
0040: import org.mule.config.DefaultMuleConfiguration;
0041: import org.mule.config.builders.DefaultsConfigurationBuilder;
0042: import org.mule.config.i18n.CoreMessages;
0043: import org.mule.config.spring.SpringXmlConfigurationBuilder;
0044: import org.mule.context.DefaultMuleContextBuilder;
0045: import org.mule.context.DefaultMuleContextFactory;
0046: import org.mule.endpoint.EndpointURIEndpointBuilder;
0047: import org.mule.endpoint.MuleEndpointURI;
0048: import org.mule.module.client.i18n.ClientMessages;
0049: import org.mule.security.MuleCredentials;
0050: import org.mule.transformer.TransformerUtils;
0051: import org.mule.transport.AbstractConnector;
0052: import org.mule.transport.NullPayload;
0053: import org.mule.util.StringUtils;
0054:
0055: import java.util.ArrayList;
0056: import java.util.HashMap;
0057: import java.util.Iterator;
0058: import java.util.LinkedList;
0059: import java.util.List;
0060: import java.util.Map;
0061:
0062: import edu.emory.mathcs.backport.java.util.concurrent.Callable;
0063: import edu.emory.mathcs.backport.java.util.concurrent.ConcurrentHashMap;
0064: import edu.emory.mathcs.backport.java.util.concurrent.ConcurrentMap;
0065:
0066: import org.apache.commons.logging.Log;
0067: import org.apache.commons.logging.LogFactory;
0068:
0069: /**
0070: * <code>MuleClient</code> is a simple interface for Mule clients to send and
0071: * receive events from a Mule Server. In most Mule applications events are triggered
0072: * by some external occurrence such as a message being received on a queue or file
0073: * being copied to a directory. The Mule client allows the user to send and receive
0074: * events programmatically through its Api.
0075: * <p>
0076: * The client defines a EndpointURI which is used to determine how a message is
0077: * sent of received. The url defines the protocol, the endpointUri destination of the
0078: * message and optionally the endpoint to use when dispatching the event. For
0079: * example:
0080: * <p>
0081: * <code>vm://my.object</code> dispatches to a <code>my.object</code> destination
0082: * using the VM endpoint. There needs to be a global VM endpoint registered for the
0083: * message to be sent.
0084: * <p>
0085: * <code>jms://jmsProvider/orders.topic</code> dispatches a JMS message via the
0086: * globally registered jmsProvider over a topic destination called
0087: * <code>orders.topic</code>.
0088: * <p>
0089: * <code>jms://orders.topic</code> is equivalent to the above except that the
0090: * endpoint is determined by the protocol, so the first JMS endpoint is used.
0091: * <p>
0092: * Note that there must be a configured MuleManager for this client to work. It will
0093: * use the one available using <code>muleContext</code>
0094: *
0095: * @see org.mule.endpoint.MuleEndpointURI
0096: */
0097: public class MuleClient implements Disposable {
0098: /**
0099: * logger used by this class
0100: */
0101: protected static final Log logger = LogFactory
0102: .getLog(MuleClient.class);
0103:
0104: /**
0105: * the local UMOManager instance
0106: */
0107: private MuleContext muleContext;
0108:
0109: private List dispatchers = new ArrayList();
0110:
0111: private MuleCredentials user;
0112:
0113: private DefaultMuleContextFactory muleContextFactory = new DefaultMuleContextFactory();
0114:
0115: private ConcurrentMap inboundEndpointCache = new ConcurrentHashMap();
0116: private ConcurrentMap outboundEndpointCache = new ConcurrentHashMap();
0117:
0118: /**
0119: * Creates a default Mule client that will use the default serverEndpoint to
0120: * connect to a remote server instance.
0121: *
0122: * @throws MuleException
0123: */
0124: public MuleClient() throws MuleException {
0125: this (true);
0126: }
0127:
0128: public MuleClient(boolean startContext) throws MuleException {
0129: init(startContext);
0130: }
0131:
0132: public MuleClient(MuleContext context) throws MuleException {
0133: this .muleContext = context;
0134: init(false);
0135: }
0136:
0137: /**
0138: * Configures a Mule CLient instance using the the default
0139: * MuleXmlConfigurationBuilder to parse the config resources
0140: *
0141: * @param configResources a config resource location to configure this client
0142: * with
0143: * @throws ConfigurationException is there is a MuleManager instance already
0144: * running in this JVM or if the builder fails to configure the
0145: * Manager
0146: */
0147: public MuleClient(String configResources) throws MuleException {
0148: this (configResources, new SpringXmlConfigurationBuilder(
0149: configResources));
0150: }
0151:
0152: /**
0153: * Configures a new MuleClient and either uses an existing Manager running in
0154: * this JVM or creates a new empty muleContext
0155: *
0156: * @param user the username to use when connecting to a remote server instance
0157: * @param password the password for the user
0158: * @throws MuleException
0159: */
0160: public MuleClient(String user, String password)
0161: throws MuleException {
0162: init(/* startManager */true);
0163: this .user = new MuleCredentials(user, password.toCharArray());
0164: }
0165:
0166: /**
0167: * Configures a Mule Client instance
0168: *
0169: * @param configResources a config resource location to configure this client
0170: * with
0171: * @param builder the configuration builder to use
0172: * @throws ConfigurationException is there is a MuleManager instance already
0173: * running in this JVM or if the builder fails to configure the
0174: * Manager
0175: * @throws InitialisationException
0176: */
0177: public MuleClient(String configResources,
0178: ConfigurationBuilder builder)
0179: throws ConfigurationException, InitialisationException {
0180: if (builder == null) {
0181: logger
0182: .info("Builder passed in was null, using default builder: "
0183: + SpringXmlConfigurationBuilder.class
0184: .getName());
0185: builder = new SpringXmlConfigurationBuilder(configResources);
0186: }
0187: logger.info("Initializing Mule...");
0188: muleContext = muleContextFactory.createMuleContext(builder);
0189: }
0190:
0191: /**
0192: * Configures a Mule Client instance
0193: *
0194: * @param configResources a config resource location to configure this client
0195: * with
0196: * @param builder the configuration builder to use
0197: * @param user the username to use when connecting to a remote server instance
0198: * @param password the password for the user
0199: * @throws ConfigurationException is there is a MuleManager instance already
0200: * running in this JVM or if the builder fails to configure the
0201: * Manager
0202: * @throws InitialisationException
0203: */
0204: public MuleClient(String configResources,
0205: ConfigurationBuilder builder, String user, String password)
0206: throws ConfigurationException, InitialisationException {
0207: this (configResources, builder);
0208: this .user = new MuleCredentials(user, password.toCharArray());
0209: }
0210:
0211: /**
0212: * Initialises a default MuleManager for use by the client.
0213: *
0214: * @param startManager start the Mule Manager if it has not yet been initialised
0215: * @throws MuleException
0216: */
0217: private void init(boolean startManager) throws MuleException {
0218: // if we are creating a server for this client then set client mode
0219: // this will disable Admin connections by default;
0220: // If there is no local muleContext present create a default muleContext
0221: if (muleContext == null) {
0222: muleContext = MuleServer.getMuleContext();
0223: }
0224: if (muleContext == null) {
0225: logger
0226: .info("No existing ManagementContext found, creating a new Mule instance");
0227:
0228: MuleContextBuilder contextBuilder = new DefaultMuleContextBuilder();
0229: DefaultMuleConfiguration config = new DefaultMuleConfiguration();
0230: config.setClientMode(true);
0231: contextBuilder.setMuleConfiguration(config);
0232: muleContext = muleContextFactory
0233: .createMuleContext(contextBuilder);
0234: } else {
0235: logger.info("Using existing MuleContext: " + muleContext);
0236: }
0237:
0238: if (!muleContext.isStarted() && startManager == true) {
0239: logger.info("Starting Mule...");
0240: muleContext.start();
0241: }
0242: }
0243:
0244: /**
0245: * Dispatches an event asynchronously to a endpointUri via a mule server. the Url
0246: * determines where to dispathc the event to, this can be in the form of
0247: *
0248: * @param url the Mule url used to determine the destination and transport of the
0249: * message
0250: * @param payload the object that is the payload of the event
0251: * @param messageProperties any properties to be associated with the payload. In
0252: * the case of Jms you could set the JMSReplyTo property in these
0253: * properties.
0254: * @throws org.mule.api.MuleException
0255: */
0256: public void dispatch(String url, Object payload,
0257: Map messageProperties) throws MuleException {
0258: dispatch(url,
0259: new DefaultMuleMessage(payload, messageProperties));
0260: }
0261:
0262: /**
0263: * Dispatches an event asynchronously to a endpointUri via a mule server. the Url
0264: * determines where to dispathc the event to, this can be in the form of
0265: *
0266: * @param url the Mule url used to determine the destination and transport of the
0267: * message
0268: * @param message the message to send
0269: * @throws org.mule.api.MuleException
0270: */
0271: public void dispatch(String url, MuleMessage message)
0272: throws MuleException {
0273: MuleEvent event = getEvent(message, url, false, false);
0274: try {
0275: event.getSession().dispatchEvent(event);
0276: } catch (MuleException e) {
0277: throw e;
0278: } catch (Exception e) {
0279: throw new DispatchException(ClientMessages
0280: .failedToDispatchClientEvent(), event.getMessage(),
0281: event.getEndpoint(), e);
0282: }
0283: }
0284:
0285: /**
0286: * sends an event synchronously to a components
0287: *
0288: * @param component the name of the Mule components to send to
0289: * @param transformers a comma separated list of transformers to apply to the
0290: * result message
0291: * @param payload the object that is the payload of the event
0292: * @param messageProperties any properties to be associated with the payload. as
0293: * null
0294: * @return the result message if any of the invocation
0295: * @throws org.mule.api.MuleException if the dispatch fails or the components or
0296: * transfromers cannot be found
0297: */
0298: public MuleMessage sendDirect(String component,
0299: String transformers, Object payload, Map messageProperties)
0300: throws MuleException {
0301: MuleMessage message = new DefaultMuleMessage(payload,
0302: messageProperties);
0303: return sendDirect(component, transformers, message);
0304: }
0305:
0306: /**
0307: * sends an event synchronously to a components
0308: *
0309: * @param componentName the name of the Mule components to send to
0310: * @param transformers a comma separated list of transformers to apply to the
0311: * result message
0312: * @param message the message to send
0313: * @return the result message if any of the invocation
0314: * @throws org.mule.api.MuleException if the dispatch fails or the components or
0315: * transfromers cannot be found
0316: */
0317: public MuleMessage sendDirect(String componentName,
0318: String transformers, MuleMessage message)
0319: throws MuleException {
0320: Service service = muleContext.getRegistry().lookupService(
0321: componentName);
0322: if (service == null) {
0323: throw new MessagingException(CoreMessages
0324: .objectNotRegistered("Service", componentName),
0325: message);
0326: }
0327: List trans = null;
0328: if (transformers != null) {
0329: trans = TransformerUtils.getTransformers(transformers);
0330: }
0331:
0332: if (!muleContext.getConfiguration()
0333: .isDefaultSynchronousEndpoints()) {
0334: logger
0335: .warn("The mule muleContext is not running synchronously, a null message payload will be returned");
0336: }
0337: MuleSession session = new DefaultMuleSession(service,
0338: muleContext);
0339: ImmutableEndpoint endpoint = getDefaultClientEndpoint(service,
0340: message.getPayload());
0341: MuleEvent event = new DefaultMuleEvent(message, endpoint,
0342: session, true);
0343:
0344: if (logger.isDebugEnabled()) {
0345: logger.debug("MuleClient sending event direct to: "
0346: + componentName + ". MuleEvent is: " + event);
0347: }
0348:
0349: MuleMessage result = event.getService().sendEvent(event);
0350:
0351: if (logger.isDebugEnabled()) {
0352: logger.debug("Result of MuleClient sendDirect is: "
0353: + (result == null ? "null" : result.getPayload()));
0354: }
0355:
0356: if (result != null && trans != null) {
0357: result.applyTransformers(trans);
0358: }
0359: return result;
0360: }
0361:
0362: /**
0363: * dispatches an event asynchronously to the components
0364: *
0365: * @param component the name of the Mule components to dispatch to
0366: * @param payload the object that is the payload of the event
0367: * @param messageProperties any properties to be associated with the payload. as
0368: * null
0369: * @throws org.mule.api.MuleException if the dispatch fails or the components or
0370: * transfromers cannot be found
0371: */
0372: public void dispatchDirect(String component, Object payload,
0373: Map messageProperties) throws MuleException {
0374: dispatchDirect(component, new DefaultMuleMessage(payload,
0375: messageProperties));
0376: }
0377:
0378: /**
0379: * dispatches an event asynchronously to the components
0380: *
0381: * @param componentName the name of the Mule components to dispatch to
0382: * @param message the message to send
0383: * @throws org.mule.api.MuleException if the dispatch fails or the components or
0384: * transfromers cannot be found
0385: */
0386: public void dispatchDirect(String componentName, MuleMessage message)
0387: throws MuleException {
0388: Service service = muleContext.getRegistry().lookupService(
0389: componentName);
0390: if (service == null) {
0391: throw new MessagingException(CoreMessages
0392: .objectNotRegistered("Service", componentName),
0393: message);
0394: }
0395: MuleSession session = new DefaultMuleSession(service,
0396: muleContext);
0397: ImmutableEndpoint endpoint = getDefaultClientEndpoint(service,
0398: message.getPayload());
0399: MuleEvent event = new DefaultMuleEvent(message, endpoint,
0400: session, true);
0401:
0402: if (logger.isDebugEnabled()) {
0403: logger.debug("MuleClient dispatching event direct to: "
0404: + componentName + ". MuleEvent is: " + event);
0405: }
0406:
0407: event.getService().dispatchEvent(event);
0408: }
0409:
0410: /**
0411: * sends an event request to a Url, making the result of the event trigger
0412: * available as a Future result that can be accessed later by client code.
0413: *
0414: * @param url the url to make a request on
0415: * @param payload the object that is the payload of the event
0416: * @param messageProperties any properties to be associated with the payload. as
0417: * null
0418: * @return the result message if any of the invocation
0419: * @throws org.mule.api.MuleException if the dispatch fails or the components or
0420: * transfromers cannot be found
0421: */
0422: public FutureMessageResult sendAsync(final String url,
0423: final Object payload, final Map messageProperties)
0424: throws MuleException {
0425: return sendAsync(url, payload, messageProperties, 0);
0426: }
0427:
0428: /**
0429: * sends an event request to a Url, making the result of the event trigger
0430: * available as a Future result that can be accessed later by client code.
0431: *
0432: * @param url the url to make a request on
0433: * @param message the message to send
0434: * @return the result message if any of the invocation
0435: * @throws org.mule.api.MuleException if the dispatch fails or the components or
0436: * transfromers cannot be found
0437: */
0438: public FutureMessageResult sendAsync(final String url,
0439: final MuleMessage message) throws MuleException {
0440: return sendAsync(url, message, MuleEvent.TIMEOUT_NOT_SET_VALUE);
0441: }
0442:
0443: /**
0444: * sends an event request to a Url, making the result of the event trigger
0445: * available as a Future result that can be accessed later by client code.
0446: *
0447: * @param url the url to make a request on
0448: * @param payload the object that is the payload of the event
0449: * @param messageProperties any properties to be associated with the payload. as
0450: * null
0451: * @param timeout how long to block in milliseconds waiting for a result
0452: * @return the result message if any of the invocation
0453: * @throws org.mule.api.MuleException if the dispatch fails or the components or
0454: * transfromers cannot be found
0455: */
0456: public FutureMessageResult sendAsync(final String url,
0457: final Object payload, final Map messageProperties,
0458: final int timeout) throws MuleException {
0459: return sendAsync(url, new DefaultMuleMessage(payload,
0460: messageProperties), timeout);
0461: }
0462:
0463: /**
0464: * sends an event request to a Url, making the result of the event trigger
0465: * available as a Future result that can be accessed later by client code.
0466: *
0467: * @param url the url to make a request on
0468: * @param message the message to send
0469: * @param timeout how long to block in milliseconds waiting for a result
0470: * @return the result message if any of the invocation
0471: * @throws org.mule.api.MuleException if the dispatch fails or the components or
0472: * transfromers cannot be found
0473: */
0474: public FutureMessageResult sendAsync(final String url,
0475: final MuleMessage message, final int timeout)
0476: throws MuleException {
0477: Callable call = new Callable() {
0478: public Object call() throws Exception {
0479: return send(url, message, timeout);
0480: }
0481: };
0482:
0483: FutureMessageResult result = new FutureMessageResult(call);
0484:
0485: if (muleContext.getWorkManager() != null) {
0486: result.setExecutor(muleContext.getWorkManager());
0487: }
0488:
0489: result.execute();
0490: return result;
0491: }
0492:
0493: /**
0494: * sends an event to a components on a local Mule instance, while making the
0495: * result of the event trigger available as a Future result that can be accessed
0496: * later by client code. If forwardDirectRequests flag s set and the components
0497: * is not found on the local Mule instance it will forward to a remote server.
0498: * Users can endpoint a url to a remote Mule server in the constructor of a Mule
0499: * client, by default the default Mule server url tcp://localhost:60504 is used.
0500: *
0501: * @param component the name of the Mule components to send to
0502: * @param transformers a comma separated list of transformers to apply to the
0503: * result message
0504: * @param payload the object that is the payload of the event
0505: * @param messageProperties any properties to be associated with the payload. as
0506: * null
0507: * @return the result message if any of the invocation
0508: * @throws org.mule.api.MuleException if the dispatch fails or the components or
0509: * transfromers cannot be found
0510: */
0511: public FutureMessageResult sendDirectAsync(final String component,
0512: String transformers, final Object payload,
0513: final Map messageProperties) throws MuleException {
0514: return sendDirectAsync(component, transformers,
0515: new DefaultMuleMessage(payload, messageProperties));
0516: }
0517:
0518: /**
0519: * sends an event to a components on a local Mule instance, while making the
0520: * result of the event trigger available as a Future result that can be accessed
0521: * later by client code. If forwardDirectRequests flag s set and the components
0522: * is not found on the local Mule instance it will forward to a remote server.
0523: * Users can endpoint a url to a remote Mule server in the constructor of a Mule
0524: * client, by default the default Mule server url tcp://localhost:60504 is used.
0525: *
0526: * @param component the name of the Mule components to send to
0527: * @param transformers a comma separated list of transformers to apply to the
0528: * result message
0529: * @param message the message to send
0530: * @return the result message if any of the invocation
0531: * @throws org.mule.api.MuleException if the dispatch fails or the components or
0532: * transfromers cannot be found
0533: */
0534: public FutureMessageResult sendDirectAsync(final String component,
0535: String transformers, final MuleMessage message)
0536: throws MuleException {
0537: Callable call = new Callable() {
0538: public Object call() throws Exception {
0539: return sendDirect(component, null, message);
0540: }
0541: };
0542:
0543: FutureMessageResult result = new FutureMessageResult(call);
0544:
0545: if (muleContext.getWorkManager() != null) {
0546: result.setExecutor(muleContext.getWorkManager());
0547: }
0548:
0549: if (StringUtils.isNotBlank(transformers)) {
0550: result.setTransformers(TransformerUtils
0551: .getTransformers(transformers));
0552: }
0553:
0554: result.execute();
0555: return result;
0556: }
0557:
0558: /**
0559: * Sends an event synchronously to a endpointUri via a mule server and a
0560: * resulting message is returned.
0561: *
0562: * @param url the Mule url used to determine the destination and transport of the
0563: * message
0564: * @param payload the object that is the payload of the event
0565: * @param messageProperties any properties to be associated with the payload. In
0566: * the case of Jms you could set the JMSReplyTo property in these
0567: * properties.
0568: * @return A return message, this could be null if the the components invoked
0569: * explicitly sets a return as null
0570: * @throws org.mule.api.MuleException
0571: */
0572: public MuleMessage send(String url, Object payload,
0573: Map messageProperties) throws MuleException {
0574: return send(url, payload, messageProperties,
0575: MuleEvent.TIMEOUT_NOT_SET_VALUE);
0576: }
0577:
0578: /**
0579: * Sends an event synchronously to a endpointUri via a mule server and a
0580: * resulting message is returned.
0581: *
0582: * @param url the Mule url used to determine the destination and transport of the
0583: * message
0584: * @param message the Message for the event
0585: * @return A return message, this could be null if the the components invoked
0586: * explicitly sets a return as null
0587: * @throws org.mule.api.MuleException
0588: */
0589: public MuleMessage send(String url, MuleMessage message)
0590: throws MuleException {
0591: return send(url, message, MuleEvent.TIMEOUT_NOT_SET_VALUE);
0592: }
0593:
0594: /**
0595: * Sends an event synchronously to a endpointUri via a mule server and a
0596: * resulting message is returned.
0597: *
0598: * @param url the Mule url used to determine the destination and transport of the
0599: * message
0600: * @param payload the object that is the payload of the event
0601: * @param messageProperties any properties to be associated with the payload. In
0602: * the case of Jms you could set the JMSReplyTo property in these
0603: * properties.
0604: * @param timeout The time in milliseconds the the call should block waiting for
0605: * a response
0606: * @return A return message, this could be null if the the components invoked
0607: * explicitly sets a return as null
0608: * @throws org.mule.api.MuleException
0609: */
0610: public MuleMessage send(String url, Object payload,
0611: Map messageProperties, int timeout) throws MuleException {
0612: if (messageProperties == null) {
0613: messageProperties = new HashMap();
0614: }
0615: if (messageProperties
0616: .get(MuleProperties.MULE_REMOTE_SYNC_PROPERTY) == null) {
0617: messageProperties.put(
0618: MuleProperties.MULE_REMOTE_SYNC_PROPERTY, "true");
0619: }
0620: MuleMessage message = new DefaultMuleMessage(payload,
0621: messageProperties);
0622: return send(url, message, timeout);
0623: }
0624:
0625: /**
0626: * Sends an event synchronously to a endpointUri via a mule server and a
0627: * resulting message is returned.
0628: *
0629: * @param url the Mule url used to determine the destination and transport of the
0630: * message
0631: * @param message The message to send
0632: * @param timeout The time in milliseconds the the call should block waiting for
0633: * a response
0634: * @return A return message, this could be null if the the components invoked
0635: * explicitly sets a return as null
0636: * @throws org.mule.api.MuleException
0637: */
0638: public MuleMessage send(String url, MuleMessage message, int timeout)
0639: throws MuleException {
0640: MuleEvent event = getEvent(message, url, true, false);
0641: event.setTimeout(timeout);
0642:
0643: try {
0644: MuleMessage msg = event.getSession().sendEvent(event);
0645: if (msg == null) {
0646: msg = new DefaultMuleMessage(NullPayload.getInstance());
0647: }
0648: return msg;
0649: } catch (MuleException e) {
0650: throw e;
0651: } catch (Exception e) {
0652: throw new DispatchException(ClientMessages
0653: .failedToDispatchClientEvent(), event.getMessage(),
0654: event.getEndpoint(), e);
0655: }
0656: }
0657:
0658: /**
0659: * Will receive an event from an endpointUri determined by the url
0660: *
0661: * @param url the Mule url used to determine the destination and transport of the
0662: * message
0663: * @param timeout how long to block waiting to receive the event, if set to 0 the
0664: * receive will not wait at all and if set to -1 the receive will wait
0665: * forever
0666: * @return the message received or null if no message was received
0667: * @throws org.mule.api.MuleException
0668: */
0669: public MuleMessage request(String url, long timeout)
0670: throws MuleException {
0671: InboundEndpoint endpoint = getInboundEndpoint(url);
0672: try {
0673: MuleMessage message = endpoint.request(timeout);
0674: if (message != null && endpoint.getTransformers() != null) {
0675: message.applyTransformers(endpoint.getTransformers());
0676: }
0677: return message;
0678: } catch (Exception e) {
0679: throw new ReceiveException(endpoint, timeout, e);
0680: }
0681: }
0682:
0683: /**
0684: * Will receive an event from an endpointUri determined by the url
0685: *
0686: * @param url the Mule url used to determine the destination and transport of the
0687: * message
0688: * @param transformers A comma separated list of transformers used to apply to
0689: * the result message
0690: * @param timeout how long to block waiting to receive the event, if set to 0 the
0691: * receive will not wait at all and if set to -1 the receive will wait
0692: * forever
0693: * @return the message received or null if no message was received
0694: * @throws org.mule.api.MuleException
0695: */
0696: public MuleMessage request(String url, String transformers,
0697: long timeout) throws MuleException {
0698: return request(url, TransformerUtils
0699: .getTransformers(transformers), timeout);
0700: }
0701:
0702: /**
0703: * Will receive an event from an endpointUri determined by the url
0704: *
0705: * @param url the Mule url used to determine the destination and transport of the
0706: * message
0707: * @param transformers Transformers used to modify the result message
0708: * @param timeout how long to block waiting to receive the event, if set to 0 the
0709: * receive will not wait at all and if set to -1 the receive will wait
0710: * forever
0711: * @return the message received or null if no message was received
0712: * @throws org.mule.api.MuleException
0713: */
0714: public MuleMessage request(String url, List transformers,
0715: long timeout) throws MuleException {
0716: MuleMessage message = request(url, timeout);
0717: if (message != null && transformers != null) {
0718: message.applyTransformers(transformers);
0719: }
0720: return message;
0721: }
0722:
0723: /**
0724: * Packages a mule event for the current request
0725: *
0726: * @param message the event payload
0727: * @param uri the destination endpointUri
0728: * @param synchronous whether the event will be synchronously processed
0729: * @param streaming
0730: * @return the MuleEvent
0731: * @throws MuleException
0732: */
0733: protected MuleEvent getEvent(MuleMessage message, String uri,
0734: boolean synchronous, boolean streaming)
0735: throws MuleException {
0736: ImmutableEndpoint endpoint = getOutboundEndpoint(uri);
0737: if (!endpoint.getConnector().isStarted()
0738: && muleContext.isStarted()) {
0739: endpoint.getConnector().start();
0740: }
0741: try {
0742: DefaultMuleSession session = new DefaultMuleSession(
0743: message, ((AbstractConnector) endpoint
0744: .getConnector()).getSessionHandler(),
0745: muleContext);
0746:
0747: if (user != null) {
0748: message
0749: .setProperty(MuleProperties.MULE_USER_PROPERTY,
0750: MuleCredentials.createHeader(user
0751: .getUsername(), user
0752: .getPassword()));
0753: }
0754: DefaultMuleEvent event = new DefaultMuleEvent(message,
0755: endpoint, session, synchronous);
0756: return event;
0757: } catch (Exception e) {
0758: throw new DispatchException(CoreMessages
0759: .failedToCreate("Client event"), message, endpoint,
0760: e);
0761: }
0762: }
0763:
0764: protected InboundEndpoint getInboundEndpoint(String uri)
0765: throws MuleException {
0766: // There was a potential leak here between get() and putIfAbsent(). This
0767: // would cause the endpoint that was created to be used rather an endpoint
0768: // with the same key that has been created and put in the cache by another
0769: // thread. To avoid this we test for the result of putIfAbsent result and if
0770: // it is non-null then an endpoint was created and added concurrently and we
0771: // return this instance instead.
0772: InboundEndpoint endpoint = (InboundEndpoint) inboundEndpointCache
0773: .get(uri);
0774: if (endpoint == null) {
0775: endpoint = muleContext.getRegistry()
0776: .lookupEndpointFactory().getInboundEndpoint(uri);
0777: InboundEndpoint concurrentlyAddedEndpoint = (InboundEndpoint) inboundEndpointCache
0778: .putIfAbsent(uri, endpoint);
0779: if (concurrentlyAddedEndpoint != null) {
0780: return concurrentlyAddedEndpoint;
0781: }
0782: }
0783: return endpoint;
0784: }
0785:
0786: protected OutboundEndpoint getOutboundEndpoint(String uri)
0787: throws MuleException {
0788: // There was a potential leak here between get() and putIfAbsent(). This
0789: // would cause the endpoint that was created to be used rather an endpoint
0790: // with the same key that has been created and put in the cache by another
0791: // thread. To avoid this we test for the result of putIfAbsent result and if
0792: // it is non-null then an endpoint was created and added concurrently and we
0793: // return this instance instead.
0794: OutboundEndpoint endpoint = (OutboundEndpoint) outboundEndpointCache
0795: .get(uri);
0796: if (endpoint == null) {
0797: endpoint = muleContext.getRegistry()
0798: .lookupEndpointFactory().getOutboundEndpoint(uri);
0799: OutboundEndpoint concurrentlyAddedEndpoint = (OutboundEndpoint) outboundEndpointCache
0800: .putIfAbsent(uri, endpoint);
0801: if (concurrentlyAddedEndpoint != null) {
0802: return concurrentlyAddedEndpoint;
0803: }
0804: }
0805: return endpoint;
0806: }
0807:
0808: protected ImmutableEndpoint getDefaultClientEndpoint(
0809: Service service, Object payload) throws MuleException {
0810: // as we are bypassing the message transport layer we need to check that
0811: ImmutableEndpoint endpoint = (ImmutableEndpoint) service
0812: .getInboundRouter().getEndpoints().get(0);
0813: if (endpoint != null) {
0814: if (endpoint.getTransformers() != null) {
0815: // the original code here really did just check the first exception
0816: // as far as i can tell
0817: if (TransformerUtils.isSourceTypeSupportedByFirst(
0818: endpoint.getTransformers(), payload.getClass())) {
0819: return endpoint;
0820: } else {
0821: EndpointBuilder builder = new EndpointURIEndpointBuilder(
0822: endpoint, muleContext);
0823: builder.setTransformers(new LinkedList());
0824: return muleContext.getRegistry()
0825: .lookupEndpointFactory()
0826: .getInboundEndpoint(builder);
0827: }
0828: } else {
0829: return endpoint;
0830: }
0831: } else {
0832: EndpointBuilder builder = new EndpointURIEndpointBuilder(
0833: "vm://mule.client", muleContext);
0834: builder.setName("muleClientProvider");
0835: endpoint = muleContext.getRegistry()
0836: .lookupEndpointFactory()
0837: .getInboundEndpoint(builder);
0838: }
0839: return endpoint;
0840: }
0841:
0842: /**
0843: * Sends an event synchronously to a endpointUri via a mule server without
0844: * waiting for the result.
0845: *
0846: * @param url the Mule url used to determine the destination and transport of the
0847: * message
0848: * @param payload the object that is the payload of the event
0849: * @param messageProperties any properties to be associated with the payload. In
0850: * the case of Jms you could set the JMSReplyTo property in these
0851: * properties.
0852: * @throws org.mule.api.MuleException
0853: */
0854: public void sendNoReceive(String url, Object payload,
0855: Map messageProperties) throws MuleException {
0856: if (messageProperties == null) {
0857: messageProperties = new HashMap();
0858: }
0859: messageProperties.put(MuleProperties.MULE_REMOTE_SYNC_PROPERTY,
0860: "false");
0861: MuleMessage message = new DefaultMuleMessage(payload,
0862: messageProperties);
0863: MuleEvent event = getEvent(message, url, true, false);
0864: try {
0865: event.getSession().sendEvent(event);
0866: } catch (MuleException e) {
0867: throw e;
0868: } catch (Exception e) {
0869: throw new DispatchException(ClientMessages
0870: .failedToDispatchClientEvent(), event.getMessage(),
0871: event.getEndpoint(), e);
0872: }
0873: }
0874:
0875: /**
0876: * Overriding methods may want to return a custom muleContext here
0877: *
0878: * @return the UMOManager to use
0879: */
0880: public MuleContext getMuleContext() {
0881: return muleContext;
0882: }
0883:
0884: /**
0885: * Registers a java object as a Umo pcomponent that listens for events on the
0886: * given url. By default the ThreadingProfile for the components will be set so
0887: * that there will only be one thread of execution.
0888: *
0889: * @param component any java object, Mule will it's endpointUri discovery to
0890: * determine which event to invoke based on the evnet payload type
0891: * @param name The identifying name of the components. This can be used to later
0892: * unregister it
0893: * @param listenerEndpoint The url endpointUri to listen to
0894: * @throws MuleException
0895: * @deprecated Use the RegistryContext to get the registry and register the
0896: * service there
0897: */
0898: public void registerComponent(Object component, String name,
0899: EndpointURI listenerEndpoint) throws MuleException {
0900: throw new UnsupportedOperationException("registerComponent");
0901: // builder.registerComponentInstance(service, name, listenerEndpoint,
0902: // null);
0903: }
0904:
0905: /**
0906: * Registers a java object as a Umo pcomponent that listens for and sends events
0907: * on the given urls. By default the ThreadingProfile for the components will be
0908: * set so that there will only be one thread of execution.
0909: *
0910: * @param component any java object, Mule will it's endpointUri discovery to
0911: * determine which event to invoke based on the evnet payload type
0912: * @param name The identifying name of the components. This can be used to later
0913: * unregister it
0914: * @param listenerEndpoint The url endpointUri to listen to
0915: * @param sendEndpoint The url endpointUri to dispatch to
0916: * @throws MuleException
0917: * @deprecated Use the RegistryContext to get the registry and register the
0918: * service there
0919: */
0920: public void registerComponent(Object component, String name,
0921: MuleEndpointURI listenerEndpoint,
0922: MuleEndpointURI sendEndpoint) throws MuleException {
0923: throw new UnsupportedOperationException("registerComponent");
0924: // builder.registerComponentInstance(service, name, listenerEndpoint,
0925: // sendEndpoint);
0926: }
0927:
0928: /**
0929: * Registers a user configured MuleDescriptor of a components to the server. If
0930: * users want to register object instances with the server rather than class
0931: * names that get created at runtime or reference to objects in the container,
0932: * the user must call the descriptors setImplementationInstance() method - <code>
0933: * MyBean implementation = new MyBean();
0934: * descriptor.setImplementationInstance(implementation);
0935: * </code>
0936: * Calling this method is equivilent to calling Model.registerComponent(..)
0937: *
0938: * @param descriptor the componet descriptor to register
0939: * @throws MuleException the descriptor is invalid or cannot be initialised or
0940: * started
0941: * @see org.mule.api.model.Model
0942: * @deprecated Use the RegistryContext to get the registry and register the
0943: * service there
0944: */
0945: // public void registerComponent(UMODescriptor descriptor) throws MuleException
0946: // {
0947: // throw new UnsupportedOperationException("registerComponent");
0948: // //builder.registerComponent(descriptor);
0949: // }
0950: /**
0951: * Unregisters a previously register components. This will also unregister any
0952: * listeners for the components Calling this method is equivilent to calling
0953: * Model.unregisterComponent(..)
0954: *
0955: * @param name the name of the componet to unregister
0956: * @throws MuleException if unregistering the components fails, i.e. The
0957: * underlying transport fails to unregister a listener. If the
0958: * components does not exist, this method should not throw an
0959: * exception.
0960: * @see org.mule.api.model.Model
0961: * @deprecated Use the RegistryContext to get the registry and register the
0962: * service there
0963: */
0964: public void unregisterComponent(String name) throws MuleException {
0965: throw new UnsupportedOperationException("registerComponent");
0966:
0967: // builder.unregisterComponent(name);
0968: }
0969:
0970: public RemoteDispatcher getRemoteDispatcher(String serverEndpoint)
0971: throws MuleException {
0972: RemoteDispatcher rd = new RemoteDispatcher(serverEndpoint);
0973: rd.setExecutor(muleContext.getWorkManager());
0974: dispatchers.add(rd);
0975: return rd;
0976: }
0977:
0978: public RemoteDispatcher getRemoteDispatcher(String serverEndpoint,
0979: String user, String password) throws MuleException {
0980: RemoteDispatcher rd = new RemoteDispatcher(serverEndpoint,
0981: new MuleCredentials(user, password.toCharArray()));
0982: rd.setExecutor(muleContext.getWorkManager());
0983: dispatchers.add(rd);
0984: return rd;
0985: }
0986:
0987: /**
0988: * Will dispose the MuleManager instance *IF* a new instance was created for this
0989: * client. Otherwise this method only cleans up resources no longer needed
0990: */
0991: public void dispose() {
0992: synchronized (dispatchers) {
0993: for (Iterator iterator = dispatchers.iterator(); iterator
0994: .hasNext();) {
0995: RemoteDispatcher remoteDispatcher = (RemoteDispatcher) iterator
0996: .next();
0997: remoteDispatcher.dispose();
0998: remoteDispatcher = null;
0999: }
1000: dispatchers.clear();
1001: }
1002: // Dispose the muleContext only if the muleContext was created for this
1003: // client
1004: if (muleContext.getConfiguration().isClientMode()) {
1005: logger.info("Stopping Mule...");
1006: muleContext.dispose();
1007: }
1008: }
1009:
1010: public void setProperty(String key, Object value) {
1011: try {
1012: muleContext.getRegistry().registerObject(key, value);
1013: } catch (RegistrationException e) {
1014: logger.error(e);
1015: }
1016: }
1017:
1018: public Object getProperty(String key) {
1019: return muleContext.getRegistry().lookupObject(key);
1020: }
1021:
1022: public MuleConfiguration getConfiguration() {
1023: return muleContext.getConfiguration();
1024: }
1025: }
|