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.kernel.portlet.bridges.mvc;
016    
017    import com.liferay.portal.kernel.log.Log;
018    import com.liferay.portal.kernel.log.LogFactoryUtil;
019    import com.liferay.portal.kernel.util.InstanceFactory;
020    import com.liferay.portal.kernel.util.StringBundler;
021    import com.liferay.portal.kernel.util.StringPool;
022    import com.liferay.portal.kernel.util.StringUtil;
023    import com.liferay.portal.kernel.util.Validator;
024    import com.liferay.registry.Filter;
025    import com.liferay.registry.Registry;
026    import com.liferay.registry.RegistryUtil;
027    import com.liferay.registry.ServiceReference;
028    import com.liferay.registry.ServiceTracker;
029    import com.liferay.registry.ServiceTrackerCustomizer;
030    import com.liferay.registry.util.StringPlus;
031    
032    import java.util.ArrayList;
033    import java.util.List;
034    import java.util.Map;
035    import java.util.concurrent.ConcurrentHashMap;
036    
037    /**
038     * @author Sergio Gonz??lez
039     */
040    public class MVCCommandCache {
041    
042            public MVCCommandCache(
043                    MVCCommand emptyMVCCommand, String packagePrefix, String portletName,
044                    String mvcCommandClassName, String mvcCommandPostFix) {
045    
046                    _emptyMVCCommand = emptyMVCCommand;
047                    _mvcComandPostFix = mvcCommandPostFix;
048    
049                    if (Validator.isNotNull(packagePrefix) &&
050                            !packagePrefix.endsWith(StringPool.PERIOD)) {
051    
052                            packagePrefix = packagePrefix + StringPool.PERIOD;
053                    }
054    
055                    _packagePrefix = packagePrefix;
056    
057                    Registry registry = RegistryUtil.getRegistry();
058    
059                    Filter filter = registry.getFilter(
060                            "(&(javax.portlet.name=" + portletName +")(mvc.command.name=*)" +
061                                    "(objectClass=" + mvcCommandClassName + "))");
062    
063                    _serviceTracker = registry.trackServices(
064                            filter, new MVCCommandServiceTrackerCustomizer());
065    
066                    _serviceTracker.open();
067            }
068    
069            public void close() {
070                    _serviceTracker.close();
071            }
072    
073            public MVCCommand getMVCCommand(String mvcCommandName) {
074                    String className = null;
075    
076                    try {
077                            MVCCommand mvcCommand = _mvcCommandCache.get(mvcCommandName);
078    
079                            if (mvcCommand != null) {
080                                    return mvcCommand;
081                            }
082    
083                            if (Validator.isNull(_packagePrefix)) {
084                                    return _emptyMVCCommand;
085                            }
086    
087                            StringBundler sb = new StringBundler(4);
088    
089                            sb.append(_packagePrefix);
090                            sb.append(Character.toUpperCase(mvcCommandName.charAt(0)));
091                            sb.append(mvcCommandName.substring(1));
092                            sb.append(_mvcComandPostFix);
093    
094                            className = sb.toString();
095    
096                            mvcCommand = (MVCCommand)InstanceFactory.newInstance(className);
097    
098                            _mvcCommandCache.put(mvcCommandName, mvcCommand);
099    
100                            return mvcCommand;
101                    }
102                    catch (Exception e) {
103                            if (_log.isWarnEnabled()) {
104                                    _log.warn("Unable to instantiate MVCCommand " + className);
105                            }
106    
107                            _mvcCommandCache.put(mvcCommandName, _emptyMVCCommand);
108    
109                            return _emptyMVCCommand;
110                    }
111            }
112    
113            public List<? extends MVCCommand> getMVCCommands(String key) {
114                    List<MVCCommand> mvcCommands = _mvcCommands.get(key);
115    
116                    if (mvcCommands != null) {
117                            return mvcCommands;
118                    }
119    
120                    mvcCommands = new ArrayList<>();
121    
122                    String[] mvcCommandNames = StringUtil.split(key);
123    
124                    for (String mvcCommandName : mvcCommandNames) {
125                            MVCCommand mvcCommand = getMVCCommand(mvcCommandName);
126    
127                            if (mvcCommand != _emptyMVCCommand) {
128                                    mvcCommands.add(mvcCommand);
129                            }
130                            else {
131                                    if (_log.isWarnEnabled()) {
132                                            _log.warn("Unable to find MVCCommand " + key);
133                                    }
134                            }
135                    }
136    
137                    _mvcCommands.put(key, mvcCommands);
138    
139                    return mvcCommands;
140            }
141    
142            public boolean isEmpty() {
143                    return _mvcCommandCache.isEmpty();
144            }
145    
146            private static final Log _log = LogFactoryUtil.getLog(
147                    MVCCommandCache.class);
148    
149            private final MVCCommand _emptyMVCCommand;
150            private final String _mvcComandPostFix;
151            private final Map<String, MVCCommand> _mvcCommandCache =
152                    new ConcurrentHashMap<>();
153            private final Map<String, List<MVCCommand>> _mvcCommands =
154                    new ConcurrentHashMap<>();
155            private final String _packagePrefix;
156            private final ServiceTracker<MVCCommand, MVCCommand> _serviceTracker;
157    
158            private class MVCCommandServiceTrackerCustomizer
159                    implements ServiceTrackerCustomizer<MVCCommand, MVCCommand> {
160    
161                    @Override
162                    public MVCCommand addingService(
163                            ServiceReference<MVCCommand> serviceReference) {
164    
165                            Registry registry = RegistryUtil.getRegistry();
166    
167                            MVCCommand mvcCommand = registry.getService(serviceReference);
168    
169                            List<String> mvcCommandNames = StringPlus.asList(
170                                    serviceReference.getProperty("mvc.command.name"));
171    
172                            for (String mvcCommandName : mvcCommandNames) {
173                                    _mvcCommandCache.put(mvcCommandName, mvcCommand);
174                            }
175    
176                            return mvcCommand;
177                    }
178    
179                    @Override
180                    public void modifiedService(
181                            ServiceReference<MVCCommand> serviceReference,
182                            MVCCommand mvcCommand) {
183                    }
184    
185                    @Override
186                    public void removedService(
187                            ServiceReference<MVCCommand> serviceReference,
188                            MVCCommand mvcCommand) {
189    
190                            Registry registry = RegistryUtil.getRegistry();
191    
192                            registry.ungetService(serviceReference);
193    
194                            List<String> mvcCommandNames = StringPlus.asList(
195                                    serviceReference.getProperty("mvc.command.name"));
196    
197                            for (String mvcCommandName : mvcCommandNames) {
198                                    _mvcCommandCache.remove(mvcCommandName);
199    
200                                    for (List<MVCCommand> mvcCommands : _mvcCommands.values()) {
201                                            mvcCommands.remove(mvcCommand);
202                                    }
203                            }
204                    }
205    
206            }
207    
208    }