View Javadoc
1   /*
2    * Copyright (c) MuleSoft, Inc.  All rights reserved.  http://www.mulesoft.com
3    * The software in this package is published under the terms of the CPAL v1.0
4    * license, a copy of which has been included with this distribution in the
5    * LICENSE.txt file.
6    */
7   package org.mule.config.processors;
8   
9   import org.mule.api.AnnotationException;
10  import org.mule.api.EndpointAnnotationParser;
11  import org.mule.api.MessageProcessorAnnotationParser;
12  import org.mule.api.MuleContext;
13  import org.mule.api.MuleException;
14  import org.mule.api.MuleRuntimeException;
15  import org.mule.api.annotations.meta.Channel;
16  import org.mule.api.annotations.meta.ChannelType;
17  import org.mule.api.annotations.meta.Router;
18  import org.mule.api.annotations.meta.RouterType;
19  import org.mule.api.config.MuleProperties;
20  import org.mule.api.context.MuleContextAware;
21  import org.mule.api.endpoint.InboundEndpoint;
22  import org.mule.api.endpoint.OutboundEndpoint;
23  import org.mule.api.lifecycle.Initialisable;
24  import org.mule.api.processor.MessageProcessor;
25  import org.mule.api.registry.PreInitProcessor;
26  import org.mule.api.routing.OutboundRouter;
27  import org.mule.api.routing.OutboundRouterCollection;
28  import org.mule.api.service.Service;
29  import org.mule.api.source.CompositeMessageSource;
30  import org.mule.component.AbstractJavaComponent;
31  import org.mule.config.AnnotationsParserFactory;
32  import org.mule.config.endpoint.AnnotatedEndpointHelper;
33  import org.mule.config.i18n.AnnotationsMessages;
34  import org.mule.config.i18n.CoreMessages;
35  import org.mule.registry.RegistryMap;
36  import org.mule.routing.outbound.OutboundPassThroughRouter;
37  import org.mule.service.ServiceCompositeMessageSource;
38  import org.mule.util.TemplateParser;
39  import org.mule.util.annotation.AnnotationMetaData;
40  import org.mule.util.annotation.AnnotationUtils;
41  
42  import java.lang.annotation.Annotation;
43  import java.lang.annotation.ElementType;
44  import java.util.Collection;
45  import java.util.Collections;
46  import java.util.List;
47  
48  import org.apache.commons.logging.Log;
49  import org.apache.commons.logging.LogFactory;
50  
51  /**
52   * This object processor allows users to register annotated services directly to the registry
53   * and have them configured correctly.
54   * It will look for a non-system {@link org.mule.api.model.Model} registered with the Registry.
55   * If one is not found a default  SEDA Model will be created
56   * Finally, the processor will register the service with the Registry and return null.
57   */
58  public class DecoratingAnnotatedServiceProcessor implements PreInitProcessor, MuleContextAware
59  {
60      /**
61       * logger used by this class
62       */
63      protected transient final Log logger = LogFactory.getLog(DecoratingAnnotatedServiceProcessor.class);
64  
65      protected MuleContext context;
66      private final TemplateParser parser = TemplateParser.createAntStyleParser();
67      protected RegistryMap regProps;
68      protected AnnotatedEndpointHelper helper;
69      protected AnnotationsParserFactory parserFactory;
70  
71      public DecoratingAnnotatedServiceProcessor()
72      {
73      }
74  
75      public DecoratingAnnotatedServiceProcessor(MuleContext context)
76      {
77          setMuleContext(context);
78      }
79  
80      public void setMuleContext(MuleContext context)
81      {
82          try
83          {
84              this.context = context;
85              this.regProps = new RegistryMap(context.getRegistry());
86              this.helper = new AnnotatedEndpointHelper(context);
87              this.parserFactory = context.getRegistry().lookupObject(AnnotationsParserFactory.class);
88              if(parserFactory==null)
89              {
90                  logger.info(AnnotationsParserFactory.class.getName() +" implementation not found in registry, annotations not enabled");
91              }
92          }
93          catch (MuleException e)
94          {
95              throw new MuleRuntimeException(CoreMessages.failedToCreate(getClass().getName()), e);
96          }
97      }
98  
99      public Object process(Object object)
100     {
101         if (object == null || parserFactory == null)
102         {
103             return object;
104         }
105 
106         if (object instanceof Service)
107         {
108             Service service = (Service) object;
109             //Annotations only supported on Java components
110             if (service.getComponent() instanceof AbstractJavaComponent)
111             {
112                 try
113                 {
114                     AbstractJavaComponent component = (AbstractJavaComponent) service.getComponent();
115                     if(AnnotationUtils.getMethodMetaAnnotations(component.getObjectType(), Channel.class).size()==0)
116                     {
117                         return object;
118                     }
119                     
120                     processInbound(component.getObjectType(), service);
121                     processOutbound(component.getObjectType(), service);
122 
123                     //Check for Async reply Config
124                     processReply(component.getObjectType(), service);
125                 }
126                 catch (MuleException e)
127                 {
128                     e.printStackTrace();
129                 }
130             }
131 
132         }
133         return object;
134     }
135 
136     protected void processInbound(Class componentFactoryClass, org.mule.api.service.Service service) throws MuleException
137     {
138 
139         InboundEndpoint inboundEndpoint;
140         List<AnnotationMetaData> annotations = AnnotationUtils.getClassAndMethodAnnotations(componentFactoryClass);
141         for (AnnotationMetaData annotation : annotations)
142         {
143             inboundEndpoint = tryInboundEndpointAnnotation(annotation, ChannelType.Inbound);
144             if (inboundEndpoint != null)
145             {
146                 if (annotation.getType() == ElementType.METHOD)
147                 {
148                     inboundEndpoint.getProperties().put(MuleProperties.MULE_METHOD_PROPERTY, annotation.getElementName());
149                 }
150                 ((CompositeMessageSource) service.getMessageSource()).addSource(inboundEndpoint);
151             }
152         }
153 
154         //Lets process the inbound routers
155         processInboundRouters(componentFactoryClass, service);
156     }
157 
158     protected void processInboundRouters(Class componentFactoryClass, org.mule.api.service.Service service) throws MuleException
159     {
160         for (int i = 0; i < componentFactoryClass.getAnnotations().length; i++)
161         {
162             Annotation annotation = componentFactoryClass.getAnnotations()[i];
163             Router routerAnnotation = annotation.annotationType().getAnnotation(Router.class);
164             if (routerAnnotation != null && routerAnnotation.type() == RouterType.Inbound)
165             {
166                 MessageProcessorAnnotationParser parser = parserFactory.getRouterParser(annotation, componentFactoryClass, null);
167                 if (parser != null)
168                 {
169                     ((ServiceCompositeMessageSource) service.getMessageSource()).addMessageProcessor(parser.parseMessageProcessor(annotation));
170                 }
171                 else
172                 {
173                     //TODO i18n
174                     throw new IllegalStateException("Cannot find parser for router annotation: " + annotation.toString());
175                 }
176             }
177         }
178     }
179 
180     protected void processReplyRouters(Class componentFactoryClass, org.mule.api.service.Service service) throws MuleException
181     {
182         List<AnnotationMetaData> annotations = AnnotationUtils.getClassAndMethodAnnotations(componentFactoryClass);
183         for (AnnotationMetaData metaData : annotations)
184         {
185             Router routerAnnotation = metaData.getAnnotation().annotationType().getAnnotation(Router.class);
186             if (routerAnnotation != null && routerAnnotation.type() == RouterType.ReplyTo)
187             {
188 
189 
190                 MessageProcessorAnnotationParser parser = parserFactory.getRouterParser(metaData.getAnnotation(), metaData.getClazz(), metaData.getMember());
191                 if (parser != null)
192                 {
193                     MessageProcessor router = parser.parseMessageProcessor(metaData.getAnnotation());
194                     //Todo, wrap lifecycle
195                     if (router instanceof MuleContextAware)
196                     {
197                         ((MuleContextAware) router).setMuleContext(context);
198                     }
199                     if (router instanceof Initialisable)
200                     {
201                         ((Initialisable) router).initialise();
202                     }
203                     // service.getResponseRouter().addRouter(router);
204                     break;
205                 }
206                 else
207                 {
208                     //TODO i18n
209                     throw new IllegalStateException("Cannot find parser for router annotation: " + metaData.getAnnotation().toString());
210                 }
211             }
212         }
213     }
214 
215     protected OutboundRouter processOutboundRouter(Class componentFactoryClass) throws MuleException
216     {
217         Collection routerParsers = context.getRegistry().lookupObjects(MessageProcessorAnnotationParser.class);
218         OutboundRouter router = null;
219 
220         List<AnnotationMetaData> annotations = AnnotationUtils.getClassAndMethodAnnotations(componentFactoryClass);
221         for (AnnotationMetaData metaData : annotations)
222         {
223             Router routerAnnotation = metaData.getAnnotation().annotationType().getAnnotation(Router.class);
224             if (routerAnnotation != null && routerAnnotation.type() == RouterType.Outbound)
225             {
226                 if (router != null)
227                 {
228                     //TODO i18n
229                     throw new IllegalStateException("You can only configure one outbound router on a service");
230                 }
231                 MessageProcessorAnnotationParser parser = parserFactory.getRouterParser(metaData.getAnnotation(), metaData.getClazz(), metaData.getMember());
232                 if (parser != null)
233                 {
234                     router = (OutboundRouter) parser.parseMessageProcessor(metaData.getAnnotation());
235                 }
236                 else
237                 {
238                     //TODO i18n
239                     throw new IllegalStateException("Cannot find parser for router annotation: " + metaData.getAnnotation().toString());
240                 }
241             }
242         }
243         if (router == null)
244         {
245             router = new OutboundPassThroughRouter();
246         }
247         //Todo, wrap lifecycle
248         if (router instanceof MuleContextAware)
249         {
250             ((MuleContextAware) router).setMuleContext(context);
251         }
252         router.initialise();
253         return router;
254     }
255 
256     protected void processOutbound(Class componentFactoryClass, org.mule.api.service.Service service) throws MuleException
257     {
258         OutboundRouter router = processOutboundRouter(componentFactoryClass);
259 
260         OutboundEndpoint outboundEndpoint;
261         List<AnnotationMetaData> annotations = AnnotationUtils.getClassAndMethodAnnotations(componentFactoryClass);
262         for (AnnotationMetaData annotation : annotations)
263         {
264             outboundEndpoint = tryOutboundEndpointAnnotation(annotation, ChannelType.Outbound);
265             if (outboundEndpoint != null)
266             {
267                 router.addRoute(outboundEndpoint);
268             }
269         }
270 
271         if (router instanceof MuleContextAware)
272         {
273             ((MuleContextAware) router).setMuleContext(context);
274         }
275         router.initialise();
276         ((OutboundRouterCollection) service.getOutboundMessageProcessor()).addRoute(router);
277     }
278 
279     protected InboundEndpoint tryInboundEndpointAnnotation(AnnotationMetaData metaData, ChannelType channelType) throws MuleException
280     {
281         Channel channelAnno = metaData.getAnnotation().annotationType().getAnnotation(Channel.class);
282         if (channelAnno != null && channelAnno.type() == channelType)
283         {
284             EndpointAnnotationParser parser = parserFactory.getEndpointParser(metaData.getAnnotation(), metaData.getClazz(), metaData.getMember());
285             if (parser == null)
286             {
287                 //TODO i18n
288                 throw new AnnotationException(AnnotationsMessages.createStaticMessage("No parser found for annotation: " + metaData));
289             }
290             else
291             {
292                 return parser.parseInboundEndpoint(metaData.getAnnotation(), Collections.EMPTY_MAP);
293             }
294         }
295         return null;
296     }
297 
298     protected OutboundEndpoint tryOutboundEndpointAnnotation(AnnotationMetaData metaData, ChannelType channelType) throws MuleException
299     {
300         Channel channelAnno = metaData.getAnnotation().annotationType().getAnnotation(Channel.class);
301         if (channelAnno != null && channelAnno.type() == channelType)
302         {
303             EndpointAnnotationParser parser = parserFactory.getEndpointParser(metaData.getAnnotation(), metaData.getClazz(), metaData.getMember());
304             if (parser == null)
305             {
306                 //TODO i18n
307                 throw new AnnotationException(AnnotationsMessages.createStaticMessage("No parser found for annotation: " + metaData));
308             }
309             else
310             {
311                 return parser.parseOutboundEndpoint(metaData.getAnnotation(), Collections.EMPTY_MAP);
312             }
313         }
314         return null;
315     }
316 
317 
318     protected void processReply(Class componentFactoryClass, org.mule.api.service.Service service) throws MuleException
319     {
320 
321         InboundEndpoint inboundEndpoint;
322         for (int i = 0; i < componentFactoryClass.getAnnotations().length; i++)
323         {
324             Annotation annotation = componentFactoryClass.getAnnotations()[i];
325             inboundEndpoint = tryInboundEndpointAnnotation(
326                     new AnnotationMetaData(componentFactoryClass, null, ElementType.TYPE, annotation), ChannelType.Reply);
327             if (inboundEndpoint != null)
328             {
329                 service.getAsyncReplyMessageSource().addSource(inboundEndpoint);
330             }
331         }
332 
333         //Lets process the reply routers
334         processReplyRouters(componentFactoryClass, service);
335     }
336 
337     protected String getValue(String key)
338     {
339         return parser.parse(regProps, key);
340     }
341 
342 }