/** * 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.kernel.portlet.bridges.mvc; import com.liferay.portal.kernel.log.Log; import com.liferay.portal.kernel.log.LogFactoryUtil; import com.liferay.portal.kernel.util.ClassUtil; import com.liferay.portal.kernel.util.InstanceFactory; import com.liferay.portal.kernel.util.StringBundler; import com.liferay.portal.kernel.util.StringPool; import com.liferay.portal.kernel.util.StringUtil; import com.liferay.portal.kernel.util.Validator; import com.liferay.registry.ServiceReference; import com.liferay.registry.collections.ServiceReferenceMapper; import com.liferay.registry.collections.ServiceTrackerCollections; import com.liferay.registry.collections.ServiceTrackerMap; import com.liferay.registry.util.StringPlus; import java.util.ArrayList; import java.util.Arrays; import java.util.List; import java.util.Map; import java.util.Set; import java.util.concurrent.ConcurrentHashMap; /** * @author Sergio González * @author Raymond Augé */ public class MVCCommandCache { public MVCCommandCache( MVCCommand emptyMVCCommand, String packagePrefix, String portletName, Class<? extends MVCCommand> mvcCommandClass, String mvcCommandPostFix) { this( emptyMVCCommand, packagePrefix, portletName, portletName, mvcCommandClass, mvcCommandPostFix); } public MVCCommandCache( MVCCommand emptyMVCCommand, String packagePrefix, String portletName, String portletId, Class<? extends MVCCommand> mvcCommandClass, String mvcCommandPostFix) { _emptyMVCCommand = emptyMVCCommand; _mvcComandPostFix = mvcCommandPostFix; if (Validator.isNotNull(packagePrefix) && !packagePrefix.endsWith(StringPool.PERIOD)) { packagePrefix = packagePrefix + StringPool.PERIOD; } _packagePrefix = packagePrefix; _serviceTrackerMap = ServiceTrackerCollections.openSingleValueMap( mvcCommandClass, "(&(|(javax.portlet.name=" + portletName + ")(javax.portlet.name=" + portletId + "))(mvc.command.name=*))", new ServiceReferenceMapper<String, MVCCommand>() { @Override public void map( ServiceReference<MVCCommand> serviceReference, Emitter<String> emitter) { List<String> mvcCommandNames = StringPlus.asList( serviceReference.getProperty("mvc.command.name")); for (String mvcCommandName : mvcCommandNames) { emitter.emit(mvcCommandName); } } }); } /** * @deprecated As of 7.0.0, replaced by {@link #MVCCommandCache(MVCCommand, * String, String, Class, String)} */ @Deprecated public MVCCommandCache( MVCCommand emptyMVCCommand, String packagePrefix, String portletName, String mvcCommandClassName, String mvcCommandPostFix) { this( emptyMVCCommand, packagePrefix, portletName, _getMVCCommandClass(mvcCommandClassName), mvcCommandPostFix); } public void close() { _serviceTrackerMap.close(); } public MVCCommand getMVCCommand(String mvcCommandName) { String className = null; MVCCommand mvcCommand = _serviceTrackerMap.getService(mvcCommandName); if (mvcCommand != null) { return mvcCommand; } try { mvcCommand = _mvcCommandCache.get(mvcCommandName); if (mvcCommand != null) { return mvcCommand; } if (Validator.isNull(_packagePrefix)) { return _emptyMVCCommand; } StringBundler sb = new StringBundler(4); sb.append(_packagePrefix); sb.append(Character.toUpperCase(mvcCommandName.charAt(0))); sb.append(mvcCommandName.substring(1)); sb.append(_mvcComandPostFix); className = sb.toString(); mvcCommand = (MVCCommand)InstanceFactory.newInstance(className); _mvcCommandCache.put(mvcCommandName, mvcCommand); return mvcCommand; } catch (Exception e) { if (_log.isWarnEnabled()) { _log.warn("Unable to instantiate MVCCommand " + className); } _mvcCommandCache.put(mvcCommandName, _emptyMVCCommand); return _emptyMVCCommand; } } public Set<String> getMVCCommandNames() { return _serviceTrackerMap.keySet(); } public List<? extends MVCCommand> getMVCCommands(String key) { List<MVCCommand> mvcCommands = _mvcCommands.get(key); String[] mvcCommandNames = StringUtil.split(key); if ((mvcCommands != null) && (mvcCommands.size() == mvcCommandNames.length)) { return mvcCommands; } mvcCommands = new ArrayList<>(); for (String mvcCommandName : mvcCommandNames) { MVCCommand mvcCommand = getMVCCommand(mvcCommandName); if (mvcCommand != _emptyMVCCommand) { mvcCommands.add(mvcCommand); } else { if (_log.isWarnEnabled()) { _log.warn("Unable to find MVCCommand " + key); } } } _mvcCommands.put(key, mvcCommands); for (MVCCommand mvcCommand : mvcCommands) { String mvcCommandClassName = ClassUtil.getClassName(mvcCommand); List<String> keys = _mvcCommandKeys.get(mvcCommandClassName); if (keys == null) { keys = new ArrayList<>(); _mvcCommandKeys.put(mvcCommandClassName, keys); } keys.add(key); } return mvcCommands; } public boolean isEmpty() { return _mvcCommandCache.isEmpty(); } private static Class<? extends MVCCommand> _getMVCCommandClass( String mvcCommandClassName) { Class<? extends MVCCommand> mvcCommandClass = null; for (Class<? extends MVCCommand> curMVCCommandClass : _mvcCommandClasses) { if (mvcCommandClassName.equals(curMVCCommandClass.getName())) { mvcCommandClass = curMVCCommandClass; break; } } if (mvcCommandClass == null) { throw new IllegalArgumentException(); } return mvcCommandClass; } private static final Log _log = LogFactoryUtil.getLog( MVCCommandCache.class); private static final List<Class<? extends MVCCommand>> _mvcCommandClasses = Arrays.asList( MVCActionCommand.class, MVCRenderCommand.class, MVCResourceCommand.class); private final MVCCommand _emptyMVCCommand; private final String _mvcComandPostFix; private final Map<String, MVCCommand> _mvcCommandCache = new ConcurrentHashMap<>(); private final Map<String, List<String>> _mvcCommandKeys = new ConcurrentHashMap<>(); private final Map<String, List<MVCCommand>> _mvcCommands = new ConcurrentHashMap<>(); private final String _packagePrefix; private final ServiceTrackerMap<String, ? extends MVCCommand> _serviceTrackerMap; }