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();
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> {
107 private boolean inModules, inServices, inCapabilities;
108 private final StringBuffer modulesBuffer = new StringBuffer(), servicesBuilder = new StringBuffer();
109 private final SortedSet<String> caps = new TreeSet<>();
112 public String getResult() {
117 public boolean processLine(String line) throws IOException {
119 String lineWithNewLine = line + System.lineSeparator();
120 if (line.equals(DirectoryPersister.MODULES_START)) {
121 checkState(inModules == false && inServices == false && inCapabilities == false);
123 } else if (line.equals(DirectoryPersister.SERVICES_START)) {
124 checkState(inModules == true && inServices == false && inCapabilities == false);
127 } else if (line.equals(DirectoryPersister.CAPABILITIES_START)) {
128 checkState(inModules == false && inServices == true && inCapabilities == false);
130 inCapabilities = true;
131 } else if (inModules) {
132 modulesBuffer.append(lineWithNewLine);
133 } else if (inServices) {
134 servicesBuilder.append(lineWithNewLine);
141 String getModules() {
142 checkState(inCapabilities);
143 return modulesBuffer.toString();
146 String getServices() {
147 checkState(inCapabilities);
148 return servicesBuilder.toString();
151 SortedSet<String> getCapabilities() {
152 checkState(inCapabilities);
158 class ConfigSnapshotHolderImpl implements ConfigSnapshotHolder {
160 private final String snapshot;
161 private final SortedSet<String> caps;
163 public ConfigSnapshotHolderImpl(String configSnapshot, SortedSet<String> capabilities) {
164 this.snapshot = configSnapshot;
165 this.caps = capabilities;
169 public String getConfigSnapshot() {
174 public SortedSet<String> getCapabilities() {