Removed sonar warnings.
[controller.git] / opendaylight / config / config-persister-feature-adapter / src / main / java / org / opendaylight / controller / configpusherfeature / internal / AbstractFeatureWrapper.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 package org.opendaylight.controller.configpusherfeature.internal;
9
10 import com.google.common.base.Optional;
11 import com.google.common.base.Preconditions;
12 import com.google.common.io.Files;
13 import java.io.File;
14 import java.io.FileInputStream;
15 import java.util.LinkedHashSet;
16 import java.util.List;
17 import javax.xml.bind.JAXBException;
18 import javax.xml.parsers.DocumentBuilderFactory;
19 import javax.xml.stream.XMLStreamException;
20 import org.apache.karaf.features.BundleInfo;
21 import org.apache.karaf.features.Conditional;
22 import org.apache.karaf.features.ConfigFileInfo;
23 import org.apache.karaf.features.ConfigInfo;
24 import org.apache.karaf.features.Dependency;
25 import org.apache.karaf.features.Feature;
26 import org.opendaylight.controller.config.persist.storage.file.xml.model.ConfigSnapshot;
27 import org.slf4j.Logger;
28 import org.slf4j.LoggerFactory;
29 import org.w3c.dom.Element;
30
31 /*
32  * Wrap a Feature for the purposes of extracting the FeatureConfigSnapshotHolders from
33  * its underlying ConfigFileInfo's
34  *
35  * Delegates the the contained feature and provides additional methods.
36  */
37 public class AbstractFeatureWrapper implements Feature {
38     private static final Logger LOG = LoggerFactory.getLogger(AbstractFeatureWrapper.class);
39
40     protected static final String CONFIG_FILE_SUFFIX = "xml";
41
42     protected Feature feature = null;
43
44     protected AbstractFeatureWrapper() {
45         // prevent instantiation without Feature
46     }
47
48     /*
49      * @param f Feature to wrap
50      */
51     public AbstractFeatureWrapper(final Feature f) {
52         Preconditions.checkNotNull(f,"FeatureWrapper requires non-null Feature in constructor");
53         this.feature = f;
54     }
55
56     /*
57      * Get FeatureConfigSnapshotHolders appropriate to feed to the config subsystem
58      * from the underlying Feature Config files
59      */
60     public LinkedHashSet<FeatureConfigSnapshotHolder> getFeatureConfigSnapshotHolders() throws Exception {
61         final LinkedHashSet <FeatureConfigSnapshotHolder> snapShotHolders = new LinkedHashSet<>();
62         for(final ConfigFileInfo c: getConfigurationFiles()) {
63             // Skip non config snapshot XML files
64             if(isConfigSnapshot(c.getFinalname())) {
65                 final Optional<FeatureConfigSnapshotHolder> featureConfigSnapshotHolder = getFeatureConfigSnapshotHolder(c);
66                 if(featureConfigSnapshotHolder.isPresent()) {
67                     snapShotHolders.add(featureConfigSnapshotHolder.get());
68                 }
69             }
70         }
71         return snapShotHolders;
72     }
73
74     protected Optional<FeatureConfigSnapshotHolder> getFeatureConfigSnapshotHolder(final ConfigFileInfo c) {
75         try {
76             return Optional.of(new FeatureConfigSnapshotHolder(c, this));
77         } catch (final JAXBException e) {
78             LOG.warn("Unable to parse configuration snapshot. Config from '{}' will be IGNORED. " +
79                     "Note that subsequent config files may fail due to this problem. " +
80                     "Xml markup in this file needs to be fixed, for detailed information see enclosed exception.",
81                     c.getFinalname(), e);
82         } catch (final XMLStreamException e) {
83             // Files that cannot be loaded are ignored as non config subsystem files e.g. jetty.xml
84             LOG.debug("Unable to read configuration file '{}'. Not a configuration snapshot",
85                     c.getFinalname(), e);
86         }
87         return Optional.absent();
88     }
89
90     private static boolean isConfigSnapshot(String fileName) {
91         if(!Files.getFileExtension(fileName).equals(CONFIG_FILE_SUFFIX)) {
92             return false;
93         }
94
95         if(fileName.endsWith("jetty.xml")) {
96             // Special case - ignore the jetty.xml file as it contains a DTD and causes a "Connection refused"
97             // error when it tries to go out to the network to retrieve it. We don't want it trying to go out
98             // to the network nor do we want an error logged trying to parse it.
99             return false;
100         }
101
102         File file = new File(System.getProperty("karaf.home"), fileName);
103         try(FileInputStream fis = new FileInputStream(file)) {
104             DocumentBuilderFactory builderFactory = DocumentBuilderFactory.newInstance();
105             builderFactory.setNamespaceAware(true);
106             builderFactory.setCoalescing(true);
107             builderFactory.setIgnoringElementContentWhitespace(true);
108             builderFactory.setIgnoringComments(true);
109
110             Element root = builderFactory.newDocumentBuilder().parse(fis).getDocumentElement();
111             return ConfigSnapshot.SNAPSHOT_ROOT_ELEMENT_NAME.equals(root.getLocalName());
112         } catch (Exception e) {
113             LOG.error("Could not parse XML file {}", file, e);
114             return false;
115         }
116     }
117
118     @Override
119     public int hashCode() {
120         final int prime = 31;
121         int result = 1;
122         result = prime * result + (feature == null ? 0 : feature.hashCode());
123         return result;
124     }
125
126     @Override
127     public boolean equals(final Object obj) {
128         if (this == obj) {
129             return true;
130         }
131         if (obj == null) {
132             return false;
133         }
134         if (getClass() != obj.getClass()) {
135             return false;
136         }
137         final AbstractFeatureWrapper other = (AbstractFeatureWrapper) obj;
138         if (feature == null) {
139             if (other.feature != null) {
140                 return false;
141             }
142         } else if (!feature.equals(other.feature)) {
143             return false;
144         }
145         return true;
146     }
147
148     @Override
149     public String toString() {
150         return feature.getName();
151     }
152
153     /**
154      * @return
155      * @see org.apache.karaf.features.Feature#getId()
156      */
157     @Override
158     public String getId() {
159         return feature.getId();
160     }
161
162     /**
163      * @return
164      * @see org.apache.karaf.features.Feature#getName()
165      */
166     @Override
167     public String getName() {
168         return feature.getName();
169     }
170
171     /**
172      * @return
173      * @see org.apache.karaf.features.Feature#getDescription()
174      */
175     @Override
176     public String getDescription() {
177         return feature.getDescription();
178     }
179
180     /**
181      * @return
182      * @see org.apache.karaf.features.Feature#getDetails()
183      */
184     @Override
185     public String getDetails() {
186         return feature.getDetails();
187     }
188
189     /**
190      * @return
191      * @see org.apache.karaf.features.Feature#getVersion()
192      */
193     @Override
194     public String getVersion() {
195         return feature.getVersion();
196     }
197
198     /**
199      * @return
200      * @see org.apache.karaf.features.Feature#hasVersion()
201      */
202     @Override
203     public boolean hasVersion() {
204         return feature.hasVersion();
205     }
206
207     /**
208      * @return
209      * @see org.apache.karaf.features.Feature#getResolver()
210      */
211     @Override
212     public String getResolver() {
213         return feature.getResolver();
214     }
215
216     /**
217      * @return
218      * @see org.apache.karaf.features.Feature#getInstall()
219      */
220     @Override
221     public String getInstall() {
222         return feature.getInstall();
223     }
224
225     /**
226      * @return
227      * @see org.apache.karaf.features.Feature#getDependencies()
228      */
229     @Override
230     public List<Dependency> getDependencies() {
231         return feature.getDependencies();
232     }
233
234     /**
235      * @return
236      * @see org.apache.karaf.features.Feature#getBundles()
237      */
238     @Override
239     public List<BundleInfo> getBundles() {
240         return feature.getBundles();
241     }
242
243     /**
244      * @return
245      * @see org.apache.karaf.features.Feature#getConfigurations()
246      */
247     @Override
248     public List<ConfigInfo> getConfigurations() {
249         return feature.getConfigurations();
250     }
251
252     /**
253      * @return
254      * @see org.apache.karaf.features.Feature#getConfigurationFiles()
255      */
256     @Override
257     public List<ConfigFileInfo> getConfigurationFiles() {
258         return feature.getConfigurationFiles();
259     }
260
261     /**
262      * @return
263      * @see org.apache.karaf.features.Feature#getConditional()
264      */
265     @Override
266     public List<? extends Conditional> getConditional() {
267         return feature.getConditional();
268     }
269
270     /**
271      * @return
272      * @see org.apache.karaf.features.Feature#getStartLevel()
273      */
274     @Override
275     public int getStartLevel() {
276         return feature.getStartLevel();
277     }
278
279     /**
280      * @return
281      * @see org.apache.karaf.features.Feature#getRegion()
282      */
283     @Override
284     public String getRegion() {
285         return feature.getRegion();
286     }
287
288 }