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.builders;
8   
9   import org.mule.MuleServer;
10  import org.mule.api.MuleContext;
11  import org.mule.api.MuleException;
12  import org.mule.api.config.ConfigurationException;
13  import org.mule.api.config.MuleProperties;
14  import org.mule.api.context.MuleContextBuilder;
15  import org.mule.api.context.MuleContextFactory;
16  import org.mule.api.lifecycle.InitialisationException;
17  import org.mule.config.DefaultMuleConfiguration;
18  import org.mule.config.PropertiesMuleConfigurationFactory;
19  import org.mule.config.spring.SpringXmlConfigurationBuilder;
20  import org.mule.context.DefaultMuleContextBuilder;
21  import org.mule.context.DefaultMuleContextFactory;
22  import org.mule.util.FilenameUtils;
23  import org.mule.util.StringUtils;
24  
25  import java.io.File;
26  
27  import javax.servlet.ServletContext;
28  import javax.servlet.ServletContextEvent;
29  import javax.servlet.ServletContextListener;
30  
31  import org.apache.commons.logging.Log;
32  import org.apache.commons.logging.LogFactory;
33  import org.springframework.context.ApplicationContext;
34  import org.springframework.web.context.WebApplicationContext;
35  
36  /**
37   * <code>MuleXmlBuilderContextListener</code> is a bootstrap listener used to
38   * construct a {@link org.mule.api.MuleContext} instance. This listener delegates to the
39   * <i>MuleXmlConfigurationBuilder</i>.
40   * <p>
41   * The location of the configuration file can be specified in a init parameter called
42   * <i>org.mule.config</i>, the value can be a path on the local file system or on
43   * the classpath. If a config parameter is not specified a default <i>mule-config.xml</i>
44   * will be used.
45   * </p>
46   * 
47   * @see SpringXmlConfigurationBuilder
48   */
49  
50  public class MuleXmlBuilderContextListener implements ServletContextListener
51  {
52      /**
53       * One or more Mule config files.
54       */
55      public static final String INIT_PARAMETER_MULE_CONFIG = "org.mule.config";
56  
57      public static final String INIT_PARAMETER_MULE_APP_CONFIG = "org.mule.app.config";
58  
59      /**
60       * Name of the temp dir param as per the servlet spec. The object will be a java.io.File.
61       */
62      public static final String ATTR_JAVAX_SERVLET_CONTEXT_TEMPDIR = "javax.servlet.context.tempdir";
63  
64      protected MuleContext muleContext;
65  
66      protected transient final Log logger = LogFactory.getLog(MuleXmlBuilderContextListener.class);
67  
68      public void contextInitialized(ServletContextEvent event)
69      {
70          initialize(event.getServletContext());
71      }
72  
73      public void initialize(ServletContext context)
74      {
75          String config = context.getInitParameter(INIT_PARAMETER_MULE_CONFIG);
76          if (config == null)
77          {
78              config = getDefaultConfigResource();
79              if (logger.isDebugEnabled())
80              {
81                  logger.debug("No Mule config file(s) specified, using default: " + config);
82              }
83          }
84          else
85          {
86              if (logger.isDebugEnabled())
87              {
88                  logger.debug("Mule config file(s): " + config);
89              }
90          }
91  
92          try
93          {
94              muleContext = createMuleContext(config, context);
95              context.setAttribute(MuleProperties.MULE_CONTEXT_PROPERTY, muleContext);
96              muleContext.start();
97          }
98          catch (MuleException ex)
99          {
100             context.log(ex.getMessage(), ex);
101             // Logging is not configured OOTB for Tomcat, so we'd better make a
102             // start-up failure plain to see.
103             ex.printStackTrace();
104         }
105         catch (Error error)
106         {
107             // WSAD doesn't always report the java.lang.Error, log it
108             context.log(error.getMessage(), error);
109             // Logging is not configured OOTB for Tomcat, so we'd better make a
110             // start-up failure plain to see.
111             error.printStackTrace();
112             throw error;
113         }
114     }
115 
116     /**
117      * Creates the MuleContext based on the configuration resource(s) and possibly 
118      * init parameters for the Servlet.
119      */
120     protected MuleContext createMuleContext(String configResource, ServletContext servletContext)
121         throws ConfigurationException, InitialisationException
122     {
123         String serverId = StringUtils.defaultIfEmpty(servletContext.getInitParameter("mule.serverId"), null);
124 
125         // serverId will be used as a sub-folder in Mule working directory (.mule)
126 
127         if (serverId == null)
128         {
129             // guess this app's context name from the temp/work dir the container created us
130             // Servlet 2.5 has servletContext.getContextPath(), but we can't force users to upgrade yet
131             final File tempDir = (File) servletContext.getAttribute(ATTR_JAVAX_SERVLET_CONTEXT_TEMPDIR);
132             final String contextName = FilenameUtils.getBaseName(tempDir.toString());
133             serverId = contextName;
134         }
135 
136         WebappMuleXmlConfigurationBuilder builder = new WebappMuleXmlConfigurationBuilder(servletContext, configResource);
137         MuleContextFactory muleContextFactory = new DefaultMuleContextFactory();
138 
139         String muleAppConfig = servletContext.getInitParameter(INIT_PARAMETER_MULE_APP_CONFIG) != null
140             ? servletContext.getInitParameter(INIT_PARAMETER_MULE_APP_CONFIG)
141             : PropertiesMuleConfigurationFactory.getMuleAppConfiguration(configResource);
142         
143         DefaultMuleConfiguration muleConfiguration = new PropertiesMuleConfigurationFactory(muleAppConfig).createConfiguration();
144 
145         /*
146             We deliberately enable container mode here to allow for multi-tenant environment (multiple WARs
147             embedding Mule instance each). See property javadocs for more info.
148          */
149         muleConfiguration.setContainerMode(true);
150 
151         if (serverId != null)
152         {
153             muleConfiguration.setId(serverId);
154         }
155         MuleContextBuilder muleContextBuilder = new DefaultMuleContextBuilder();
156         muleContextBuilder.setMuleConfiguration(muleConfiguration);
157 
158         // Support Spring-first configuration in webapps
159         final ApplicationContext parentContext = (ApplicationContext) servletContext.getAttribute(
160                                                         WebApplicationContext.ROOT_WEB_APPLICATION_CONTEXT_ATTRIBUTE);
161         if (parentContext != null)
162         {
163             builder.setParentContext(parentContext);
164         }
165         return muleContextFactory.createMuleContext(builder, muleContextBuilder);
166     }
167 
168     /**
169      * If no config location resource is configured on the servlet context, the value
170      * returned from this method will be used to initialise the MuleManager.
171      * 
172      * @return the default config resource location
173      */
174     protected String getDefaultConfigResource()
175     {
176         return MuleServer.DEFAULT_CONFIGURATION;
177     }
178 
179     public void contextDestroyed(ServletContextEvent event)
180     {
181         destroy();
182     }
183 
184     public void destroy()
185     {
186         if (muleContext != null)
187         {
188             if (!muleContext.isDisposing() || !muleContext.isDisposed())
189             {
190                 muleContext.dispose();
191             }
192         }
193     }
194 }