Merge changes Ia268965a,Iefa79f99
[controller.git] / opendaylight / config / config-persister-directory-adapter / src / main / java / org / opendaylight / controller / config / persist / storage / directory / DirectoryPersister.java
1 /*
2  * Copyright (c) 2013 Cisco Systems, Inc. and others.  All rights reserved.
3  *
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
7  */
8 package org.opendaylight.controller.config.persist.storage.directory;
9
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;
18
19 import java.io.File;
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;
28
29 import static com.google.common.base.Preconditions.checkArgument;
30 import static com.google.common.base.Preconditions.checkState;
31
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;
35
36     static final String MODULES_START = "//MODULES START";
37     static final String SERVICES_START = "//SERVICES START";
38     static final String CAPABILITIES_START = "//CAPABILITIES START";
39
40
41     private final File storage;
42     private final String header, middle, footer;
43
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");
50
51     }
52
53     private static String readResource(String resource) {
54         try {
55             return IOUtils.toString(DirectoryPersister.class.getResourceAsStream("/" + resource));
56         } catch (IOException e) {
57             throw new IllegalStateException("Cannot load " + resource, e);
58         }
59     }
60
61     @Override
62     public void persistConfig(ConfigSnapshotHolder holder) throws IOException {
63         throw new UnsupportedOperationException("This adapter is read only. Please set readonly=true on " + getClass());
64     }
65
66     @Override
67     public Optional<ConfigSnapshotHolder> loadLastConfig() throws IOException {
68         File[] filesArray = storage.listFiles();
69         if (filesArray.length == 0) {
70             return Optional.absent();
71         }
72         List<File> sortedFiles = new ArrayList<>(Arrays.asList(filesArray));
73         Collections.sort(sortedFiles);
74         // combine all found files
75
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);
80
81             final MyLineProcessor lineProcessor = new MyLineProcessor();
82             Files.readLines(file, ENCODING, lineProcessor);
83
84             modulesBuilder.append(lineProcessor.getModules());
85             servicesBuilder.append(lineProcessor.getServices());
86             combinedCapabilities.addAll(lineProcessor.getCapabilities());
87         }
88         String combinedSnapshot = header + modulesBuilder.toString() + middle + servicesBuilder.toString() + footer;
89         ConfigSnapshotHolder result = new ConfigSnapshotHolderImpl(combinedSnapshot, combinedCapabilities);
90         return Optional.of(result);
91     }
92
93
94     @Override
95     public void close() {
96
97     }
98
99     @Override
100     public String toString() {
101         return "FileStorageAdapter [storage=" + storage + "]";
102     }
103 }
104
105 class MyLineProcessor implements com.google.common.io.LineProcessor<String> {
106
107     private boolean inModules, inServices, inCapabilities;
108     private final StringBuffer modulesBuffer = new StringBuffer(), servicesBuilder = new StringBuffer();
109     private final SortedSet<String> caps = new TreeSet<>();
110
111     @Override
112     public String getResult() {
113         return null;
114     }
115
116     @Override
117     public boolean processLine(String line) throws IOException {
118
119         String lineWithNewLine = line + System.lineSeparator();
120         if (line.equals(DirectoryPersister.MODULES_START)) {
121             checkState(inModules == false && inServices == false && inCapabilities == false);
122             inModules = true;
123         } else if (line.equals(DirectoryPersister.SERVICES_START)) {
124             checkState(inModules == true && inServices == false && inCapabilities == false);
125             inModules = false;
126             inServices = true;
127         } else if (line.equals(DirectoryPersister.CAPABILITIES_START)) {
128             checkState(inModules == false && inServices == true && inCapabilities == false);
129             inServices = false;
130             inCapabilities = true;
131         } else if (inModules) {
132             modulesBuffer.append(lineWithNewLine);
133         } else if (inServices) {
134             servicesBuilder.append(lineWithNewLine);
135         } else {
136             caps.add(line);
137         }
138         return true;
139     }
140
141     String getModules() {
142         checkState(inCapabilities);
143         return modulesBuffer.toString();
144     }
145
146     String getServices() {
147         checkState(inCapabilities);
148         return servicesBuilder.toString();
149     }
150
151     SortedSet<String> getCapabilities() {
152         checkState(inCapabilities);
153         return caps;
154     }
155
156 }
157
158 class ConfigSnapshotHolderImpl implements ConfigSnapshotHolder {
159
160     private final String snapshot;
161     private final SortedSet<String> caps;
162
163     public ConfigSnapshotHolderImpl(String configSnapshot, SortedSet<String> capabilities) {
164         this.snapshot = configSnapshot;
165         this.caps = capabilities;
166     }
167
168     @Override
169     public String getConfigSnapshot() {
170         return snapshot;
171     }
172
173     @Override
174     public SortedSet<String> getCapabilities() {
175         return caps;
176     }
177 }