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.config.to; 019 020import java.io.ByteArrayInputStream; 021import java.io.File; 022import java.io.FileOutputStream; 023import java.util.ArrayList; 024import java.util.List; 025 026import org.apache.commons.io.output.ByteArrayOutputStream; 027import org.simpleframework.xml.Element; 028import org.simpleframework.xml.ElementList; 029import org.simpleframework.xml.Root; 030import org.simpleframework.xml.Serializer; 031import org.simpleframework.xml.core.Commit; 032import org.simpleframework.xml.core.Complete; 033import org.simpleframework.xml.core.Persist; 034import org.simpleframework.xml.core.Persister; 035import org.syncany.config.ConfigException; 036import org.syncany.crypto.CipherSpec; 037import org.syncany.crypto.CipherUtil; 038import org.syncany.crypto.SaltedSecretKey; 039import org.syncany.util.StringUtil; 040 041/** 042 * The repo transfer object is used to create and load the repo file 043 * from/to XML. The repo file identifies the repository with a unique 044 * repo ID, and defines the chunking framework settings. It is 045 * stored locally and on the remote storage. 046 * 047 * <p>It uses the Simple framework for XML serialization, and its corresponding 048 * annotation-based configuration. 049 * 050 * @see <a href="http://simple.sourceforge.net/">Simple framework</a> 051 * @author Philipp C. Heckel (philipp.heckel@gmail.com) 052 */ 053@Root(name = "repo", strict = false) 054public class RepoTO { 055 @Element(name = "repoid", required = true) 056 private String repoIdEncoded; 057 private byte[] repoId; 058 059 @Element(name = "chunker", required = false) 060 private ChunkerTO chunker; 061 062 @Element(name = "multichunker", required = false) 063 private MultiChunkerTO multiChunker; 064 065 @ElementList(name = "transformers", required = false, entry = "transformer") 066 private ArrayList<TransformerTO> transformers; 067 068 public byte[] getRepoId() { 069 return repoId; 070 } 071 072 public void setRepoId(byte[] repoId) { 073 this.repoId = repoId; 074 } 075 076 public void save(File file) throws ConfigException { 077 try { 078 new Persister().write(this, file); 079 } 080 catch (Exception e) { 081 throw new ConfigException("Cannot write repoTO to file " + file, e); 082 } 083 } 084 085 public void save(File file, List<CipherSpec> cipherSpecs, SaltedSecretKey masterKey) throws ConfigException { 086 try { 087 088 ByteArrayOutputStream plaintextRepoOutputStream = new ByteArrayOutputStream(); 089 090 Serializer serializer = new Persister(); 091 serializer.write(this, plaintextRepoOutputStream); 092 093 CipherUtil.encrypt(new ByteArrayInputStream(plaintextRepoOutputStream.toByteArray()), new FileOutputStream(file), cipherSpecs, masterKey); 094 } 095 catch (Exception e) { 096 throw new ConfigException("Cannot write repoTO (encrypted) to file " + file, e); 097 } 098 } 099 100 @Persist 101 public void prepare() { 102 repoIdEncoded = (repoId != null) ? StringUtil.toHex(repoId) : null; 103 } 104 105 @Complete 106 public void release() { 107 repoIdEncoded = null; 108 } 109 110 @Commit 111 public void commit() { 112 repoId = (repoIdEncoded != null) ? StringUtil.fromHex(repoIdEncoded) : null; 113 } 114 115 public ChunkerTO getChunkerTO() { 116 return chunker; 117 } 118 119 public void setChunkerTO(ChunkerTO chunker) { 120 this.chunker = chunker; 121 } 122 123 public MultiChunkerTO getMultiChunker() { 124 return multiChunker; 125 } 126 127 public void setMultiChunker(MultiChunkerTO multiChunker) { 128 this.multiChunker = multiChunker; 129 } 130 131 public List<TransformerTO> getTransformers() { 132 return transformers; 133 } 134 135 public void setTransformers(List<TransformerTO> transformers) { 136 this.transformers = (transformers != null) ? new ArrayList<TransformerTO>(transformers) : null; 137 } 138 139 /** 140 * Configuration object for the deduplication chunker. As of 141 * today, this is a key/value based configuration. 142 */ 143 public static class ChunkerTO extends TypedPropertyListTO { 144 // Nothing special about this 145 } 146 147 /** 148 * Configuration object for the deduplication multi-chunker. As of 149 * today, this is a key/value based configuration. 150 */ 151 public static class MultiChunkerTO extends TypedPropertyListTO { 152 // Nothing special about this 153 } 154 155 /** 156 * Configuration object for the deduplication transformer. As of 157 * today, this is a key/value based configuration. 158 */ 159 public static class TransformerTO extends TypedPropertyListTO { 160 // Nothing special about this 161 } 162}