org.parallelj.launching.transport.tcp.command.AbstractLaunchTcpCommand.java Source code

Java tutorial

Introduction

Here is the source code for org.parallelj.launching.transport.tcp.command.AbstractLaunchTcpCommand.java

Source

/*
 *     ParallelJ, framework for parallel computing
 *
 *     Copyright (C) 2010, 2011, 2012 Atos Worldline or third-party contributors as
 *     indicated by the @author tags or express copyright attribution
 *     statements applied by the authors.
 *
 *     This library is free software; you can redistribute it and/or
 *     modify it under the terms of the GNU Lesser General Public
 *     License as published by the Free Software Foundation; either
 *     version 2.1 of the License.
 *
 *     This library is distributed in the hope that it will be useful,
 *     but WITHOUT ANY WARRANTY; without even the implied warranty of
 *     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
 *     Lesser General Public License for more details.
 *
 *     You should have received a copy of the GNU Lesser General Public
 *     License along with this library; if not, write to the Free Software
 *     Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
 */
package org.parallelj.launching.transport.tcp.command;

import java.io.IOException;
import java.io.PrintWriter;
import java.io.StringWriter;
import java.io.Writer;
import java.util.ArrayList;
import java.util.Collections;
import java.util.Comparator;
import java.util.List;
import java.util.ServiceLoader;

import org.apache.commons.cli.CommandLine;
import org.apache.commons.cli.CommandLineParser;
import org.apache.commons.cli.HelpFormatter;
import org.apache.commons.cli.Option;
import org.apache.commons.cli.Options;
import org.apache.commons.cli.ParseException;
import org.apache.commons.cli.PosixParser;
import org.apache.mina.core.session.IoSession;
import org.parallelj.launching.LaunchingMessageKind;
import org.parallelj.launching.internal.spi.CacheableServiceLoader;
import org.parallelj.launching.parser.ParserException;
import org.parallelj.launching.remote.RemoteProgram;
import org.parallelj.launching.transport.tcp.TcpIpHandlerAdapter;
import org.parallelj.launching.transport.tcp.command.option.IIdOption;
import org.parallelj.launching.transport.tcp.command.option.IOption;
import org.parallelj.launching.transport.tcp.command.option.OptionException;

/**
 * Define a Program launch Command available in a TcpIpServer
 */
abstract class AbstractLaunchTcpCommand extends AbstractTcpCommand {

    /** default number of characters per line */
    public static final int DEFAULT_WIDTH = 74;

    /** default padding to the left of each line */
    public static final int DEFAULT_LEFT_PAD = 4;

    /**
     * the number of characters of padding to be prefixed to each description
     * line
     */
    public static final int DEFAULT_DESC_PAD = 3;

    private List<IOption> options;

    /*
     * (non-Javadoc)
     * 
     * @see
     * org.parallelj.launching.transport.tcp.command.TcpCommand#process(org.
     * apache.mina.core.session.IoSession, java.lang.String[])
     */
    public abstract String process(IoSession session, String... args);

    /*
     * (non-Javadoc)
     * 
     * @see org.parallelj.launching.transport.tcp.command.TcpCommand#getType()
     */
    public abstract String getType();

    public RemoteProgram parseCommandLine(final String... args) throws ParseException, OptionException {
        // Get sorted options
        final List<IOption> ioptions = getOptions();
        final Options options = new Options();
        for (IOption ioption : ioptions) {
            options.addOption(ioption.getOption());
        }

        // create the command line parser
        final CommandLineParser parser = new PosixParser();

        // parse the command line arguments
        // CommandLine cmdLine = parser.parse(options, args);
        final CommandLine cmdLine = parser.parse(options, args);
        // As Options are reinitialized after parsing,
        // we need to re-affect IOption.option
        for (Option option : cmdLine.getOptions()) {
            for (IOption ioption : getOptions()) {
                if (ioption.getOption().getOpt().equals(option.getOpt())) {
                    ioption.setOption(option);
                    break;
                }
            }
        }

        // First, we need to get the IIdOption to get the Program
        // We are sure this option is present as it it mandatory!
        IIdOption idOption = null;
        for (IOption ioption : ioptions) {
            if (ioption instanceof IIdOption) {
                idOption = (IIdOption) ioption;
                break;
            }
        }
        final RemoteProgram remoteProgram = idOption.getProgram();

        // Check all defined Options with the selected Program
        try {
            for (IOption ioption : ioptions) {
                ioption.ckeckOption(remoteProgram);
            }
            return remoteProgram;
        } catch (ParserException e) {
            throw new OptionException(e.getFormatedMessage());
        }
    }

    public List<IOption> getOptions() {
        final Class<? extends IOption> iOptionClass = this.getOptionClass();
        if (iOptionClass != null) {
            if (this.options == null) {
                this.options = new ArrayList<IOption>();
                ServiceLoader<? extends IOption> loader = CacheableServiceLoader.INSTANCE.load(iOptionClass,
                        AbstractLaunchTcpCommand.class.getClassLoader());
                if (loader == null || loader.iterator() == null || !loader.iterator().hasNext()) {
                    loader = CacheableServiceLoader.INSTANCE.load(iOptionClass,
                            Thread.currentThread().getContextClassLoader());
                }
                for (IOption option : loader) {
                    this.options.add(option);
                }
            }
        }

        // Sort the list of IOption.
        // The first IOption should be "id" as it is the only once mandatory
        final Comparator<IOption> comparator = new Comparator<IOption>() {
            public int compare(final IOption option1, final IOption option2) {
                if (option1.getOption() != null && option1.getOption().isRequired()) {
                    return -1;
                }
                if (option2.getOption() != null && option2.getOption().isRequired()) {
                    return 1;
                }
                return 0;
            }
        };
        Collections.sort(this.options, comparator);

        return this.options;
    }

    public abstract Class<? extends IOption> getOptionClass();

    @Override
    public String getHelp() {
        final Writer writer = new StringWriter();
        final PrintWriter printWriter = new PrintWriter(writer);
        final Options options = new Options();
        for (IOption ioption : this.getOptions()) {
            options.addOption(ioption.getOption());
        }
        final HelpFormatter formatter = new HelpFormatter();
        formatter.setSyntaxPrefix("  ");
        final Comparator<Option> comparator = new Comparator<Option>() {
            public int compare(final Option option1, final Option option2) {
                if (option1.isRequired()) {
                    return -1;
                }
                if (option2.isRequired()) {
                    return 1;
                }
                return 0;
            }
        };
        formatter.setOptionComparator(comparator);
        printWriter.print(getUsage() + TcpIpHandlerAdapter.ENDLINE);
        formatter.printHelp(printWriter, DEFAULT_WIDTH, getType(), null, options, DEFAULT_LEFT_PAD,
                DEFAULT_DESC_PAD, null, true);
        printWriter.flush();
        try {
            writer.flush();
        } catch (IOException e) {
            LaunchingMessageKind.EREMOTE0009.format(e);
        }
        return writer.toString();
    }
}