Package org.cyclopsgroup.jmxterm.cc

Source Code of org.cyclopsgroup.jmxterm.cc.CommandCenter

package org.cyclopsgroup.jmxterm.cc;

import java.io.IOException;
import java.io.PrintWriter;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;
import java.util.Set;
import java.util.concurrent.locks.Lock;
import java.util.concurrent.locks.ReentrantLock;

import javax.management.JMException;
import javax.management.remote.JMXServiceURL;

import org.apache.commons.lang.ArrayUtils;
import org.apache.commons.lang.StringUtils;
import org.apache.commons.lang.Validate;
import org.cyclopsgroup.caff.token.EscapingValueTokenizer;
import org.cyclopsgroup.caff.token.TokenEvent;
import org.cyclopsgroup.caff.token.TokenEventHandler;
import org.cyclopsgroup.caff.token.ValueTokenizer;
import org.cyclopsgroup.jcli.ArgumentProcessor;
import org.cyclopsgroup.jmxterm.Command;
import org.cyclopsgroup.jmxterm.CommandFactory;
import org.cyclopsgroup.jmxterm.JavaProcessManager;
import org.cyclopsgroup.jmxterm.Session;
import org.cyclopsgroup.jmxterm.io.CommandInput;
import org.cyclopsgroup.jmxterm.io.CommandOutput;
import org.cyclopsgroup.jmxterm.io.RuntimeIOException;
import org.cyclopsgroup.jmxterm.io.VerboseLevel;

/**
* Facade class where commands are maintained and executed
*
* @author <a href="mailto:jiaqi.guo@gmail.com">Jiaqi Guo</a>
*/
public class CommandCenter
{
    private static final String COMMAND_DELIMITER = "&&";

    /**
     * Argument tokenizer that parses arguments
     */
    final ValueTokenizer argTokenizer = new EscapingValueTokenizer();

    /**
     * Command factory that creates commands
     */
    final CommandFactory commandFactory;

    private final Lock lock = new ReentrantLock();

    private final JavaProcessManager processManager;

    /**
     * A handler to session
     */
    final Session session;

    /**
     * Constructor with given output {@link PrintWriter}
     *
     * @param output Message output. It can't be NULL
     * @param input Command line input
     * @throws IOException Thrown for file access failure
     */
    public CommandCenter( CommandOutput output, CommandInput input )
        throws IOException
    {
        this( output, input, new PredefinedCommandFactory() );
    }

    /**
     * This constructor is for testing purpose only
     *
     * @param output Output result
     * @param input Command input
     * @param commandFactory Given command factory
     * @throws IOException IO problem
     */
    public CommandCenter( CommandOutput output, CommandInput input, CommandFactory commandFactory )
        throws IOException
    {
        Validate.notNull( output, "Output can't be NULL" );
        Validate.notNull( commandFactory, "Command factory can't be NULL" );
        processManager = new JPMFactory().getProcessManager();
        this.session = new SessionImpl( output, input, processManager );
        this.commandFactory = commandFactory;

    }

    /**
     * Close session
     */
    public void close()
    {
        session.close();
    }

    /**
     * @param url MBeanServer location. It can be <code>AAA:###</code> or full JMX server URL
     * @param env Environment variables
     * @throws IOException Thrown when connection can't be established
     */
    public void connect( JMXServiceURL url, Map<String, Object> env )
        throws IOException
    {
        Validate.notNull( url, "URL can't be NULL" );
        session.connect( url, env );
    }

    private void doExecute( String command )
        throws JMException
    {
        command = StringUtils.trimToNull( command );
        // Ignore empty line
        if ( command == null )
        {
            return;
        }
        // Ignore line comment
        if ( command.startsWith( "#" ) )
        {
            return;
        }
        // Truncate command if there's # character
        int commandEnds = command.indexOf( '#' );
        if ( commandEnds != -1 )
        {
            command = command.substring( 0, commandEnds );
        }
        // If command includes multiple segments, call them one by one using recursive call
        if ( command.indexOf( COMMAND_DELIMITER ) != -1 )
        {
            String[] commands = StringUtils.split( command, COMMAND_DELIMITER );
            for ( String c : commands )
            {
                execute( c );
            }
            return;
        }

        // Take the first argument out since it's command name
        final List<String> args = new ArrayList<String>();
        argTokenizer.parse( command, new TokenEventHandler()
        {
            public void handleEvent( TokenEvent event )
            {
                args.add( event.getToken() );
            }
        } );
        String commandName = args.remove( 0 );
        // Leave the rest of arguments for command
        String[] commandArgs = args.toArray( ArrayUtils.EMPTY_STRING_ARRAY );
        // Call command with parsed command name and arguments
        try
        {
            doExecute( commandName, commandArgs, command );
        }
        catch ( IOException e )
        {
            throw new RuntimeIOException( "Runtime IO exception: " + e.getMessage(), e );
        }
    }

    private void doExecute( String commandName, String[] commandArgs, String originalCommand )
        throws JMException, IOException
    {
        Command cmd = commandFactory.createCommand( commandName );
        if ( cmd instanceof HelpCommand )
        {
            ( (HelpCommand) cmd ).setCommandCenter( this );
        }
        ArgumentProcessor<Command> ap = (ArgumentProcessor<Command>) ArgumentProcessor.newInstance( cmd.getClass() );

        ap.process( commandArgs, cmd );
        // Print out usage if help option is specified
        if ( cmd.isHelp() )
        {
            ap.printHelp( new PrintWriter( System.out, true ) );
            return;
        }
        cmd.setSession( session );
        // Make sure concurrency and run command
        lock.lock();
        try
        {
            cmd.execute();
        }
        finally
        {
            lock.unlock();
        }
    }

    /**
     * Execute a command. Command can be a valid full command, a comment, command followed by comment or empty
     *
     * @param command String command to execute
     * @return True if successful
     */
    public boolean execute( String command )
    {
        try
        {
            doExecute( command );
            return true;
        }
        catch ( JMException e )
        {
            session.output.printError( e );
            return false;
        }
        catch ( RuntimeException e )
        {
            session.output.printError( e );
            return false;
        }
    }

    /**
     * @return Set of command names
     */
    public Set<String> getCommandNames()
    {
        return commandFactory.getCommandTypes().keySet();
    }

    /**
     * @param name Command name
     * @return Type of command associated with given name
     */
    public Class<? extends Command> getCommandType( String name )
    {
        return commandFactory.getCommandTypes().get( name );
    }

    /**
     * @return Java process manager implementation
     */
    public final JavaProcessManager getProcessManager()
    {
        return processManager;
    }

    /**
     * @return True if command center is closed
     */
    public boolean isClosed()
    {
        return session.isClosed();
    }

    /**
     * @param verboseLevel New verbose level value
     */
    public void setVerboseLevel( VerboseLevel verboseLevel )
    {
        session.setVerboseLevel( verboseLevel );
    }
}
TOP

Related Classes of org.cyclopsgroup.jmxterm.cc.CommandCenter

TOP
Copyright © 2018 www.massapi.com. All rights reserved.
All source code are property of their respective owners. Java is a trademark of Sun Microsystems, Inc and owned by ORACLE Inc. Contact coftware#gmail.com.