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.security.lang;
016    
017    import com.liferay.portal.kernel.log.Log;
018    import com.liferay.portal.kernel.log.LogFactoryUtil;
019    import com.liferay.portal.kernel.security.pacl.DoPrivileged;
020    import com.liferay.portal.kernel.util.ArrayUtil;
021    import com.liferay.portal.kernel.util.ProxyUtil;
022    import com.liferay.portal.kernel.util.ReflectionUtil;
023    import com.liferay.portal.util.ClassLoaderUtil;
024    
025    import java.security.AccessController;
026    import java.security.PrivilegedAction;
027    
028    import org.springframework.beans.BeansException;
029    import org.springframework.beans.factory.config.BeanPostProcessor;
030    
031    /**
032     * @author Raymond Augé
033     */
034    public class DoPrivilegedFactory implements BeanPostProcessor {
035    
036            public static <T> T wrap(T bean) {
037                    return AccessController.doPrivileged(new BeanPrivilegedAction<T>(bean));
038            }
039    
040            public DoPrivilegedFactory() {
041            }
042    
043            public Object postProcessAfterInitialization(Object bean, String beanName)
044                    throws BeansException {
045    
046                    if (SecurityManagerUtil.isPACLDisabled()) {
047                            return bean;
048                    }
049    
050                    Class<?> clazz = bean.getClass();
051    
052                    if (!_isDoPrivileged(clazz) && !_isFinderOrPersistence(beanName)) {
053                            return bean;
054                    }
055    
056                    if (_log.isDebugEnabled()) {
057                            _log.debug(
058                                    "Wrapping calls to bean " + beanName + " of type " +
059                                            clazz + " with access controller checking");
060                    }
061    
062                    return wrap(bean);
063            }
064    
065            public Object postProcessBeforeInitialization(Object bean, String beanName)
066                    throws BeansException {
067    
068                    return bean;
069            }
070    
071            private boolean _isDoPrivileged(Class<?> beanClass) {
072                    DoPrivileged doPrivileged = beanClass.getAnnotation(DoPrivileged.class);
073    
074                    while ((doPrivileged == null) &&
075                               (beanClass = beanClass.getSuperclass()) != null) {
076    
077                            doPrivileged = beanClass.getAnnotation(DoPrivileged.class);
078                    }
079    
080                    if (doPrivileged != null) {
081                            return true;
082                    }
083    
084                    return false;
085            }
086    
087            private boolean _isFinderOrPersistence(String beanName) {
088                    if (beanName.endsWith(_BEAN_NAME_SUFFIX_FINDER) ||
089                            beanName.endsWith(_BEAN_NAME_SUFFIX_PERSISTENCE)) {
090    
091                            return true;
092                    }
093    
094                    return false;
095            }
096    
097            private static final String _BEAN_NAME_SUFFIX_FINDER = "Finder";
098    
099            private static final String _BEAN_NAME_SUFFIX_PERSISTENCE = "Persistence";
100    
101            private static Log _log = LogFactoryUtil.getLog(DoPrivilegedFactory.class);
102    
103            private static class BeanPrivilegedAction <T>
104                    implements PrivilegedAction<T> {
105    
106                    public BeanPrivilegedAction(T bean) {
107                            _bean = bean;
108                    }
109    
110                    public T run() {
111                            Class<?> clazz = _bean.getClass();
112    
113                            if (clazz.isPrimitive()) {
114                                    return _bean;
115                            }
116    
117                            Package pkg = clazz.getPackage();
118    
119                            if (pkg != null) {
120                                    String packageName = pkg.getName();
121    
122                                    if (packageName.startsWith("java.")) {
123                                            return _bean;
124                                    }
125                            }
126    
127                            Class<?>[] interfaces = ReflectionUtil.getInterfaces(_bean);
128    
129                            if (interfaces.length <= 0) {
130                                    return _bean;
131                            }
132    
133                            interfaces = ArrayUtil.append(interfaces, DoPrivilegedBean.class);
134    
135                            try {
136                                    return (T)ProxyUtil.newProxyInstance(
137                                            ClassLoaderUtil.getPortalClassLoader(), interfaces,
138                                            new DoPrivilegedHandler(_bean));
139                            }
140                            catch (Exception e) {
141                                    if (_log.isWarnEnabled()) {
142                                            _log.warn(e, e);
143                                    }
144                            }
145    
146                            return _bean;
147                    }
148    
149                    private T _bean;
150    
151            }
152    
153    }