001: /**
002: * $Id: MultiProcessCommand.java,v 1.6 2006/02/08 00:55:10 cathywu Exp $
003: * Copyright 2004 Sun Microsystems, Inc. All
004: * rights reserved. Use of this product is subject
005: * to license terms. Federal Acquisitions:
006: * Commercial Software -- Government Users
007: * Subject to Standard License Terms and
008: * Conditions.
009: *
010: * Sun, Sun Microsystems, the Sun logo, and Sun ONE
011: * are trademarks or registered trademarks of Sun Microsystems,
012: * Inc. in the United States and other countries.
013: */package com.sun.portal.admin.cli.commands;
014:
015: import java.util.logging.Logger;
016: import java.util.logging.Level;
017:
018: import java.lang.Character;
019: import java.io.IOException;
020: import java.util.StringTokenizer;
021: import java.util.Vector;
022:
023: import javax.management.MBeanServerConnection;
024:
025: import com.sun.enterprise.cli.framework.*;
026:
027: /**
028: Creates a multimode environment for executing the commands from a file or
029: by supplying commands interactively. Displays the help message for the
030: command if help is sought.
031: */
032: public class MultiProcessCommand extends AdminBaseCommand {
033: private static final String OPT_PRINTPROMPT = "printprompt";
034: private static final String OPT_INPUT = "input";
035: private static final String OPT_ECHO = "echo";
036: private static final String OPT_ENCODING = "encoding";
037: private static final String EXIT = "exit";
038: private static final String ERROR_ON_LINE = "error.psadmin.multimode.errorOnLine";
039:
040: private boolean mDone = false;
041: private boolean printPrompt = true;
042: private final String kPromptString = getLocalizedString("psadmin.prompt");
043:
044: /**
045: * Default constructor to initialize the class.
046: */
047: public MultiProcessCommand() {
048: super ();
049: }
050:
051: /**
052: * Checks whether options are specified at the command line.
053: * If options are specified, then it validates for the options else
054: * it assumes no options are specified. In MultiProcessCommand without
055: * specifying an option brings up the interactive mode, otherwise it
056: * reads the commands from a file with option specified.
057: */
058: public boolean validateOptions() throws CommandValidationException {
059: if (super .validateOptions()) {
060:
061: printPrompt = getBooleanOption(OPT_PRINTPROMPT);
062: // echo the command if echo is turned on
063: if (getBooleanOption(OPT_ECHO)) {
064: CLILogger.getInstance().printMessage(this .toString());
065: }
066: return true;
067: }
068:
069: return false;
070: }
071:
072: /**
073: * Implements the execution of MultiProcessCommand whether the input
074: * is from a file or from a standard input interactively.
075: * @throws CommandException
076: */
077: public void runCommand() throws CommandException,
078: CommandValidationException {
079: validateOptions();
080: if (getUserId() != null) {
081: setEnvironment(OPT_ADMIN_USER, getUserId());
082: }
083:
084: if (getPassword() != null) {
085: setEnvironment(OPT_PASSWORDFILE,
086: getOption(OPT_PASSWORDFILE));
087: }
088:
089: //this prevents subsequent subcommands to get
090: //MBeanServerConnection multiple times.
091: try {
092:
093: MBeanServerConnection mbs = getMBeanServerConnection(
094: getUserId(), getPassword(), getHost());
095:
096: System.setProperty(PSADMIN_MULTI_MODE_RUNNING, "true");
097: } catch (Exception e) {
098: //if this fails, do nothing. The
099: //getMBeanServerConnection() is just to set the
100: //MBeanServerConnection for subsequent commands that are
101: //executed in the multimode process. In case the option
102: //adminuser or password file is not presented, the
103: //command process should still continue.
104: }
105:
106: String line = null;
107: int lineNo = 0;
108:
109: try {
110: if (isFileOptionSpecified()) {
111: CLILogger.getInstance().printDebugMessage(
112: "file option specified");
113: checkForFileExistence(null, getOption(OPT_INPUT));
114: setInputStreamToFile();
115: } else {
116: printExitMessage();
117: }
118:
119: line = printPromptAndReadLine();
120:
121: while (!isExitLine(line)) {
122: lineNo++;
123: if (isExecutableLine(line)) {
124: processLine(line, lineNo);
125: }
126: line = printPromptAndReadLine();
127: }
128:
129: } catch (CommandException ce) {
130: System.setProperty(PSADMIN_MULTI_MODE_RUNNING, "false");
131: closeMBeanServerConnection();
132: logger.log(Level.SEVERE, "PSALI_CSPACC0008", ce);
133: throw ce;
134: } catch (Exception e) {
135: System.setProperty(PSADMIN_MULTI_MODE_RUNNING, "false");
136: closeMBeanServerConnection();
137: logger.log(Level.SEVERE, "PSALI_CSPACC0010", e);
138: throw new CommandException(e);
139: }
140:
141: System.setProperty(PSADMIN_MULTI_MODE_RUNNING, "false");
142: closeMBeanServerConnection();
143: }
144:
145: /**
146: * Prints the exit message for the mulitprocess command input
147: */
148: private void printExitMessage() {
149: CLILogger.getInstance().printMessage(
150: getLocalizedString("ExitMessage"));
151: }
152:
153: /**
154: * Prints the prompt to the standard output
155: * Reads the line from the buffered input stream
156: * @return String The line read from the inputstream or file
157: */
158: private String printPromptAndReadLine() throws CommandException {
159: try {
160: if (printPrompt)
161: InputsAndOutputs.getInstance().getUserOutput().print(
162: kPromptString);
163: String line = InputsAndOutputs.getInstance().getUserInput()
164: .getLine();
165: if (line == null && isFileOptionSpecified() == true)
166: return EXIT;
167: else
168: return line;
169: } catch (IOException ioe) {
170: throw new CommandException(
171: getLocalizedString("CouldNotPrintOrRead"), ioe);
172: }
173: }
174:
175: /**
176: * Checks to see if the line is executable, i.e if the line in non-empty and
177: * the line doesnt start with "#"
178: */
179: private boolean isExecutableLine(final String line) {
180: boolean isExecutable = true;
181: if (line == null) {
182: isExecutable = false;
183: } else if (line.trim().equals("") || line.startsWith("#")
184: || line.length() < 1) {
185: isExecutable = false;
186: }
187: return isExecutable;
188: }
189:
190: /**
191: * set user input stream
192: * this method assumes that file option is set
193: * @throws CommandException
194: */
195: private void setInputStreamToFile() throws CommandException {
196: try {
197: final String sEncoding = getOption(OPT_ENCODING);
198: if (sEncoding == null) {
199: CLILogger.getInstance().printDebugMessage(
200: "Set input stream");
201: InputsAndOutputs.getInstance().setUserInputFile(
202: getOption(OPT_INPUT));
203: } else {
204: InputsAndOutputs.getInstance().setUserInputFile(
205: getOption(OPT_INPUT), sEncoding);
206: }
207: } catch (IOException ioe) {
208: throw new CommandException(
209: getLocalizedString("CouldNotSetInputStream"), ioe);
210: }
211: }
212:
213: /**
214: * This method will split the string to array of string separted by space(s)
215: * If there is a quote " around the string, then the string will not be
216: * splitted. For example, if the string is: abcd efg "hij klm", the string
217: * array will contain abcd|efg|hij klm|
218: * @param line - string to be converted
219: * @return - string array
220: * @throws CommandException
221: */
222: private String[] splitStringToArray(String line)
223: throws CommandException {
224: final CLITokenizer cliTokenizer = new CLITokenizer(line, " ");
225: String[] strArray = new String[cliTokenizer.countTokens()];
226: int ii = 0;
227: while (cliTokenizer.hasMoreTokens()) {
228: strArray[ii++] = cliTokenizer
229: .nextTokenWithoutEscapeAndQuoteChars();
230: CLILogger.getInstance().printDebugMessage(
231: "CLIToken = [" + strArray[ii - 1] + "]");
232:
233: }
234: return strArray;
235: }
236:
237: /**
238: * Checks to see if the user supplied an "exit" or "quit"
239: */
240: private boolean isExitLine(final String line) {
241: if (line == null
242: || (line != null && (line.equalsIgnoreCase("exit") || line
243: .equalsIgnoreCase("quit")))) {
244: return true;
245: }
246: return false;
247: }
248:
249: /**
250: * Checks to see if the 'file' option is specified
251: * @return boolean returns true if specified else false
252: */
253: private boolean isFileOptionSpecified() {
254: return (getOption(OPT_INPUT) != null);
255: }
256:
257: /**
258: * check if validCommand is null
259: */
260: private void checkValidCommand(ValidCommand validCommand,
261: String commandName) throws CommandException {
262: if (validCommand == null) {
263: throw new CommandException(getLocalizedString(
264: "InvalidCommand", new Object[] { commandName }));
265: }
266:
267: }
268:
269: /**
270: * Process the input line supplied by the user.
271: * The line is converted to array of args and supplied to CommandFactory
272: **/
273: private void processLine(String line, int lineNo) {
274: ValidCommand validCommand = null;
275: try {
276: String[] commandLine = splitStringToArray(line);
277:
278: //get CLI descriptor instance
279: CLIDescriptorsReader cliDescriptorsReader = CLIDescriptorsReader
280: .getInstance();
281:
282: //get the validCommand object from CLI descriptor
283: validCommand = cliDescriptorsReader
284: .getCommand(commandLine[0]);
285:
286: //check if command is help then throw the HelpException to
287: //display the manpage or usage-text
288: if (commandLine[0].equals("help"))
289: throw new HelpException(commandLine.length < 2 ? null
290: : commandLine[1]);
291:
292: checkValidCommand(validCommand, commandLine[0]);
293:
294: //parse the command line arguments
295: CommandLineParser clp = new CommandLineParser(commandLine,
296: validCommand);
297:
298: //validate the command line arguments with the validCommand object
299: CommandValidator commandValidator = new CommandValidator();
300: commandValidator.validateCommandAndOptions(validCommand,
301: clp.getOptionsList(), clp.getOperands());
302:
303: //creates the command object using command factory
304: Command command = CommandFactory.createCommand(
305: validCommand, clp.getOptionsList(), clp
306: .getOperands());
307: //invoke the command
308: command.runCommand();
309: } catch (HelpException he) {
310: invokeHelpClass(he.getHelpClassName(), he.getCommandName(),
311: he.getUsageText());
312:
313: } catch (CommandValidationException cve) {
314: printUsageText(validCommand);
315: CLILogger.getInstance().printExceptionStackTrace(cve);
316: CLILogger.getInstance().printError(
317: getLocalizedString(ERROR_ON_LINE) + " "
318: + Integer.toString(lineNo));
319: CLILogger.getInstance().printError(
320: cve.getLocalizedMessage());
321: } catch (CommandException ce) {
322: CLILogger.getInstance().printExceptionStackTrace(ce);
323: CLILogger.getInstance().printError(
324: getLocalizedString(ERROR_ON_LINE) + " "
325: + Integer.toString(lineNo));
326: CLILogger.getInstance()
327: .printError(ce.getLocalizedMessage());
328: }
329: }
330:
331: /**
332: * This method invokes the help command class.
333: * If help command clss is invalid then the usage text is displayed.
334: */
335: private void invokeHelpClass(String helpClassName,
336: String helpCommandName, String commandUsageText) {
337: try {
338: Command helpCommand = null;
339: Class helpClass = Class.forName(helpClassName);
340: helpCommand = (Command) helpClass.newInstance();
341: helpCommand.setName(helpCommandName);
342: if (helpCommandName != null)
343: helpCommand
344: .setOperands(new java.util.Vector(
345: java.util.Arrays
346: .asList(new String[] { helpCommandName })));
347: //set an internal option called isMultiMode
348: helpCommand.setOption("isMultiMode", "true");
349:
350: //get interactive value from the environment
351: final String interactiveVal = (String) CommandEnvironment
352: .getInstance().getEnvironments().get(INTERACTIVE);
353: //set the interactive mode
354: helpCommand.setOption(INTERACTIVE,
355: interactiveVal == null ? "true" : interactiveVal);
356:
357: helpCommand.runCommand();
358: } catch (Exception e) {
359: if (commandUsageText == null)
360: CLILogger.getInstance().printMessage(
361: getLocalizedString("NoUsageText",
362: new Object[] { helpCommandName }));
363: else
364: CLILogger.getInstance().printMessage(
365: getLocalizedString("Usage",
366: new Object[] { commandUsageText }));
367: }
368: }
369:
370: /**
371: * this method prints the usage text from validCommand
372: * @param validCommand - contains the usage text
373: */
374: private void printUsageText(final ValidCommand validCommand) {
375: if (validCommand != null && validCommand.getUsageText() != null) {
376: CLILogger.getInstance()
377: .printError(
378: getLocalizedString("Usage",
379: new Object[] { validCommand
380: .getUsageText() }));
381: }
382: }
383:
384: }
|