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.module.guice;
8   
9   import org.mule.api.MuleContext;
10  import org.mule.api.config.ConfigurationException;
11  import org.mule.config.builders.AbstractConfigurationBuilder;
12  import org.mule.config.i18n.CoreMessages;
13  import org.mule.util.ClassUtils;
14  import org.mule.util.scan.ClasspathScanner;
15  
16  import com.google.inject.Guice;
17  import com.google.inject.Injector;
18  import com.google.inject.Module;
19  import com.google.inject.Stage;
20  
21  import java.util.ArrayList;
22  import java.util.Arrays;
23  import java.util.List;
24  import java.util.Set;
25  
26  import org.guiceyfruit.mule.MuleModule;
27  
28  
29  /**
30   * Provides the configuration entry point for loading Guice modules into Mule.  Users can pass in an array of
31   * {@link Module} into this builder or provide a base search path that Mule will use to search the
32   * classpath for any modules that implement {@link Module}. The basepath is a path on the classpath.
33   * Note for better performance, any basepath set should be qualified to your application. For example, if your application
34   * has a package com.mycompany.app, its better to set the base path to 'com/mycompany/app' over 'com/' or '/' since they will
35   * search everything on the classpath that matches the specified package.
36   */
37  public class GuiceConfigurationBuilder extends AbstractConfigurationBuilder
38  {
39      public static final String DEFAULT_PACKAGE = "";
40  
41      protected String basepath = DEFAULT_PACKAGE;
42  
43      protected Module[] modules = null;
44  
45      protected Stage stage;
46  
47      protected ClassLoader classLoader;
48  
49      public GuiceConfigurationBuilder()
50      {
51          super();
52          classLoader = Thread.currentThread().getContextClassLoader();
53      }
54  
55      public GuiceConfigurationBuilder(ClassLoader classLoader)
56      {
57          this.classLoader = classLoader;
58      }
59  
60      public GuiceConfigurationBuilder(String basepath)
61      {
62          this();
63          this.basepath = basepath;
64      }
65  
66      public GuiceConfigurationBuilder(String basepath, ClassLoader classLoader)
67      {
68          this.basepath = basepath;
69          this.classLoader = classLoader;
70      }
71  
72      public GuiceConfigurationBuilder(Module... modules)
73      {
74          this.modules = modules;
75      }
76  
77      public GuiceConfigurationBuilder(Stage stage, Module... modules)
78      {
79          this.stage = stage;
80          this.modules = modules;
81      }
82  
83      protected void doConfigure(MuleContext muleContext) throws Exception
84      {
85  
86          List<Module> allModules = getSystemModules(muleContext);
87  
88          Injector injector;
89          if (basepath != null && basepath.startsWith("/"))
90          {
91              basepath = basepath.substring(1);
92          }
93  
94          //No modules were set explicitly on this ConfigurationBuilder so we now try and discover
95          //modules and {@link GuiceModuleFactory} instances on the classpath
96          if (modules == null)
97          {
98              ClasspathScanner scanner = new ClasspathScanner(classLoader, basepath);
99              Set<Class> classes = scanner.scanFor(Module.class);
100             Set<Class> factories = scanner.scanFor(GuiceModuleFactory.class);
101 
102             if (classes.size() == 0 && factories.size() == 0)
103             {
104                 try
105                 {
106                     basepath = getClass().getClassLoader().getResources(basepath).toString();
107                 }
108                 catch (Exception e)
109                 {
110                     basepath = (basepath.equals("") ? "/" : basepath);
111                 }
112                 //lets just log a noticeable exception as a warning since the Guice build can compliment other configuration builders
113                 logger.warn(new ConfigurationException(CoreMessages.createStaticMessage("There are no Guice modules or module factories on the classpath under: " + basepath)));
114                 return;
115             }
116 
117             for (Class moduleClass : classes)
118             {
119                 allModules.add((Module) ClassUtils.instanciateClass(moduleClass, ClassUtils.NO_ARGS));
120             }
121             for (Class factoryClass : factories)
122             {
123                 GuiceModuleFactory factory = (GuiceModuleFactory) ClassUtils.instanciateClass(factoryClass, ClassUtils.NO_ARGS);
124                 allModules.add(factory.createModule());
125             }
126         }
127         else
128         {
129             allModules.addAll(Arrays.asList(modules));
130         }
131 
132         for (Module module : allModules)
133         {
134             if (module instanceof AbstractMuleGuiceModule)
135             {
136                 ((AbstractMuleGuiceModule) module).setMuleContext(muleContext);
137             }
138         }
139 
140         if (stage != null)
141         {
142             injector = Guice.createInjector(stage, allModules);
143         }
144         else
145         {
146             injector = Guice.createInjector(allModules);
147         }
148         
149         GuiceRegistry registry = new GuiceRegistry(injector, muleContext);
150         registry.initialise();
151         muleContext.addRegistry(registry);
152     }
153 
154     protected List<Module> getSystemModules(MuleContext muleContext)
155     {
156         List<Module> modules = new ArrayList<Module>();
157         //JSR-250 lifecycle and @Resource annotation support & Mule lifecycle support
158         modules.add(new MuleModule());
159         modules.add(new MuleSupportModule(muleContext));
160         return modules;
161     }
162 }