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.resiliency.spi;
016    
017    import com.liferay.portal.kernel.concurrent.ConcurrentHashSet;
018    import com.liferay.portal.kernel.log.Log;
019    import com.liferay.portal.kernel.log.LogFactoryUtil;
020    import com.liferay.portal.kernel.resiliency.spi.SPI;
021    import com.liferay.portal.kernel.resiliency.spi.SPIConfiguration;
022    import com.liferay.portal.kernel.resiliency.spi.SPIRegistry;
023    import com.liferay.portal.kernel.resiliency.spi.SPIRegistryValidator;
024    import com.liferay.portal.model.Portlet;
025    import com.liferay.portal.model.PortletApp;
026    import com.liferay.portal.service.PortletLocalServiceUtil;
027    import com.liferay.portal.spring.aop.ServiceBeanAopCacheManagerUtil;
028    
029    import java.rmi.RemoteException;
030    
031    import java.util.ArrayList;
032    import java.util.List;
033    import java.util.Map;
034    import java.util.Set;
035    import java.util.concurrent.ConcurrentHashMap;
036    import java.util.concurrent.locks.Lock;
037    import java.util.concurrent.locks.ReentrantLock;
038    
039    /**
040     * @author Shuyang Zhou
041     */
042    public class SPIRegistryImpl implements SPIRegistry {
043    
044            @Override
045            public void addExcludedPortletId(String portletId) {
046                    _excludedPortletIds.add(portletId);
047            }
048    
049            @Override
050            public SPI getErrorSPI() {
051                    return _errorSPI;
052            }
053    
054            @Override
055            public Set<String> getExcludedPortletIds() {
056                    return _excludedPortletIds;
057            }
058    
059            @Override
060            public SPI getPortletSPI(String portletId) {
061                    if (_excludedPortletIds.contains(portletId)) {
062                            return null;
063                    }
064    
065                    SPI spi = _portletSPIs.get(portletId);
066    
067                    if (_spiRegistryValidator != null) {
068                            spi = _spiRegistryValidator.validatePortletSPI(portletId, spi);
069                    }
070    
071                    return spi;
072            }
073    
074            @Override
075            public SPI getServletContextSPI(String servletContextName) {
076                    SPI spi = _servletContextSPIs.get(servletContextName);
077    
078                    if (_spiRegistryValidator != null) {
079                            spi = _spiRegistryValidator.validateServletContextSPI(
080                                    servletContextName, spi);
081                    }
082    
083                    return spi;
084            }
085    
086            @Override
087            public void registerSPI(SPI spi) throws RemoteException {
088                    List<String> portletIds = new ArrayList<String>();
089    
090                    SPIConfiguration spiConfiguration = spi.getSPIConfiguration();
091    
092                    for (String portletId : spiConfiguration.getPortletIds()) {
093                            Portlet portlet = PortletLocalServiceUtil.getPortletById(portletId);
094    
095                            if (portlet == null) {
096                                    if (_log.isWarnEnabled()) {
097                                            _log.warn("Skip unknown portlet id " + portletId);
098                                    }
099                            }
100                            else {
101                                    portletIds.add(portletId);
102                            }
103                    }
104    
105                    String[] servletContextNames =
106                            spiConfiguration.getServletContextNames();
107    
108                    for (String servletContextName : servletContextNames) {
109                            PortletApp portletApp = PortletLocalServiceUtil.getPortletApp(
110                                    servletContextName);
111    
112                            if (portletApp == null) {
113                                    if (_log.isWarnEnabled()) {
114                                            _log.warn(
115                                                    "Skip unknown servlet context name " +
116                                                            servletContextName);
117                                    }
118                            }
119                            else {
120                                    List<Portlet> portlets = portletApp.getPortlets();
121    
122                                    for (Portlet portlet : portlets) {
123                                            portletIds.add(portlet.getPortletId());
124                                    }
125                            }
126                    }
127    
128                    _lock.lock();
129    
130                    try {
131                            for (String portletId : portletIds) {
132                                    _portletSPIs.put(portletId, spi);
133                            }
134    
135                            _portletIds.put(
136                                    spi, portletIds.toArray(new String[portletIds.size()]));
137    
138                            for (String servletContextName : servletContextNames) {
139                                    _servletContextSPIs.put(servletContextName, spi);
140                            }
141    
142                            _servletContextNames.put(spi, servletContextNames.clone());
143    
144                            ServiceBeanAopCacheManagerUtil.reset();
145                    }
146                    finally {
147                            _lock.unlock();
148                    }
149            }
150    
151            @Override
152            public void removeExcludedPortletId(String portletId) {
153                    _excludedPortletIds.remove(portletId);
154            }
155    
156            public void setErrorSPI(SPI errorSPI) {
157                    _errorSPI = errorSPI;
158            }
159    
160            @Override
161            public void setSPIRegistryValidator(
162                    SPIRegistryValidator spiRegistryValidator) {
163    
164                    _spiRegistryValidator = spiRegistryValidator;
165            }
166    
167            @Override
168            public void unregisterSPI(SPI spi) {
169                    _lock.lock();
170    
171                    try {
172                            String[] portletIds = _portletIds.remove(spi);
173    
174                            if (portletIds != null) {
175                                    for (String portletId : portletIds) {
176                                            _portletSPIs.remove(portletId);
177                                    }
178                            }
179    
180                            String[] servletContextNames = _servletContextNames.remove(spi);
181    
182                            if (servletContextNames != null) {
183                                    for (String servletContextName : servletContextNames) {
184                                            _servletContextSPIs.remove(servletContextName);
185                                    }
186                            }
187                    }
188                    finally {
189                            _lock.unlock();
190                    }
191            }
192    
193            private static Log _log = LogFactoryUtil.getLog(SPIRegistryImpl.class);
194    
195            private SPI _errorSPI;
196            private Set<String> _excludedPortletIds = new ConcurrentHashSet<String>();
197            private Lock _lock = new ReentrantLock();
198            private Map<SPI, String[]> _portletIds =
199                    new ConcurrentHashMap<SPI, String[]>();
200            private Map<String, SPI> _portletSPIs =
201                    new ConcurrentHashMap<String, SPI>();
202            private Map<SPI, String[]> _servletContextNames =
203                    new ConcurrentHashMap<SPI, String[]>();
204            private Map<String, SPI> _servletContextSPIs =
205                    new ConcurrentHashMap<String, SPI>();
206            private SPIRegistryValidator _spiRegistryValidator;
207    
208    }