1. /*
  2. * @(#)JPasswordField.java 1.54 04/06/02
  3. *
  4. * Copyright 2004 Sun Microsystems, Inc. All rights reserved.
  5. * SUN PROPRIETARY/CONFIDENTIAL. Use is subject to license terms.
  6. */
  7. package javax.swing;
  8. import javax.swing.text.*;
  9. import javax.swing.plaf.*;
  10. import javax.accessibility.*;
  11. import java.io.ObjectOutputStream;
  12. import java.io.ObjectInputStream;
  13. import java.io.IOException;
  14. /**
  15. * <code>JPasswordField</code> is a lightweight component that allows
  16. * the editing of a single line of text where the view indicates
  17. * something was typed, but does not show the original characters.
  18. * You can find further information and examples in
  19. * <a href="http://java.sun.com/docs/books/tutorial/uiswing/components/textfield.html">How to Use Text Fields</a>,
  20. * a section in <em>The Java Tutorial.</em>
  21. * <p>
  22. * <code>JPasswordField</code> is intended
  23. * to be source-compatible with <code>java.awt.TextField</code>
  24. * used with <code>echoChar</code> set. It is provided separately
  25. * to make it easier to safely change the UI for the
  26. * <code>JTextField</code> without affecting password entries.
  27. * <p>
  28. * <strong>Warning:</strong>
  29. * Serialized objects of this class will not be compatible with
  30. * future Swing releases. The current serialization support is
  31. * appropriate for short term storage or RMI between applications running
  32. * the same version of Swing. As of 1.4, support for long term storage
  33. * of all JavaBeans<sup><font size="-2">TM</font></sup>
  34. * has been added to the <code>java.beans</code> package.
  35. * Please see {@link java.beans.XMLEncoder}.
  36. *
  37. * @beaninfo
  38. * attribute: isContainer false
  39. * description: Allows the editing of a line of text but doesn't show the characters.
  40. *
  41. * @author Timothy Prinzing
  42. * @version 1.54 06/02/04
  43. */
  44. public class JPasswordField extends JTextField {
  45. /**
  46. * Constructs a new <code>JPasswordField</code>,
  47. * with a default document, <code>null</code> starting
  48. * text string, and 0 column width.
  49. */
  50. public JPasswordField() {
  51. this(null,null,0);
  52. }
  53. /**
  54. * Constructs a new <code>JPasswordField</code> initialized
  55. * with the specified text. The document model is set to the
  56. * default, and the number of columns to 0.
  57. *
  58. * @param text the text to be displayed, <code>null</code> if none
  59. */
  60. public JPasswordField(String text) {
  61. this(null, text, 0);
  62. }
  63. /**
  64. * Constructs a new empty <code>JPasswordField</code> with the specified
  65. * number of columns. A default model is created, and the initial string
  66. * is set to <code>null</code>.
  67. *
  68. * @param columns the number of columns >= 0
  69. */
  70. public JPasswordField(int columns) {
  71. this(null, null, columns);
  72. }
  73. /**
  74. * Constructs a new <code>JPasswordField</code> initialized with
  75. * the specified text and columns. The document model is set to
  76. * the default.
  77. *
  78. * @param text the text to be displayed, <code>null</code> if none
  79. * @param columns the number of columns >= 0
  80. */
  81. public JPasswordField(String text, int columns) {
  82. this(null, text, columns);
  83. }
  84. /**
  85. * Constructs a new <code>JPasswordField</code> that uses the
  86. * given text storage model and the given number of columns.
  87. * This is the constructor through which the other constructors feed.
  88. * The echo character is set to '*'. If the document model is
  89. * <code>null</code>, a default one will be created.
  90. *
  91. * @param doc the text storage to use
  92. * @param txt the text to be displayed, <code>null</code> if none
  93. * @param columns the number of columns to use to calculate
  94. * the preferred width >= 0; if columns is set to zero, the
  95. * preferred width will be whatever naturally results from
  96. * the component implementation
  97. */
  98. public JPasswordField(Document doc, String txt, int columns) {
  99. super(doc, txt, columns);
  100. echoChar = '*';
  101. // We could either leave this on, which wouldn't be secure,
  102. // or obscure the composted text, which essentially makes displaying
  103. // it useless. Therefore, we turn off input methods.
  104. enableInputMethods(false);
  105. }
  106. /**
  107. * Returns the name of the L&F class that renders this component.
  108. *
  109. * @return the string "PasswordFieldUI"
  110. * @see JComponent#getUIClassID
  111. * @see UIDefaults#getUI
  112. */
  113. public String getUIClassID() {
  114. return uiClassID;
  115. }
  116. /**
  117. * Returns the character to be used for echoing. The default is '*'.
  118. *
  119. * @return the echo character, 0 if unset
  120. * @see #setEchoChar
  121. * @see #echoCharIsSet
  122. */
  123. public char getEchoChar() {
  124. return echoChar;
  125. }
  126. /**
  127. * Sets the echo character for this <code>JPasswordField</code>.
  128. * Note that this is largely a suggestion, since the
  129. * view that gets installed can use whatever graphic techniques
  130. * it desires to represent the field. Setting a value of 0 indicates
  131. * that you wish to see the text as it is typed, similar to
  132. * the behavior of a standard <code>JTextField</code>.
  133. *
  134. * @param c the echo character to display
  135. * @see #echoCharIsSet
  136. * @see #getEchoChar
  137. * @beaninfo
  138. * description: character to display in place of the real characters
  139. * attribute: visualUpdate true
  140. */
  141. public void setEchoChar(char c) {
  142. echoChar = c;
  143. repaint();
  144. revalidate();
  145. }
  146. /**
  147. * Returns true if this <code>JPasswordField</code> has a character
  148. * set for echoing. A character is considered to be set if the echo
  149. * character is not 0.
  150. *
  151. * @return true if a character is set for echoing
  152. * @see #setEchoChar
  153. * @see #getEchoChar
  154. */
  155. public boolean echoCharIsSet() {
  156. return echoChar != 0;
  157. }
  158. // --- JTextComponent methods ----------------------------------
  159. /**
  160. * Invokes <code>provideErrorFeedback</code> on the current
  161. * look and feel, which typically initiates an error beep.
  162. * The normal behavior of transferring the
  163. * currently selected range in the associated text model
  164. * to the system clipboard, and removing the contents from
  165. * the model, is not acceptable for a password field.
  166. */
  167. public void cut() {
  168. if (getClientProperty("JPasswordField.cutCopyAllowed") != Boolean.TRUE) {
  169. UIManager.getLookAndFeel().provideErrorFeedback(this);
  170. } else {
  171. super.cut();
  172. }
  173. }
  174. /**
  175. * Invokes <code>provideErrorFeedback</code> on the current
  176. * look and feel, which typically initiates an error beep.
  177. * The normal behavior of transferring the
  178. * currently selected range in the associated text model
  179. * to the system clipboard, and leaving the contents from
  180. * the model, is not acceptable for a password field.
  181. */
  182. public void copy() {
  183. if (getClientProperty("JPasswordField.cutCopyAllowed") != Boolean.TRUE) {
  184. UIManager.getLookAndFeel().provideErrorFeedback(this);
  185. } else {
  186. super.copy();
  187. }
  188. }
  189. /**
  190. * Returns the text contained in this <code>TextComponent</code>.
  191. * If the underlying document is <code>null</code>, will give a
  192. * <code>NullPointerException</code>.
  193. * <p>
  194. * For security reasons, this method is deprecated. Use the
  195. <code>* getPassword</code> method instead.
  196. * @deprecated As of Java 2 platform v1.2,
  197. * replaced by <code>getPassword</code>.
  198. * @return the text
  199. */
  200. @Deprecated
  201. public String getText() {
  202. return super.getText();
  203. }
  204. /**
  205. * Fetches a portion of the text represented by the
  206. * component. Returns an empty string if length is 0.
  207. * <p>
  208. * For security reasons, this method is deprecated. Use the
  209. * <code>getPassword</code> method instead.
  210. * @deprecated As of Java 2 platform v1.2,
  211. * replaced by <code>getPassword</code>.
  212. * @param offs the offset >= 0
  213. * @param len the length >= 0
  214. * @return the text
  215. * @exception BadLocationException if the offset or length are invalid
  216. */
  217. @Deprecated
  218. public String getText(int offs, int len) throws BadLocationException {
  219. return super.getText(offs, len);
  220. }
  221. /**
  222. * Returns the text contained in this <code>TextComponent</code>.
  223. * If the underlying document is <code>null</code>, will give a
  224. * <code>NullPointerException</code>. For stronger
  225. * security, it is recommended that the returned character array be
  226. * cleared after use by setting each character to zero.
  227. *
  228. * @return the text
  229. */
  230. public char[] getPassword() {
  231. Document doc = getDocument();
  232. Segment txt = new Segment();
  233. try {
  234. doc.getText(0, doc.getLength(), txt); // use the non-String API
  235. } catch (BadLocationException e) {
  236. return null;
  237. }
  238. char[] retValue = new char[txt.count];
  239. System.arraycopy(txt.array, txt.offset, retValue, 0, txt.count);
  240. return retValue;
  241. }
  242. /**
  243. * See readObject() and writeObject() in JComponent for more
  244. * information about serialization in Swing.
  245. */
  246. private void writeObject(ObjectOutputStream s) throws IOException {
  247. s.defaultWriteObject();
  248. if (getUIClassID().equals(uiClassID)) {
  249. byte count = JComponent.getWriteObjCounter(this);
  250. JComponent.setWriteObjCounter(this, --count);
  251. if (count == 0 && ui != null) {
  252. ui.installUI(this);
  253. }
  254. }
  255. }
  256. // --- variables -----------------------------------------------
  257. /**
  258. * @see #getUIClassID
  259. * @see #readObject
  260. */
  261. private static final String uiClassID = "PasswordFieldUI";
  262. private char echoChar;
  263. /**
  264. * Returns a string representation of this <code>JPasswordField</code>.
  265. * This method is intended to be used only for debugging purposes, and the
  266. * content and format of the returned string may vary between
  267. * implementations. The returned string may be empty but may not
  268. * be <code>null</code>.
  269. *
  270. * @return a string representation of this <code>JPasswordField</code>
  271. */
  272. protected String paramString() {
  273. return super.paramString() +
  274. ",echoChar=" + echoChar;
  275. }
  276. /////////////////
  277. // Accessibility support
  278. ////////////////
  279. /**
  280. * Returns the <code>AccessibleContext</code> associated with this
  281. * <code>JPasswordField</code>. For password fields, the
  282. * <code>AccessibleContext</code> takes the form of an
  283. * <code>AccessibleJPasswordField</code>.
  284. * A new <code>AccessibleJPasswordField</code> instance is created
  285. * if necessary.
  286. *
  287. * @return an <code>AccessibleJPasswordField</code> that serves as the
  288. * <code>AccessibleContext</code> of this
  289. * <code>JPasswordField</code>
  290. */
  291. public AccessibleContext getAccessibleContext() {
  292. if (accessibleContext == null) {
  293. accessibleContext = new AccessibleJPasswordField();
  294. }
  295. return accessibleContext;
  296. }
  297. /**
  298. * This class implements accessibility support for the
  299. * <code>JPasswordField</code> class. It provides an implementation of the
  300. * Java Accessibility API appropriate to password field user-interface
  301. * elements.
  302. * <p>
  303. * <strong>Warning:</strong>
  304. * Serialized objects of this class will not be compatible with
  305. * future Swing releases. The current serialization support is
  306. * appropriate for short term storage or RMI between applications running
  307. * the same version of Swing. As of 1.4, support for long term storage
  308. * of all JavaBeans<sup><font size="-2">TM</font></sup>
  309. * has been added to the <code>java.beans</code> package.
  310. * Please see {@link java.beans.XMLEncoder}.
  311. */
  312. protected class AccessibleJPasswordField extends AccessibleJTextField {
  313. /**
  314. * Gets the role of this object.
  315. *
  316. * @return an instance of AccessibleRole describing the role of the
  317. * object (AccessibleRole.PASSWORD_TEXT)
  318. * @see AccessibleRole
  319. */
  320. public AccessibleRole getAccessibleRole() {
  321. return AccessibleRole.PASSWORD_TEXT;
  322. }
  323. }
  324. }