/** * Copyright (c) 2000-present Liferay, Inc. All rights reserved. * * This library is free software; you can redistribute it and/or modify it under * the terms of the GNU Lesser General Public License as published by the Free * Software Foundation; either version 2.1 of the License, or (at your option) * any later version. * * This library is distributed in the hope that it will be useful, but WITHOUT * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS * FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more * details. */ package com.liferay.portal.dao.orm.hibernate; import com.liferay.portal.kernel.annotation.ImplementationClassName; import com.liferay.portal.kernel.concurrent.ConcurrentReferenceKeyHashMap; import com.liferay.portal.kernel.dao.orm.DynamicQuery; import com.liferay.portal.kernel.dao.orm.DynamicQueryFactory; import com.liferay.portal.kernel.log.Log; import com.liferay.portal.kernel.log.LogFactoryUtil; import com.liferay.portal.kernel.memory.FinalizeManager; import com.liferay.portal.kernel.security.pacl.permission.PortalRuntimePermission; import com.liferay.portal.security.lang.DoPrivilegedUtil; import java.security.PrivilegedAction; import java.util.HashMap; import java.util.Map; import java.util.concurrent.ConcurrentMap; import org.hibernate.criterion.DetachedCriteria; /** * @author Brian Wing Shun Chan */ public class DynamicQueryFactoryImpl implements DynamicQueryFactory { @Override public DynamicQuery forClass(Class<?> clazz) { clazz = getImplClass(clazz, null); return DoPrivilegedUtil.wrap( new DynamicQueryPrivilegedAction(clazz, null)); } @Override public DynamicQuery forClass(Class<?> clazz, ClassLoader classLoader) { clazz = getImplClass(clazz, classLoader); return DoPrivilegedUtil.wrap( new DynamicQueryPrivilegedAction(clazz, null)); } @Override public DynamicQuery forClass(Class<?> clazz, String alias) { clazz = getImplClass(clazz, null); return DoPrivilegedUtil.wrap( new DynamicQueryPrivilegedAction(clazz, alias)); } @Override public DynamicQuery forClass( Class<?> clazz, String alias, ClassLoader classLoader) { clazz = getImplClass(clazz, classLoader); return DoPrivilegedUtil.wrap( new DynamicQueryPrivilegedAction(clazz, alias)); } protected Class<?> getImplClass(Class<?> clazz, ClassLoader classLoader) { ImplementationClassName implementationClassName = clazz.getAnnotation( ImplementationClassName.class); if (implementationClassName == null) { String className = clazz.getName(); if (!className.endsWith("Impl")) { _log.error("Unable find model for " + clazz); } PortalRuntimePermission.checkDynamicQuery(clazz); return clazz; } Class<?> implClass = clazz; String implClassName = implementationClassName.value(); try { implClass = getImplClass(implClassName, classLoader); } catch (Exception e1) { if (classLoader != _portalClassLoader) { try { implClass = getImplClass(implClassName, _portalClassLoader); } catch (Exception e2) { _log.error("Unable find model " + implClassName, e2); } } else { _log.error("Unable find model " + implClassName, e1); } } PortalRuntimePermission.checkDynamicQuery(implClass); return implClass; } protected Class<?> getImplClass( String implClassName, ClassLoader classLoader) throws ClassNotFoundException { Map<String, Class<?>> classes = _classes.get(classLoader); if (classes == null) { classes = new HashMap<>(); _classes.put(classLoader, classes); } Class<?> clazz = classes.get(implClassName); if (clazz == null) { clazz = classLoader.loadClass(implClassName); classes.put(implClassName, clazz); } return clazz; } private static final Log _log = LogFactoryUtil.getLog( DynamicQueryFactoryImpl.class); private static final ConcurrentMap<ClassLoader, Map<String, Class<?>>> _classes = new ConcurrentReferenceKeyHashMap<>( FinalizeManager.WEAK_REFERENCE_FACTORY); private final ClassLoader _portalClassLoader = DynamicQueryFactoryImpl.class.getClassLoader(); private static class DynamicQueryPrivilegedAction implements PrivilegedAction<DynamicQuery> { public DynamicQueryPrivilegedAction(Class<?> clazz, String alias) { _clazz = clazz; _alias = alias; } @Override public DynamicQuery run() { if (_alias != null) { return new DynamicQueryImpl( DetachedCriteria.forClass(_clazz, _alias)); } return new DynamicQueryImpl(DetachedCriteria.forClass(_clazz)); } private final String _alias; private final Class<?> _clazz; } }