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.cli; 019 020import java.io.File; 021import java.io.PrintStream; 022 023import org.syncany.cli.util.CarriageReturnPrinter; 024import org.syncany.config.Config; 025import org.syncany.config.LocalEventBus; 026import org.syncany.operations.OperationOptions; 027import org.syncany.operations.OperationResult; 028 029/** 030 * Commands are the central part of Syncany's command line client. Each implementation 031 * of this abstract class represents a command that a user can run on the command line. 032 * 033 * <p>The purpose of a command is to read required and optional arguments from the command 034 * line, run the corresponding operation, and display the results on the console. 035 * Implementations are not supposed to actually run any detailed logic, but are merely 036 * the user interface to collection options and print operation output. 037 * 038 * <p>Implementations must implement the {@link #execute(String[]) execute()} method and 039 * the {@link #getRequiredCommandScope()} method. While the former actually implements 040 * the logic, the latter specifies whether a command must be called inside (or outside) a 041 * local Syncany directory. 042 * 043 * <p>Commands are automatically mapped from their camel case name on the command line 044 * to a class name using the {@link CommandFactory}. The command 'ls-remote', for instance, 045 * is mapped to the <code>LsRemoteCommand</code>. 046 * 047 * @author Philipp C. Heckel (philipp.heckel@gmail.com) 048 */ 049public abstract class Command { 050 protected Config config; 051 protected File localDir; 052 protected CarriageReturnPrinter out; 053 054 protected LocalEventBus eventBus; 055 056 public Command() { 057 this.eventBus = LocalEventBus.getInstance(); 058 this.eventBus.register(this); 059 } 060 061 /** 062 * This method implements the command-specific option-parsing, operation calling 063 * and output printing. To do so, the method must read and evaluate the given 064 * arguments, prepare a corresponding operation, call it and display the results 065 * according to a well-defined format. 066 * 067 * <p>Implementations should not move any business logic in the execute method 068 * (or any other parts of the command). 069 * 070 * @param operationArgs Command-specific arguments (might also contain global options) 071 * @return Returns a return code 072 * @throws Exception If the command or the corresponding operation fails 073 */ 074 public abstract int execute(String[] operationArgs) throws Exception; 075 076 /** 077 * A command can either be executed within an initialized local directory or 078 * in a regular (non-Syncany) directory. Syncany determines this by searching for 079 * a .syncany folder. 080 * 081 * <p>The required command scope resembles whether or not a command must be executed 082 * inside a .syncany directory or not -- or whether it does not matter. 083 * 084 * @return Returns the required command scope of the command 085 */ 086 public abstract CommandScope getRequiredCommandScope(); 087 088 /** 089 * Returns whether a command can be run inside the scope of the daemon. 090 * 091 * <p>If a folder is daemon-managed, the command line client passes the command 092 * to the daemon via REST and the daemon executes this command/operation. For some 093 * commands, this does not make sense or is dangerous. This method allows certain 094 * commands to be daemon-enabled, and other to be daemon-disabled. 095 */ 096 public abstract boolean canExecuteInDaemonScope(); 097 098 /** 099 * A command can typically be configured using command line options. This method 100 * parses these command line options and returns an {@link OperationOptions} object 101 * representing the options. 102 */ 103 public abstract OperationOptions parseOptions(String[] operationArgs) throws Exception; 104 105 /** 106 * A command typically prints a result to the console. This method takes an 107 * {@link OperationResult} object and formats it to be human-readable. 108 */ 109 public abstract void printResults(OperationResult result); 110 111 public void setLocalDir(File localDir) { 112 this.localDir = localDir; 113 } 114 115 public Config getConfig() { 116 return config; 117 } 118 119 public void setConfig(Config config) { 120 this.config = config; 121 } 122 123 public void setOut(PrintStream out) { 124 this.out = new CarriageReturnPrinter(out); 125 } 126 127 public void setOut(CarriageReturnPrinter out) { 128 this.out = out; 129 } 130}