/* * Syncany, www.syncany.org * Copyright (C) 2011-2015 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.plugins.transfer; import java.lang.reflect.Constructor; import java.lang.reflect.InvocationTargetException; import org.syncany.config.Config; import org.syncany.plugins.Plugin; import org.syncany.plugins.transfer.files.RemoteFile; import org.syncany.util.ReflectionUtil; /** * The transfer plugin is a special plugin responsible for transferring files * to the remote storage. Implementations must provide implementations for * {@link TransferPlugin} (this class), {@link TransferSettings} (connection * details) and {@link TransferManager} (transfer methods).<br/><br/> * * *<i>Plugins have to follow a naming convention</i> * <ul> * <li>Package names have to be lower snaked cased</li> * <li>Class names have to be camel cased</li> * <li>Package names will be converted to class names by replacing underscores ('_') and uppercasing the * subsequent character.</li> * </ul> * * Example: * A plugin is called DummyPlugin, hence <i>org.syncany.plugins.dummy_plugin.DummyPluginTransferPlugin</i> is the * plugin's {@link TransferPlugin} class and <i>org.syncany.plugins.dummy_plugin.DummyPluginTransferSettings</i> is the * corresponding {@link TransferSettings} implementation. * * @author Philipp C. Heckel <philipp.heckel@gmail.com> * @author Christian Roth <christian.roth@port17.de> */ public abstract class TransferPlugin extends Plugin { public TransferPlugin(String pluginId) { super(pluginId); } /** * Creates an empty plugin-specific {@link org.syncany.plugins.transfer.TransferSettings} instance. * * @return Empty plugin-specific {@link org.syncany.plugins.transfer.TransferSettings} instance. * @throws StorageException Thrown if no {@link org.syncany.plugins.transfer.TransferSettings} are attached to a * plugin using {@link org.syncany.plugins.transfer.PluginSettings} */ @SuppressWarnings("unchecked") public final <T extends TransferSettings> T createEmptySettings() throws StorageException { final Class<? extends TransferSettings> transferSettings = TransferPluginUtil.getTransferSettingsClass(this.getClass()); if (transferSettings == null) { throw new StorageException("TransferPlugin does not have any settings attached!"); } try { return (T) transferSettings.newInstance(); } catch (InstantiationException | IllegalAccessException e) { throw new RuntimeException("Unable to create TransferSettings: " + e.getMessage()); } } /** * Creates an initialized, plugin-specific {@link org.syncany.plugins.transfer.TransferManager} object using the given * connection details. * * <p>The created instance can be used to upload/download/delete {@link RemoteFile}s * and query the remote storage for a file list. * * @param transferSettings A valid {@link org.syncany.plugins.transfer.TransferSettings} instance. * @param config A valid {@link org.syncany.config.Config} instance. * @return A initialized, plugin-specific {@link org.syncany.plugins.transfer.TransferManager} instance. * @throws StorageException Thrown if no (valid) {@link org.syncany.plugins.transfer.TransferManager} are attached to * a plugin using {@link org.syncany.plugins.transfer.PluginManager} */ @SuppressWarnings("unchecked") public final <T extends TransferManager> T createTransferManager(TransferSettings transferSettings, Config config) throws StorageException { if (!transferSettings.isValid()) { throw new StorageException("Unable to create transfer manager: connection isn't valid (perhaps missing some mandatory fields?)"); } final Class<? extends TransferSettings> transferSettingsClass = TransferPluginUtil.getTransferSettingsClass(this.getClass()); final Class<? extends TransferManager> transferManagerClass = TransferPluginUtil.getTransferManagerClass(this.getClass()); if (transferSettingsClass == null) { throw new RuntimeException("Unable to create transfer manager: No settings class attached"); } if (transferManagerClass == null) { throw new RuntimeException("Unable to create transfer manager: No manager class attached"); } try { Constructor<?> potentialConstructor = ReflectionUtil.getMatchingConstructorForClass(transferManagerClass, TransferSettings.class, Config.class); if (potentialConstructor == null) { throw new RuntimeException("Invalid arguments for constructor in pluginclass -- must be 2 and subclass of " + TransferSettings.class + " and " + Config.class); } return (T) potentialConstructor.newInstance(transferSettingsClass.cast(transferSettings), config); } catch (InstantiationException | IllegalAccessException | InvocationTargetException e) { throw new RuntimeException("Unable to create transfer settings: " + e.getMessage(), e); } } }