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            /**
131             * This method ensures the calls stack is the proper length.
132             */
133            protected <T> Map<String, T> doLocate(Class<T> clazz) throws Exception {
134                    PortalRuntimePermission.checkGetBeanProperty(
135                            _paclServletContextName, clazz);
136    
137                    return _applicationContext.getBeansOfType(clazz);
138            }
139    
140            protected Object doLocate(String name) throws Exception {
141                    if (_log.isDebugEnabled()) {
142                            _log.debug("Locating " + name);
143                    }
144    
145                    if (name.equals("portletClassLoader")) {
146                            PortalRuntimePermission.checkGetClassLoader(
147                                    _paclServletContextName);
148                    }
149    
150                    Object bean = null;
151    
152                    if (name.endsWith(VELOCITY_SUFFIX)) {
153                            Object velocityBean = _velocityBeans.get(name);
154    
155                            if (velocityBean == null) {
156                                    String originalName = name.substring(
157                                            0, name.length() - VELOCITY_SUFFIX.length());
158    
159                                    Object curBean = _applicationContext.getBean(originalName);
160    
161                                    velocityBean = ProxyUtil.newProxyInstance(
162                                            _classLoader,
163                                            ReflectionUtil.getInterfaces(curBean, _classLoader),
164                                            new VelocityBeanHandler(curBean, _classLoader));
165    
166                                    _velocityBeans.put(name, velocityBean);
167                            }
168    
169                            bean = velocityBean;
170                    }
171                    else {
172                            bean = _applicationContext.getBean(name);
173                    }
174    
175                    if (bean == null) {
176                            return bean;
177                    }
178    
179                    if (bean instanceof DoPrivilegedBean) {
180                            PortalRuntimePermission.checkGetBeanProperty(bean.getClass());
181    
182                            return bean;
183                    }
184    
185                    return _pacl.getBean(bean, _classLoader);
186            }
187    
188            private static Log _log = LogFactoryUtil.getLog(BeanLocatorImpl.class);
189    
190            private static PACL _pacl = new NoPACL();
191    
192            private ApplicationContext _applicationContext;
193            private ClassLoader _classLoader;
194            private Map<String, Object> _deprecatedBeans =
195                    new ConcurrentHashMap<String, Object>();
196            private String _paclServletContextName;
197            private Map<String, Object> _velocityBeans =
198                    new ConcurrentHashMap<String, Object>();
199    
200            private static class NoPACL implements PACL {
201    
202                    @Override
203                    public Object getBean(Object bean, ClassLoader classLoader) {
204                            return bean;
205                    }
206    
207            }
208    
209            public static interface PACL {
210    
211                    public Object getBean(Object bean, ClassLoader classLoader);
212    
213            }
214    
215    }