001: /*
002: * $Id: WebappMuleXmlConfigurationBuilder.java 10789 2008-02-12 20:04:43Z dfeist $
003: * --------------------------------------------------------------------------------------
004: * Copyright (c) MuleSource, Inc. All rights reserved. http://www.mulesource.com
005: *
006: * The software in this package is published under the terms of the CPAL v1.0
007: * license, a copy of which has been included with this distribution in the
008: * LICENSE.txt file.
009: */
010:
011: package org.mule.config.builders;
012:
013: import org.mule.api.MuleContext;
014: import org.mule.api.config.ConfigurationException;
015: import org.mule.api.registry.Registry;
016: import org.mule.config.ConfigResource;
017: import org.mule.config.spring.MuleApplicationContext;
018: import org.mule.config.spring.SpringXmlConfigurationBuilder;
019:
020: import java.io.FileNotFoundException;
021: import java.io.IOException;
022: import java.io.InputStream;
023:
024: import javax.servlet.ServletContext;
025:
026: import org.apache.commons.logging.Log;
027: import org.apache.commons.logging.LogFactory;
028: import org.springframework.beans.BeansException;
029: import org.springframework.beans.factory.access.BeanFactoryLocator;
030: import org.springframework.context.ApplicationContext;
031: import org.springframework.context.ApplicationContextException;
032: import org.springframework.context.access.ContextSingletonBeanFactoryLocator;
033: import org.springframework.core.io.AbstractResource;
034: import org.springframework.core.io.ClassPathResource;
035: import org.springframework.core.io.Resource;
036: import org.springframework.util.Assert;
037: import org.springframework.util.ClassUtils;
038: import org.springframework.util.StringUtils;
039: import org.springframework.web.context.ContextLoader;
040: import org.springframework.web.context.support.ServletContextResource;
041:
042: /**
043: * <code>WebappMuleXmlConfigurationBuilder</code> will first try and load config resources using the
044: * ServletContext and if this fails then it will attempt to load config resource from the classpath.
045: * <li> ServletContext resources should be relative to the webapp root directory and start with '/'.
046: * <li> Classpath resources should be in the webapp classpath and should not start with '/'.
047: *
048: * @see org.mule.config.builders.SpringXmlConfigurationBuilder
049: */
050: public class WebappMuleXmlConfigurationBuilder extends
051: SpringXmlConfigurationBuilder {
052: /**
053: * Logger used by this class
054: */
055: protected transient final Log logger = LogFactory
056: .getLog(getClass());
057:
058: private ServletContext context;
059:
060: public WebappMuleXmlConfigurationBuilder(
061: ServletContext servletContext, String configResources)
062: throws ConfigurationException {
063: super (configResources);
064: context = servletContext;
065: }
066:
067: public WebappMuleXmlConfigurationBuilder(
068: ServletContext servletContext, String[] configResources)
069: throws ConfigurationException {
070: super (configResources);
071: context = servletContext;
072: }
073:
074: public WebappMuleXmlConfigurationBuilder(
075: ServletContext servletContext,
076: ConfigResource[] configResources) {
077: super (configResources);
078: context = servletContext;
079: }
080:
081: protected void createSpringParentRegistry(MuleContext muleContext,
082: Registry registry, ConfigResource[] all) {
083: Resource[] servletContextResources = new Resource[all.length];
084: for (int i = 0; i < all.length; i++) {
085: servletContextResources[i] = new ServletContextOrClassPathResource(
086: context, all[i].getResourceName());
087: }
088:
089: parentContext = loadParentContext(context);
090:
091: try {
092: if (parentContext != null) {
093: new MuleApplicationContext(muleContext, registry,
094: servletContextResources, parentContext);
095: } else {
096: new MuleApplicationContext(muleContext, registry,
097: servletContextResources);
098: }
099: } catch (BeansException e) {
100: // If creation of MuleApplicationContext fails, remove
101: // TransientRegistry->SpringRegistry parent relationship
102: registry.setParent(null);
103: throw e;
104: } catch (IOException e) {
105: registry.setParent(null);
106: throw new ApplicationContextException(
107: "Failed to load config resource", e);
108: }
109: }
110:
111: /**
112: * Used to lookup parent spring ApplicationContext. This allows a parent spring ApplicatonContet to be
113: * provided in the same way you would configure a parent ApplicationContext for a spring
114: * WebAppplicationContext
115: *
116: * @param servletContext
117: * @return
118: * @throws BeansException
119: */
120: protected ApplicationContext loadParentContext(
121: ServletContext servletContext) throws BeansException {
122:
123: ApplicationContext parentContext = null;
124: String locatorFactorySelector = servletContext
125: .getInitParameter(ContextLoader.LOCATOR_FACTORY_SELECTOR_PARAM);
126: String parentContextKey = servletContext
127: .getInitParameter(ContextLoader.LOCATOR_FACTORY_KEY_PARAM);
128:
129: if (parentContextKey != null) {
130: // locatorFactorySelector may be null, indicating the default
131: // "classpath*:beanRefContext.xml"
132: BeanFactoryLocator locator = ContextSingletonBeanFactoryLocator
133: .getInstance(locatorFactorySelector);
134: if (logger.isDebugEnabled()) {
135: logger
136: .debug("Getting parent context definition: using parent context key of '"
137: + parentContextKey
138: + "' with BeanFactoryLocator");
139: }
140: parentContext = (ApplicationContext) locator
141: .useBeanFactory(parentContextKey).getFactory();
142: }
143:
144: return parentContext;
145: }
146:
147: }
148:
149: /**
150: * Combines {@link ServletContextResource} and {@link ClassPathResource} to create a {@link Resource}
151: * implementation that first tries to load a resource using the {@link ServletContext} and then fails back to
152: * use try to load the resource from the classpath.
153: */
154: class ServletContextOrClassPathResource extends AbstractResource {
155:
156: private final ServletContext servletContext;
157:
158: private final String path;
159:
160: public ServletContextOrClassPathResource(
161: ServletContext servletContext, String path) {
162: Assert
163: .notNull(servletContext,
164: "Cannot resolve ServletContextResource without ServletContext");
165: this .servletContext = servletContext;
166: // check path
167: Assert.notNull(path, "path is required");
168: this .path = StringUtils.cleanPath(path);
169: }
170:
171: public InputStream getInputStream() throws IOException {
172: InputStream is = getServletContextInputStream();
173: if (is == null) {
174: is = getClasspathInputStream();
175: }
176: if (is == null) {
177: throw new FileNotFoundException(getDescription()
178: + " cannot be opened because it does not exist");
179: }
180: return is;
181: }
182:
183: protected InputStream getServletContextInputStream() {
184: String servletContextPath = path;
185: if (!servletContextPath.startsWith("/")) {
186: servletContextPath = "/" + servletContextPath;
187: }
188: return servletContext.getResourceAsStream(servletContextPath);
189: }
190:
191: protected InputStream getClasspathInputStream() {
192: String classpathPath = path;
193: if (classpathPath.startsWith("/")) {
194: classpathPath = classpathPath.substring(1);
195: }
196: return ClassUtils.getDefaultClassLoader().getResourceAsStream(
197: classpathPath);
198: }
199:
200: public String getDescription() {
201: return path;
202: }
203:
204: }
|