001/*
002 * Copyright 2002-2009 the original author or authors.
003 *
004 * Licensed under the Apache License, Version 2.0 (the "License");
005 * you may not use this file except in compliance with the License.
006 * You may obtain a copy of the License at
007 *
008 *      https://www.apache.org/licenses/LICENSE-2.0
009 *
010 * Unless required by applicable law or agreed to in writing, software
011 * distributed under the License is distributed on an "AS IS" BASIS,
012 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
013 * See the License for the specific language governing permissions and
014 * limitations under the License.
015 */
016
017package org.springframework.web.portlet.context;
018
019import java.io.IOException;
020
021import org.springframework.beans.BeansException;
022import org.springframework.beans.factory.support.DefaultListableBeanFactory;
023import org.springframework.beans.factory.xml.ResourceEntityResolver;
024import org.springframework.beans.factory.xml.XmlBeanDefinitionReader;
025
026/**
027 * Portlet-based {@link org.springframework.web.context.WebApplicationContext}
028 * implementation which takes its configuration from XML documents, understood
029 * by an {@link org.springframework.beans.factory.xml.XmlBeanDefinitionReader}.
030 * This is essentially the equivalent of
031 * {@link org.springframework.context.support.AbstractXmlApplicationContext}
032 * for a portlet environment.
033 *
034 * <p>By default, the configuration will be taken from "/WEB-INF/applicationContext.xml"
035 * for the root context, and "/WEB-INF/test-portlet.xml" for a context with the namespace
036 * "test-portlet" (like for a DispatcherPortlet instance with the portlet-name "test").
037 *
038 * <p>The config location defaults can be overridden via the "contextConfigLocation"
039 * portlet init-param of {@link org.springframework.web.portlet.FrameworkPortlet}.
040 * Config locations can either denote concrete files like "/WEB-INF/context.xml"
041 * or Ant-style patterns like "/WEB-INF/*-context.xml" (see
042 * {@link org.springframework.util.PathMatcher} javadoc for pattern details).
043 *
044 * <p>Note: In case of multiple config locations, later bean definitions will
045 * override ones defined in earlier loaded files. This can be leveraged to
046 * deliberately override certain bean definitions via an extra XML file.
047 *
048 * <p><b>For a Portlet-based context that reads in a different bean definition format,
049 * create an analogous subclass of {@link AbstractRefreshablePortletApplicationContext}.</b>
050 * Such a context implementation can be specified as "contextClass" init-param
051 * for a FrameworkPortlet instance.
052 *
053 * @author Juergen Hoeller
054 * @author John A. Lewis
055 * @since 2.0
056 * @see #setNamespace
057 * @see #setConfigLocations
058 * @see org.springframework.beans.factory.xml.XmlBeanDefinitionReader
059 * @see org.springframework.web.portlet.FrameworkPortlet#initPortletApplicationContext
060 */
061public class XmlPortletApplicationContext extends AbstractRefreshablePortletApplicationContext {
062
063        /** Default config location for the root context */
064        public static final String DEFAULT_CONFIG_LOCATION = "/WEB-INF/applicationContext.xml";
065
066        /** Default prefix for building a config location for a namespace */
067        public static final String DEFAULT_CONFIG_LOCATION_PREFIX = "/WEB-INF/";
068
069        /** Default suffix for building a config location for a namespace */
070        public static final String DEFAULT_CONFIG_LOCATION_SUFFIX = ".xml";
071
072
073        /**
074         * Loads the bean definitions via an XmlBeanDefinitionReader.
075         * @see org.springframework.beans.factory.xml.XmlBeanDefinitionReader
076         * @see #initBeanDefinitionReader
077         * @see #loadBeanDefinitions
078         */
079        @Override
080        protected void loadBeanDefinitions(DefaultListableBeanFactory beanFactory) throws BeansException, IOException {
081                // Create a new XmlBeanDefinitionReader for the given BeanFactory.
082                XmlBeanDefinitionReader beanDefinitionReader = new XmlBeanDefinitionReader(beanFactory);
083
084                // Configure the bean definition reader with this context's
085                // resource loading environment.
086                beanDefinitionReader.setEnvironment(this.getEnvironment());
087                beanDefinitionReader.setResourceLoader(this);
088                beanDefinitionReader.setEntityResolver(new ResourceEntityResolver(this));
089
090                // Allow a subclass to provide custom initialization of the reader,
091                // then proceed with actually loading the bean definitions.
092                initBeanDefinitionReader(beanDefinitionReader);
093                loadBeanDefinitions(beanDefinitionReader);
094        }
095
096        /**
097         * Initialize the bean definition reader used for loading the bean
098         * definitions of this context. Default implementation is empty.
099         * <p>Can be overridden in subclasses, e.g. for turning off XML validation
100         * or using a different XmlBeanDefinitionParser implementation.
101         * @param beanDefinitionReader the bean definition reader used by this context
102         * @see org.springframework.beans.factory.xml.XmlBeanDefinitionReader#setValidationMode
103         * @see org.springframework.beans.factory.xml.XmlBeanDefinitionReader#setDocumentReaderClass
104         */
105        protected void initBeanDefinitionReader(XmlBeanDefinitionReader beanDefinitionReader) {
106        }
107
108        /**
109         * Load the bean definitions with the given XmlBeanDefinitionReader.
110         * <p>The lifecycle of the bean factory is handled by the refreshBeanFactory method;
111         * therefore this method is just supposed to load and/or register bean definitions.
112         * <p>Delegates to a ResourcePatternResolver for resolving location patterns
113         * into Resource instances.
114         * @throws org.springframework.beans.BeansException in case of bean registration errors
115         * @throws java.io.IOException if the required XML document isn't found
116         * @see #refreshBeanFactory
117         * @see #getConfigLocations
118         * @see #getResources
119         * @see #getResourcePatternResolver
120         */
121        protected void loadBeanDefinitions(XmlBeanDefinitionReader reader) throws BeansException, IOException {
122                String[] configLocations = getConfigLocations();
123                if (configLocations != null) {
124                        for (int i = 0; i < configLocations.length; i++) {
125                                reader.loadBeanDefinitions(configLocations[i]);
126                        }
127                }
128        }
129
130        /**
131         * The default location for the root context is "/WEB-INF/applicationContext.xml",
132         * and "/WEB-INF/test-portlet.xml" for a context with the namespace "test-portlet"
133         * (like for a DispatcherPortlet instance with the portlet-name "test").
134         */
135        @Override
136        protected String[] getDefaultConfigLocations() {
137                if (getNamespace() != null) {
138                        return new String[] {DEFAULT_CONFIG_LOCATION_PREFIX + getNamespace() + DEFAULT_CONFIG_LOCATION_SUFFIX};
139                }
140                else {
141                        return new String[] {DEFAULT_CONFIG_LOCATION};
142                }
143        }
144
145}