package co.codewizards.cloudstore.client;
import java.io.Console;
import co.codewizards.cloudstore.ls.rest.client.LocalServerRestClient;
import co.codewizards.cloudstore.ls.server.LocalServer;
/**
* <p>
* Sub-command for a certain CLI operation.
* <p>
* The CloudStore-command-line-interface uses a syntax similar to the svn command and the logic of the
* command 'java -jar co.codewizards.cloudstore.client-VERSION.jar SUBCOMMAND -arg1 val1 -arg2 val2 ...'
* is thus actually implemented by a class extending this class and {@link #getSubCommandName() registering}
* for a certain 'SUBCOMMAND'.
* <p>
* Every subclass of this class can declare its arguments using annotations like {@link Option}.
*
* @author Marco หงุ่ยตระกูล-Schulze - marco at nightlabs dot de
*/
public abstract class SubCommand
{
private String subCommandName;
private LocalServer localServer;
/**
* Get the name of the sub-command, i.e. what the user has to write in the command line.
* @return the name of the sub-command.
*/
public String getSubCommandName() {
if (subCommandName == null) {
final String suffix = "SubCommand";
String simpleName = this.getClass().getSimpleName();
if (!simpleName.endsWith(suffix))
throw new IllegalStateException(
String.format("Class name '%s' does not end with suffix '%s'! Rename the class or override the 'getSubCommand()' method!",
simpleName, suffix));
StringBuilder sb = new StringBuilder();
sb.append(simpleName.substring(0, simpleName.length() - suffix.length()));
if (sb.length() == 0)
throw new IllegalStateException(
String.format("Class name '%s' equals suffix '%s'! There should be sth. before the suffix! Rename the class or override the 'getSubCommand()' method!",
simpleName, suffix));
sb.setCharAt(0, Character.toLowerCase(sb.charAt(0)));
subCommandName = sb.toString();
}
return subCommandName;
}
/**
* Get the description for this sub-command.
* @return the description.
*/
public abstract String getSubCommandDescription();
/**
* Invoked before {@link #run()}.
* <p>
* Implementors should always invoked the super-method when overriding!
* @throws Exception in case, the preparation failed.
* @see #cleanUp()
*/
public void prepare() throws Exception {
localServer = new LocalServer();
if (! localServer.start())
localServer = null;
}
public abstract void run()
throws Exception;
/**
* Invoked after {@link #run()}.
* <p>
* This method is always invoked, when {@link #prepare()} was invoked - even if {@link #run()} failed with an exception.
* <p>
* Implementors should always invoked the super-method when overriding (preferably at the end)!
* @throws Exception in case, cleaning up failed.
* @see #prepare()
*/
public void cleanUp() throws Exception {
if (localServer != null) {
localServer.stop();
localServer = null;
}
}
protected String promptPassword(String fmt, Object ... args) {
Console console = System.console();
if (console == null)
throw new IllegalStateException("There is no system console! Cannot prompt \"" + String.format(fmt, args) + "\"!!!");
char[] pw = console.readPassword(fmt, args);
if (pw == null)
return null;
else
return new String(pw);
}
protected String prompt(String fmt, Object ... args) {
Console console = System.console();
if (console == null)
throw new IllegalStateException("There is no system console! Cannot prompt \"" + String.format(fmt, args) + "\"!!!");
String result = console.readLine(fmt, args);
return result;
}
public boolean isVisibleInHelp() {
return true;
}
public LocalServerRestClient getLocalServerRestClient() {
return LocalServerRestClient.getInstance();
}
}