2 * Copyright (c) 2014 Cisco Systems, Inc. and others. All rights reserved.
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
8 package org.opendaylight.controller.configpusherfeature.internal;
10 import com.google.common.base.Optional;
11 import com.google.common.base.Preconditions;
12 import com.google.common.io.Files;
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;
32 * Wrap a Feature for the purposes of extracting the FeatureConfigSnapshotHolders from
33 * its underlying ConfigFileInfo's
35 * Delegates the the contained feature and provides additional methods.
37 public class AbstractFeatureWrapper implements Feature {
38 private static final Logger LOG = LoggerFactory.getLogger(AbstractFeatureWrapper.class);
40 protected static final String CONFIG_FILE_SUFFIX = "xml";
42 protected Feature feature = null;
44 protected AbstractFeatureWrapper() {
45 // prevent instantiation without Feature
49 * @param f Feature to wrap
51 public AbstractFeatureWrapper(final Feature f) {
52 Preconditions.checkNotNull(f,"FeatureWrapper requires non-null Feature in constructor");
57 * Get FeatureConfigSnapshotHolders appropriate to feed to the config subsystem
58 * from the underlying Feature Config files
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());
71 return snapShotHolders;
74 protected Optional<FeatureConfigSnapshotHolder> getFeatureConfigSnapshotHolder(final ConfigFileInfo c) {
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.",
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",
87 return Optional.absent();
90 private static boolean isConfigSnapshot(String fileName) {
91 if(!Files.getFileExtension(fileName).equals(CONFIG_FILE_SUFFIX)) {
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.
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);
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);
119 public int hashCode() {
120 final int prime = 31;
122 result = prime * result + (feature == null ? 0 : feature.hashCode());
127 public boolean equals(final Object obj) {
134 if (getClass() != obj.getClass()) {
137 final AbstractFeatureWrapper other = (AbstractFeatureWrapper) obj;
138 if (feature == null) {
139 if (other.feature != null) {
142 } else if (!feature.equals(other.feature)) {
149 public String toString() {
150 return feature.getName();
155 * @see org.apache.karaf.features.Feature#getId()
158 public String getId() {
159 return feature.getId();
164 * @see org.apache.karaf.features.Feature#getName()
167 public String getName() {
168 return feature.getName();
173 * @see org.apache.karaf.features.Feature#getDescription()
176 public String getDescription() {
177 return feature.getDescription();
182 * @see org.apache.karaf.features.Feature#getDetails()
185 public String getDetails() {
186 return feature.getDetails();
191 * @see org.apache.karaf.features.Feature#getVersion()
194 public String getVersion() {
195 return feature.getVersion();
200 * @see org.apache.karaf.features.Feature#hasVersion()
203 public boolean hasVersion() {
204 return feature.hasVersion();
209 * @see org.apache.karaf.features.Feature#getResolver()
212 public String getResolver() {
213 return feature.getResolver();
218 * @see org.apache.karaf.features.Feature#getInstall()
221 public String getInstall() {
222 return feature.getInstall();
227 * @see org.apache.karaf.features.Feature#getDependencies()
230 public List<Dependency> getDependencies() {
231 return feature.getDependencies();
236 * @see org.apache.karaf.features.Feature#getBundles()
239 public List<BundleInfo> getBundles() {
240 return feature.getBundles();
245 * @see org.apache.karaf.features.Feature#getConfigurations()
248 public List<ConfigInfo> getConfigurations() {
249 return feature.getConfigurations();
254 * @see org.apache.karaf.features.Feature#getConfigurationFiles()
257 public List<ConfigFileInfo> getConfigurationFiles() {
258 return feature.getConfigurationFiles();
263 * @see org.apache.karaf.features.Feature#getConditional()
266 public List<? extends Conditional> getConditional() {
267 return feature.getConditional();
272 * @see org.apache.karaf.features.Feature#getStartLevel()
275 public int getStartLevel() {
276 return feature.getStartLevel();
281 * @see org.apache.karaf.features.Feature#getRegion()
284 public String getRegion() {
285 return feature.getRegion();