001    /**
002     * Copyright (c) 2000-2012 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.PACLConstants;
022    import com.liferay.portal.kernel.util.ProxyUtil;
023    import com.liferay.portal.kernel.util.StringPool;
024    import com.liferay.portal.security.pacl.PACLBeanHandler;
025    import com.liferay.portal.service.ResourceService;
026    import com.liferay.portal.service.persistence.BasePersistence;
027    import com.liferay.portal.service.persistence.ResourcePersistence;
028    
029    import java.security.Permission;
030    
031    import java.util.ArrayList;
032    import java.util.List;
033    import java.util.Map;
034    import java.util.concurrent.ConcurrentHashMap;
035    
036    import org.springframework.context.ApplicationContext;
037    
038    /**
039     * @author Brian Wing Shun Chan
040     * @author Miguel Pastor
041     */
042    @SuppressWarnings("deprecation")
043    public class BeanLocatorImpl implements BeanLocator {
044    
045            public static final String VELOCITY_SUFFIX = ".velocity";
046    
047            public BeanLocatorImpl(
048                    ClassLoader classLoader, ApplicationContext applicationContext) {
049    
050                    _classLoader = classLoader;
051                    _applicationContext = applicationContext;
052            }
053    
054            public ApplicationContext getApplicationContext() {
055                    return _applicationContext;
056            }
057    
058            public ClassLoader getClassLoader() {
059                    return _classLoader;
060            }
061    
062            public String[] getNames() {
063                    return _applicationContext.getBeanDefinitionNames();
064            }
065    
066            public Class<?> getType(String name) {
067                    try {
068                            return _applicationContext.getType(name);
069                    }
070                    catch (Exception e) {
071                            throw new BeanLocatorException(e);
072                    }
073            }
074    
075            public <T> Map<String, T> locate(Class<T> clazz) {
076                    try {
077                            return _applicationContext.getBeansOfType(clazz);
078                    }
079                    catch (Exception e) {
080                            throw new BeanLocatorException(e);
081                    }
082            }
083    
084            public Object locate(String name) throws BeanLocatorException {
085                    try {
086                            return doLocate(name);
087                    }
088                    catch (SecurityException se) {
089                            throw se;
090                    }
091                    catch (Exception e) {
092                            Object bean = _deprecatedBeans.get(name);
093    
094                            if (bean != null) {
095                                    return bean;
096                            }
097    
098                            if (name.equals(ResourcePersistence.class.getName())) {
099                                    bean = new ResourcePersistence() {};
100    
101                                    _deprecatedBeans.put(name, bean);
102    
103                                    return bean;
104                            }
105                            else if (name.equals(ResourceService.class.getName())) {
106                                    bean = new ResourceService() {};
107    
108                                    _deprecatedBeans.put(name, bean);
109    
110                                    return bean;
111                            }
112    
113                            throw new BeanLocatorException(e);
114                    }
115            }
116    
117            public void setPACLServletContextName(String paclServletContextName) {
118                    _paclServletContextName = paclServletContextName;
119            }
120    
121            public void setPACLWrapPersistence(boolean paclWrapPersistence) {
122                    _paclWrapPersistence = paclWrapPersistence;
123            }
124    
125            protected Object doLocate(String name) throws Exception {
126                    if (_log.isDebugEnabled()) {
127                            _log.debug("Locating " + name);
128                    }
129    
130                    if (name.equals("portletClassLoader")) {
131                            SecurityManager securityManager = System.getSecurityManager();
132    
133                            if (securityManager != null) {
134                                    Permission permission = new RuntimePermission(
135                                            PACLConstants.RUNTIME_PERMISSION_GET_CLASSLOADER.concat(
136                                                    StringPool.PERIOD).concat(_paclServletContextName));
137    
138                                    securityManager.checkPermission(permission);
139                            }
140                    }
141    
142                    if (name.endsWith(VELOCITY_SUFFIX)) {
143                            Object velocityBean = _velocityBeans.get(name);
144    
145                            if (velocityBean == null) {
146                                    String originalName = name.substring(
147                                            0, name.length() - VELOCITY_SUFFIX.length());
148    
149                                    Object bean = _applicationContext.getBean(originalName);
150    
151                                    velocityBean = ProxyUtil.newProxyInstance(
152                                            _classLoader, getInterfaces(bean),
153                                            new VelocityBeanHandler(bean, _classLoader));
154    
155                                    _velocityBeans.put(name, velocityBean);
156                            }
157    
158                            return velocityBean;
159                    }
160    
161                    Object bean = _applicationContext.getBean(name);
162    
163                    if (_paclWrapPersistence && (bean != null) &&
164                            (bean instanceof BasePersistence)) {
165    
166                            Object paclPersistenceBean = _paclPersistenceBeans.get(name);
167    
168                            if (paclPersistenceBean != null) {
169                                    return paclPersistenceBean;
170                            }
171    
172                            paclPersistenceBean = ProxyUtil.newProxyInstance(
173                                    _classLoader, getInterfaces(bean), new PACLBeanHandler(bean));
174    
175                            _paclPersistenceBeans.put(name, paclPersistenceBean);
176    
177                            return paclPersistenceBean;
178                    }
179    
180                    return bean;
181            }
182    
183            protected void getInterfaces(
184                    List<Class<?>> interfaceClasses, Class<?> clazz) {
185    
186                    for (Class<?> interfaceClass : clazz.getInterfaces()) {
187                            try {
188                                    interfaceClasses.add(
189                                            _classLoader.loadClass(interfaceClass.getName()));
190                            }
191                            catch (ClassNotFoundException cnfe) {
192                            }
193                    }
194            }
195    
196            protected Class<?>[] getInterfaces(Object object) {
197                    List<Class<?>> interfaceClasses = new ArrayList<Class<?>>();
198    
199                    Class<?> clazz = object.getClass();
200    
201                    getInterfaces(interfaceClasses, clazz);
202    
203                    Class<?> superClass = clazz.getSuperclass();
204    
205                    while (superClass != null) {
206                            getInterfaces(interfaceClasses, superClass);
207    
208                            superClass = superClass.getSuperclass();
209                    }
210    
211                    return interfaceClasses.toArray(new Class<?>[interfaceClasses.size()]);
212            }
213    
214            private static Log _log = LogFactoryUtil.getLog(BeanLocatorImpl.class);
215    
216            private ApplicationContext _applicationContext;
217            private ClassLoader _classLoader;
218            private Map<String, Object> _deprecatedBeans =
219                    new ConcurrentHashMap<String, Object>();
220            private Map<String, Object> _paclPersistenceBeans =
221                    new ConcurrentHashMap<String, Object>();
222            private String _paclServletContextName;
223            private boolean _paclWrapPersistence;
224            private Map<String, Object> _velocityBeans =
225                    new ConcurrentHashMap<String, Object>();
226    
227    }