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