Package org.syncany.config

Source Code of org.syncany.config.Config

/*
* Syncany, www.syncany.org
* Copyright (C) 2011-2014 Philipp C. Heckel <philipp.heckel@gmail.com>
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program.  If not, see <http://www.gnu.org/licenses/>.
*/
package org.syncany.config;

import java.io.File;
import java.util.ArrayList;

import org.syncany.chunk.Chunker;
import org.syncany.chunk.CipherTransformer;
import org.syncany.chunk.FixedChunker;
import org.syncany.chunk.MultiChunker;
import org.syncany.chunk.NoTransformer;
import org.syncany.chunk.Transformer;
import org.syncany.config.to.ConfigTO;
import org.syncany.config.to.RepoTO;
import org.syncany.config.to.RepoTO.MultiChunkerTO;
import org.syncany.config.to.RepoTO.TransformerTO;
import org.syncany.crypto.SaltedSecretKey;
import org.syncany.database.DatabaseConnectionFactory;
import org.syncany.database.VectorClock;
import org.syncany.plugins.Plugins;
import org.syncany.plugins.transfer.TransferPlugin;
import org.syncany.plugins.transfer.TransferSettings;
import org.syncany.util.FileUtil;
import org.syncany.util.StringUtil;

/**
* The config class is the central point to configure a Syncany instance. It is mainly
* used in the operations, but parts of it are also used in other parts of the
* application -- especially file locations and names.
*
* <p>An instance of the <tt>Config</tt> class must be created through the transfer
* objects {@link ConfigTO} and {@link RepoTO}.
*
* @author Philipp C. Heckel <philipp.heckel@gmail.com>
*/
public class Config {
  public static final String DIR_APPLICATION = ".syncany";
  public static final String DIR_CACHE = "cache";
  public static final String DIR_DATABASE = "db";
  public static final String DIR_LOG = "logs";
  public static final String DIR_STATE = "state";

  // File in managed folder root
  public static final String FILE_IGNORE = ".syignore";

  // Files in .syncany
  public static final String FILE_CONFIG = "config.xml";
  public static final String FILE_REPO = "syncany";
  public static final String FILE_MASTER = "master";

  // File in .syncany/db
  public static final String FILE_DATABASE = "local.db";

  // Files in .syncany/state
  public static final String FILE_PORT = "port.xml";
  public static final String FILE_CLEANUP = "cleanup.xml";

  private byte[] repoId;
  private String machineName;
  private String displayName;
  private File localDir;
  private File appDir;
  private File cacheDir;
  private File databaseDir;
  private File logDir;
  private File stateDir;

  private SaltedSecretKey masterKey;

  private Cache cache;
  private TransferPlugin plugin;
  private TransferSettings transferSettings;
  private Chunker chunker;
  private MultiChunker multiChunker;
  private Transformer transformer;
  private IgnoredFiles ignoredFiles;

  static {
    UserConfig.init();
    Logging.init();
  }

  public Config(File aLocalDir, ConfigTO configTO, RepoTO repoTO) throws ConfigException {
    if (aLocalDir == null || configTO == null || repoTO == null) {
      throw new ConfigException("Arguments aLocalDir, configTO and repoTO cannot be null.");
    }

    initNames(configTO);
    initMasterKey(configTO);
    initDirectories(aLocalDir);
    initCache(configTO);
    initIgnoredFile();
    initRepo(repoTO);
    initConnection(configTO);
  }

  private void initNames(ConfigTO configTO) throws ConfigException {
    setMachineName(configTO.getMachineName());
    setDisplayName(configTO.getDisplayName());
  }

  private void initMasterKey(ConfigTO configTO) {
    masterKey = configTO.getMasterKey(); // can be null
  }

  private void initDirectories(File aLocalDir) throws ConfigException {
    localDir = FileUtil.getCanonicalFile(aLocalDir);
    appDir = FileUtil.getCanonicalFile(new File(localDir, DIR_APPLICATION));
    cacheDir = FileUtil.getCanonicalFile(new File(appDir, DIR_CACHE));
    databaseDir = FileUtil.getCanonicalFile(new File(appDir, DIR_DATABASE));
    logDir = FileUtil.getCanonicalFile(new File(appDir, DIR_LOG));
    stateDir = FileUtil.getCanonicalFile(new File(appDir, DIR_STATE));
  }

  private void initCache(ConfigTO configTO) {
    cache = new Cache(cacheDir);

    if (configTO.getCacheKeepBytes() != null && configTO.getCacheKeepBytes() >= 0) {
      cache.setKeepBytes(configTO.getCacheKeepBytes());
    }
  }

  private void initIgnoredFile() throws ConfigException {
    File ignoreFile = new File(localDir, FILE_IGNORE);
    ignoredFiles = new IgnoredFiles(ignoreFile);
  }

  private void initRepo(RepoTO repoTO) throws ConfigException {
    try {
      initRepoId(repoTO);
      initChunker(repoTO);
      initMultiChunker(repoTO);
      initTransformers(repoTO);
    }
    catch (Exception e) {
      throw new ConfigException("Unable to initialize repository information from config.", e);
    }
  }

  private void initRepoId(RepoTO repoTO) {
    repoId = repoTO.getRepoId();
  }

  private void initChunker(RepoTO repoTO) throws Exception {
    // TODO [feature request] make chunking options configurable, something like described in #29
    // See: https://github.com/syncany/syncany/issues/29#issuecomment-43425647

    chunker = new FixedChunker(512 * 1024, "SHA1");
  }

  private void initMultiChunker(RepoTO repoTO) throws ConfigException {
    MultiChunkerTO multiChunkerTO = repoTO.getMultiChunker();

    if (multiChunkerTO == null) {
      throw new ConfigException("No multichunker in repository config.");
    }

    multiChunker = MultiChunker.getInstance(multiChunkerTO.getType());

    if (multiChunker == null) {
      throw new ConfigException("Invalid multichunk type or settings: " + multiChunkerTO.getType());
    }

    multiChunker.init(multiChunkerTO.getSettings());
  }

  private void initTransformers(RepoTO repoTO) throws Exception {
    if (repoTO.getTransformers() == null || repoTO.getTransformers().size() == 0) {
      transformer = new NoTransformer();
    }
    else {
      ArrayList<TransformerTO> transformerTOs = new ArrayList<TransformerTO>(repoTO.getTransformers());
      Transformer lastTransformer = null;

      for (int i = transformerTOs.size() - 1; i >= 0; i--) {
        TransformerTO transformerTO = transformerTOs.get(i);
        Transformer transformer = Transformer.getInstance(transformerTO.getType());

        if (transformer == null) {
          throw new ConfigException("Cannot find transformer '" + transformerTO.getType() + "'");
        }

        if (transformer instanceof CipherTransformer) { // Dirty workaround
          transformerTO.getSettings().put(CipherTransformer.PROPERTY_MASTER_KEY, StringUtil.toHex(getMasterKey().getEncoded()));
          transformerTO.getSettings().put(CipherTransformer.PROPERTY_MASTER_KEY_SALT, StringUtil.toHex(getMasterKey().getSalt()));
        }

        transformer.init(transformerTO.getSettings());

        if (lastTransformer != null) {
          transformer.setNextTransformer(lastTransformer);
        }

        lastTransformer = transformer;
      }

      transformer = lastTransformer;
    }
  }

  private void initConnection(ConfigTO configTO) throws ConfigException {
    if (configTO.getTransferSettings() != null) {
      plugin = Plugins.get(configTO.getTransferSettings().getType(), TransferPlugin.class);

      if (plugin == null) {
        throw new ConfigException("Plugin not supported: " + configTO.getTransferSettings().getType());
      }

      try {
        transferSettings = (TransferSettings) configTO.getTransferSettings();
      }
      catch (Exception e) {
        throw new ConfigException("Cannot initialize storage: " + e.getMessage(), e);
      }
    }
  }

  public java.sql.Connection createDatabaseConnection() {
    return DatabaseConnectionFactory.createConnection(getDatabaseFile());
  }

  public File getCacheDir() {
    return cacheDir;
  }

  public File getAppDir() {
    return appDir;
  }

  public String getMachineName() {
    return machineName;
  }

  public void setMachineName(String machineName) throws ConfigException {
    if (machineName == null || !VectorClock.MACHINE_PATTERN.matcher(machineName).matches()) {
      throw new ConfigException("Machine name cannot be empty and must be only characters (A-Z).");
    }

    this.machineName = machineName;
  }

  public String getDisplayName() {
    return displayName;
  }

  public void setDisplayName(String displayName) {
    this.displayName = displayName;
  }

  public TransferPlugin getTransferPlugin() {
    return plugin;
  }

  public TransferSettings getConnection() {
    return transferSettings;
  }

  public void setConnection(TransferSettings connection) {
    this.transferSettings = connection;
  }

  public byte[] getRepoId() {
    return repoId;
  }

  public Chunker getChunker() {
    return chunker;
  }

  public Cache getCache() {
    return cache;
  }

  public IgnoredFiles getIgnoredFiles() {
    return ignoredFiles;
  }

  public MultiChunker getMultiChunker() {
    return multiChunker;
  }

  public Transformer getTransformer() {
    return transformer;
  }

  public void setCache(Cache cache) {
    this.cache = cache;
  }

  public File getLocalDir() {
    return localDir;
  }

  public File getDatabaseDir() {
    return databaseDir;
  }

  public File getLogDir() {
    return logDir;
  }

  public File getStateDir() {
    return stateDir;
  }

  public SaltedSecretKey getMasterKey() {
    return masterKey;
  }

  public File getDatabaseFile() {
    return new File(databaseDir, FILE_DATABASE);
  }

  public File getPortFile() {
    return new File(stateDir, FILE_PORT);
  }

  public File getCleanupFile() {
    return new File(stateDir, FILE_CLEANUP);
  }
}
TOP

Related Classes of org.syncany.config.Config

TOP
Copyright © 2018 www.massapi.com. All rights reserved.
All source code are property of their respective owners. Java is a trademark of Sun Microsystems, Inc and owned by ORACLE Inc. Contact coftware#gmail.com.