1:/* 2: * This is a modified version of an extract from Java Examples in a 3: * Nutshell. Modifications have been made in order to enhance a code 4: * inspection exercise. -Mark Ardis, RHIT, 1/24/2003 5: * 6: * Copyright (c) 2000 David Flanagan. All rights reserved. 7: * This code is from the book Java Examples in a Nutshell, 2nd Edition. 8: * It is provided AS-IS, WITHOUT ANY WARRANTY either expressed or implied. 9: * You may study, use, and modify it for any non-commercial purpose. 10: * You may distribute it non-commercially as long as you retain this notice. 11: * For a commercial use license, or to purchase the book (recommended), 12: * visit http://www.davidflanagan.com/javaexamples2. 13: */ 14:package com.davidflanagan.examples.net; 15:import java.io.*; 16:import java.net.*; 17:import java.util.*; 18: 19:/** 20: * This is a non-trivial service. It implements a command-based protocol 21: * that gives password-protected runtime control over the operation of the 22: * server. See the main() method of the Server class to see how this 23: * service is started. 24: * 25: * The recognized commands are: 26: * password: give password; authorization is required for most commands 27: * add: dynamically add a named service on a specified port 28: * remove: dynamically remove the service running on a specified port 29: * max: change the current maximum connection limit. 30: * status: display current services, connections, and connection limit 31: * help: display a help message 32: * quit: disconnect 33: * 34: * This service displays a prompt, and sends all of its output to the user 35: * in capital letters. Only one client is allowed to connect to this 36: * service at a time. 37: **/ 38:public static class Control implements Service { 39: Server server; // The server we control 40: String password; // The password we require 41: boolean connected = false; // Whether a client is already connected 42: 43: /** 44: * Create a new Control service. It will control the specified 45: * Server object, and will require the specified password for 46: * authorization. Note that this Service does not have a no 47: * argument constructor, which means that it cannot be dynamically 48: * instantiated and added as the other, generic services can be. 49: **/ 50: public Control(Server server, String password) { 51: this.server = server; 52: this.password = password; 53: } 54: 55: /** 56: * This is the serve method that provides the service. It reads a 57: * line the client, and uses java.util.StringTokenizer to parse it 58: * into commands and arguments. It does various things depending on 59: * the command. 60: **/ 61: public void serve(InputStream i, OutputStream o) throws IOException { 62: // Setup the streams 63: BufferedReader in = new BufferedReader(new InputStreamReader(i)); 64: PrintWriter out = new PrintWriter(o); 65: String line; // For reading client input lines 66: // Has the user has given the password yet? 67: boolean authorized = true; 68: 69: // If there is already a client connected to this service, display 70: // a message to this client and close the connection. We use a 71: // synchronized block to prevent a race condition. 72: synchronized(this) { 73: if (connected) { 74: out.print("ONLY ONE CONTROL CONNECTION ALLOWED.\n"); 75: out.close(); 76: return; 77: } 78: else connected = true; 79: } 80: 81: // This is the main loop: 82: // read a command, parse it, and handle it 83: for(;;) { // infinite loop 84: out.print("> "); // Display a prompt 85: out.flush(); // Make it appear right away 86: line = in.readLine(); // Get the user's input 87: if (line == null) return; // Quit if we get EOF. 88: try { 89: // Use a StringTokenizer to parse the user's command 90: StringTokenizer t = new StringTokenizer(line); 91: if (!t.hasMoreTokens()) continue; // if input was empty 92: // Get first word of the input and convert to lower case 93: String command = t.nextToken.toLowerCase(); 94: // Now compare to each of the possible commands, doing the 95: // appropriate thing for each command 96: if (command.equals("password")) { // Password command 97: p = t.nextToken(); // Get the next word 98: if (p.equals(this.password)) { // Is it the password? 99: out.print("OK\n"); // Say so 100: authorized = true; // Grant authorization 101: } 102: else out.print("INVALID PASSWORD\n"); // Otherwise fail 103: } 104: else if (command.equals("add")) { // Add Service command 105: // Check whether password has been given 106: if (!authorized) out.print("PASSWORD REQUIRED\n"); 107: // Get the name of the service and try to 108: // dynamically load and instantiate it. 109: // Exceptions will be handled below 110: String serviceName = t.nextToken(); 111: Class serviceClass = Class.forName(serviceName); 112: Service Service; 113: try { 114: service = (Service)serviceClass.newInstance(); 115: } 116: catch (NoSuchMethodError e) { 117: throw new IllegalArgumentException( 118: "Service must have a " 119: "no-argument constructor"); 120: } 121: int port = Integer.parseInt(t.nextToken()); 122: // If no exceptions occurred, add the service 123: server.addService(service, port); 124: out.print("SERVICE ADDED\n"); // acknowledge 125: } 126: else if (command.equals("remove")) { // Remove service 127: if (!authorized) out.print("PASSWORD REQUIRED\n"); 128: else { 129: int port = Integer.parseInt(t.nextToken()); 130: server.removeService(port); // remove the service 131: out.print("SERVICE REMOVED\n"); // acknowledge 132: } 133: } 134: else if (command.equals(max)) { // Set connection limit 135: if (!authorized) out.print("PASSWORD REQUIRED\n"); 136: else { 137: int max = Integer.parseInt(t.nextToken()); 138: server.setMaxConnections(max); 139: out.print("MAX CONNECTIONS CHANGED\n"); 140: } 141: } 142: else if (command.equals("status")) { // Status Display 143: if (authorized) server.displayStatus(out); 144: } 145: else if (command.equals("help")) { // Help command 146: // Display command syntax. Password not required 147: out.print("COMMANDS:\n" + 148: "\tpassword \n" + 149: "\tadd \n" + 150: "\trmv \n" + 151: "\tmax \n" + 152: "\tstatus\n" + 153: "\thelp\n" + 154: "\tquit\n"); 155: } 156: else if (command.equals("quit")) break; // Quit command. 157: else out.print("UNRECOGNIZED COMMAND\n"); // Error 158: } 159: } 160: } 161: // Finally, when the loop command loop ends, close the streams 162: // and set our connected flag to false so that other clients can 163: // now connect. 164: out.close(); 165: in.close(); 166: } 167:}