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 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 List<ConfigSnapshotHolder> loadLastConfigs() throws IOException {
68 File[] filesArray = storage.listFiles();
69 if (filesArray == null || filesArray.length == 0) {
70 return Collections.emptyList();
72 List<File> sortedFiles = new ArrayList<>(Arrays.asList(filesArray));
73 Collections.sort(sortedFiles);
74 // combine all found files
75 logger.debug("Reading files in following order: {}", sortedFiles);
77 List<ConfigSnapshotHolder> result = new ArrayList<>();
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);
83 result.add(lineProcessor.getConfigSnapshotHolder(header, middle, footer));
95 public String toString() {
96 return "FileStorageAdapter [storage=" + storage + "]";
100 class MyLineProcessor implements com.google.common.io.LineProcessor<String> {
101 private final String fileNameForReporting;
103 private boolean inModules, inServices, inCapabilities;
104 private final StringBuffer modulesBuffer = new StringBuffer(), servicesBuilder = new StringBuffer();
105 private final SortedSet<String> caps = new TreeSet<>();
107 MyLineProcessor(String fileNameForReporting) {
108 this.fileNameForReporting = fileNameForReporting;
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 private void checkFileConsistency(){
142 checkState(inCapabilities, "File %s is missing delimiters in this order: %s", fileNameForReporting,
143 Arrays.asList(DirectoryPersister.MODULES_START,
144 DirectoryPersister.SERVICES_START,
145 DirectoryPersister.CAPABILITIES_START));
148 String getModules() {
149 checkFileConsistency();
150 return modulesBuffer.toString();
153 String getServices() {
154 checkFileConsistency();
155 return servicesBuilder.toString();
158 SortedSet<String> getCapabilities() {
159 checkFileConsistency();
163 ConfigSnapshotHolder getConfigSnapshotHolder(String header, String middle, String footer) {
164 String combinedSnapshot = header + getModules() + middle + getServices() + footer;
165 ConfigSnapshotHolder result = new ConfigSnapshotHolderImpl(combinedSnapshot, getCapabilities(), fileNameForReporting);