Java tutorial
/* * Copyright 2006-2009,2015 National Institute of Advanced Industrial Science * and Technology (AIST), and contributors. * * 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 ow.tool.emulator; import java.io.BufferedReader; import java.io.BufferedWriter; import java.io.FileInputStream; import java.io.IOException; import java.io.InputStream; import java.io.InputStreamReader; import java.io.OutputStreamWriter; import java.io.PrintStream; import java.net.InetAddress; import java.net.Socket; import java.net.URL; import java.net.UnknownHostException; import java.util.List; import java.util.Map; import org.apache.commons.cli.CommandLine; import org.apache.commons.cli.CommandLineParser; import org.apache.commons.cli.Options; import org.apache.commons.cli.ParseException; import org.apache.commons.cli.DefaultParser; import ow.messaging.MessagingFactory; import ow.messaging.util.MessagingUtility; import ow.messaging.util.MessagingUtility.HostAndPort; import ow.tool.emulator.commands.ArgumentsCommand; import ow.tool.emulator.commands.ClassCommand; import ow.tool.emulator.commands.ControlCommand; import ow.tool.emulator.commands.ControlseriallyCommand; import ow.tool.emulator.commands.HaltCommand; import ow.tool.emulator.commands.HelpCommand; import ow.tool.emulator.commands.IncludeCommand; import ow.tool.emulator.commands.InvokeCommand; import ow.tool.emulator.commands.PriorityCommand; import ow.tool.emulator.commands.QuitCommand; import ow.tool.emulator.commands.RemoteCommand; import ow.tool.emulator.commands.ScheduleCommand; import ow.tool.emulator.commands.ScheduledaemonCommand; import ow.tool.emulator.commands.TimeoffsetCommand; import ow.tool.util.shellframework.Command; import ow.tool.util.shellframework.MessagePrinter; import ow.tool.util.shellframework.Shell; import ow.tool.util.shellframework.ShellServer; /** * The main class of distributed environment emulator. * This emulator hosts multiple instances of Java applications and * provides messaging service (ow.messaging) to them. * It reads commands from the specified scenario file or standard input. */ public class Main { private final static String COMMAND = "owemu"; // A shell/batch script provided as bin/owemu public final static int DIST_EMU_PORT = 3997; public final static long DIST_EMU_REMOTE_INVOCATION_WAIT = 10 * 1000L; public final static String ENCODING = "US-ASCII"; public final static long DEFAULT_WAIT_MILLIS = 2000L; public final static String RSH_COMMAND = "ssh"; public final static String JAVA_COMMAND = "java"; public final int DEFAULT_CONNECTION_PORT = 10101; private final static Class/*<Command<EmulatorContext>>*/[] COMMANDS = { ClassCommand.class, ArgumentsCommand.class, InvokeCommand.class, PriorityCommand.class, ControlCommand.class, ControlseriallyCommand.class, HaltCommand.class, TimeoffsetCommand.class, ScheduleCommand.class, ScheduledaemonCommand.class, IncludeCommand.class, HelpCommand.class, QuitCommand.class, RemoteCommand.class }; private final static List<Command<EmulatorContext>> commandList; private final static Map<String, Command<EmulatorContext>> commandTable; static { commandList = ShellServer.createCommandList(COMMANDS); commandTable = ShellServer.createCommandTable(commandList); } private OutputRedirector outputRedirector; private Main() { this.outputRedirector = new OutputRedirector(System.out); } public static void main(String[] args) { Main emu = new Main(); emu.start(args); } private static void usage() { System.out.print("Usage: " + COMMAND); System.out.println( " [-h] [--eventdriven] [-f <host list file>] [-w <str rep of host list>] [-c <connection target file>] [-s <self hostname>] [<scenario URL|file> ...]"); } public void start(String[] args) { EmulatorMode mode = EmulatorMode.NORMAL; boolean eventDrivenMode = false; RemoteAppInstanceTable workerTable = null; String controlTargetListFilename = null; EmulatorContext emuContext = null; int initialHostID = 0; // get self hostname InetAddress selfHostAddress = null; try { selfHostAddress = InetAddress.getLocalHost(); } catch (UnknownHostException e) { e.printStackTrace(); System.exit(1); } // parse command-line arguments Options opts = new Options(); opts.addOption("h", "help", false, "print help"); opts.addOption("E", "eventdriven", false, "emulator runs in event driven mode"); opts.addOption("f", "hostfile", true, "host file for working in master mode"); opts.addOption("w", "workertable", true, "works in worker mode"); opts.addOption("s", "selfipaddress", true, "self IP address (and port)"); opts.addOption("c", "controltargetlistfile", true, "control target list file"); CommandLineParser parser = new DefaultParser(); CommandLine cmd = null; try { cmd = parser.parse(opts, args); } catch (ParseException e) { System.out.println("There is an invalid option."); e.printStackTrace(); System.exit(1); } String optVal; if (cmd.hasOption('h')) { usage(); System.exit(1); } if (cmd.hasOption('E')) { eventDrivenMode = true; } optVal = cmd.getOptionValue('f'); if (optVal != null) { try { workerTable = RemoteAppInstanceTable.readHostFile(optVal); } catch (IOException e) { e.printStackTrace(); usage(); System.exit(1); } mode = EmulatorMode.MASTER; } optVal = cmd.getOptionValue('w'); if (optVal != null) { try { workerTable = RemoteAppInstanceTable.parseString(optVal); } catch (UnknownHostException e) { e.printStackTrace(); usage(); System.exit(1); } mode = EmulatorMode.WORKER; } optVal = cmd.getOptionValue('s'); if (optVal != null) { try { selfHostAddress = InetAddress.getByName(optVal); } catch (UnknownHostException e) { e.printStackTrace(); System.exit(1); } } optVal = cmd.getOptionValue('c'); if (optVal != null) { controlTargetListFilename = optVal; mode = EmulatorMode.CONTROLLER; } args = cmd.getArgs(); if (mode == EmulatorMode.WORKER) { // set initial host ID (emuXX) initialHostID = workerTable.getStartHostID(selfHostAddress); } // provide an EmulatorContext if (mode == EmulatorMode.MASTER) { emuContext = new EmulatorContext(System.out, initialHostID, workerTable, eventDrivenMode, mode); } else { emuContext = new EmulatorContext(System.out, initialHostID, new LocalAppInstanceTable(), eventDrivenMode, mode); } // connect to controlee if (mode == EmulatorMode.CONTROLLER) { try { this.connect(emuContext, controlTargetListFilename); } catch (IOException e) { e.printStackTrace(); return; } } // force the messaging service to use Emulator if (mode == EmulatorMode.WORKER) { MessagingFactory.forceDistributedEmulator(initialHostID, workerTable); } else { MessagingFactory.forceEmulator(initialHostID); } // parse scenario files try { parseScenario(emuContext, args); } catch (IOException e) { e.printStackTrace(); return; } } private void parseScenario(EmulatorContext emuContext, String[] filenames) throws IOException { // prepare commands ShellServer<EmulatorContext> shellServ = new ShellServer<EmulatorContext>(commandTable, commandList, new ShowPromptPrinter(), new NoCommandPrinter(), null, emuContext, -1); if (filenames != null && filenames.length > 0) { // parse scenario files for (int i = 0; i < filenames.length; i++) { InputStream in = null; try { in = (new URL(filenames[i])).openStream(); } catch (IOException e) { in = new FileInputStream(filenames[i]); } this.parseScenario(emuContext, shellServ, in, false); if (in != null) in.close(); } } else { // read standard input this.parseScenario(emuContext, shellServ, System.in, emuContext.getEmulatorMode() != EmulatorMode.WORKER); } } private void parseScenario(EmulatorContext emuContext, ShellServer<EmulatorContext> shServer, InputStream in, boolean interactive) { Shell<EmulatorContext> shell = new Shell<EmulatorContext>(in, System.out, shServer, emuContext, interactive); shell.run(); } private void connect(EmulatorContext emuContext, String targetListFile) throws IOException { InputStream in = null; try { in = (new URL(targetListFile)).openStream(); } catch (IOException e) { in = new FileInputStream(targetListFile); } BufferedReader bin = new BufferedReader(new InputStreamReader(in, ENCODING)); int hostID = 0; String aLine; while ((aLine = bin.readLine()) != null) { HostAndPort hostPort = MessagingUtility.parseHostnameAndPort(aLine, DEFAULT_CONNECTION_PORT); System.out.println("connect to " + hostPort); Socket sock = null; try { sock = new Socket(hostPort.getHostAddress(), hostPort.getPort()); } catch (IOException e) { System.out.println("Could not connect to " + hostPort); throw e; } // start an output redirector this.outputRedirector.redirect(sock.getInputStream(), "Redirector for " + hostPort); // register pipe emuContext.setControlPipe(hostID++, new BufferedWriter(new OutputStreamWriter(sock.getOutputStream(), ENCODING)), null); } } private static class ShowPromptPrinter implements MessagePrinter { public void execute(PrintStream out, String hint) { out.print("Ready." + Shell.CRLF); out.flush(); } } private static class NoCommandPrinter implements MessagePrinter { public void execute(PrintStream out, String hint) { out.print("No such command"); if (hint != null) out.print(": " + hint); else out.print("."); out.print(Shell.CRLF); out.flush(); } } }