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.xml;
10 import static com.google.common.base.Preconditions.checkArgument;
12 import com.google.common.base.Optional;
13 import com.google.common.io.Files;
15 import java.io.FilenameFilter;
16 import java.io.IOException;
17 import java.util.ArrayList;
18 import java.util.Arrays;
19 import java.util.Collections;
20 import java.util.List;
22 import java.util.SortedSet;
23 import javax.xml.bind.JAXBContext;
24 import javax.xml.bind.JAXBException;
25 import javax.xml.bind.Unmarshaller;
26 import org.opendaylight.controller.config.persist.api.ConfigSnapshotHolder;
27 import org.opendaylight.controller.config.persist.api.Persister;
28 import org.opendaylight.controller.config.persist.storage.file.xml.model.ConfigSnapshot;
29 import org.slf4j.Logger;
30 import org.slf4j.LoggerFactory;
32 public class XmlDirectoryPersister implements Persister {
33 private static final Logger LOG = LoggerFactory.getLogger(XmlDirectoryPersister.class);
35 private final File storage;
36 private final Optional<FilenameFilter> extensionsFilter;
39 * Creates XmlDirectoryPersister that picks up all files in specified folder
41 public XmlDirectoryPersister(final File storage) {
42 this(storage, Optional.<FilenameFilter>absent());
46 * Creates XmlDirectoryPersister that picks up files only with specified file extension
48 public XmlDirectoryPersister(final File storage, final Set<String> fileExtensions) {
49 this(storage, Optional.of(getFilter(fileExtensions)));
52 private XmlDirectoryPersister(final File storage, final Optional<FilenameFilter> extensionsFilter) {
53 checkArgument(storage.exists() && storage.isDirectory(), "Storage directory does not exist: " + storage);
54 this.storage = storage;
55 this.extensionsFilter = extensionsFilter;
59 public void persistConfig(final ConfigSnapshotHolder holder) throws IOException {
60 throw new UnsupportedOperationException("This adapter is read only. Please set readonly=true on " + getClass());
64 public List<ConfigSnapshotHolder> loadLastConfigs() throws IOException {
65 File[] filesArray = extensionsFilter.isPresent() ? storage.listFiles(extensionsFilter.get()) : storage.listFiles();
66 if (filesArray == null || filesArray.length == 0) {
67 return Collections.emptyList();
69 List<File> sortedFiles = new ArrayList<>(Arrays.asList(filesArray));
70 Collections.sort(sortedFiles);
71 // combine all found files
72 LOG.debug("Reading files in following order: {}", sortedFiles);
74 List<ConfigSnapshotHolder> result = new ArrayList<>();
75 for (File file : sortedFiles) {
76 LOG.trace("Adding file '{}' to combined result", file);
77 Optional<ConfigSnapshotHolder> h = fromXmlSnapshot(file);
78 // Ignore non valid snapshot
79 if(h.isPresent() == false) {
88 private Optional<ConfigSnapshotHolder> fromXmlSnapshot(final File file) {
90 return Optional.of(loadLastConfig(file));
91 } catch (JAXBException e) {
92 // In case of parse error, issue a warning, ignore and continue
94 "Unable to parse configuration snapshot from {}. Initial config from {} will be IGNORED in this run. ",
97 "Note that subsequent config files may fail due to this problem. ",
98 "Xml markup in this file needs to be fixed, for detailed information see enclosed exception.",
102 return Optional.absent();
105 public static ConfigSnapshotHolder loadLastConfig(final File file) throws JAXBException {
106 JAXBContext jaxbContext = JAXBContext.newInstance(ConfigSnapshot.class);
107 Unmarshaller um = jaxbContext.createUnmarshaller();
109 return asHolder((ConfigSnapshot) um.unmarshal(file));
112 private static ConfigSnapshotHolder asHolder(final ConfigSnapshot unmarshalled) {
113 return new ConfigSnapshotHolder() {
115 public String getConfigSnapshot() {
116 return unmarshalled.getConfigSnapshot();
120 public SortedSet<String> getCapabilities() {
121 return unmarshalled.getCapabilities();
125 public String toString() {
126 return unmarshalled.toString();
131 private static FilenameFilter getFilter(final Set<String>fileExtensions) {
132 checkArgument(fileExtensions.isEmpty() == false, "No file extension provided", fileExtensions);
134 return new FilenameFilter() {
136 public boolean accept(final File dir, final String name) {
137 String ext = Files.getFileExtension(name);
138 return fileExtensions.contains(ext);
144 public void close() {
149 public String toString() {
150 final StringBuffer sb = new StringBuffer("XmlDirectoryPersister{");
151 sb.append("storage=").append(storage);
153 return sb.toString();