View Javadoc

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