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
8 package org.opendaylight.controller.config.persist.storage.directory;
10 import com.google.common.base.Charsets;
11 import com.google.common.base.Optional;
12 import com.google.common.io.Files;
13 import org.apache.commons.io.IOUtils;
14 import org.opendaylight.controller.config.persist.api.ConfigSnapshotHolder;
15 import org.opendaylight.controller.config.persist.api.Persister;
16 import org.slf4j.Logger;
17 import org.slf4j.LoggerFactory;
20 import java.io.IOException;
21 import java.nio.charset.Charset;
22 import java.util.ArrayList;
23 import java.util.Arrays;
24 import java.util.Collections;
25 import java.util.List;
26 import java.util.SortedSet;
27 import java.util.TreeSet;
29 import static com.google.common.base.Preconditions.checkArgument;
30 import static com.google.common.base.Preconditions.checkState;
32 public class DirectoryPersister implements Persister {
33 private static final Logger logger = LoggerFactory.getLogger(DirectoryPersister.class);
34 private static final Charset ENCODING = Charsets.UTF_8;
36 static final String MODULES_START = "//MODULES START";
37 static final String SERVICES_START = "//SERVICES START";
38 static final String CAPABILITIES_START = "//CAPABILITIES START";
41 private final File storage;
42 private final String header, middle, footer;
44 public DirectoryPersister(File storage) {
45 checkArgument(storage.exists() && storage.isDirectory(), "Storage directory does not exist: " + storage);
46 this.storage = storage;
47 header = readResource("header.txt");
48 middle = readResource("middle.txt");
49 footer = readResource("footer.txt");
53 private static String readResource(String resource) {
55 return IOUtils.toString(DirectoryPersister.class.getResourceAsStream("/" + resource));
56 } catch (IOException e) {
57 throw new IllegalStateException("Cannot load " + resource, e);
62 public void persistConfig(ConfigSnapshotHolder holder) throws IOException {
63 throw new UnsupportedOperationException("This adapter is read only. Please set readonly=true on " + getClass());
67 public Optional<ConfigSnapshotHolder> loadLastConfig() throws IOException {
68 File[] filesArray = storage.listFiles();
69 if (filesArray.length == 0) {
70 return Optional.absent();
72 List<File> sortedFiles = new ArrayList<>(Arrays.asList(filesArray));
73 Collections.sort(sortedFiles);
74 // combine all found files
76 SortedSet<String> combinedCapabilities = new TreeSet<>();
77 StringBuilder modulesBuilder = new StringBuilder(), servicesBuilder = new StringBuilder();
78 for (File file : sortedFiles) {
79 logger.trace("Adding file '{}' to combined result", file);
81 final MyLineProcessor lineProcessor = new MyLineProcessor(file.getAbsolutePath());
82 Files.readLines(file, ENCODING, lineProcessor);
84 modulesBuilder.append(lineProcessor.getModules());
85 servicesBuilder.append(lineProcessor.getServices());
86 combinedCapabilities.addAll(lineProcessor.getCapabilities());
88 String combinedSnapshot = header + modulesBuilder.toString() + middle + servicesBuilder.toString() + footer;
89 ConfigSnapshotHolder result = new ConfigSnapshotHolderImpl(combinedSnapshot, combinedCapabilities);
90 return Optional.of(result);
100 public String toString() {
101 return "FileStorageAdapter [storage=" + storage + "]";
105 class MyLineProcessor implements com.google.common.io.LineProcessor<String> {
106 private final String fileNameForReporting;
108 private boolean inModules, inServices, inCapabilities;
109 private final StringBuffer modulesBuffer = new StringBuffer(), servicesBuilder = new StringBuffer();
110 private final SortedSet<String> caps = new TreeSet<>();
112 MyLineProcessor(String fileNameForReporting) {
113 this.fileNameForReporting = fileNameForReporting;
117 public String getResult() {
122 public boolean processLine(String line) throws IOException {
124 String lineWithNewLine = line + System.lineSeparator();
125 if (line.equals(DirectoryPersister.MODULES_START)) {
126 checkState(inModules == false && inServices == false && inCapabilities == false);
128 } else if (line.equals(DirectoryPersister.SERVICES_START)) {
129 checkState(inModules == true && inServices == false && inCapabilities == false);
132 } else if (line.equals(DirectoryPersister.CAPABILITIES_START)) {
133 checkState(inModules == false && inServices == true && inCapabilities == false);
135 inCapabilities = true;
136 } else if (inModules) {
137 modulesBuffer.append(lineWithNewLine);
138 } else if (inServices) {
139 servicesBuilder.append(lineWithNewLine);
146 private void checkFileConsistency(){
147 checkState(inCapabilities, "File {} is missing delimiters in this order: {}", fileNameForReporting,
148 Arrays.asList(DirectoryPersister.MODULES_START,
149 DirectoryPersister.SERVICES_START,
150 DirectoryPersister.CAPABILITIES_START));
153 String getModules() {
154 checkFileConsistency();
155 return modulesBuffer.toString();
158 String getServices() {
159 checkFileConsistency();
160 return servicesBuilder.toString();
163 SortedSet<String> getCapabilities() {
164 checkFileConsistency();
170 class ConfigSnapshotHolderImpl implements ConfigSnapshotHolder {
172 private final String snapshot;
173 private final SortedSet<String> caps;
175 public ConfigSnapshotHolderImpl(String configSnapshot, SortedSet<String> capabilities) {
176 this.snapshot = configSnapshot;
177 this.caps = capabilities;
181 public String getConfigSnapshot() {
186 public SortedSet<String> getCapabilities() {