001    /**
002     * Copyright (c) 2000-present Liferay, Inc. All rights reserved.
003     *
004     * This library is free software; you can redistribute it and/or modify it under
005     * the terms of the GNU Lesser General Public License as published by the Free
006     * Software Foundation; either version 2.1 of the License, or (at your option)
007     * any later version.
008     *
009     * This library is distributed in the hope that it will be useful, but WITHOUT
010     * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
011     * FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more
012     * details.
013     */
014    
015    package com.liferay.portal.bean;
016    
017    import com.liferay.portal.kernel.bean.BeanLocator;
018    import com.liferay.portal.kernel.bean.BeanLocatorException;
019    import com.liferay.portal.kernel.log.Log;
020    import com.liferay.portal.kernel.log.LogFactoryUtil;
021    import com.liferay.portal.kernel.security.pacl.DoPrivileged;
022    import com.liferay.portal.kernel.security.pacl.permission.PortalRuntimePermission;
023    import com.liferay.portal.kernel.util.ProxyUtil;
024    import com.liferay.portal.kernel.util.ReflectionUtil;
025    import com.liferay.portal.security.lang.DoPrivilegedBean;
026    
027    import java.util.Map;
028    import java.util.concurrent.ConcurrentHashMap;
029    
030    import org.springframework.context.ApplicationContext;
031    import org.springframework.context.support.AbstractApplicationContext;
032    
033    /**
034     * @author Brian Wing Shun Chan
035     * @author Miguel Pastor
036     */
037    @DoPrivileged
038    public class BeanLocatorImpl implements BeanLocator {
039    
040            public static final String VELOCITY_SUFFIX = ".velocity";
041    
042            public BeanLocatorImpl(
043                    ClassLoader classLoader, ApplicationContext applicationContext) {
044    
045                    _classLoader = classLoader;
046                    _applicationContext = applicationContext;
047            }
048    
049            @Override
050            public void destroy() {
051                    if (_applicationContext instanceof AbstractApplicationContext) {
052                            AbstractApplicationContext abstractApplicationContext =
053                                    (AbstractApplicationContext)_applicationContext;
054    
055                            abstractApplicationContext.destroy();
056                    }
057    
058                    _applicationContext = null;
059            }
060    
061            public ApplicationContext getApplicationContext() {
062                    return _applicationContext;
063            }
064    
065            @Override
066            public ClassLoader getClassLoader() {
067                    PortalRuntimePermission.checkGetClassLoader(_paclServletContextName);
068    
069                    return _classLoader;
070            }
071    
072            @Override
073            public String[] getNames() {
074                    return _applicationContext.getBeanDefinitionNames();
075            }
076    
077            @Override
078            public Class<?> getType(String name) {
079                    try {
080                            return _applicationContext.getType(name);
081                    }
082                    catch (Exception e) {
083                            throw new BeanLocatorException(e);
084                    }
085            }
086    
087            @Override
088            public <T> Map<String, T> locate(Class<T> clazz)
089                    throws BeanLocatorException {
090    
091                    try {
092                            return doLocate(clazz);
093                    }
094                    catch (SecurityException se) {
095                            throw se;
096                    }
097                    catch (Exception e) {
098                            throw new BeanLocatorException(e);
099                    }
100            }
101    
102            @Override
103            public Object locate(String name) throws BeanLocatorException {
104                    try {
105                            return doLocate(name);
106                    }
107                    catch (SecurityException se) {
108                            throw se;
109                    }
110                    catch (Exception e) {
111                            throw new BeanLocatorException(e);
112                    }
113            }
114    
115            public void setPACLServletContextName(String paclServletContextName) {
116                    _paclServletContextName = paclServletContextName;
117            }
118    
119            public interface PACL {
120    
121                    public Object getBean(Object bean, ClassLoader classLoader);
122    
123            }
124    
125            /**
126             * This method ensures the calls stack is the proper length.
127             */
128            protected <T> Map<String, T> doLocate(Class<T> clazz) throws Exception {
129                    PortalRuntimePermission.checkGetBeanProperty(
130                            _paclServletContextName, clazz);
131    
132                    return _applicationContext.getBeansOfType(clazz);
133            }
134    
135            protected Object doLocate(String name) throws Exception {
136                    if (_log.isDebugEnabled()) {
137                            _log.debug("Locating " + name);
138                    }
139    
140                    if (name.equals("portletClassLoader")) {
141                            PortalRuntimePermission.checkGetClassLoader(
142                                    _paclServletContextName);
143                    }
144    
145                    Object bean = null;
146    
147                    if (name.endsWith(VELOCITY_SUFFIX)) {
148                            Object velocityBean = _velocityBeans.get(name);
149    
150                            if (velocityBean == null) {
151                                    String originalName = name.substring(
152                                            0, name.length() - VELOCITY_SUFFIX.length());
153    
154                                    Object curBean = _applicationContext.getBean(originalName);
155    
156                                    velocityBean = ProxyUtil.newProxyInstance(
157                                            _classLoader,
158                                            ReflectionUtil.getInterfaces(curBean, _classLoader),
159                                            new VelocityBeanHandler(curBean, _classLoader));
160    
161                                    _velocityBeans.put(name, velocityBean);
162                            }
163    
164                            bean = velocityBean;
165                    }
166                    else {
167                            bean = _applicationContext.getBean(name);
168                    }
169    
170                    if (bean == null) {
171                            return bean;
172                    }
173    
174                    if (bean instanceof DoPrivilegedBean) {
175                            PortalRuntimePermission.checkGetBeanProperty(bean.getClass());
176    
177                            return bean;
178                    }
179    
180                    return _pacl.getBean(bean, _classLoader);
181            }
182    
183            private static final Log _log = LogFactoryUtil.getLog(
184                    BeanLocatorImpl.class);
185    
186            private static final PACL _pacl = new NoPACL();
187    
188            private ApplicationContext _applicationContext;
189            private final ClassLoader _classLoader;
190            private String _paclServletContextName;
191            private final Map<String, Object> _velocityBeans =
192                    new ConcurrentHashMap<>();
193    
194            private static class NoPACL implements PACL {
195    
196                    @Override
197                    public Object getBean(Object bean, ClassLoader classLoader) {
198                            return bean;
199                    }
200    
201            }
202    
203    }