You are viewing a plain text version of this content. The canonical link for it is here.
Posted to dev@tomcat.apache.org by la...@apache.org on 2001/10/08 07:23:57 UTC

cvs commit: jakarta-tomcat/proposals/PasswordPrompter/WEB-INF/classes/org/apache/tomcat/util/io Prompter.java PrompterException.java

larryi      01/10/07 22:23:57

  Added:       proposals/PasswordPrompter build.xml
               proposals/PasswordPrompter/WEB-INF interceptors.xml
               proposals/PasswordPrompter/WEB-INF/classes/org/apache/tomcat/modules/config
                        PasswordPrompter.java
               proposals/PasswordPrompter/WEB-INF/classes/org/apache/tomcat/util/io
                        Prompter.java PrompterException.java
  Log:
  Add sample add-on module.  PasswordPrompter will prompt for pass words
  for secure PoolTcpConnectors and JDBCRealms.
  
  Revision  Changes    Path
  1.1                  jakarta-tomcat/proposals/PasswordPrompter/build.xml
  
  Index: build.xml
  ===================================================================
  <?xml version="1.0"?> 
  <project name="PasswordPrompter" default="main" basedir=".">
  
    <!-- Compilation properties -->
  
    <property name="build.compiler" value="classic"/>
    <property name="optimize" value="false"/>
    <property name="debug" value="on"/>
  
    <!-- Directories -->
    <property name="ws" value="../../.."/> 
    <property name="work.dir" value="${ws}/jakarta-tomcat"/> 
  
    <property name="tomcat.build" value="${ws}/jakarta-tomcat/build/tomcat"/>
    <property name="tomcat.dist" value="${ws}/jakarta-tomcat/dist/tomcat"/>
  
    <property name="tomcat.build.modules" value="${tomcat.build}/modules"/>
    <property name="tomcat.dist.modules" value="${tomcat.dist}/modules"/>
  
    <!-- ==================== Initialization - check if build and dist present ========== -->
    <target name="init">
      <available file="${tomcat.build.modules}" property="build.modules.available"/>
      <available file="${tomcat.dist.modules}" property="dist.modules.available"/>
    </target>
  
    <!-- ==================== Preparation ==================== -->
  
    <target name="prepare" depends="init">
    </target>
  
    <target name="build.modules.check" depends="prepare" unless="build.modules.available">
      <echo message="You must build Tomcat first!"/>
    </target>
  
    <target name="dist.modules.check" depends="prepare" unless="dist.modules.available">
      <echo message="You must build the Tomcat distribution first!"/>
    </target>
  
    <!-- ==================== Build the Password Prompter sample add-on ================== -->
  
    <target name="password.prompter" depends="prepare" if="build.modules.available">
  
      <mkdir dir="${tomcat.build.modules}/PasswordPrompter"/>
      <copy todir="${tomcat.build.modules}/PasswordPrompter">
              <fileset dir="${work.dir}/proposals/PasswordPrompter" excludes="build.xml"/>
      </copy>
  
      <javac srcdir="${tomcat.build.modules}/PasswordPrompter/WEB-INF/classes" 
  	   optimize="${optimize}"
             debug="${debug}"
  	   destdir="${tomcat.build.modules}/PasswordPrompter/WEB-INF/classes" 
  	   classpath="${tomcat.build}/classes"/>
  
      <mkdir dir="${tomcat.build.modules}/PasswordPrompter/WEB-INF/lib"/>
  
      <jar jarFile="${tomcat.build.modules}/PasswordPrompter/WEB-INF/lib/PasswordPrompter.jar"
           basedir="${tomcat.build.modules}/PasswordPrompter/WEB-INF/classes"/>
  
      <delete dir="${tomcat.build.modules}/PasswordPrompter/WEB-INF/classes"/>
  
    </target>
  
    <!-- ==================== Build the Password Prompter sample add-on WAR ================== -->
  
    <target name="password.prompter.war"
            depends="build.modules.check,dist.modules.check,password.prompter"
            if="dist.modules.available">
      <jar jarFile="${tomcat.dist.modules}/PasswordPrompter.war"
           baseDir="${tomcat.build.modules}/PasswordPrompter"/>
    </target> 
  
    <!-- ==================== Admin & agreagate ==================== -->
     
    <target name="clean" depends="init">
      <delete dir="${tomcat.build.modules}/PasswordPrompter"/>
      <delete dir="${tomcat.dist.modules}/PasswordPrompter"/>
      <delete file="${tomcat.dist.modules}/PasswordPrompter.war"/>
    </target>
    
    <target name="main" depends="build.modules.check,password.prompter"/>
  
  </project>
  
  
  1.1                  jakarta-tomcat/proposals/PasswordPrompter/WEB-INF/interceptors.xml
  
  Index: interceptors.xml
  ===================================================================
  <?xml version="1.0" encoding="UTF-8"?>
  <Server>
      <module name="PasswordPrompter" javaClass="org.apache.tomcat.modules.config.PasswordPrompter" />
      <ContextManager>
          <PasswordPrompter />
      </ContextManager>
  </Server>
  
  
  
  1.1                  jakarta-tomcat/proposals/PasswordPrompter/WEB-INF/classes/org/apache/tomcat/modules/config/PasswordPrompter.java
  
  Index: PasswordPrompter.java
  ===================================================================
  /*
   * ====================================================================
   *
   * The Apache Software License, Version 1.1
   *
   * Copyright (c) 2001 The Apache Software Foundation.  All rights
   * reserved.
   *
   * Redistribution and use in source and binary forms, with or without
   * modification, are permitted provided that the following conditions
   * are met:
   *
   * 1. Redistributions of source code must retain the above copyright
   *    notice, this list of conditions and the following disclaimer.
   *
   * 2. Redistributions in binary form must reproduce the above copyright
   *    notice, this list of conditions and the following disclaimer in
   *    the documentation and/or other materials provided with the
   *    distribution.
   *
   * 3. The end-user documentation included with the redistribution, if
   *    any, must include the following acknowlegement:
   *       "This product includes software developed by the
   *        Apache Software Foundation (http://www.apache.org/)."
   *    Alternately, this acknowlegement may appear in the software itself,
   *    if and wherever such third-party acknowlegements normally appear.
   *
   * 4. The names "The Jakarta Project", "Tomcat", and "Apache Software
   *    Foundation" must not be used to endorse or promote products derived
   *    from this software without prior written permission. For written
   *    permission, please contact apache@apache.org.
   *
   * 5. Products derived from this software may not be called "Apache"
   *    nor may "Apache" appear in their names without prior written
   *    permission of the Apache Group.
   *
   * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED
   * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
   * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
   * DISCLAIMED.  IN NO EVENT SHALL THE APACHE SOFTWARE FOUNDATION OR
   * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
   * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
   * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
   * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
   * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
   * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
   * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
   * SUCH DAMAGE.
   * ====================================================================
   *
   * This software consists of voluntary contributions made by many
   * individuals on behalf of the Apache Software Foundation.  For more
   * information on the Apache Software Foundation, please see
   * <http://www.apache.org/>.
   *
   * [Additional notices, if required by prior licensing conditions]
   *
   */
  package org.apache.tomcat.modules.config;
  
  import java.io.IOException;
  import org.apache.tomcat.core.*;
  import org.apache.tomcat.modules.aaa.*;
  import org.apache.tomcat.modules.server.*;
  import org.apache.tomcat.util.log.Log;
  import org.apache.tomcat.util.io.*;
  
  /** 
   * <code>PasswordPrompter</code> is a add-on module for the Tomcat 3.3
   * server. By installing this module, any secure connectors listed in the
   * <code>server.xml</code> configuration file can be defined without the
   * "keystorePass" attribute (where the password for the certificate
   * keystore is traditionally set). At startup, each secure connector without
   * a predefined password will result in a command-line prompt for the password.
   * This has the advantage of increased security, as the certificate password
   * need not be stored in the configuration files.
   *
   * Also, any JDBCRealm in <code>server.xml</code> defined without a
   * connectionPassword will result in a command-line prompt for the password. 
   *
   * <p>
   * <strong>Installation</strong>
   * <p>
   *
   * Place the PasswordPrompter.war file in Tomcat 3.3's modules directory
   * prior to starting Tomcat.
   * 
   * <p>
   * <strong>Notes</strong>
   * <p>
   *
   * This module does NOT attempt any additional validation on the supplied
   * password. It will simply pass the value on just as if it had been entered
   * into the <code>server.xml</code> file.
   *
   * Finally, this is primarily a simple example of an add-on module for Tomcat 3.3.
   * It tries to do something usefull as well, but leaves a fair amount of
   * room for improvement. It should not be considered a finished solution to
   * the security issue of protecting passwords.
   *
   * @author    Larry Isaacs
   * @author    Christopher Cain
   * @version   $Revision: 1.1 $ $Date: 2001/10/08 05:23:57 $
   */
  public class PasswordPrompter extends BaseInterceptor {
  
      // ----------------------------------------------------------------- Fields
  
      /** The name of the module */
      public static final String MOD_NAME = "PasswordPrompter";
  
      /** The current version number */
      public static final String MOD_VERSION = "1.0";
  
      /** Number of lines to scroll to hide password */
      private int scroll = 25;
  
      // ------------------------------------------------------------ Constructor
  
      /** Default constructor. */
      public PasswordPrompter() {
      }
  
      // ------------------------------------------------------------- Attributes
  
      /** Set number of lines to scroll display to hide the password */
      public void setScroll( int lines ) {
          scroll = lines;
      }
  
      // ------------------------------------------------ Implementation (Public)
  
      /**
       * Returns the name of this module.
       *
       * @return   the module name
       */
      public static String getModName() {
          return MOD_NAME;
      }
  
      /**
       * Returns the current verion number of the module.
       *
       * @return   the current version number
       */
      public static String getModVersion() {
          return MOD_VERSION;
      }
  
      // -------------------------------------------------------------- Callbacks
  
      /**
       * This callback is automatically executed by the startup process each time
       * an interceptor is added to a context. For the purposes of this
       * particular module, processing is only done when this interceptor itself
       * is added.
       *
       * @param cm    the <code>ContextManager</code> for which the interceptor
       *              is being added
       * @param ctx   the <code>Context</code> for which the interceptor is being
       *              added
       * @param i     the interceptor being added to the Context
       */
      public void addInterceptor( ContextManager cm, Context ctx,
                                  BaseInterceptor i )
      {
          // If executing config generation, don't prompt for passwords
          if ( cm.getProperty("jkconf") != null )
              return;
  
          if ( i == this ) {
  
              BaseInterceptor[] interceptors = cm.getContainer().getInterceptors(
                  Container.H_engineInit
              );
  
              for ( int idx = 0; idx < interceptors.length; idx++ )
              {
  
                  if ( interceptors[idx] instanceof PoolTcpConnector )
                  {
                      // We have an Http connector, set certificate password if appropriate
                      processTcpConnector( (PoolTcpConnector)interceptors[idx] );
                  }
                  else if ( interceptors[idx] instanceof JDBCRealm )
                  {
                      // We have a JDBC realm, set DB connection password if appropriate
                      processJDBCRealm( (JDBCRealm)interceptors[idx] );
                  }
              }
          } else {
              if ( i instanceof PoolTcpConnector ) {
                  processTcpConnector( (PoolTcpConnector)i );
              }
          }
      }
  
      private void processTcpConnector( PoolTcpConnector connector )
      {
          // We have an Http connector, check to see if it's secure
          if ( connector.isSecure() )
          {
              // It's secure, now check to see if the keystore pass was
              // already specified in the config file
              if (!connector.isKeypassSet()) {
                  // insure log flushed
                  Log logger = getLog();
                  if (logger != null )
                      logger.flush();
  
                  // Go ahead with the prompting
                  String certpwd = null;
                  try {
                      certpwd = Prompter.promptForInput(
                              "SSL socket detected, please enter " +
                              "the certificate password:", scroll );
                  } catch (IOException ioe) {
                      log( "IO problem with command line: " + ioe.toString() );
                  } catch (PrompterException pe) {
                      log( "Prompter problem: " + pe.toString() );
                  }
  
                  if ( certpwd != null )
                      connector.setKeypass(certpwd);
              }
          }
      }
  
      private void processJDBCRealm( JDBCRealm realm )
      {
          // Check to see if the connection password was
          // already specified in the config file
          if (!realm.isConnectionPasswordSet()) {
              // insure log flushed
              Log logger = getLog();
              if (logger != null )
                  logger.flush();
  
              // Go ahead with the prompting
              String connpwd = null;
              try {
                  connpwd = Prompter.promptForInput(
                          "JDBC Realm detected, please enter " +
         	                "the connection password:", scroll );
  	    } catch (IOException ioe) {
  	        log( "IO problem with command line: " + ioe.toString() );
  	    } catch (PrompterException pe) {
  	        log( "Prompter problem: " + pe.toString() );
  	    }
  
  	    if ( connpwd != null )
  	        realm.setConnectionPassword(connpwd);
          }
      }
  }
  
  
  
  1.1                  jakarta-tomcat/proposals/PasswordPrompter/WEB-INF/classes/org/apache/tomcat/util/io/Prompter.java
  
  Index: Prompter.java
  ===================================================================
  /*
   * ====================================================================
   *
   * The Apache Software License, Version 1.1
   *
   * Copyright (c) 2001 The Apache Software Foundation.  All rights 
   * reserved.
   *
   * Redistribution and use in source and binary forms, with or without
   * modification, are permitted provided that the following conditions
   * are met:
   *
   * 1. Redistributions of source code must retain the above copyright
   *    notice, this list of conditions and the following disclaimer. 
   *
   * 2. Redistributions in binary form must reproduce the above copyright
   *    notice, this list of conditions and the following disclaimer in
   *    the documentation and/or other materials provided with the
   *    distribution.
   *
   * 3. The end-user documentation included with the redistribution, if
   *    any, must include the following acknowlegement:  
   *       "This product includes software developed by the 
   *        Apache Software Foundation (http://www.apache.org/)."
   *    Alternately, this acknowlegement may appear in the software itself,
   *    if and wherever such third-party acknowlegements normally appear.
   *
   * 4. The names "The Jakarta Project", "Tomcat", and "Apache Software
   *    Foundation" must not be used to endorse or promote products derived
   *    from this software without prior written permission. For written 
   *    permission, please contact apache@apache.org.
   *
   * 5. Products derived from this software may not be called "Apache"
   *    nor may "Apache" appear in their names without prior written
   *    permission of the Apache Group.
   *
   * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED
   * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
   * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
   * DISCLAIMED.  IN NO EVENT SHALL THE APACHE SOFTWARE FOUNDATION OR
   * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
   * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
   * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
   * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
   * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
   * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
   * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
   * SUCH DAMAGE.
   * ====================================================================
   *
   */ 
  
  package org.apache.tomcat.util.io;
  
  import java.io.*;
  
  /** 
   * This utility class allows for command-line interaction with
   * the user during Tomcat startup. This is particularly useful in capturing
   * sensitive information, such as resource passwords, that may not be suitable
   * for inclusion in the various configuration files due to security concerns.
   * <p>
   * It is designed primarily as a "building block" utility.
   * Its purpose is to provide a common API for any Tomcat listeners/interceptors
   * that may wish to communicate via the command-line during container startup.
   * <p>
   * All public methods in this class should be synchronized, and they should
   * follow the general layout described below (see
   * <a href="#promptForInput(java.lang.String)">promptForInput</a> for an
   * example implementation):
   *
   * <ol>
   *    <li>Get a copy of the current <code>stdout</code> stream by calling
   *        <a href="#cloneStdOut()">cloneStdOut</a>
   *    <li>Temporarily seize control of the <code>stdout</code> stream by
   *        calling <a href="#setStdOut()">setStdOut</a>
   *    <li>(Process the required interaction)
   *    <li>Restore <code>stdout</code> to its original value by calling
   *        <a href="#restoreStdOut(java.io.PrintStream)">restoreStdOut</a> with
   *        the clone
   * </ol>
   *
   * <i>Threading Considerations</i>
   * <p>
   * Note that sychronizing the interaction methods prevents multiple threads
   * from attempting command-line interaction at the same time. Modules calling
   * this utility will therefore be guaranteed a single atmoic
   * challenge/response, but not necessarily a single atomic "session" with the
   * command line. For example, if a module prompts for a password, determines
   * that the password is invalid, and then reprompts, there is no guarantee that
   * another thread has not prompted for something else in the meantime. In
   * practice, this would have to involve multiple threads from a single
   * command-line/JVM attempting to start multiple instances for Tomcat with a
   * single command. Nevertheless, modules should send very specific prompt
   * messages to avoid any potential user confusion.
   *
   * @author    Christopher Cain
   * @version   $Revision: 1.1 $ $Date: 2001/10/08 05:23:57 $
   */
  public class Prompter {
  
      // ----------------------------------------------------- Fields (Constants)
  
      /** The maximum allowed input size */
      public static final int MAX_INPUT_LENGTH = 1024;
  
      // ------------------------------------------------------------ Constructor
  
      /**
       * The default constructor is <code>private</code>, as instantiation of
       * this class is not permitted.
       */
      private Prompter() {
      }
  
      /**
       * StringBuffer containing EOL character sequence
       */
      private static final StringBuffer eol =
              new StringBuffer(System.getProperty("line.separator"));
  
      // --------------------------------------------------------- Public Methods
  
      /**
       * Request a value from the user, using the given text as a prompt.
       * <p>
       * @param promptMessage   the prompt text to display to the user
       * @return   This method returns a non-null string containing the user
       *           input. If the user didn't enter a value, an empty string is
       *           returned. If the value exceeds the arbitrary size limit
       *           (currently 1k), or if it fails the
       *           <a href="#isMalformed(java.lang.String)">isMalformed</a>
       *           check, a <code>PrompterException</code> is thrown.
       * @exception IOException        any IO problems communicating with the terminal
       * @exception PrompterException  any validator exceptions with the given input
       */
      public static synchronized String promptForInput( String promptMessage, int scroll )
      throws IOException, PrompterException {
  
          /* Setup */
  
          String userInput = "";
          BufferedReader br = null;
          IOException ioeThrow = null;
  
          // Aim stdout at the terminal
          PrintStream initialStdOut = cloneStdOut();
          setStdOut();
  
          /* Execution */
  
          try {
  
              // Display the prompt
  
              System.out.println();
              System.out.println( promptMessage );
  
              // Read the input
  
              br = new BufferedReader(new InputStreamReader(System.in));
              userInput = br.readLine();
  
              // Hide the input by scrolling the display
              for ( int i = 0; i < scroll; i++ )
                  System.out.println();
  
              // Basic validation
  
              if ( userInput == null )
                  throw new PrompterException("Unable to read password from System.in");
              else if ( userInput.length() > MAX_INPUT_LENGTH )
                  throw new PrompterException("Input limit exceeded");
              else if ( isMalformed(userInput) )
                  throw new PrompterException("Input contains illegal character(s)");
  
              // Return
  
              return userInput;
  
          } catch ( IOException ioe ) {
              throw ioe;
          } finally {
              restoreStdOut(initialStdOut);
          }
      }
  
      // ----------------------------------------- Private Implementation Methods
  
      /**
       * Return a cloned copy of the current <code>stdout</code>. This should
       * only be called from synchronized methods.
       * <p>
       * @return   a clone of <code>stdout</code>
       */
      protected static PrintStream cloneStdOut() {
  
          // Note: Deep cloning doesn't appear to be necessary
  
          return new PrintStream(System.out);
  
      }
  
      /**
       * Temporarily redirect <code>stdout</code> to the command line (in case
       * it isn't already). This should only be called from synchronized methods.
       */
      protected static void setStdOut() {
  
          System.setOut(
              new PrintStream(
                  new BufferedOutputStream(
                      new FileOutputStream(FileDescriptor.out),
                      128
                  ),
                  true
              )
          );
  
      }
  
      /**
       * Restore <code>stdout</code> to its original value. This should only be
       * called from synchronized methods.
       */
      protected static void restoreStdOut( PrintStream origStream ) {
  
          System.setOut(origStream);
  
      }
  
      /**
       * Perform a basic integrity check against the command-line user input.
       * Arbitrary command-line input should <b>always</b> be scanned for
       * unusual character sequences, primarily as a precaution against
       * malicious code being embeded into the reply value.
       * <p>
       * This check is currently implemented as an search for non-printing
       * characters, which usually indicates either an attempted attack or an
       * accidental key-combination (CTRL + letter). It will also disallow tabs.
       * <p>
       * This check will help prevent problems such as sending a questionable
       * string as a parameter to another program. It will <b>NOT</b> save you if
       * you are using the arbitrary user input to directly construct a command
       * string (a system-level command, a SQL statement through string
       * concatenation, etc.). In general, you <i>really</i> don't want to do
       * that.
       * <p>
       * @param inputValue   the value supplied by the user
       * @return             <code>true</code> if the input contains
       *                     immediately-suspicious characters, otherwise
       *                     <code>false</code>
       */
      protected static boolean isMalformed( String inputValue ) {
  
          // Note: We don't care about line separators, as BufferedReader sees
          // them as the input terminator. It is therefore impossible for the
          // input value to contain them.
  
          char nextChar;
          int charType;
  
          for ( int x = 0; x < inputValue.length(); x++ ) {
  
              nextChar = inputValue.charAt(x);
  
              if ( Character.isISOControl(nextChar) )
                  return true;
              else {
  
                  charType = Character.getType(nextChar);
  
                  if ( charType == Character.CONTROL ||
                       charType == Character.FORMAT ||
                       charType == Character.UNASSIGNED ||
                       charType == Character.PRIVATE_USE ||
                       charType == Character.SURROGATE
                  )
                      return true;
  
              }
  
          }
  
          return false;
      }
  }
  
  
  
  1.1                  jakarta-tomcat/proposals/PasswordPrompter/WEB-INF/classes/org/apache/tomcat/util/io/PrompterException.java
  
  Index: PrompterException.java
  ===================================================================
  /*
   * ====================================================================
   *
   * The Apache Software License, Version 1.1
   *
   * Copyright (c) 2001 The Apache Software Foundation.  All rights 
   * reserved.
   *
   * Redistribution and use in source and binary forms, with or without
   * modification, are permitted provided that the following conditions
   * are met:
   *
   * 1. Redistributions of source code must retain the above copyright
   *    notice, this list of conditions and the following disclaimer. 
   *
   * 2. Redistributions in binary form must reproduce the above copyright
   *    notice, this list of conditions and the following disclaimer in
   *    the documentation and/or other materials provided with the
   *    distribution.
   *
   * 3. The end-user documentation included with the redistribution, if
   *    any, must include the following acknowlegement:  
   *       "This product includes software developed by the 
   *        Apache Software Foundation (http://www.apache.org/)."
   *    Alternately, this acknowlegement may appear in the software itself,
   *    if and wherever such third-party acknowlegements normally appear.
   *
   * 4. The names "The Jakarta Project", "Tomcat", and "Apache Software
   *    Foundation" must not be used to endorse or promote products derived
   *    from this software without prior written permission. For written 
   *    permission, please contact apache@apache.org.
   *
   * 5. Products derived from this software may not be called "Apache"
   *    nor may "Apache" appear in their names without prior written
   *    permission of the Apache Group.
   *
   * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED
   * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
   * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
   * DISCLAIMED.  IN NO EVENT SHALL THE APACHE SOFTWARE FOUNDATION OR
   * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
   * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
   * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
   * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
   * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
   * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
   * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
   * SUCH DAMAGE.
   * ====================================================================
   *
   */ 
  
  package org.apache.tomcat.util.io;
  
  /** 
   * A general purpose exception class for the <code>Prompter</code> utility.
   * An exception of this type indicates an internal <code>Prompter</code>
   * problem.
   *
   * @author    Christopher Cain
   * @version   $Revision: 1.1 $ $Date: 2001/10/08 05:23:57 $
   */
  public class PrompterException extends Exception {
  
      // -------------------------------------------------------- Instance Fields
  
      /** The error message passed (if any) */
      protected String message = null;
  
      /** The underlying exception passed (if any) */
      protected Throwable throwable = null;
  
      // ----------------------------------------------------------- Constructors
  
      /**
       * Construct a new <code>PrompterException</code> with no additional
       * information.
       */
      public PrompterException() {
  
      }
  
      /**
       * Construct a new <code>PrompterException</code> with the specified
       * message.
       *
       * @param message   message describing the exception
       */
      public PrompterException( String message ) {
  
          this(message, null);
  
      }
  
      /**
       * Construct a new <code>PrompterException</code> with the specified
       * throwable.
       *
       * @param throwable   throwable that caused the exception
       */
      public PrompterException( Throwable throwable ) {
  
          this(null, throwable);
  
      }
  
      /**
       * Construct a new <code>PrompterException</code> with the specified
       * message and throwable.
       *
       * @param message     message describing the exception
       * @param throwable   throwable that caused the exception
       */
      public PrompterException( String message, Throwable throwable ) {
  
  	super();
  	this.message = message;
  	this.throwable = throwable;
  
      }
  
      //---------------------------------------------------------- Public Methods
  
      /**
       * Return the message associated with this exception.
       *
       * @return   the exception message (if any)
       */
      public String getMessage() {
  
          return (message);
  
      }
  
      /**
       * Return the throwable that caused this exception.
       *
       * @return   the underlying exception (if any)
       */
      public Throwable getThrowable() {
  
          return (throwable);
  
      }
  
      /**
       * Return a formatted string that describes this exception.
       *
       * @return   a description of the exception
       */
      public String toString() {
  
          StringBuffer sb = new StringBuffer("PrompterException: ");
  
          if (message != null) {
              sb.append(message);
  
              if (throwable != null)
                  sb.append(":  ");
          }
  
          if (throwable != null)
              sb.append(throwable.toString());
  
  	return (sb.toString());
  
      }
  }
  
  
  

Re: cvs commit: jakarta-tomcat/proposals/PasswordPrompter/WEB-INF/classes/org/apache/tomcat/util/io Prompter.java PrompterException.java

Posted by Christopher Cain <cc...@mhsoftware.com>.
Quoting larryi@apache.org:

[snip]

>  // Hide the input by scrolling the display
>  for ( int i = 0; i < scroll; i++ )
>      System.out.println();

Very clever. I hadn't thought of that. A very nice, simple hack to at least vex 
the simple over-the-shoulder peepers. That gets points for ingenuity, Larry-Man 
=)

- Christopher

/**
 * Pleurez, pleurez, mes yeux, et fondez vous en eau!
 * La moitiƩ de ma vie a mis l'autre au tombeau.
 *    ---Corneille
 */