001
014
015 package com.liferay.portal.kernel.servlet.filters.invoker;
016
017 import com.liferay.portal.kernel.log.Log;
018 import com.liferay.portal.kernel.log.LogFactoryUtil;
019 import com.liferay.portal.kernel.servlet.ServletContextPool;
020 import com.liferay.portal.kernel.util.GetterUtil;
021 import com.liferay.portal.kernel.util.InstanceFactory;
022 import com.liferay.portal.kernel.util.StringPool;
023 import com.liferay.portal.kernel.util.StringUtil;
024 import com.liferay.portal.kernel.util.Validator;
025 import com.liferay.portal.kernel.xml.Document;
026 import com.liferay.portal.kernel.xml.Element;
027 import com.liferay.portal.kernel.xml.SAXReaderUtil;
028 import com.liferay.registry.Registry;
029 import com.liferay.registry.RegistryUtil;
030 import com.liferay.registry.ServiceReference;
031 import com.liferay.registry.ServiceTracker;
032 import com.liferay.registry.ServiceTrackerCustomizer;
033 import com.liferay.registry.util.StringPlus;
034
035 import java.io.InputStream;
036
037 import java.util.ArrayList;
038 import java.util.HashMap;
039 import java.util.List;
040 import java.util.Map;
041 import java.util.concurrent.CopyOnWriteArrayList;
042
043 import javax.servlet.Filter;
044 import javax.servlet.FilterChain;
045 import javax.servlet.FilterConfig;
046 import javax.servlet.ServletContext;
047 import javax.servlet.ServletException;
048 import javax.servlet.http.HttpServletRequest;
049
050
054 public class InvokerFilterHelper {
055
056 public void destroy() {
057 _serviceTracker.close();
058
059 for (Map.Entry<String, Filter> entry : _filters.entrySet()) {
060 Filter filter = entry.getValue();
061
062 try {
063 filter.destroy();
064 }
065 catch (Exception e) {
066 _log.error(e, e);
067 }
068 }
069
070 _filterConfigs.clear();
071 _filterMappings.clear();
072 _filters.clear();
073
074 for (InvokerFilter invokerFilter : _invokerFilters) {
075 invokerFilter.clearFilterChainsCache();
076 }
077 }
078
079 public Filter getFilter(String filterName) {
080 return _filters.get(filterName);
081 }
082
083 public FilterConfig getFilterConfig(String filterName) {
084 return _filterConfigs.get(filterName);
085 }
086
087 public void init(FilterConfig filterConfig) throws ServletException {
088 try {
089 ServletContext servletContext = filterConfig.getServletContext();
090
091 readLiferayFilterWebXML(servletContext, "/WEB-INF/liferay-web.xml");
092
093 Registry registry = RegistryUtil.getRegistry();
094
095 String servletContextName = GetterUtil.getString(
096 servletContext.getServletContextName());
097
098 com.liferay.registry.Filter filter = registry.getFilter(
099 "(&(objectClass=" + Filter.class.getName() +
100 ")(servlet-context-name=" + servletContextName +
101 ")(servlet-filter-name=*))");
102
103 _serviceTracker = registry.trackServices(
104 filter, new FilterServiceTrackerCustomizer());
105
106 _serviceTracker.open();
107 }
108 catch (Exception e) {
109 _log.error(e, e);
110
111 throw new ServletException(e);
112 }
113 }
114
115 public Filter registerFilter(String filterName, Filter filter) {
116 Filter previousFilter = _filters.put(filterName, filter);
117
118 if (previousFilter != null) {
119 for (FilterMapping filterMapping : _filterMappings) {
120 if (filterMapping.getFilter() == previousFilter) {
121 if (filter != null) {
122 filterMapping.setFilter(filter);
123 }
124 else {
125 _filterMappings.remove(filterMapping);
126 _filterConfigs.remove(filterName);
127 }
128 }
129 }
130 }
131
132 for (InvokerFilter invokerFilter : _invokerFilters) {
133 invokerFilter.clearFilterChainsCache();
134 }
135
136 return previousFilter;
137 }
138
139 public void registerFilterMapping(
140 FilterMapping filterMapping, String filterName, boolean after) {
141
142 int x = 0;
143 int y = 0;
144
145 if (Validator.isNotNull(filterName)) {
146 Filter filter = _filters.get(filterName);
147
148 if (filter != null) {
149 for (; x < _filterMappings.size(); x++) {
150 FilterMapping currentFilterMapping = _filterMappings.get(x);
151
152 if (currentFilterMapping.getFilter() == filter) {
153 if (after) {
154 y = x;
155 }
156 else {
157 break;
158 }
159 }
160 }
161 }
162 }
163
164 if (after) {
165 x = ++y;
166 }
167
168 _filterMappings.add(x, filterMapping);
169
170 for (InvokerFilter invokerFilter : _invokerFilters) {
171 invokerFilter.clearFilterChainsCache();
172 }
173 }
174
175 public void unregisterFilterMapping(FilterMapping filterMapping) {
176 _filterMappings.remove(filterMapping);
177
178 for (InvokerFilter invokerFilter : _invokerFilters) {
179 invokerFilter.clearFilterChainsCache();
180 }
181 }
182
183 protected void addInvokerFilter(InvokerFilter invokerFilter) {
184 _invokerFilters.add(invokerFilter);
185 }
186
187 protected InvokerFilterChain createInvokerFilterChain(
188 HttpServletRequest request, Dispatcher dispatcher, String uri,
189 FilterChain filterChain) {
190
191 InvokerFilterChain invokerFilterChain = new InvokerFilterChain(
192 filterChain);
193
194 for (FilterMapping filterMapping : _filterMappings) {
195 if (filterMapping.isMatch(request, dispatcher, uri)) {
196 Filter filter = filterMapping.getFilter();
197
198 invokerFilterChain.addFilter(filter);
199 }
200 }
201
202 return invokerFilterChain;
203 }
204
205 protected Filter getFilter(
206 ServletContext servletContext, String filterClassName,
207 FilterConfig filterConfig) {
208
209 ClassLoader pluginClassLoader = getPluginClassLoader(servletContext);
210
211 Thread currentThread = Thread.currentThread();
212
213 ClassLoader contextClassLoader = currentThread.getContextClassLoader();
214
215 try {
216 if (contextClassLoader != pluginClassLoader) {
217 currentThread.setContextClassLoader(pluginClassLoader);
218 }
219
220 Filter filter = (Filter)InstanceFactory.newInstance(
221 pluginClassLoader, filterClassName);
222
223 filter.init(filterConfig);
224
225 return filter;
226 }
227 catch (Exception e) {
228 _log.error("Unable to initialize filter " + filterClassName, e);
229 }
230 finally {
231 if (contextClassLoader != pluginClassLoader) {
232 currentThread.setContextClassLoader(contextClassLoader);
233 }
234 }
235
236 return null;
237 }
238
239 protected ClassLoader getPluginClassLoader(ServletContext servletContext) {
240 return servletContext.getClassLoader();
241 }
242
243 protected void initFilter(
244 ServletContext servletContext, String filterName,
245 String filterClassName, Map<String, String> initParameterMap)
246 throws Exception {
247
248 FilterConfig filterConfig = new InvokerFilterConfig(
249 servletContext, filterName, initParameterMap);
250
251 Filter filter = getFilter(
252 servletContext, filterClassName, filterConfig);
253
254 if (filter == null) {
255 return;
256 }
257
258 _filterConfigs.put(filterName, filterConfig);
259 _filters.put(filterName, filter);
260 }
261
262 protected void initFilterMapping(
263 String filterName, List<String> urlPatterns, List<String> dispatchers) {
264
265 Filter filter = _filters.get(filterName);
266
267 if (filter == null) {
268 return;
269 }
270
271 FilterConfig filterConfig = _filterConfigs.get(filterName);
272
273 if (filterConfig == null) {
274 return;
275 }
276
277 FilterMapping filterMapping = new FilterMapping(
278 filter, filterConfig, urlPatterns, dispatchers);
279
280 _filterMappings.add(filterMapping);
281 }
282
283 protected void readLiferayFilterWebXML(
284 ServletContext servletContext, String path)
285 throws Exception {
286
287 InputStream inputStream = servletContext.getResourceAsStream(path);
288
289 if (inputStream == null) {
290 return;
291 }
292
293 Document document = SAXReaderUtil.read(inputStream, true);
294
295 Element rootElement = document.getRootElement();
296
297 List<Element> filterElements = rootElement.elements("filter");
298
299 for (Element filterElement : filterElements) {
300 String filterName = filterElement.elementText("filter-name");
301 String filterClassName = filterElement.elementText("filter-class");
302
303 Map<String, String> initParameterMap =
304 new HashMap<String, String>();
305
306 List<Element> initParamElements = filterElement.elements(
307 "init-param");
308
309 for (Element initParamElement : initParamElements) {
310 String name = initParamElement.elementText("param-name");
311 String value = initParamElement.elementText("param-value");
312
313 initParameterMap.put(name, value);
314 }
315
316 initFilter(
317 servletContext, filterName, filterClassName, initParameterMap);
318 }
319
320 List<Element> filterMappingElements = rootElement.elements(
321 "filter-mapping");
322
323 for (Element filterMappingElement : filterMappingElements) {
324 String filterName = filterMappingElement.elementText("filter-name");
325
326 List<String> urlPatterns = new ArrayList<String>();
327
328 List<Element> urlPatternElements = filterMappingElement.elements(
329 "url-pattern");
330
331 for (Element urlPatternElement : urlPatternElements) {
332 urlPatterns.add(urlPatternElement.getTextTrim());
333 }
334
335 List<String> dispatchers = new ArrayList<String>(4);
336
337 List<Element> dispatcherElements = filterMappingElement.elements(
338 "dispatcher");
339
340 for (Element dispatcherElement : dispatcherElements) {
341 String dispatcher = StringUtil.toUpperCase(
342 dispatcherElement.getTextTrim());
343
344 dispatchers.add(dispatcher);
345 }
346
347 initFilterMapping(filterName, urlPatterns, dispatchers);
348 }
349 }
350
351 protected void registerFilterMapping(
352 String filterName, List<String> urlPatterns, List<String> dispatchers,
353 String positionFilterName,
354 boolean after) {
355
356 Filter filter = getFilter(filterName);
357
358 FilterConfig filterConfig = _filterConfigs.get(filterName);
359
360 if (filterConfig == null) {
361 filterConfig = getFilterConfig(filterName);
362 }
363
364 if (filter == null) {
365 if (_log.isWarnEnabled()) {
366 _log.warn("No filter exists with filter mapping " + filterName);
367 }
368
369 return;
370 }
371
372 FilterMapping filterMapping = new FilterMapping(
373 filter, filterConfig, urlPatterns, dispatchers);
374
375 registerFilterMapping(filterMapping, positionFilterName, after);
376 }
377
378 private static Log _log = LogFactoryUtil.getLog(InvokerFilterHelper.class);
379
380 private Map<String, FilterConfig> _filterConfigs =
381 new HashMap<String, FilterConfig>();
382 private List<FilterMapping> _filterMappings =
383 new CopyOnWriteArrayList<FilterMapping>();
384 private Map<String, Filter> _filters = new HashMap<String, Filter>();
385 private List<InvokerFilter> _invokerFilters =
386 new ArrayList<InvokerFilter>();
387 private ServiceTracker<Filter, FilterMapping> _serviceTracker;
388
389 private class FilterServiceTrackerCustomizer
390 implements ServiceTrackerCustomizer<Filter, FilterMapping> {
391
392 @Override
393 public FilterMapping addingService(
394 ServiceReference<Filter> serviceReference) {
395
396 Registry registry = RegistryUtil.getRegistry();
397
398 Filter filter = registry.getService(serviceReference);
399
400 String afterFilter = GetterUtil.getString(
401 serviceReference.getProperty("after-filter"));
402 String beforeFilter = GetterUtil.getString(
403 serviceReference.getProperty("before-filter"));
404 List<String> dispatchers = StringPlus.asList(
405 serviceReference.getProperty("dispatcher"));
406 String servletContextName = GetterUtil.getString(
407 serviceReference.getProperty("servlet-context-name"),
408 StringPool.BLANK);
409 String servletFilterName = GetterUtil.getString(
410 serviceReference.getProperty("servlet-filter-name"));
411 List<String> urlPatterns = StringPlus.asList(
412 serviceReference.getProperty("url-pattern"));
413
414 String positionFilterName = beforeFilter;
415 boolean after = false;
416
417 if (Validator.isNotNull(afterFilter)) {
418 positionFilterName = afterFilter;
419 after = true;
420 }
421
422 Map<String, String> initParameterMap =
423 new HashMap<String, String>();
424
425 Map<String, Object> properties = serviceReference.getProperties();
426
427 for (String key : properties.keySet()) {
428 if (!key.startsWith("init.param.")) {
429 continue;
430 }
431
432 String value = GetterUtil.getString(
433 serviceReference.getProperty(key));
434
435 initParameterMap.put(key, value);
436 }
437
438 ServletContext servletContext = ServletContextPool.get(
439 servletContextName);
440
441 FilterConfig filterConfig = new InvokerFilterConfig(
442 servletContext, servletFilterName, initParameterMap);
443
444 try {
445 filter.init(filterConfig);
446 }
447 catch (ServletException se) {
448 _log.error(se, se);
449
450 registry.ungetService(serviceReference);
451
452 return null;
453 }
454
455 _filterConfigs.put(servletFilterName, filterConfig);
456
457 registerFilter(servletFilterName, filter);
458
459 FilterMapping filterMapping = new FilterMapping(
460 filter, filterConfig, urlPatterns, dispatchers);
461
462 registerFilterMapping(filterMapping, positionFilterName, after);
463
464 return filterMapping;
465 }
466
467 @Override
468 public void modifiedService(
469 ServiceReference<Filter> serviceReference,
470 FilterMapping filterMapping) {
471
472 removedService(serviceReference, filterMapping);
473
474 addingService(serviceReference);
475 }
476
477 @Override
478 public void removedService(
479 ServiceReference<Filter> serviceReference,
480 FilterMapping filterMapping) {
481
482 Registry registry = RegistryUtil.getRegistry();
483
484 registry.ungetService(serviceReference);
485
486 String servletFilterName = GetterUtil.getString(
487 serviceReference.getProperty("servlet-filter-name"));
488
489 unregisterFilterMapping(filterMapping);
490
491 _filterConfigs.remove(servletFilterName);
492
493 Filter filter = _filters.remove(servletFilterName);
494
495 if (filter == null) {
496 return;
497 }
498
499 try {
500 filter.destroy();
501 }
502 catch (Exception e) {
503 _log.error(e, e);
504 }
505 }
506
507 }
508
509 }