2 * Copyright (c) 2013 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
9 package org.opendaylight.controller.config.persist.storage.file.xml;
11 import com.google.common.annotations.VisibleForTesting;
12 import com.google.common.base.Optional;
13 import com.google.common.base.Preconditions;
14 import com.google.common.collect.Lists;
16 import java.io.IOException;
17 import java.util.Collections;
18 import java.util.List;
20 import java.util.SortedSet;
21 import org.opendaylight.controller.config.persist.api.ConfigSnapshotHolder;
22 import org.opendaylight.controller.config.persist.api.Persister;
23 import org.opendaylight.controller.config.persist.api.PropertiesProvider;
24 import org.opendaylight.controller.config.persist.api.StorageAdapter;
25 import org.opendaylight.controller.config.persist.storage.file.xml.model.Config;
26 import org.opendaylight.controller.config.persist.storage.file.xml.model.ConfigSnapshot;
27 import org.slf4j.Logger;
28 import org.slf4j.LoggerFactory;
31 * StorageAdapter that stores configuration in an xml file.
33 public class XmlFileStorageAdapter implements StorageAdapter, Persister {
34 private static final Logger LOG = LoggerFactory.getLogger(XmlFileStorageAdapter.class);
36 public static final String FILE_STORAGE_PROP = "fileStorage";
37 public static final String NUMBER_OF_BACKUPS = "numberOfBackups";
39 private static Integer numberOfStoredBackups;
42 private static volatile XmlFileStorageAdapter instance;
43 private volatile ConfigSnapshot lastCfgSnapshotCache;
44 private volatile Optional<FeatureListProvider> featuresService = Optional.absent();
49 lastCfgSnapshotCache = null;
50 featuresService = null;
54 public Persister instantiate(PropertiesProvider propertiesProvider) {
55 if(instance != null) {
59 File storage = extractStorageFileFromProperties(propertiesProvider);
60 LOG.debug("Using file {}", storage.getAbsolutePath());
61 // Create file if it does not exist
62 File parentFile = storage.getAbsoluteFile().getParentFile();
63 if (parentFile.exists() == false) {
64 LOG.debug("Creating parent folders {}", parentFile);
67 if (storage.exists() == false) {
68 LOG.debug("Storage file does not exist, creating empty file");
70 boolean result = storage.createNewFile();
71 if (result == false) {
72 throw new RuntimeException("Unable to create storage file " + storage);
74 } catch (IOException e) {
75 throw new RuntimeException("Unable to create storage file " + storage, e);
78 if (numberOfStoredBackups == 0) {
79 throw new RuntimeException(NUMBER_OF_BACKUPS
80 + " property should be either set to positive value, or ommited. Can not be set to 0.");
82 setFileStorage(storage);
88 public static Optional<XmlFileStorageAdapter> getInstance() {
89 return Optional.fromNullable(instance);
92 public Set<String> getPersistedFeatures() {
93 return lastCfgSnapshotCache == null ? Collections.<String>emptySet() : lastCfgSnapshotCache.getFeatures();
96 public void setFeaturesService(final FeatureListProvider featuresService) {
97 this.featuresService = Optional.of(featuresService);
101 public void setFileStorage(File storage) {
102 this.storage = storage;
106 public void setNumberOfBackups(Integer numberOfBackups) {
107 numberOfStoredBackups = numberOfBackups;
110 private static File extractStorageFileFromProperties(PropertiesProvider propertiesProvider) {
111 String fileStorageProperty = propertiesProvider.getProperty(FILE_STORAGE_PROP);
112 Preconditions.checkNotNull(fileStorageProperty, "Unable to find " + propertiesProvider.getFullKeyForReporting(FILE_STORAGE_PROP));
113 File result = new File(fileStorageProperty);
114 String numberOfBackupsAsString = propertiesProvider.getProperty(NUMBER_OF_BACKUPS);
115 if (numberOfBackupsAsString != null) {
116 numberOfStoredBackups = Integer.valueOf(numberOfBackupsAsString);
118 numberOfStoredBackups = Integer.MAX_VALUE;
120 LOG.trace("Property {} set to {}", NUMBER_OF_BACKUPS, numberOfStoredBackups);
125 public void persistConfig(ConfigSnapshotHolder holder) throws IOException {
126 Preconditions.checkNotNull(storage, "Storage file is null");
128 Set<String> installedFeatureIds = Collections.emptySet();
129 if(featuresService.isPresent()) {
130 installedFeatureIds = featuresService.get().listFeatures();
133 Config cfg = Config.fromXml(storage);
134 cfg.addConfigSnapshot(ConfigSnapshot.fromConfigSnapshot(holder, installedFeatureIds), numberOfStoredBackups);
139 public List<ConfigSnapshotHolder> loadLastConfigs() throws IOException {
140 Preconditions.checkNotNull(storage, "Storage file is null");
142 if (!storage.exists()) {
143 return Collections.emptyList();
146 Optional<ConfigSnapshot> lastSnapshot = Config.fromXml(storage).getLastSnapshot();
148 if (lastSnapshot.isPresent()) {
149 lastCfgSnapshotCache = lastSnapshot.get();
150 return Lists.newArrayList(toConfigSnapshot(lastCfgSnapshotCache));
152 return Collections.emptyList();
157 public ConfigSnapshotHolder toConfigSnapshot(final ConfigSnapshot configSnapshot) {
158 return new ConfigSnapshotHolder() {
160 public String getConfigSnapshot() {
161 return configSnapshot.getConfigSnapshot();
165 public SortedSet<String> getCapabilities() {
166 return configSnapshot.getCapabilities();
170 public String toString() {
171 return configSnapshot.toString();
177 public void close() {
182 public String toString() {
183 return "XmlFileStorageAdapter [storage=" + storage + "]";