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