001/* 002 * Syncany, www.syncany.org 003 * Copyright (C) 2011-2016 Philipp C. Heckel <philipp.heckel@gmail.com> 004 * 005 * This program is free software: you can redistribute it and/or modify 006 * it under the terms of the GNU General Public License as published by 007 * the Free Software Foundation, either version 3 of the License, or 008 * (at your option) any later version. 009 * 010 * This program is distributed in the hope that it will be useful, 011 * but WITHOUT ANY WARRANTY; without even the implied warranty of 012 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 013 * GNU General Public License for more details. 014 * 015 * You should have received a copy of the GNU General Public License 016 * along with this program. If not, see <http://www.gnu.org/licenses/>. 017 */ 018package org.syncany.database.dao; 019 020import java.io.File; 021import java.io.FileInputStream; 022import java.io.FileOutputStream; 023import java.io.IOException; 024import java.io.InputStream; 025import java.io.OutputStreamWriter; 026import java.io.PrintWriter; 027import java.util.Iterator; 028import java.util.List; 029import java.util.logging.Level; 030import java.util.logging.Logger; 031 032import javax.xml.parsers.SAXParser; 033import javax.xml.parsers.SAXParserFactory; 034import javax.xml.stream.XMLStreamException; 035 036import org.syncany.chunk.Transformer; 037import org.syncany.database.DatabaseVersion; 038import org.syncany.database.MemoryDatabase; 039import org.syncany.database.VectorClock; 040 041/** 042 * Serializes a {@link MemoryDatabase} or a list of {@link DatabaseVersion}s to an 043 * XML-based file format, using a {@link Transformer} to compress/encrypt the file 044 * before writing, and to decompress/decrypt it before reading. 045 * 046 * <p>The class offers a variety of <code>save()</code> to serialize and store a memory 047 * database to a file, and several <code>load()</code> methods to load them from disk. 048 * 049 * <p>It uses a {@link DatabaseXmlWriter} to write XML files to disk and 050 * {@link DatabaseXmlParseHandler} to parse them while reading. 051 * 052 * @see DatabaseXmlParseHandler 053 * @see DatabaseXmlWriter 054 * @author Philipp C. Heckel (philipp.heckel@gmail.com) 055 */ 056public class DatabaseXmlSerializer { 057 private static final Logger logger = Logger.getLogger(DatabaseXmlSerializer.class.getSimpleName()); 058 059 public enum DatabaseReadType { 060 FULL, HEADER_ONLY 061 } 062 063 private Transformer transformer; 064 065 public DatabaseXmlSerializer() { 066 this(null); 067 } 068 069 public DatabaseXmlSerializer(Transformer transformer) { 070 this.transformer = transformer; 071 } 072 073 public void save(List<DatabaseVersion> databaseVersions, File destinationFile) throws IOException { 074 save(databaseVersions.iterator(), destinationFile); 075 } 076 077 public void save(Iterator<DatabaseVersion> databaseVersions, File destinationFile) throws IOException { 078 try { 079 PrintWriter out; 080 081 if (transformer == null) { 082 out = new PrintWriter(new OutputStreamWriter( 083 new FileOutputStream(destinationFile), "UTF-8")); 084 } 085 else { 086 out = new PrintWriter(new OutputStreamWriter( 087 transformer.createOutputStream(new FileOutputStream(destinationFile)), "UTF-8")); 088 } 089 090 // Initialize XML writer 091 new DatabaseXmlWriter(databaseVersions, out).write(); 092 } 093 catch (XMLStreamException e) { 094 throw new IOException(e); 095 } 096 } 097 098 public void load(MemoryDatabase db, File databaseFile, VectorClock fromVersion, VectorClock toVersion, DatabaseReadType readType) 099 throws IOException { 100 101 InputStream is; 102 103 if (transformer == null) { 104 is = new FileInputStream(databaseFile); 105 } 106 else { 107 is = transformer.createInputStream(new FileInputStream(databaseFile)); 108 } 109 110 try { 111 logger.log(Level.INFO, "- Loading database ({0}) from file {1} ...", new Object[] { readType, databaseFile }); 112 113 SAXParserFactory factory = SAXParserFactory.newInstance(); 114 SAXParser saxParser = factory.newSAXParser(); 115 116 saxParser.parse(is, new DatabaseXmlParseHandler(db, fromVersion, toVersion, readType)); 117 } 118 catch (Exception e) { 119 throw new IOException(e); 120 } 121 } 122 123}