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.plugins.transfer;
019
020import java.io.File;
021import java.io.IOException;
022import java.util.logging.Level;
023import java.util.logging.Logger;
024
025import org.syncany.config.Config;
026import org.syncany.plugins.transfer.features.Retriable;
027import org.syncany.plugins.transfer.features.TransactionAware;
028import org.syncany.util.StringUtil;
029
030/**
031 * Implements basic functionality of a {@link TransferManager} which
032 * can be implemented sub-classes.
033 * 
034 * <p>This transfer manager is enhanced with the {@link TransactionAware}
035 * and {@link Retriable} annotations, thereby making it reliable.
036 *
037 * @author Philipp C. Heckel (philipp.heckel@gmail.com)
038 * @author Christian Roth (christian.roth@port17.de)
039 */
040@TransactionAware
041@Retriable(numberRetries = 3, sleepInterval = 3000)
042public abstract class AbstractTransferManager implements TransferManager { // TODO [medium] Rename this to AbstractReliableTransferManager
043        private static final Logger logger = Logger.getLogger(AbstractTransferManager.class.getSimpleName());
044
045        protected TransferSettings settings;
046        protected Config config;
047
048        public AbstractTransferManager(TransferSettings settings, Config config) {
049                this.settings = settings;
050                this.config = config;
051        }
052
053        /**
054         * Creates a temporary file, either using the config (if initialized) or
055         * using the global temporary directory.
056         */
057        protected File createTempFile(String name) throws IOException {
058                if (config == null) {
059                        return File.createTempFile(String.format("temp-%s-", name), ".tmp");
060                }
061                else {
062                        return config.getCache().createTempFile(name);
063                }
064        }
065
066        /**
067         * Checks whether the settings given to this transfer manager can be
068         * used to create or connect to a remote repository.
069         *
070         * <p>Tests if the target exists, if it can be written to and if a
071         * repository can be created.
072         */
073        @Override
074        public StorageTestResult test(boolean testCreateTarget) {
075                logger.log(Level.INFO, "Performing storage test TM.test() ...");
076                StorageTestResult result = new StorageTestResult();
077
078                try {
079                        logger.log(Level.INFO, "- Running connect() ...");
080                        connect();
081
082                        result.setTargetExists(testTargetExists());
083                        result.setTargetCanWrite(testTargetCanWrite());
084                        result.setRepoFileExists(testRepoFileExists());
085
086                        if (result.isTargetExists()) {
087                                result.setTargetCanCreate(true);
088                        }
089                        else {
090                                if (testCreateTarget) {
091                                        result.setTargetCanCreate(testTargetCanCreate());
092                                }
093                                else {
094                                        result.setTargetCanCreate(false);
095                                }
096                        }
097
098                        result.setTargetCanConnect(true);
099                }
100                catch (StorageException e) {
101                        result.setTargetCanConnect(false);
102                        result.setErrorMessage(StringUtil.getStackTrace(e));
103
104                        logger.log(Level.INFO, "-> Testing storage failed. Returning " + result, e);
105                }
106                finally {
107                        try {
108                                disconnect();
109                        }
110                        catch (StorageException e) {
111                                logger.log(Level.FINE, "Could not disconnect", e);
112                        }
113                }
114
115                return result;
116        }
117}