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