/* * Copyright (c) 2014 Cisco Systems, Inc. and others. All rights reserved. * * This program and the accompanying materials are made available under the * terms of the Eclipse Public License v1.0 which accompanies this distribution, * and is available at http://www.eclipse.org/legal/epl-v10.html */ package org.opendaylight.controller.filtervalve.cors.jaxb; import static com.google.common.base.Preconditions.checkArgument; import static com.google.common.base.Preconditions.checkState; import com.google.common.base.Optional; import com.google.common.collect.MapDifference; import com.google.common.collect.Maps; import java.util.ArrayList; import java.util.Collections; import java.util.Enumeration; import java.util.HashMap; import java.util.Iterator; import java.util.List; import java.util.Map; import java.util.Map.Entry; import java.util.Objects; import javax.servlet.FilterConfig; import javax.servlet.ServletContext; import javax.xml.bind.annotation.XmlElement; import javax.xml.bind.annotation.XmlRootElement; import org.slf4j.Logger; import org.slf4j.LoggerFactory; @XmlRootElement public class Filter implements FilterConfig { private static final Logger logger = LoggerFactory.getLogger(Filter.class); private String filterName; private String filterClass; private List initParams = new ArrayList<>(); private javax.servlet.Filter actualFilter; private boolean initialized, isTemplate; /** * Called in filter-template nodes defined in node - do not actually initialize the filter. * In this case filter is only used to hold values of init params to be merged with * filter defined in */ public synchronized void initializeTemplate(){ checkState(initialized == false, "Already initialized"); for (InitParam initParam : initParams) { initParam.inititialize(); } isTemplate = true; initialized = true; } public synchronized void initialize(String fileName, Optional maybeTemplate) { checkState(initialized == false, "Already initialized"); logger.trace("Initializing filter {} : {}", filterName, filterClass); for (InitParam initParam : initParams) { initParam.inititialize(); } if (maybeTemplate.isPresent()) { // merge non conflicting init params Filter template = maybeTemplate.get(); checkArgument(template.isTemplate); Map templateParams = template.getInitParamsMap(); Map currentParams = getInitParamsMap(); // add values of template that are not present in current MapDifference difference = Maps.difference(templateParams, currentParams); for (Entry templateUnique : difference.entriesOnlyOnLeft().entrySet()) { initParams.add(templateUnique.getValue()); } // merge filterClass if (filterClass == null) { filterClass = template.filterClass; } else if (Objects.equals(filterClass, template.filterClass) == false) { logger.error("Conflict detected in filter-class of {} defined in {}, template class {}, child class {}" , filterName, fileName, template.filterClass, filterClass); throw new IllegalStateException("Conflict detected in template/filter filter-class definitions," + " filter name: " + filterName + " in file " + fileName); } } initParams = Collections.unmodifiableList(new ArrayList<>(initParams)); Class clazz; try { clazz = Class.forName(filterClass); } catch (Exception e) { throw new IllegalStateException("Cannot instantiate class defined in filter " + filterName + " in file " + fileName, e); } try { actualFilter = (javax.servlet.Filter) clazz.newInstance(); } catch (Exception e) { throw new IllegalStateException("Cannot instantiate class defined in filter " + filterName + " in file " + fileName, e); } logger.trace("Initializing {} with following init-params:{}", filterName, getInitParams()); try { actualFilter.init(this); } catch (Exception e) { throw new IllegalStateException("Cannot initialize filter " + filterName + " in file " + fileName, e); } initialized = true; } @Override public ServletContext getServletContext() { throw new UnsupportedOperationException("Getting ServletContext is currently not supported"); } @Override public String getInitParameter(String name) { for (InitParam initParam : initParams) { if (Objects.equals(name, initParam.getParamName())) { return initParam.getParamValue(); } } return null; } @Override public Enumeration getInitParameterNames() { final Iterator iterator = initParams.iterator(); return new Enumeration() { @Override public boolean hasMoreElements() { return iterator.hasNext(); } @Override public String nextElement() { return iterator.next().getParamName(); } }; } public javax.servlet.Filter getActualFilter() { checkState(initialized, "Not initialized"); return actualFilter; } public boolean isInitialized() { return initialized; } @XmlElement(name = "filter-name") public String getFilterName() { return filterName; } public void setFilterName(String filterName) { this.filterName = filterName; } @XmlElement(name = "filter-class") public String getFilterClass() { return filterClass; } public void setFilterClass(String filterClass) { this.filterClass = filterClass; } @XmlElement(name = "init-param") public List getInitParams() { return initParams; } public void setInitParams(List initParams) { this.initParams = initParams; } @Override public String toString() { return "Filter{" + "filterName='" + filterName + '\'' + '}'; } public Map getInitParamsMap() { Map result = new HashMap<>(); for (InitParam initParam : initParams) { checkState(initParam.isInitialized()); result.put(initParam.getParamName(), initParam); } return result; } }