001    /**
002     * Copyright (c) 2000-2012 Liferay, Inc. All rights reserved.
003     *
004     * The contents of this file are subject to the terms of the Liferay Enterprise
005     * Subscription License ("License"). You may not use this file except in
006     * compliance with the License. You can obtain a copy of the License by
007     * contacting Liferay, Inc. See the License for the specific language governing
008     * permissions and limitations under the License, including but not limited to
009     * distribution rights of the Software.
010     *
011     *
012     *
013     */
014    
015    package com.liferay.portal.spring.context;
016    
017    import com.liferay.portal.kernel.configuration.Configuration;
018    import com.liferay.portal.kernel.configuration.ConfigurationFactoryUtil;
019    import com.liferay.portal.kernel.log.Log;
020    import com.liferay.portal.kernel.log.LogFactoryUtil;
021    import com.liferay.portal.kernel.portlet.PortletClassLoaderUtil;
022    import com.liferay.portal.kernel.util.AggregateClassLoader;
023    import com.liferay.portal.kernel.util.ArrayUtil;
024    import com.liferay.portal.kernel.util.PreloadClassLoader;
025    import com.liferay.portal.kernel.util.PropsKeys;
026    import com.liferay.portal.security.lang.PortalSecurityManagerThreadLocal;
027    import com.liferay.portal.security.pacl.PACLClassLoaderUtil;
028    import com.liferay.portal.security.pacl.PACLPolicyManager;
029    import com.liferay.portal.spring.util.FilterClassLoader;
030    import com.liferay.portal.util.PropsValues;
031    
032    import java.io.FileNotFoundException;
033    
034    import java.util.HashMap;
035    import java.util.Map;
036    
037    import org.springframework.beans.factory.xml.XmlBeanDefinitionReader;
038    import org.springframework.web.context.support.XmlWebApplicationContext;
039    
040    /**
041     * <p>
042     * This web application context will first load bean definitions in the
043     * portalContextConfigLocation parameter in web.xml. Then, the context will load
044     * bean definitions specified by the property "spring.configs" in
045     * service.properties.
046     * </p>
047     *
048     * @author Brian Wing Shun Chan
049     * @see    PortletContextLoader
050     * @see    PortletContextLoaderListener
051     */
052    public class PortletApplicationContext extends XmlWebApplicationContext {
053    
054            public static ClassLoader getBeanClassLoader() {
055                    if (_isUseRestrictedClassLoader()) {
056                            boolean enabled = PortalSecurityManagerThreadLocal.isEnabled();
057    
058                            try {
059                                    PortalSecurityManagerThreadLocal.setEnabled(false);
060    
061                                    return new PreloadClassLoader(
062                                            PortletClassLoaderUtil.getClassLoader(), _classes);
063                            }
064                            finally {
065                                    PortalSecurityManagerThreadLocal.setEnabled(enabled);
066                            }
067                    }
068    
069                    ClassLoader beanClassLoader =
070                            AggregateClassLoader.getAggregateClassLoader(
071                                    new ClassLoader[] {
072                                            PortletClassLoaderUtil.getClassLoader(),
073                                            PACLClassLoaderUtil.getPortalClassLoader()
074                                    });
075    
076                    return new FilterClassLoader(beanClassLoader);
077            }
078    
079            @Override
080            protected String[] getDefaultConfigLocations() {
081                    return new String[0];
082            }
083    
084            protected String[] getPortletConfigLocations() {
085                    String[] configLocations = getConfigLocations();
086    
087                    ClassLoader classLoader = PortletClassLoaderUtil.getClassLoader();
088    
089                    Configuration serviceBuilderPropertiesConfiguration = null;
090    
091                    try {
092                            serviceBuilderPropertiesConfiguration =
093                                    ConfigurationFactoryUtil.getConfiguration(
094                                            classLoader, "service");
095                    }
096                    catch (Exception e) {
097                            if (_log.isDebugEnabled()) {
098                                    _log.debug("Unable to read service.properties");
099                            }
100    
101                            return configLocations;
102                    }
103    
104                    return ArrayUtil.append(
105                            configLocations,
106                            serviceBuilderPropertiesConfiguration.getArray(
107                                    PropsKeys.SPRING_CONFIGS));
108            }
109    
110            @Override
111            protected void initBeanDefinitionReader(
112                    XmlBeanDefinitionReader xmlBeanDefinitionReader) {
113    
114                    xmlBeanDefinitionReader.setBeanClassLoader(getBeanClassLoader());
115            }
116    
117            @Override
118            protected void loadBeanDefinitions(
119                    XmlBeanDefinitionReader xmlBeanDefinitionReader) {
120    
121                    String[] configLocations = getPortletConfigLocations();
122    
123                    if (configLocations == null) {
124                            return;
125                    }
126    
127                    for (String configLocation : configLocations) {
128                            boolean checkReadFile =
129                                    PortalSecurityManagerThreadLocal.isCheckReadFile();
130    
131                            try {
132                                    PortalSecurityManagerThreadLocal.setCheckReadFile(false);
133    
134                                    xmlBeanDefinitionReader.loadBeanDefinitions(configLocation);
135                            }
136                            catch (Exception e) {
137                                    Throwable cause = e.getCause();
138    
139                                    if (cause instanceof FileNotFoundException) {
140                                            if (_log.isWarnEnabled()) {
141                                                    _log.warn(cause.getMessage());
142                                            }
143                                    }
144                                    else {
145                                            _log.error(e, e);
146                                    }
147                            }
148                            finally {
149                                    PortalSecurityManagerThreadLocal.setCheckReadFile(
150                                            checkReadFile);
151                            }
152                    }
153            }
154    
155            private static boolean _isUseRestrictedClassLoader() {
156                    return PACLPolicyManager.isActive();
157            }
158    
159            private static Log _log = LogFactoryUtil.getLog(
160                    PortletApplicationContext.class);
161    
162            private static Map<String, Class<?>> _classes =
163                    new HashMap<String, Class<?>>();
164    
165            static {
166                    for (String className :
167                                    PropsValues.
168                                            PORTAL_SECURITY_MANAGER_PRELOAD_CLASSLOADER_CLASSES) {
169    
170                            Class<?> clazz = null;
171    
172                            try {
173                                    clazz = Class.forName(className);
174                            }
175                            catch (ClassNotFoundException e) {
176                                    _log.error(e, e);
177                            }
178    
179                            _classes.put(clazz.getName(), clazz);
180                    }
181            }
182    
183    }