/*
* The MIT License
*
* Copyright (c) 2014 Red Hat, Inc.
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in
* all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
* THE SOFTWARE.
*/
package com.github.olivergondza.dumpling.cli;
import java.io.IOException;
import java.io.InputStream;
import java.io.PrintStream;
import java.util.Comparator;
import java.util.SortedSet;
import java.util.TreeSet;
import javax.annotation.Nonnull;
import org.kohsuke.args4j.Argument;
import org.kohsuke.args4j.CmdLineException;
import org.kohsuke.args4j.CmdLineParser;
public class HelpCommand implements CliCommand {
@Argument(usage = "Print detailed usage", metaVar = "COMMAND")
private String commandName;
@Override
public String getName() {
return "help";
}
@Override
public String getDescription() {
return "Print dumpling usage";
}
@Override
public int run(@Nonnull ProcessStream process) throws CmdLineException {
if (commandName == null) {
printUsage(process.out());
} else {
CliCommand command = CliCommandOptionHandler.getHandler(commandName);
if (command == null) throw new CmdLineException(null, "No such command " + commandName);
printUsage(command, process.out());
}
return 0;
}
/*package*/ static void printUsage(CliCommand handler, PrintStream out, CmdLineException ex) {
if (handler == null) {
printUsage(out);
} else if (ex instanceof Main.ProcessRuntimeOptionHandler.UnknownRuntimeKind) {
printAvailableRuntimeSources(out);
} else {
printUsage(handler, out);
}
}
/*package*/ static void printUsage(PrintStream out) {
out.printf(usage("<COMMAND> [...]%n%n"));
out.printf("Available commands:%n%n");
for (CliCommand handler: sortedHandlers()) {
CmdLineParser parser = new CmdLineParser(handler);
out.print(handler.getName());
parser.printSingleLineUsage(out);
out.printf("%n\t%s%n", handler.getDescription());
}
printAvailableRuntimeSources(out);
}
private static void printAvailableRuntimeSources(PrintStream out) {
out.printf("%nAvailable runtime source KINDs:%n%n");
for (CliRuntimeFactory<?> factory: Main.ProcessRuntimeOptionHandler.getFactories()) {
out.println(factory.getKind());
out.printf("\t%s%n", factory.getDescription());
}
}
/*package*/ static void printUsage(CliCommand handler, PrintStream out) {
out.print(handler.getDescription());
out.printf("%n%n");
CmdLineParser parser = new CmdLineParser(handler);
out.print(usage(handler.getName()));
parser.printSingleLineUsage(out);
out.printf("%n");
parser.printUsage(out);
printLongDescription(handler, out);
}
private static void printLongDescription(CliCommand handler, PrintStream out) {
String name = "command."+ handler.getName() + ".usage";
InputStream description = handler.getClass().getResourceAsStream(name);
if (description == null) return;
out.printf("%n");
try {
try {
forward(description, out);
} finally {
description.close();
}
} catch (IOException ex) {
throw new CommandFailedException("Unable to read detailed usage for " + handler.getName(), ex);
}
}
private static void forward(InputStream description, PrintStream out) throws IOException {
byte[] buffer = new byte[1024];
int len;
while ((len = description.read(buffer)) != -1) {
out.write(buffer, 0, len);
}
}
private static SortedSet<? extends CliCommand> sortedHandlers() {
TreeSet<CliCommand> sorted = new TreeSet<CliCommand>(new Comparator<CliCommand>() {
@Override
public int compare(CliCommand lhs, CliCommand rhs) {
return lhs.getName().compareTo(rhs.getName());
}
});
sorted.addAll(CliCommandOptionHandler.getAllHandlers());
return sorted;
}
private static String usage(String rest) {
return "Usage: ./dumpling.sh " + rest;
}
}