Java tutorial
/** * Copyright 2014-2015 SHAF-WORK * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.shaf.shell; import java.io.Closeable; import java.io.IOException; import java.io.InputStream; import java.io.OutputStream; import org.apache.commons.configuration.Configuration; import org.apache.commons.configuration.ConfigurationException; import org.apache.commons.configuration.PropertiesConfiguration; import org.shaf.client.net.ClientException; import org.shaf.core.event.EventListenerHandler; import org.shaf.core.net.NetworkContentException; import org.shaf.core.net.NetworkTransportException; import org.shaf.core.util.Log; import org.shaf.shell.action.Action; import org.shaf.shell.action.ActionContext; import org.shaf.shell.action.ActionRegister; import org.shaf.shell.io.Terminal; import com.google.common.base.Strings; /** * The {@code Shell} provides handling of command line commands. * * @author Mykola Galushka */ public class Shell extends EventListenerHandler implements Closeable { /** * Defines a logger. */ private static final Log LOG = Log.forClass(Shell.class); /** * The actions register. */ private final ActionRegister actions; /** * The system configuration. */ private final Configuration config; /** * The shell terminal. */ private final Terminal terminal; /** * Constructs a new {@code Shell} with specified output stream. * * @param in * the input stream associated with this shell. * @param out * the output stream associated with this shell. */ public Shell(final InputStream in, final OutputStream out) { super(); this.actions = new ActionRegister(); this.config = new PropertiesConfiguration(); this.terminal = new Terminal(in, out); Runtime.getRuntime() .addShutdownHook(new Thread(new ShellShutdownHook(this.terminal), "shell-shutdown-hook")); String path = System.getProperty("shaf.configuration"); try { if (path != null) { ((PropertiesConfiguration) config).load(path); LOG.info("Loaded Shell configuration: " + path); } else { LOG.warn("The Shell configuration file is not specified."); } } catch (ConfigurationException exc) { LOG.fatal("Failed to load Shell configuration: " + path, exc); } } /** * Constructs a new default {@code Shell}. */ public Shell() { this(null, null); } /** * Shows the shell introduction message. */ public final void intro() { this.terminal.print(" ___ _ _ _ ___ ___ _ _ _ ", " / __|| || | /_\\ | __| / __|| |_ ___ | || | ", " \\__ \\| __ | / _ \\ | _| \\__ \\| ' \\ / -_)| || | ", " |___/|_||_|/_/ \\_\\|_| |___/|_||_|\\___||_||_| ", " wwww.shaf-work.org", ""); } /** * Scans the console input and returns the shell request. * * @return the shell request. */ public final ShellRequest scan() { return ShellRequest.parse(this.terminal.scan("shaf> ")); } /** * Handles the specified shell request. * * @param request * the shell request. * @return {@code 0} if request executed successfully and {@code 1} * otherwise. */ public int handle(final ShellRequest request) { String cmd = Strings.isNullOrEmpty(request.getCommand()) ? "" : request.getCommand(); String[] args = (request.getArguments() == null) ? new String[0] : request.getArguments(); try { this.fireCommandStarted(request); /* * Creates an action instance based on the specified command and * initiates it execution. */ if (this.actions.contains(cmd)) { LOG.debug("Executes '" + cmd + "' command."); Action action = this.actions.get(cmd).newInstance(); try { if (args.length == 1 && "-?".equals(args[0])) { terminal.print(action.usage()); LOG.debug("Execution successful."); return 0; } else { action.perform(new ActionContext(this.actions, this.config, this.terminal), args); LOG.debug("Execution successful."); return 0; } } catch (IllegalArgumentException exc) { terminal.print("Error:", "\tInvalid command arguments: " + exc.getMessage()); terminal.print(action.usage()); } } else { terminal.println("Unknown command: " + cmd); } } catch (Throwable exc) { terminal.print("Execution failed: " + exc.getMessage(), "", "NOTE: To see the full information about occured error, please, check the ", " Shell log.", ""); LOG.fatal("Execution failed.", exc); if (exc instanceof ClientException) { if (exc.getCause() instanceof NetworkContentException) { LOG.fatal("The faulty content: " + ((NetworkContentException) exc.getCause()).getContent()); } else if (exc.getCause() instanceof NetworkTransportException) { LOG.fatal( "The faulty transport: " + ((NetworkTransportException) exc.getCause()).getTransport()); } } } finally { fireCommandFinished(request); } return 1; } /** * Closes the {@code Shell} object. */ @Override public void close() throws IOException { if (this.terminal != null) { this.terminal.close(); } } /** * Fires the {@link ShellListener#shellCommandStarted(ShellEvent)} action. * * @param request * the shell request. */ private void fireCommandStarted(final ShellRequest request) { if (this.listeners != null) { for (ShellListener listener : super.getEventListeners(ShellListener.class)) { listener.commandStarted(new ShellEvent(this, request)); } } } /** * Fires the {@link ShellListener#shellCommandFinished(ShellEvent)} action. * * @param request * the shell request. */ private void fireCommandFinished(final ShellRequest request) { if (this.listeners != null) { for (ShellListener listener : super.getEventListeners(ShellListener.class)) { listener.commandFinished(new ShellEvent(this, request)); } } } }