001    /**
002     * Copyright (c) 2000-present 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.dao.orm.hibernate;
016    
017    import com.liferay.portal.kernel.concurrent.ConcurrentReferenceKeyHashMap;
018    import com.liferay.portal.kernel.dao.orm.DynamicQuery;
019    import com.liferay.portal.kernel.dao.orm.DynamicQueryFactory;
020    import com.liferay.portal.kernel.log.Log;
021    import com.liferay.portal.kernel.log.LogFactoryUtil;
022    import com.liferay.portal.kernel.memory.FinalizeManager;
023    import com.liferay.portal.kernel.security.pacl.permission.PortalRuntimePermission;
024    import com.liferay.portal.kernel.util.ClassLoaderUtil;
025    import com.liferay.portal.security.lang.DoPrivilegedUtil;
026    
027    import java.security.PrivilegedAction;
028    
029    import java.util.HashMap;
030    import java.util.Map;
031    import java.util.concurrent.ConcurrentMap;
032    
033    import org.hibernate.criterion.DetachedCriteria;
034    
035    /**
036     * @author Brian Wing Shun Chan
037     */
038    public class DynamicQueryFactoryImpl implements DynamicQueryFactory {
039    
040            @Override
041            public DynamicQuery forClass(Class<?> clazz) {
042                    clazz = getImplClass(clazz, null);
043    
044                    return DoPrivilegedUtil.wrap(
045                            new DynamicQueryPrivilegedAction(clazz, null));
046            }
047    
048            @Override
049            public DynamicQuery forClass(Class<?> clazz, ClassLoader classLoader) {
050                    clazz = getImplClass(clazz, classLoader);
051    
052                    return DoPrivilegedUtil.wrap(
053                            new DynamicQueryPrivilegedAction(clazz, null));
054            }
055    
056            @Override
057            public DynamicQuery forClass(Class<?> clazz, String alias) {
058                    clazz = getImplClass(clazz, null);
059    
060                    return DoPrivilegedUtil.wrap(
061                            new DynamicQueryPrivilegedAction(clazz, alias));
062            }
063    
064            @Override
065            public DynamicQuery forClass(
066                    Class<?> clazz, String alias, ClassLoader classLoader) {
067    
068                    clazz = getImplClass(clazz, classLoader);
069    
070                    return DoPrivilegedUtil.wrap(
071                            new DynamicQueryPrivilegedAction(clazz, alias));
072            }
073    
074            protected Class<?> getImplClass(Class<?> clazz, ClassLoader classLoader) {
075                    Class<?> implClass = clazz;
076    
077                    String className = clazz.getName();
078    
079                    if (!className.endsWith("Impl")) {
080                            if (classLoader == null) {
081                                    classLoader = ClassLoaderUtil.getContextClassLoader();
082                            }
083    
084                            Package pkg = clazz.getPackage();
085    
086                            String implClassName =
087                                    pkg.getName() + ".impl." + clazz.getSimpleName() + "Impl";
088    
089                            try {
090                                    implClass = getImplClass(implClassName, classLoader);
091                            }
092                            catch (Exception e1) {
093                                    if (classLoader != _portalClassLoader) {
094                                            try {
095                                                    implClass = getImplClass(
096                                                            implClassName, _portalClassLoader);
097                                            }
098                                            catch (Exception e2) {
099                                                    _log.error("Unable find model " + implClassName, e2);
100                                            }
101                                    }
102                                    else {
103                                            _log.error("Unable find model " + implClassName, e1);
104                                    }
105                            }
106                    }
107    
108                    PortalRuntimePermission.checkDynamicQuery(implClass);
109    
110                    return implClass;
111            }
112    
113            protected Class<?> getImplClass(
114                            String implClassName, ClassLoader classLoader)
115                    throws ClassNotFoundException {
116    
117                    Map<String, Class<?>> classes = _classes.get(classLoader);
118    
119                    if (classes == null) {
120                            classes = new HashMap<>();
121    
122                            _classes.put(classLoader, classes);
123                    }
124    
125                    Class<?> clazz = classes.get(implClassName);
126    
127                    if (clazz == null) {
128                            clazz = classLoader.loadClass(implClassName);
129    
130                            classes.put(implClassName, clazz);
131                    }
132    
133                    return clazz;
134            }
135    
136            private static final Log _log = LogFactoryUtil.getLog(
137                    DynamicQueryFactoryImpl.class);
138    
139            private static final
140                    ConcurrentMap<ClassLoader, Map<String, Class<?>>> _classes =
141                            new ConcurrentReferenceKeyHashMap<>(
142                                    FinalizeManager.WEAK_REFERENCE_FACTORY);
143    
144            private final ClassLoader _portalClassLoader =
145                    DynamicQueryFactoryImpl.class.getClassLoader();
146    
147            private class DynamicQueryPrivilegedAction
148                    implements PrivilegedAction<DynamicQuery> {
149    
150                    public DynamicQueryPrivilegedAction(Class<?> clazz, String alias) {
151                            _clazz = clazz;
152                            _alias = alias;
153                    }
154    
155                    @Override
156                    public DynamicQuery run() {
157                            if (_alias != null) {
158                                    return new DynamicQueryImpl(
159                                            DetachedCriteria.forClass(_clazz, _alias));
160                            }
161    
162                            return new DynamicQueryImpl(DetachedCriteria.forClass(_clazz));
163                    }
164    
165                    private final String _alias;
166                    private final Class<?> _clazz;
167    
168            }
169    
170    }