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, boolean after) {
354
355 Filter filter = getFilter(filterName);
356
357 FilterConfig filterConfig = _filterConfigs.get(filterName);
358
359 if (filterConfig == null) {
360 filterConfig = getFilterConfig(filterName);
361 }
362
363 if (filter == null) {
364 if (_log.isWarnEnabled()) {
365 _log.warn("No filter exists with filter mapping " + filterName);
366 }
367
368 return;
369 }
370
371 FilterMapping filterMapping = new FilterMapping(
372 filter, filterConfig, urlPatterns, dispatchers);
373
374 registerFilterMapping(filterMapping, positionFilterName, after);
375 }
376
377 private static Log _log = LogFactoryUtil.getLog(InvokerFilterHelper.class);
378
379 private Map<String, FilterConfig> _filterConfigs =
380 new HashMap<String, FilterConfig>();
381 private List<FilterMapping> _filterMappings =
382 new CopyOnWriteArrayList<FilterMapping>();
383 private Map<String, Filter> _filters = new HashMap<String, Filter>();
384 private List<InvokerFilter> _invokerFilters =
385 new ArrayList<InvokerFilter>();
386 private ServiceTracker<Filter, FilterMapping> _serviceTracker;
387
388 private class FilterServiceTrackerCustomizer
389 implements ServiceTrackerCustomizer<Filter, FilterMapping> {
390
391 @Override
392 public FilterMapping addingService(
393 ServiceReference<Filter> serviceReference) {
394
395 Registry registry = RegistryUtil.getRegistry();
396
397 Filter filter = registry.getService(serviceReference);
398
399 String afterFilter = GetterUtil.getString(
400 serviceReference.getProperty("after-filter"));
401 String beforeFilter = GetterUtil.getString(
402 serviceReference.getProperty("before-filter"));
403 List<String> dispatchers = StringPlus.asList(
404 serviceReference.getProperty("dispatcher"));
405 String servletContextName = GetterUtil.getString(
406 serviceReference.getProperty("servlet-context-name"),
407 StringPool.BLANK);
408 String servletFilterName = GetterUtil.getString(
409 serviceReference.getProperty("servlet-filter-name"));
410 List<String> urlPatterns = StringPlus.asList(
411 serviceReference.getProperty("url-pattern"));
412
413 String positionFilterName = beforeFilter;
414 boolean after = false;
415
416 if (Validator.isNotNull(afterFilter)) {
417 positionFilterName = afterFilter;
418 after = true;
419 }
420
421 Map<String, String> initParameterMap =
422 new HashMap<String, String>();
423
424 Map<String, Object> properties = serviceReference.getProperties();
425
426 for (String key : properties.keySet()) {
427 if (!key.startsWith("init.param.")) {
428 continue;
429 }
430
431 String value = GetterUtil.getString(
432 serviceReference.getProperty(key));
433
434 initParameterMap.put(key, value);
435 }
436
437 ServletContext servletContext = ServletContextPool.get(
438 servletContextName);
439
440 FilterConfig filterConfig = new InvokerFilterConfig(
441 servletContext, servletFilterName, initParameterMap);
442
443 try {
444 filter.init(filterConfig);
445 }
446 catch (ServletException se) {
447 _log.error(se, se);
448
449 registry.ungetService(serviceReference);
450
451 return null;
452 }
453
454 _filterConfigs.put(servletFilterName, filterConfig);
455
456 registerFilter(servletFilterName, filter);
457
458 FilterMapping filterMapping = new FilterMapping(
459 filter, filterConfig, urlPatterns, dispatchers);
460
461 registerFilterMapping(filterMapping, positionFilterName, after);
462
463 return filterMapping;
464 }
465
466 @Override
467 public void modifiedService(
468 ServiceReference<Filter> serviceReference,
469 FilterMapping filterMapping) {
470
471 removedService(serviceReference, filterMapping);
472
473 addingService(serviceReference);
474 }
475
476 @Override
477 public void removedService(
478 ServiceReference<Filter> serviceReference,
479 FilterMapping filterMapping) {
480
481 Registry registry = RegistryUtil.getRegistry();
482
483 registry.ungetService(serviceReference);
484
485 String servletFilterName = GetterUtil.getString(
486 serviceReference.getProperty("servlet-filter-name"));
487
488 unregisterFilterMapping(filterMapping);
489
490 _filterConfigs.remove(servletFilterName);
491
492 Filter filter = _filters.remove(servletFilterName);
493
494 if (filter == null) {
495 return;
496 }
497
498 try {
499 filter.destroy();
500 }
501 catch (Exception e) {
502 _log.error(e, e);
503 }
504 }
505
506 }
507
508 }