Added xml storage adapter bundle fragments for config persister.
[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.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;
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 List<ConfigSnapshotHolder> loadLastConfigs() throws IOException {
68         File[] filesArray = storage.listFiles();
69         if (filesArray == null || filesArray.length == 0) {
70             return Collections.emptyList();
71         }
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);
76
77         List<ConfigSnapshotHolder> result = new ArrayList<>();
78         for (File file : sortedFiles) {
79             logger.trace("Adding file '{}' to combined result", file);
80
81             final MyLineProcessor lineProcessor = new MyLineProcessor(file.getAbsolutePath());
82             Files.readLines(file, ENCODING, lineProcessor);
83             result.add(lineProcessor.getConfigSnapshotHolder(header, middle, footer));
84         }
85         return result;
86     }
87
88
89     @Override
90     public void close() {
91
92     }
93
94     @Override
95     public String toString() {
96         return "FileStorageAdapter [storage=" + storage + "]";
97     }
98 }
99
100 class MyLineProcessor implements com.google.common.io.LineProcessor<String> {
101     private final String fileNameForReporting;
102
103     private boolean inModules, inServices, inCapabilities;
104     private final StringBuffer modulesBuffer = new StringBuffer(), servicesBuilder = new StringBuffer();
105     private final SortedSet<String> caps = new TreeSet<>();
106
107     MyLineProcessor(String fileNameForReporting) {
108         this.fileNameForReporting = fileNameForReporting;
109     }
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     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));
146     }
147
148     String getModules() {
149         checkFileConsistency();
150         return modulesBuffer.toString();
151     }
152
153     String getServices() {
154         checkFileConsistency();
155         return servicesBuilder.toString();
156     }
157
158     SortedSet<String> getCapabilities() {
159         checkFileConsistency();
160         return caps;
161     }
162
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);
166         return result;
167     }
168
169 }
170