View Javadoc

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