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.io.Files;
12 import org.apache.commons.io.IOUtils;
13 import org.opendaylight.controller.config.persist.api.ConfigSnapshotHolder;
14 import org.opendaylight.controller.config.persist.api.ConfigSnapshotHolderImpl;
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 public 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 static final String header, middle, footer;
45 header = readResource("header.txt");
46 middle = readResource("middle.txt");
47 footer = readResource("footer.txt");
50 public DirectoryPersister(File storage) {
51 checkArgument(storage.exists() && storage.isDirectory(), "Storage directory does not exist: " + storage);
52 this.storage = storage;
55 private static String readResource(String resource) {
57 return IOUtils.toString(DirectoryPersister.class.getResourceAsStream("/" + resource));
58 } catch (IOException e) {
59 throw new IllegalStateException("Cannot load " + resource, e);
64 public void persistConfig(ConfigSnapshotHolder holder) throws IOException {
65 throw new UnsupportedOperationException("This adapter is read only. Please set readonly=true on " + getClass());
69 public List<ConfigSnapshotHolder> loadLastConfigs() throws IOException {
70 File[] filesArray = storage.listFiles();
71 if (filesArray == null || filesArray.length == 0) {
72 return Collections.emptyList();
74 List<File> sortedFiles = new ArrayList<>(Arrays.asList(filesArray));
75 Collections.sort(sortedFiles);
76 // combine all found files
77 logger.debug("Reading files in following order: {}", sortedFiles);
79 List<ConfigSnapshotHolder> result = new ArrayList<>();
80 for (File file : sortedFiles) {
81 logger.trace("Adding file '{}' to combined result", file);
83 ConfigSnapshotHolder configSnapshotHolder = loadLastConfig(file);
84 result.add(configSnapshotHolder);
89 public static ConfigSnapshotHolder loadLastConfig(File file) throws IOException {
90 final MyLineProcessor lineProcessor = new MyLineProcessor(file.getAbsolutePath());
91 Files.readLines(file, ENCODING, lineProcessor);
92 return lineProcessor.getConfigSnapshotHolder(header, middle, footer);
102 public String toString() {
103 return "FileStorageAdapter [storage=" + storage + "]";
107 class MyLineProcessor implements com.google.common.io.LineProcessor<String> {
108 private final String fileNameForReporting;
110 private boolean inModules, inServices, inCapabilities;
111 private final StringBuffer modulesBuffer = new StringBuffer(), servicesBuilder = new StringBuffer();
112 private final SortedSet<String> caps = new TreeSet<>();
114 MyLineProcessor(String fileNameForReporting) {
115 this.fileNameForReporting = fileNameForReporting;
119 public String getResult() {
124 public boolean processLine(String line) throws IOException {
126 String lineWithNewLine = line + System.lineSeparator();
127 if (line.equals(DirectoryPersister.MODULES_START)) {
128 checkState(inModules == false && inServices == false && inCapabilities == false);
130 } else if (line.equals(DirectoryPersister.SERVICES_START)) {
131 checkState(inModules == true && inServices == false && inCapabilities == false);
134 } else if (line.equals(DirectoryPersister.CAPABILITIES_START)) {
135 checkState(inModules == false && inServices == true && inCapabilities == false);
137 inCapabilities = true;
138 } else if (inModules) {
139 modulesBuffer.append(lineWithNewLine);
140 } else if (inServices) {
141 servicesBuilder.append(lineWithNewLine);
148 private void checkFileConsistency(){
149 checkState(inCapabilities, "File %s is missing delimiters in this order: %s", fileNameForReporting,
150 Arrays.asList(DirectoryPersister.MODULES_START,
151 DirectoryPersister.SERVICES_START,
152 DirectoryPersister.CAPABILITIES_START));
155 String getModules() {
156 checkFileConsistency();
157 return modulesBuffer.toString();
160 String getServices() {
161 checkFileConsistency();
162 return servicesBuilder.toString();
165 SortedSet<String> getCapabilities() {
166 checkFileConsistency();
170 ConfigSnapshotHolder getConfigSnapshotHolder(String header, String middle, String footer) {
171 String combinedSnapshot = header + getModules() + middle + getServices() + footer;
172 ConfigSnapshotHolder result = new ConfigSnapshotHolderImpl(combinedSnapshot, getCapabilities(), fileNameForReporting);