001    /**
002     * Copyright (c) 2000-2013 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    
032    /**
033     * @author Brian Wing Shun Chan
034     * @author Miguel Pastor
035     */
036    @DoPrivileged
037    public class BeanLocatorImpl implements BeanLocator {
038    
039            public static final String VELOCITY_SUFFIX = ".velocity";
040    
041            public BeanLocatorImpl(
042                    ClassLoader classLoader, ApplicationContext applicationContext) {
043    
044                    _classLoader = classLoader;
045                    _applicationContext = applicationContext;
046            }
047    
048            public ApplicationContext getApplicationContext() {
049                    return _applicationContext;
050            }
051    
052            @Override
053            public ClassLoader getClassLoader() {
054                    PortalRuntimePermission.checkGetClassLoader(_paclServletContextName);
055    
056                    return _classLoader;
057            }
058    
059            @Override
060            public String[] getNames() {
061                    return _applicationContext.getBeanDefinitionNames();
062            }
063    
064            @Override
065            public Class<?> getType(String name) {
066                    try {
067                            return _applicationContext.getType(name);
068                    }
069                    catch (Exception e) {
070                            throw new BeanLocatorException(e);
071                    }
072            }
073    
074            @Override
075            public <T> Map<String, T> locate(Class<T> clazz)
076                    throws BeanLocatorException {
077    
078                    try {
079                            return doLocate(clazz);
080                    }
081                    catch (SecurityException se) {
082                            throw se;
083                    }
084                    catch (Exception e) {
085                            throw new BeanLocatorException(e);
086                    }
087            }
088    
089            @Override
090            public Object locate(String name) throws BeanLocatorException {
091                    try {
092                            return doLocate(name);
093                    }
094                    catch (SecurityException se) {
095                            throw se;
096                    }
097                    catch (Exception e) {
098                            throw new BeanLocatorException(e);
099                    }
100            }
101    
102            public void setPACLServletContextName(String paclServletContextName) {
103                    _paclServletContextName = paclServletContextName;
104            }
105    
106            /**
107             * This method ensures the calls stack is the proper length.
108             */
109            protected <T> Map<String, T> doLocate(Class<T> clazz) throws Exception {
110                    PortalRuntimePermission.checkGetBeanProperty(
111                            _paclServletContextName, clazz);
112    
113                    return _applicationContext.getBeansOfType(clazz);
114            }
115    
116            protected Object doLocate(String name) throws Exception {
117                    if (_log.isDebugEnabled()) {
118                            _log.debug("Locating " + name);
119                    }
120    
121                    if (name.equals("portletClassLoader")) {
122                            PortalRuntimePermission.checkGetClassLoader(
123                                    _paclServletContextName);
124                    }
125    
126                    Object bean = null;
127    
128                    if (name.endsWith(VELOCITY_SUFFIX)) {
129                            Object velocityBean = _velocityBeans.get(name);
130    
131                            if (velocityBean == null) {
132                                    String originalName = name.substring(
133                                            0, name.length() - VELOCITY_SUFFIX.length());
134    
135                                    Object curBean = _applicationContext.getBean(originalName);
136    
137                                    velocityBean = ProxyUtil.newProxyInstance(
138                                            _classLoader,
139                                            ReflectionUtil.getInterfaces(curBean, _classLoader),
140                                            new VelocityBeanHandler(curBean, _classLoader));
141    
142                                    _velocityBeans.put(name, velocityBean);
143                            }
144    
145                            bean = velocityBean;
146                    }
147                    else {
148                            bean = _applicationContext.getBean(name);
149                    }
150    
151                    if (bean == null) {
152                            return bean;
153                    }
154    
155                    if (bean instanceof DoPrivilegedBean) {
156                            PortalRuntimePermission.checkGetBeanProperty(bean.getClass());
157    
158                            return bean;
159                    }
160    
161                    return _pacl.getBean(bean, _classLoader);
162            }
163    
164            private static Log _log = LogFactoryUtil.getLog(BeanLocatorImpl.class);
165    
166            private static PACL _pacl = new NoPACL();
167    
168            private ApplicationContext _applicationContext;
169            private ClassLoader _classLoader;
170            private String _paclServletContextName;
171            private Map<String, Object> _velocityBeans =
172                    new ConcurrentHashMap<String, Object>();
173    
174            private static class NoPACL implements PACL {
175    
176                    @Override
177                    public Object getBean(Object bean, ClassLoader classLoader) {
178                            return bean;
179                    }
180    
181            }
182    
183            public static interface PACL {
184    
185                    public Object getBean(Object bean, ClassLoader classLoader);
186    
187            }
188    
189    }