Bug 951 - Externalize cors definition of restconf
[controller.git] / opendaylight / commons / filter-valve / src / main / java / org / opendaylight / controller / filtervalve / cors / jaxb / Filter.java
diff --git a/opendaylight/commons/filter-valve/src/main/java/org/opendaylight/controller/filtervalve/cors/jaxb/Filter.java b/opendaylight/commons/filter-valve/src/main/java/org/opendaylight/controller/filtervalve/cors/jaxb/Filter.java
new file mode 100644 (file)
index 0000000..3dde5b1
--- /dev/null
@@ -0,0 +1,194 @@
+/*
+ * 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<InitParam> initParams = new ArrayList<>();
+    private javax.servlet.Filter actualFilter;
+    private boolean initialized, isTemplate;
+
+
+    /**
+     * Called in filter-template nodes defined in <Host/> 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 <Context/>
+     */
+    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<Filter> 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<String, InitParam> templateParams = template.getInitParamsMap();
+            Map<String, InitParam> currentParams = getInitParamsMap();
+            // add values of template that are not present in current
+            MapDifference<String, InitParam> difference = Maps.difference(templateParams, currentParams);
+            for (Entry<String, InitParam> 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<String> getInitParameterNames() {
+        final Iterator<InitParam> iterator = initParams.iterator();
+        return new Enumeration<String>() {
+            @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<InitParam> getInitParams() {
+        return initParams;
+    }
+
+    public void setInitParams(List<InitParam> initParams) {
+        this.initParams = initParams;
+    }
+
+
+    @Override
+    public String toString() {
+        return "Filter{" +
+                "filterName='" + filterName + '\'' +
+                '}';
+    }
+
+    public Map<String, InitParam> getInitParamsMap() {
+        Map<String, InitParam> result = new HashMap<>();
+        for (InitParam initParam : initParams) {
+            checkState(initParam.isInitialized());
+            result.put(initParam.getParamName(), initParam);
+        }
+        return result;
+    }
+}