3dde5b1cfac3bdd436c42df7d2193f2c829daec5
[controller.git] / opendaylight / commons / filter-valve / src / main / java / org / opendaylight / controller / filtervalve / cors / jaxb / Filter.java
1 /*
2  * Copyright (c) 2014 Cisco Systems, Inc. and others.  All rights reserved.
3  *
4  * This program and the accompanying materials are made available under the
5  * terms of the Eclipse Public License v1.0 which accompanies this distribution,
6  * and is available at http://www.eclipse.org/legal/epl-v10.html
7  */
8
9 package org.opendaylight.controller.filtervalve.cors.jaxb;
10
11 import static com.google.common.base.Preconditions.checkArgument;
12 import static com.google.common.base.Preconditions.checkState;
13
14 import com.google.common.base.Optional;
15 import com.google.common.collect.MapDifference;
16 import com.google.common.collect.Maps;
17 import java.util.ArrayList;
18 import java.util.Collections;
19 import java.util.Enumeration;
20 import java.util.HashMap;
21 import java.util.Iterator;
22 import java.util.List;
23 import java.util.Map;
24 import java.util.Map.Entry;
25 import java.util.Objects;
26 import javax.servlet.FilterConfig;
27 import javax.servlet.ServletContext;
28 import javax.xml.bind.annotation.XmlElement;
29 import javax.xml.bind.annotation.XmlRootElement;
30 import org.slf4j.Logger;
31 import org.slf4j.LoggerFactory;
32
33 @XmlRootElement
34 public class Filter implements FilterConfig {
35     private static final Logger logger = LoggerFactory.getLogger(Filter.class);
36
37     private String filterName;
38     private String filterClass;
39     private List<InitParam> initParams = new ArrayList<>();
40     private javax.servlet.Filter actualFilter;
41     private boolean initialized, isTemplate;
42
43
44     /**
45      * Called in filter-template nodes defined in <Host/> node - do not actually initialize the filter.
46      * In this case filter is only used to hold values of init params to be merged with
47      * filter defined in <Context/>
48      */
49     public synchronized void initializeTemplate(){
50         checkState(initialized == false, "Already initialized");
51         for (InitParam initParam : initParams) {
52             initParam.inititialize();
53         }
54         isTemplate = true;
55         initialized = true;
56     }
57
58
59     public synchronized void initialize(String fileName, Optional<Filter> maybeTemplate) {
60         checkState(initialized == false, "Already initialized");
61         logger.trace("Initializing filter {} : {}", filterName, filterClass);
62         for (InitParam initParam : initParams) {
63             initParam.inititialize();
64         }
65         if (maybeTemplate.isPresent()) {
66             // merge non conflicting init params
67             Filter template = maybeTemplate.get();
68             checkArgument(template.isTemplate);
69             Map<String, InitParam> templateParams = template.getInitParamsMap();
70             Map<String, InitParam> currentParams = getInitParamsMap();
71             // add values of template that are not present in current
72             MapDifference<String, InitParam> difference = Maps.difference(templateParams, currentParams);
73             for (Entry<String, InitParam> templateUnique : difference.entriesOnlyOnLeft().entrySet()) {
74                 initParams.add(templateUnique.getValue());
75             }
76             // merge filterClass
77             if (filterClass == null) {
78                 filterClass = template.filterClass;
79             } else if (Objects.equals(filterClass, template.filterClass) == false) {
80                 logger.error("Conflict detected in filter-class of {} defined in {}, template class {}, child class {}" ,
81                         filterName, fileName, template.filterClass, filterClass);
82                 throw new IllegalStateException("Conflict detected in template/filter filter-class definitions," +
83                         " filter name: " + filterName + " in file " + fileName);
84             }
85         }
86         initParams = Collections.unmodifiableList(new ArrayList<>(initParams));
87         Class<?> clazz;
88         try {
89             clazz = Class.forName(filterClass);
90         } catch (Exception e) {
91             throw new IllegalStateException("Cannot instantiate class defined in filter " + filterName
92                     + " in file " + fileName, e);
93         }
94         try {
95             actualFilter = (javax.servlet.Filter) clazz.newInstance();
96         } catch (Exception e) {
97             throw new IllegalStateException("Cannot instantiate class defined in filter " + filterName
98                     + " in file " + fileName, e);
99         }
100         logger.trace("Initializing {} with following init-params:{}", filterName, getInitParams());
101         try {
102             actualFilter.init(this);
103         } catch (Exception e) {
104             throw new IllegalStateException("Cannot initialize filter " + filterName
105                     + " in file " + fileName, e);
106         }
107         initialized = true;
108     }
109
110     @Override
111     public ServletContext getServletContext() {
112         throw new UnsupportedOperationException("Getting ServletContext is currently not supported");
113     }
114
115     @Override
116     public String getInitParameter(String name) {
117         for (InitParam initParam : initParams) {
118             if (Objects.equals(name, initParam.getParamName())) {
119                 return initParam.getParamValue();
120             }
121         }
122         return null;
123     }
124
125     @Override
126     public Enumeration<String> getInitParameterNames() {
127         final Iterator<InitParam> iterator = initParams.iterator();
128         return new Enumeration<String>() {
129             @Override
130             public boolean hasMoreElements() {
131                 return iterator.hasNext();
132             }
133
134             @Override
135             public String nextElement() {
136                 return iterator.next().getParamName();
137             }
138         };
139     }
140
141     public javax.servlet.Filter getActualFilter() {
142         checkState(initialized, "Not initialized");
143         return actualFilter;
144     }
145
146     public boolean isInitialized() {
147         return initialized;
148     }
149
150
151     @XmlElement(name = "filter-name")
152     public String getFilterName() {
153         return filterName;
154     }
155
156     public void setFilterName(String filterName) {
157         this.filterName = filterName;
158     }
159
160     @XmlElement(name = "filter-class")
161     public String getFilterClass() {
162         return filterClass;
163     }
164
165     public void setFilterClass(String filterClass) {
166         this.filterClass = filterClass;
167     }
168
169     @XmlElement(name = "init-param")
170     public List<InitParam> getInitParams() {
171         return initParams;
172     }
173
174     public void setInitParams(List<InitParam> initParams) {
175         this.initParams = initParams;
176     }
177
178
179     @Override
180     public String toString() {
181         return "Filter{" +
182                 "filterName='" + filterName + '\'' +
183                 '}';
184     }
185
186     public Map<String, InitParam> getInitParamsMap() {
187         Map<String, InitParam> result = new HashMap<>();
188         for (InitParam initParam : initParams) {
189             checkState(initParam.isInitialized());
190             result.put(initParam.getParamName(), initParam);
191         }
192         return result;
193     }
194 }