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.portlet;
016    
017    import com.liferay.portal.kernel.log.Log;
018    import com.liferay.portal.kernel.log.LogFactoryUtil;
019    import com.liferay.portal.kernel.util.ClassLoaderUtil;
020    import com.liferay.portal.kernel.util.ClassUtil;
021    import com.liferay.portal.kernel.util.GetterUtil;
022    import com.liferay.portal.model.Portlet;
023    import com.liferay.portal.model.impl.PortletFilterImpl;
024    import com.liferay.portal.util.PropsValues;
025    import com.liferay.registry.Filter;
026    import com.liferay.registry.Registry;
027    import com.liferay.registry.RegistryUtil;
028    import com.liferay.registry.ServiceReference;
029    import com.liferay.registry.ServiceRegistration;
030    import com.liferay.registry.ServiceTracker;
031    import com.liferay.registry.ServiceTrackerCustomizer;
032    
033    import java.io.Closeable;
034    
035    import java.util.Collections;
036    import java.util.HashMap;
037    import java.util.List;
038    import java.util.Map;
039    import java.util.concurrent.CopyOnWriteArrayList;
040    
041    import javax.portlet.PortletContext;
042    import javax.portlet.PortletException;
043    import javax.portlet.filter.ActionFilter;
044    import javax.portlet.filter.EventFilter;
045    import javax.portlet.filter.FilterConfig;
046    import javax.portlet.filter.PortletFilter;
047    import javax.portlet.filter.RenderFilter;
048    import javax.portlet.filter.ResourceFilter;
049    
050    /**
051     * @author Raymond Aug??
052     */
053    public class InvokerFilterContainerImpl
054            implements Closeable, InvokerFilterContainer {
055    
056            public InvokerFilterContainerImpl(
057                            Portlet portlet, PortletContext portletContext)
058                    throws PortletException {
059    
060                    String rootPortletId = portlet.getRootPortletId();
061    
062                    Registry registry = RegistryUtil.getRegistry();
063    
064                    Filter filter = registry.getFilter(
065                            "(&(javax.portlet.name=" + rootPortletId + ")(objectClass=" +
066                                    PortletFilter.class.getName() + "))");
067    
068                    _serviceTracker = registry.trackServices(
069                            filter, new PortletFilterServiceTrackerCustomizer(portletContext));
070    
071                    _serviceTracker.open();
072    
073                    Map<String, Object> properties = new HashMap<>();
074    
075                    properties.put("javax.portlet.name", rootPortletId);
076                    properties.put("preinitialized.filter", Boolean.TRUE);
077    
078                    Map<String, com.liferay.portal.model.PortletFilter> portletFilters =
079                            portlet.getPortletFilters();
080    
081                    for (Map.Entry<String, com.liferay.portal.model.PortletFilter> entry :
082                                    portletFilters.entrySet()) {
083    
084                            com.liferay.portal.model.PortletFilter portletFilterModel =
085                                    entry.getValue();
086    
087                            PortletFilter portletFilter = PortletFilterFactory.create(
088                                    portletFilterModel, portletContext);
089    
090                            ServiceRegistration<PortletFilter> serviceRegistration =
091                                    registry.registerService(
092                                            PortletFilter.class, portletFilter, properties);
093    
094                            ServiceRegistrationTuple serviceRegistrationTuple =
095                                    new ServiceRegistrationTuple(
096                                            portletFilterModel, serviceRegistration);
097    
098                            _serviceRegistrationTuples.add(serviceRegistrationTuple);
099                    }
100    
101                    ClassLoader classLoader = ClassLoaderUtil.getContextClassLoader();
102    
103                    try {
104                            ClassLoaderUtil.setContextClassLoader(
105                                    ClassLoaderUtil.getPortalClassLoader());
106    
107                            for (String portletFilterClassName :
108                                            PropsValues.PORTLET_FILTERS_SYSTEM) {
109    
110                                    com.liferay.portal.model.PortletFilter portletFilterModel =
111                                            new PortletFilterImpl(
112                                                    portletFilterClassName, portletFilterClassName,
113                                                    Collections.<String>emptySet(),
114                                                    Collections.<String, String>emptyMap(),
115                                                    portlet.getPortletApp());
116    
117                                    PortletFilter portletFilter = PortletFilterFactory.create(
118                                            portletFilterModel, portletContext);
119    
120                                    ServiceRegistration<PortletFilter> serviceRegistration =
121                                            registry.registerService(
122                                                    PortletFilter.class, portletFilter, properties);
123    
124                                    _serviceRegistrationTuples.add(
125                                            new ServiceRegistrationTuple(
126                                                    portletFilterModel, serviceRegistration));
127                            }
128                    }
129                    finally {
130                            ClassLoaderUtil.setContextClassLoader(classLoader);
131                    }
132            }
133    
134            @Override
135            public void close() {
136                    for (ServiceRegistrationTuple serviceRegistrationTuple :
137                                    _serviceRegistrationTuples) {
138    
139                            PortletFilterFactory.destroy(
140                                    serviceRegistrationTuple.getPortletFilterModel());
141    
142                            ServiceRegistration<PortletFilter> serviceRegistration =
143                                    serviceRegistrationTuple.getServiceRegistration();
144    
145                            serviceRegistration.unregister();
146                    }
147    
148                    _serviceRegistrationTuples.clear();
149    
150                    _serviceTracker.close();
151    
152                    _actionFilters.clear();
153                    _eventFilters.clear();
154                    _renderFilters.clear();
155                    _resourceFilters.clear();
156            }
157    
158            @Override
159            public List<ActionFilter> getActionFilters() {
160                    return _actionFilters;
161            }
162    
163            @Override
164            public List<EventFilter> getEventFilters() {
165                    return _eventFilters;
166            }
167    
168            @Override
169            public List<RenderFilter> getRenderFilters() {
170                    return _renderFilters;
171            }
172    
173            @Override
174            public List<ResourceFilter> getResourceFilters() {
175                    return _resourceFilters;
176            }
177    
178            private static final Log _log = LogFactoryUtil.getLog(
179                    InvokerFilterContainerImpl.class);
180    
181            private final List<ActionFilter> _actionFilters =
182                    new CopyOnWriteArrayList<>();
183            private final List<EventFilter> _eventFilters =
184                    new CopyOnWriteArrayList<>();
185            private final List<RenderFilter> _renderFilters =
186                    new CopyOnWriteArrayList<>();
187            private final List<ResourceFilter> _resourceFilters =
188                    new CopyOnWriteArrayList<>();
189            private final List<ServiceRegistrationTuple>
190                    _serviceRegistrationTuples = new CopyOnWriteArrayList<>();
191            private final ServiceTracker<PortletFilter, PortletFilter> _serviceTracker;
192    
193            private static class ServiceRegistrationTuple {
194    
195                    public ServiceRegistrationTuple(
196                            com.liferay.portal.model.PortletFilter portletFilterModel,
197                            ServiceRegistration<PortletFilter> serviceRegistration) {
198    
199                            _portletFilterModel = portletFilterModel;
200                            _serviceRegistration = serviceRegistration;
201                    }
202    
203                    public com.liferay.portal.model.PortletFilter getPortletFilterModel() {
204                            return _portletFilterModel;
205                    }
206    
207                    public ServiceRegistration<PortletFilter> getServiceRegistration() {
208                            return _serviceRegistration;
209                    }
210    
211                    private final com.liferay.portal.model.PortletFilter
212                            _portletFilterModel;
213                    private final ServiceRegistration<PortletFilter> _serviceRegistration;
214    
215            }
216    
217            private class PortletFilterServiceTrackerCustomizer
218                    implements ServiceTrackerCustomizer<PortletFilter, PortletFilter> {
219    
220                    public PortletFilterServiceTrackerCustomizer(
221                            PortletContext portletContext) {
222    
223                            _portletContext = portletContext;
224                    }
225    
226                    @Override
227                    public PortletFilter addingService(
228                            ServiceReference<PortletFilter> serviceReference) {
229    
230                            Registry registry = RegistryUtil.getRegistry();
231    
232                            PortletFilter portletFilter = registry.getService(serviceReference);
233    
234                            boolean preinitializedFilter = GetterUtil.getBoolean(
235                                    serviceReference.getProperty("preinitialized.filter"));
236    
237                            if (!preinitializedFilter) {
238                                    String filterName = GetterUtil.getString(
239                                            serviceReference.getProperty("service.id"),
240                                            ClassUtil.getClassName(portletFilter));
241    
242                                    Map<String, String> params = new HashMap<>();
243    
244                                    for (String key : serviceReference.getPropertyKeys()) {
245                                            String value = GetterUtil.getString(
246                                                    serviceReference.getProperty(key));
247    
248                                            params.put(key, value);
249                                    }
250    
251                                    FilterConfig filterConfig = new FilterConfigImpl(
252                                            filterName, _portletContext, params);
253    
254                                    try {
255                                            portletFilter.init(filterConfig);
256                                    }
257                                    catch (PortletException e) {
258                                            _log.error(e, e);
259    
260                                            registry.ungetService(serviceReference);
261    
262                                            return null;
263                                    }
264                            }
265    
266                            if (portletFilter instanceof ActionFilter) {
267                                    _actionFilters.add((ActionFilter)portletFilter);
268                            }
269    
270                            if (portletFilter instanceof EventFilter) {
271                                    _eventFilters.add((EventFilter)portletFilter);
272                            }
273    
274                            if (portletFilter instanceof RenderFilter) {
275                                    _renderFilters.add((RenderFilter)portletFilter);
276                            }
277    
278                            if (portletFilter instanceof ResourceFilter) {
279                                    _resourceFilters.add((ResourceFilter)portletFilter);
280                            }
281    
282                            return portletFilter;
283                    }
284    
285                    @Override
286                    public void modifiedService(
287                            ServiceReference<PortletFilter> serviceReference,
288                            PortletFilter portletFilter) {
289                    }
290    
291                    @Override
292                    public void removedService(
293                            ServiceReference<PortletFilter> serviceReference,
294                            PortletFilter portletFilter) {
295    
296                            Registry registry = RegistryUtil.getRegistry();
297    
298                            registry.ungetService(serviceReference);
299    
300                            _actionFilters.remove(portletFilter);
301                            _eventFilters.remove(portletFilter);
302                            _renderFilters.remove(portletFilter);
303                            _resourceFilters.remove(portletFilter);
304    
305                            boolean preinitializedFilter = GetterUtil.getBoolean(
306                                    serviceReference.getProperty("preinitialized.filter"));
307    
308                            if (preinitializedFilter) {
309                                    return;
310                            }
311    
312                            portletFilter.destroy();
313                    }
314    
315                    private final PortletContext _portletContext;
316    
317            }
318    
319    }