Coverage Report - net.wotonomy.ui.swing.components.SmartPasswordField
 
Classes in this File Line Coverage Branch Coverage Complexity
SmartPasswordField
0% 
0% 
3.222
 
 1  
 /*
 2  
 Wotonomy: OpenStep design patterns for pure Java applications.
 3  
 Copyright (C) 2000 Blacksmith, Inc.
 4  
 
 5  
 This library is free software; you can redistribute it and/or
 6  
 modify it under the terms of the GNU Lesser General Public
 7  
 License as published by the Free Software Foundation; either
 8  
 version 2.1 of the License, or (at your option) any later version.
 9  
 
 10  
 This library is distributed in the hope that it will be useful,
 11  
 but WITHOUT ANY WARRANTY; without even the implied warranty of
 12  
 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 13  
 Lesser General Public License for more details.
 14  
 
 15  
 You should have received a copy of the GNU Lesser General Public
 16  
 License along with this library; if not, see http://www.gnu.org
 17  
 */
 18  
 
 19  
 package net.wotonomy.ui.swing.components;
 20  
 
 21  
 import java.awt.datatransfer.DataFlavor;
 22  
 import java.awt.datatransfer.Transferable;
 23  
 import java.awt.datatransfer.UnsupportedFlavorException;
 24  
 import java.awt.event.KeyEvent;
 25  
 
 26  
 import javax.swing.JPasswordField;
 27  
 
 28  
 /**
 29  
  * SmartPasswordField is an extention of JPasswordField.  It does everything
 30  
  * a JPassword does, as well as limit the number of characters.  The user
 31  
  * of this class can specify that a password can only have a maximum of
 32  
  * 10 characters for instance.
 33  
  *
 34  
  * @author rob@straylight.princeton.com
 35  
  * @author $Author: cgruber $
 36  
  * @version $Revision: 904 $
 37  
  */
 38  
 public class SmartPasswordField extends JPasswordField
 39  
 {
 40  
 
 41  
 /*******************************
 42  
 * CONSTANTS
 43  
 *******************************/
 44  
    private static final int BACKSPACE = 8;
 45  
    private static final int DELETE = 127;
 46  
    private static final int SPACE = 32;
 47  
    private static final int DASH = 45;
 48  
    private static final int UNDERSCORE = 95;
 49  
    private static final int PERIOD = 46;
 50  
    private static final int PASTE = 22;  // Ctl-V
 51  
 
 52  0
    private int passwordLength = Integer.MAX_VALUE;
 53  
 
 54  
 /*******************************
 55  
 * PUBLIC METHODS
 56  
 *******************************/
 57  
 
 58  
 /**
 59  
 * Default constructor.
 60  
 */
 61  
    public SmartPasswordField()
 62  
    {
 63  0
        super();
 64  0
    }
 65  
 
 66  
 /**
 67  
 * This constructor allows the user to set the maximum length of the password.
 68  
 * @param aLength The maximum length of the password.
 69  
 */
 70  
    public SmartPasswordField( int aLength )
 71  
    {
 72  0
        this();
 73  0
        setPasswordLength( aLength );
 74  0
    }
 75  
 
 76  
 /**
 77  
 * Sets the maximum lenght of the password.  The value must be 0 or greater.
 78  
 * If the length specified is less than 0, then no action occurs.
 79  
 * @param aLength The maximum lenght of the password.
 80  
 */
 81  
     public void setPasswordLength( int aLength )
 82  
     {
 83  0
         if ( aLength >= 0 )
 84  
         {
 85  0
             passwordLength = aLength;
 86  
         }
 87  0
     }
 88  
 
 89  
 /**
 90  
 * Returns the current maximum length of the password.
 91  
 * @return The current maximum length of the password.
 92  
 */
 93  
     public int getPasswordLength()
 94  
     {
 95  0
         return passwordLength;
 96  
     }
 97  
 
 98  
 /**
 99  
 * This method processes a key event.  This event is generated by input from the
 100  
 * keyboard when this text field has the focus.  This method is called for every
 101  
 * key that is pressed and released on the keyboard.  This includes modifier
 102  
 * keys like the shift and alt keys.  This class looks at the key and determines
 103  
 * if the key is valid input given the restrictions of this class. <BR> <BR>
 104  
 * @param e A key event generated by a keyboard action.
 105  
 */
 106  
    public void processKeyEvent(KeyEvent e)
 107  
    {
 108  0
       String currentText = "";
 109  0
       String testString = "";
 110  0
       char newChar = e.getKeyChar();
 111  0
       int currentLength = 0;
 112  0
       int selectionStart = 0;
 113  0
       int selectionEnd = 0;
 114  0
       int endOfHead = 0;
 115  0
       int startOfTail = 0;
 116  0
       boolean backspace = false;
 117  0
       boolean delete = false;
 118  0
       boolean paste = false;
 119  0
       boolean insertionPoint = false;
 120  0
       boolean selectionAtStart = false;
 121  0
       boolean selectionAtEnd = false;
 122  
 
 123  0
       backspace = (newChar == BACKSPACE);
 124  0
       delete = (newChar == DELETE);
 125  0
       paste = (newChar == PASTE);
 126  
 
 127  0
       if ((e.getKeyCode() == KeyEvent.VK_UNDEFINED) || ((backspace) || (delete) || (paste)))  // A "key-typed" event
 128  
       {
 129  0
          if (isValidCharacter(newChar))
 130  
          {
 131  
 
 132  0
             if ((isPrintableCharacter(newChar)) || (backspace) || (delete) || (paste))
 133  
             {
 134  
                // Analyze the current contents of the field
 135  0
                currentText = new String( getPassword() );
 136  0
                currentLength = currentText.length();
 137  
 
 138  0
                selectionStart = getSelectionStart();
 139  0
                selectionEnd = getSelectionEnd();
 140  
 
 141  0
                insertionPoint = (selectionStart == selectionEnd);
 142  0
                selectionAtStart = (selectionStart == 0);
 143  0
                selectionAtEnd = (selectionEnd >= currentLength);
 144  0
                if (selectionEnd > currentLength)
 145  
                {
 146  0
                   setSelectionEnd(currentLength);
 147  
                }
 148  
 
 149  
                // Generate new string
 150  0
                if (selectionStart > 0) // Create head of test string
 151  
                {
 152  0
                   endOfHead = selectionStart;
 153  0
                   if (insertionPoint && backspace)
 154  
                   {
 155  0
                      endOfHead -= 1;
 156  
                   }
 157  0
                   testString += currentText.substring(0, endOfHead);
 158  
                }
 159  
 
 160  0
                if (!(backspace || delete || paste))  // Add the new character
 161  
                {
 162  0
                   testString += newChar;
 163  
                }
 164  
 
 165  0
                if (paste)  // Add the string from the clipboard
 166  
                {
 167  0
                   Transferable data = getToolkit().getSystemClipboard().getContents(this);
 168  0
                   if (data != null)
 169  
                   {
 170  
                      try
 171  
                      {
 172  0
                         String clipString = (String)data.getTransferData(DataFlavor.stringFlavor);
 173  0
                         testString += clipString;
 174  
                      }
 175  0
                      catch (java.io.IOException ioe)
 176  
                      {
 177  
                         // Do nothing
 178  
                      }
 179  0
                      catch (UnsupportedFlavorException ufe)
 180  
                      {
 181  
                         // Do nothing
 182  0
                      }
 183  
                   }
 184  
                }
 185  
 
 186  0
                if (selectionEnd < currentLength) // Add the tail of the string
 187  
                {
 188  0
                   startOfTail = selectionEnd;
 189  0
                   if (insertionPoint && delete)
 190  
                   {
 191  0
                      startOfTail += 1;
 192  
                   }
 193  0
                   testString += currentText.substring(startOfTail);
 194  
                }
 195  
 
 196  
             }
 197  
 
 198  0
             if (testString.compareTo("") != 0)  // Null string is OK
 199  
             {
 200  0
                if (!(isValidString(testString)))
 201  
                {
 202  0
                   e.consume();
 203  0
                }
 204  
             }
 205  
          }
 206  
          else
 207  
          {
 208  0
             e.consume();
 209  
          }
 210  
       }
 211  0
       super.processKeyEvent(e);
 212  
 
 213  0
       postProcessing();
 214  0
    }
 215  
 
 216  
 
 217  
 /*******************************
 218  
 * PROTECTED METHODS
 219  
 *******************************/
 220  
 
 221  
 /**
 222  
 * Returns whether the inputted character is valid or not.  In this case all
 223  
 * characters are valid input.
 224  
 * @param aChar A character to perform the validity test with.
 225  
 * @return True if the character is valid for this subclassed text field. <BR>
 226  
 *         False is the character is not valid.
 227  
 */
 228  
    protected boolean isValidCharacter(char aChar)
 229  
    {
 230  0
        return true;
 231  
    }
 232  
 
 233  
 /**
 234  
 * Returns whether a string is valid for this text field.  As the user types from
 235  
 * the keyboard, this method is called to determine if the new string in the text
 236  
 * field is valid based upon the restriction of this class.  The length of the
 237  
 * new string is checked against the maximum password length.
 238  
 * @param aString The string to perform the validity check with.
 239  
 * @return True if the length of the string is less than or equal to the maximum length.
 240  
 *         False if the character is not valud.
 241  
 */
 242  
    protected boolean isValidString(String aString)
 243  
    {
 244  0
        if ( aString.length() > passwordLength )
 245  
        {
 246  0
            return false;
 247  
        }
 248  
 
 249  0
        return true;
 250  
    }
 251  
 
 252  
 /**
 253  
 * This class does not need any post processing.
 254  
 */
 255  
    protected void postProcessing()
 256  
    {
 257  
        /* Do Nothing */
 258  0
    }
 259  
 
 260  
 
 261  
 /*******************************
 262  
 * PRIVATE METHODS
 263  
 *******************************/
 264  
 
 265  
    private boolean isPrintableCharacter(char inputChar)
 266  
    {
 267  0
       if ((inputChar >= ' ') && (inputChar <= '~'))
 268  
       {
 269  0
          return true;
 270  
       }
 271  0
       return false;
 272  
    }
 273  
 
 274  
 }