View Javadoc

1   /*
2    * $Id: CallOutboundEndpoint.java 20385 2010-11-29 20:25:26Z dfeist $
3    * --------------------------------------------------------------------------------------
4    * Copyright (c) MuleSoft, Inc.  All rights reserved.  http://www.mulesoft.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  package org.mule.module.ibeans.spi.support;
11  
12  import org.mule.api.MuleContext;
13  import org.mule.api.MuleEvent;
14  import org.mule.api.MuleException;
15  import org.mule.api.MuleMessage;
16  import org.mule.api.endpoint.EndpointBuilder;
17  import org.mule.api.endpoint.EndpointURI;
18  import org.mule.api.endpoint.MalformedEndpointException;
19  import org.mule.api.transport.PropertyScope;
20  import org.mule.config.endpoint.AnnotatedEndpointData;
21  import org.mule.endpoint.MuleEndpointURI;
22  import org.mule.transport.AbstractConnector;
23  import org.mule.transport.service.TransportFactory;
24  import org.mule.util.BeanUtils;
25  import org.mule.util.TemplateParser;
26  import org.mule.util.UriParamFilter;
27  
28  import java.util.HashMap;
29  import java.util.Map;
30  
31  import org.apache.commons.logging.Log;
32  import org.apache.commons.logging.LogFactory;
33  import org.ibeans.api.channel.CHANNEL;
34  
35  /**
36   * A dynamic outbound endpoint defined when using the {@link org.ibeans.annotation.Call} annotation.  A CallOutboundEndpoint
37   * is generated when the Call method has a one or more payloads defined using {@link org.ibeans.annotation.param.Payload} or {@link org.ibeans.annotation.param.PayloadParam} annotations
38   * or one or more headers defined using the {@link org.ibeans.annotation.param.HeaderParam} annotation.
39   * annotations.
40   * <p/>
41   * The endpoint scheme is the only part of the URI that cannot be replaced at runtime.
42   *
43   * @see CallRequestEndpoint
44   */
45  public class CallOutboundEndpoint extends org.mule.endpoint.DynamicOutboundEndpoint
46  {
47      public static final String NULL_PARAM = "null.param";    
48  
49      /**
50       * logger used by this class
51       */
52      protected transient final Log logger = LogFactory.getLog(CallOutboundEndpoint.class);
53  
54      private static final long serialVersionUID = 1861985949279708638L;
55  
56      //The parser used to parse the @Call uri template
57      protected TemplateParser parser = TemplateParser.createCurlyBracesStyleParser();
58  
59      private UriParamFilter filter = new UriParamFilter();
60  
61      public CallOutboundEndpoint(MuleContext context, AnnotatedEndpointData epData) throws MalformedEndpointException
62      {
63          super(context, createBuilder(context, epData), epData.getAddress());
64      }
65  
66      private synchronized static EndpointBuilder createBuilder(MuleContext context, AnnotatedEndpointData epData)
67      {
68          try
69          {
70              String address = epData.getAddress();
71              int i = address.indexOf(":/");
72              String scheme;
73              if (i > -1)
74              {
75                  scheme = address.substring(0, i);
76                  address = scheme + "://dynamic";
77                  //This is used for creating the connector, since we don't know if the actual URI address is a vaild URI.
78                  EndpointURI tempUri = new MuleEndpointURI(address, context);
79                  AbstractConnector cnn = null;
80  
81                  if (epData.getConnectorName() != null)
82                  {
83                      cnn = (AbstractConnector) context.getRegistry().lookupConnector(epData.getConnectorName());
84                  }
85                  if (cnn == null)
86                  {
87                      cnn = (AbstractConnector) new TransportFactory(context).createConnector(tempUri);
88                      if (epData.getConnectorName() != null)
89                      {
90                          cnn.setName(epData.getConnectorName());
91                      }
92                      context.getRegistry().registerConnector(cnn);
93                  }
94  
95                  //This allows connector properties to be set as properties on the endpoint
96                  Map props = epData.getProperties();
97                  if (props == null)
98                  {
99                      props = new HashMap();
100                 }
101                 else
102                 {
103                     BeanUtils.populateWithoutFail(cnn, props, false);
104                 }
105                 EndpointBuilder builder = context.getEndpointFactory().getEndpointBuilder(address);
106                 builder.setConnector(cnn);
107                 builder.setName(epData.getName());
108                 builder.setProperties(props);
109 
110                 return builder;
111 
112 
113             }
114             else
115             {
116                 throw new IllegalArgumentException("When defining a dynamic endpoint the endpoint scheme must be set i.e. http://{dynamic}");
117             }
118         }
119         catch (Exception e)
120         {
121             throw new RuntimeException(e);
122         }
123     }
124 
125     @Override
126     protected void validateUriTemplate(String uri) throws MalformedEndpointException
127     {
128         //TODO
129     }
130 
131     @Override
132     protected String parseURIString(String uri, MuleMessage message)
133     {
134         //We do additional processing here to parse the URI template
135         Map<String, Object> props = getPropertiesForUriTemplate(message);
136 
137         String newUriString = parser.parse(props, uri);
138         //Remove optional params completely if null
139         newUriString = filter.filterParamsByValue(newUriString, NULL_PARAM);
140 
141         return super.parseURIString(newUriString, message);
142     }
143 
144     protected Map<String, Object> getPropertiesForUriTemplate(MuleMessage message)
145     {
146         Map<String, Object> props = (Map) message.getOutboundProperty(CHANNEL.URI_PARAM_PROPERTIES);
147         if (props == null)
148         {
149             throw new IllegalStateException(CHANNEL.URI_PARAM_PROPERTIES + " not set on message");
150         }
151         return props;
152     }
153 
154     @Override
155     public MuleEvent process(MuleEvent event) throws MuleException
156     {
157         MuleEvent result = super.process(event);
158         if (result != null)
159         {
160             result.getMessage().setProperty(CHANNEL.CALL_URI_PROPERTY, event.getEndpoint().getEndpointURI().toString(), PropertyScope.OUTBOUND);
161         }
162         return result;
163     }
164 }