/*
* Copyright 2012 The Solmix Project
*
* This is free software; you can redistribute it and/or modify it
* under the terms of the GNU Lesser General Public License as
* published by the Free Software Foundation; either version 2.1 of
* the License, or (at your option) any later version.
*
* This software is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
* http://www.gnu.org/licenses/
* or see the FSF site: http://www.fsf.org.
*/
package org.solmix.web.internal;
import static org.osgi.framework.Constants.SERVICE_ID;
import static org.osgi.framework.Constants.SERVICE_RANKING;
import static org.solmix.api.servlet.FilterManager.FILTER_NAME;
import static org.solmix.api.servlet.FilterManager.FILTER_ORDER;
import javax.servlet.Filter;
import javax.servlet.FilterConfig;
import javax.servlet.ServletContext;
import javax.servlet.ServletException;
import org.osgi.framework.BundleContext;
import org.osgi.framework.ServiceReference;
import org.osgi.util.tracker.ServiceTracker;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.solmix.web.internal.helper.SlxFilterConfig;
/**
*
* @author solmix.f@gmail.com
* @version 110035 2012-10-9
*/
public class FilterManagerTracker extends ServiceTracker<Filter, Filter>
{
/** default log */
private final Logger log = LoggerFactory.getLogger(FilterManagerTracker.class);
private static final String FILTER_SERVICE_NAME = Filter.class.getName();
private final FilterChainHelper filterChain;
private final ServletContext servletContext;
/**
* @param context
* @param clazz
* @param customizer
*/
public FilterManagerTracker(BundleContext context, ServletContext servletContext)
{
super(context, FILTER_SERVICE_NAME, null);
filterChain = new FilterChainHelper();
this.servletContext = servletContext;
}
public FilterChainHelper getFilterChain() {
return this.filterChain;
}
@Override
public Filter addingService(ServiceReference<Filter> reference) {
Filter service = super.addingService(reference);
initFilter(service, reference);
return service;
}
/**
* @param service
* @param reference
*/
private synchronized void initFilter(Filter filter, ServiceReference<Filter> reference) {
Object filterName = reference.getProperty(FILTER_NAME);
if (filterName == null) {
filterName = reference.getProperty(SERVICE_ID);
}
if (filterName == null) {
log.error("initFilter: Missing name for filter {}", reference);
} else {
try {
final FilterConfig config = new SlxFilterConfig(servletContext, reference, filterName.toString());
filter.init(config);
Long serviceId = (Long) reference.getProperty(SERVICE_ID);
int orderId;
// get the order, Integer.MAX_VALUE by default
Object orderObj = reference.getProperty(SERVICE_RANKING);
// filter order is defined as lower value has higher priority
// while service ranking is the opposite
// In addition we allow different types than Integer
if (orderObj == null) {
orderObj = reference.getProperty(FILTER_ORDER);
if (orderObj != null && orderObj instanceof Integer) {
orderId = ((Integer) orderObj).intValue();
orderId = orderId * -1;
}
}
orderId = (orderObj instanceof Integer) ? ((Integer) orderObj).intValue() : 0;
this.getFilterChain().addFilter(filter, serviceId, orderId);
} catch (ServletException e) {
log.error("Filter " + filterName + " failed to initialize", e);
} catch (Throwable t) {
log.error("Unexpected Problem initializingFilter ", t);
}
}
}
@Override
public void modifiedService(ServiceReference<Filter> reference, Filter service) {
destroyFilter(service, reference);
initFilter(service, reference);
super.modifiedService(reference, service);
}
/**
* @param service
* @param reference
*/
private void destroyFilter(Filter service, ServiceReference<Filter> reference) {
Object service_id = reference.getProperty(SERVICE_ID);
boolean remove = false;
remove = this.filterChain.removeFilterById(service_id);
if (remove) {
try {
service.destroy();
} catch (Exception e) {
log.error("Unexpected problem destroying Filter {}", filter, e);
}
}
}
@Override
public void removedService(ServiceReference<Filter> reference, Filter service) {
this.destroyFilter(service, reference);
super.removedService(reference, service);
}
}