Source Code Cross Referenced for Properties.java in  » 6.0-JDK-Core » Collections-Jar-Zip-Logging-regex » java » util » Java Source Code / Java DocumentationJava Source Code and Java Documentation

Home
Java Source Code / Java Documentation
1.6.0 JDK Core
2.6.0 JDK Modules
3.6.0 JDK Modules com.sun
4.6.0 JDK Modules com.sun.java
5.6.0 JDK Modules sun
6.6.0 JDK Platform
7.Ajax
8.Apache Harmony Java SE
9.Aspect oriented
10.Authentication Authorization
11.Blogger System
12.Build
13.Byte Code
14.Cache
15.Chart
16.Chat
17.Code Analyzer
18.Collaboration
19.Content Management System
20.Database Client
21.Database DBMS
22.Database JDBC Connection Pool
23.Database ORM
24.Development
25.EJB Server
26.ERP CRM Financial
27.ESB
28.Forum
29.Game
30.GIS
31.Graphic 3D
32.Graphic Library
33.Groupware
34.HTML Parser
35.IDE
36.IDE Eclipse
37.IDE Netbeans
38.Installer
39.Internationalization Localization
40.Inversion of Control
41.Issue Tracking
42.J2EE
43.J2ME
44.JBoss
45.JMS
46.JMX
47.Library
48.Mail Clients
49.Music
50.Net
51.Parser
52.PDF
53.Portal
54.Profiler
55.Project Management
56.Report
57.RSS RDF
58.Rule Engine
59.Science
60.Scripting
61.Search Engine
62.Security
63.Sevlet Container
64.Source Control
65.Swing Library
66.Template Engine
67.Test Coverage
68.Testing
69.UML
70.Web Crawler
71.Web Framework
72.Web Mail
73.Web Server
74.Web Services
75.Web Services apache cxf 2.2.6
76.Web Services AXIS2
77.Wiki Engine
78.Workflow Engines
79.XML
80.XML UI
Java Source Code / Java Documentation » 6.0 JDK Core » Collections Jar Zip Logging regex » java.util 
Source Cross Referenced  Class Diagram Java Document (Java Doc) 


0001        /*
0002         * Copyright 1995-2006 Sun Microsystems, Inc.  All Rights Reserved.
0003         * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
0004         *
0005         * This code is free software; you can redistribute it and/or modify it
0006         * under the terms of the GNU General Public License version 2 only, as
0007         * published by the Free Software Foundation.  Sun designates this
0008         * particular file as subject to the "Classpath" exception as provided
0009         * by Sun in the LICENSE file that accompanied this code.
0010         *
0011         * This code is distributed in the hope that it will be useful, but WITHOUT
0012         * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
0013         * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
0014         * version 2 for more details (a copy is included in the LICENSE file that
0015         * accompanied this code).
0016         *
0017         * You should have received a copy of the GNU General Public License version
0018         * 2 along with this work; if not, write to the Free Software Foundation,
0019         * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
0020         *
0021         * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
0022         * CA 95054 USA or visit www.sun.com if you need additional information or
0023         * have any questions.
0024         */
0025
0026        package java.util;
0027
0028        import java.io.IOException;
0029        import java.io.PrintStream;
0030        import java.io.PrintWriter;
0031        import java.io.InputStream;
0032        import java.io.OutputStream;
0033        import java.io.Reader;
0034        import java.io.Writer;
0035        import java.io.OutputStreamWriter;
0036        import java.io.BufferedWriter;
0037
0038        /**
0039         * The <code>Properties</code> class represents a persistent set of
0040         * properties. The <code>Properties</code> can be saved to a stream
0041         * or loaded from a stream. Each key and its corresponding value in
0042         * the property list is a string.
0043         * <p>
0044         * A property list can contain another property list as its
0045         * "defaults"; this second property list is searched if
0046         * the property key is not found in the original property list.
0047         * <p>
0048         * Because <code>Properties</code> inherits from <code>Hashtable</code>, the
0049         * <code>put</code> and <code>putAll</code> methods can be applied to a
0050         * <code>Properties</code> object.  Their use is strongly discouraged as they
0051         * allow the caller to insert entries whose keys or values are not
0052         * <code>Strings</code>.  The <code>setProperty</code> method should be used
0053         * instead.  If the <code>store</code> or <code>save</code> method is called
0054         * on a "compromised" <code>Properties</code> object that contains a
0055         * non-<code>String</code> key or value, the call will fail. Similarly, 
0056         * the call to the <code>propertyNames</code> or <code>list</code> method 
0057         * will fail if it is called on a "compromised" <code>Properties</code> 
0058         * object that contains a non-<code>String</code> key.
0059         *
0060         * <p>
0061         * The {@link #load(java.io.Reader) load(Reader)} <tt>/</tt>
0062         * {@link #store(java.io.Writer, java.lang.String) store(Writer, String)}
0063         * methods load and store properties from and to a character based stream
0064         * in a simple line-oriented format specified below.
0065         *
0066         * The {@link #load(java.io.InputStream) load(InputStream)} <tt>/</tt>
0067         * {@link #store(java.io.OutputStream, java.lang.String) store(OutputStream, String)}
0068         * methods work the same way as the load(Reader)/store(Writer, String) pair, except
0069         * the input/output stream is encoded in ISO 8859-1 character encoding.
0070         * Characters that cannot be directly represented in this encoding can be written using
0071         * <a href="http://java.sun.com/docs/books/jls/third_edition/html/lexical.html#3.3">Unicode escapes</a>
0072         * ; only a single 'u' character is allowed in an escape
0073         * sequence. The native2ascii tool can be used to convert property files to and
0074         * from other character encodings.
0075         * 
0076         * <p> The {@link #loadFromXML(InputStream)} and {@link
0077         * #storeToXML(OutputStream, String, String)} methods load and store properties
0078         * in a simple XML format.  By default the UTF-8 character encoding is used,
0079         * however a specific encoding may be specified if required.  An XML properties
0080         * document has the following DOCTYPE declaration:
0081         *
0082         * <pre>
0083         * &lt;!DOCTYPE properties SYSTEM "http://java.sun.com/dtd/properties.dtd"&gt;
0084         * </pre>
0085         * Note that the system URI (http://java.sun.com/dtd/properties.dtd) is
0086         * <i>not</i> accessed when exporting or importing properties; it merely
0087         * serves as a string to uniquely identify the DTD, which is:
0088         * <pre>
0089         *    &lt;?xml version="1.0" encoding="UTF-8"?&gt;
0090         *
0091         *    &lt;!-- DTD for properties --&gt;
0092         *
0093         *    &lt;!ELEMENT properties ( comment?, entry* ) &gt;
0094         *
0095         *    &lt;!ATTLIST properties version CDATA #FIXED "1.0"&gt;
0096         *
0097         *    &lt;!ELEMENT comment (#PCDATA) &gt;
0098         *
0099         *    &lt;!ELEMENT entry (#PCDATA) &gt;
0100         *
0101         *    &lt;!ATTLIST entry key CDATA #REQUIRED&gt;
0102         * </pre>
0103         * 
0104         * @see <a href="../../../technotes/tools/solaris/native2ascii.html">native2ascii tool for Solaris</a>
0105         * @see <a href="../../../technotes/tools/windows/native2ascii.html">native2ascii tool for Windows</a>
0106         *
0107         * <p>This class is thread-safe: multiple threads can share a single
0108         * <tt>Properties</tt> object without the need for external synchronization.
0109         *
0110         * @author  Arthur van Hoff
0111         * @author  Michael McCloskey
0112         * @author  Xueming Shen
0113         * @version 1.102, 05/05/07
0114         * @since   JDK1.0
0115         */
0116        public class Properties extends Hashtable<Object, Object> {
0117            /**
0118             * use serialVersionUID from JDK 1.1.X for interoperability
0119             */
0120            private static final long serialVersionUID = 4112578634029874840L;
0121
0122            /**
0123             * A property list that contains default values for any keys not
0124             * found in this property list.
0125             *
0126             * @serial
0127             */
0128            protected Properties defaults;
0129
0130            /**
0131             * Creates an empty property list with no default values.
0132             */
0133            public Properties() {
0134                this (null);
0135            }
0136
0137            /**
0138             * Creates an empty property list with the specified defaults.
0139             *
0140             * @param   defaults   the defaults.
0141             */
0142            public Properties(Properties defaults) {
0143                this .defaults = defaults;
0144            }
0145
0146            /**
0147             * Calls the <tt>Hashtable</tt> method <code>put</code>. Provided for
0148             * parallelism with the <tt>getProperty</tt> method. Enforces use of
0149             * strings for property keys and values. The value returned is the
0150             * result of the <tt>Hashtable</tt> call to <code>put</code>.
0151             *
0152             * @param key the key to be placed into this property list.
0153             * @param value the value corresponding to <tt>key</tt>.
0154             * @return     the previous value of the specified key in this property
0155             *             list, or <code>null</code> if it did not have one.
0156             * @see #getProperty
0157             * @since    1.2
0158             */
0159            public synchronized Object setProperty(String key, String value) {
0160                return put(key, value);
0161            }
0162
0163            /**
0164             * Reads a property list (key and element pairs) from the input
0165             * character stream in a simple line-oriented format.
0166             * <p>
0167             * Properties are processed in terms of lines. There are two
0168             * kinds of line, <i>natural lines</i> and <i>logical lines</i>.
0169             * A natural line is defined as a line of
0170             * characters that is terminated either by a set of line terminator
0171             * characters (<code>\n</code> or <code>\r</code> or <code>\r\n</code>)
0172             * or by the end of the stream. A natural line may be either a blank line,
0173             * a comment line, or hold all or some of a key-element pair. A logical
0174             * line holds all the data of a key-element pair, which may be spread
0175             * out across several adjacent natural lines by escaping
0176             * the line terminator sequence with a backslash character
0177             * <code>\</code>.  Note that a comment line cannot be extended
0178             * in this manner; every natural line that is a comment must have
0179             * its own comment indicator, as described below. Lines are read from
0180             * input until the end of the stream is reached.
0181             *
0182             * <p>
0183             * A natural line that contains only white space characters is
0184             * considered blank and is ignored.  A comment line has an ASCII
0185             * <code>'#'</code> or <code>'!'</code> as its first non-white
0186             * space character; comment lines are also ignored and do not
0187             * encode key-element information.  In addition to line
0188             * terminators, this format considers the characters space
0189             * (<code>' '</code>, <code>'&#92;u0020'</code>), tab
0190             * (<code>'\t'</code>, <code>'&#92;u0009'</code>), and form feed
0191             * (<code>'\f'</code>, <code>'&#92;u000C'</code>) to be white
0192             * space.
0193             *
0194             * <p>
0195             * If a logical line is spread across several natural lines, the
0196             * backslash escaping the line terminator sequence, the line
0197             * terminator sequence, and any white space at the start of the
0198             * following line have no affect on the key or element values.
0199             * The remainder of the discussion of key and element parsing
0200             * (when loading) will assume all the characters constituting
0201             * the key and element appear on a single natural line after
0202             * line continuation characters have been removed.  Note that
0203             * it is <i>not</i> sufficient to only examine the character
0204             * preceding a line terminator sequence to decide if the line
0205             * terminator is escaped; there must be an odd number of
0206             * contiguous backslashes for the line terminator to be escaped.
0207             * Since the input is processed from left to right, a
0208             * non-zero even number of 2<i>n</i> contiguous backslashes
0209             * before a line terminator (or elsewhere) encodes <i>n</i>
0210             * backslashes after escape processing.
0211             *
0212             * <p>
0213             * The key contains all of the characters in the line starting
0214             * with the first non-white space character and up to, but not
0215             * including, the first unescaped <code>'='</code>,
0216             * <code>':'</code>, or white space character other than a line
0217             * terminator. All of these key termination characters may be
0218             * included in the key by escaping them with a preceding backslash
0219             * character; for example,<p>
0220             *
0221             * <code>\:\=</code><p>
0222             *
0223             * would be the two-character key <code>":="</code>.  Line
0224             * terminator characters can be included using <code>\r</code> and
0225             * <code>\n</code> escape sequences.  Any white space after the
0226             * key is skipped; if the first non-white space character after
0227             * the key is <code>'='</code> or <code>':'</code>, then it is
0228             * ignored and any white space characters after it are also
0229             * skipped.  All remaining characters on the line become part of
0230             * the associated element string; if there are no remaining
0231             * characters, the element is the empty string
0232             * <code>&quot;&quot;</code>.  Once the raw character sequences
0233             * constituting the key and element are identified, escape
0234             * processing is performed as described above.
0235             *
0236             * <p>
0237             * As an example, each of the following three lines specifies the key
0238             * <code>"Truth"</code> and the associated element value
0239             * <code>"Beauty"</code>:
0240             * <p>
0241             * <pre>
0242             * Truth = Beauty
0243             *	Truth:Beauty
0244             * Truth			:Beauty
0245             * </pre>
0246             * As another example, the following three lines specify a single
0247             * property:
0248             * <p>
0249             * <pre>
0250             * fruits                           apple, banana, pear, \
0251             *                                  cantaloupe, watermelon, \
0252             *                                  kiwi, mango
0253             * </pre>
0254             * The key is <code>"fruits"</code> and the associated element is:
0255             * <p>
0256             * <pre>"apple, banana, pear, cantaloupe, watermelon, kiwi, mango"</pre>
0257             * Note that a space appears before each <code>\</code> so that a space
0258             * will appear after each comma in the final result; the <code>\</code>,
0259             * line terminator, and leading white space on the continuation line are
0260             * merely discarded and are <i>not</i> replaced by one or more other
0261             * characters.
0262             * <p>
0263             * As a third example, the line:
0264             * <p>
0265             * <pre>cheeses
0266             * </pre>
0267             * specifies that the key is <code>"cheeses"</code> and the associated
0268             * element is the empty string <code>""</code>.<p>
0269             * <p>
0270             *
0271             * <a name="unicodeescapes"></a>
0272             * Characters in keys and elements can be represented in escape
0273             * sequences similar to those used for character and string literals
0274             * (see <a
0275             * href="http://java.sun.com/docs/books/jls/third_edition/html/lexical.html#3.3">&sect;3.3</a>
0276             * and <a
0277             * href="http://java.sun.com/docs/books/jls/third_edition/html/lexical.html#3.10.6">&sect;3.10.6</a>
0278             * of the <i>Java Language Specification</i>).
0279             *
0280             * The differences from the character escape sequences and Unicode
0281             * escapes used for characters and strings are:
0282             *
0283             * <ul>
0284             * <li> Octal escapes are not recognized.
0285             *
0286             * <li> The character sequence <code>\b</code> does <i>not</i>
0287             * represent a backspace character.
0288             *
0289             * <li> The method does not treat a backslash character,
0290             * <code>\</code>, before a non-valid escape character as an
0291             * error; the backslash is silently dropped.  For example, in a
0292             * Java string the sequence <code>"\z"</code> would cause a
0293             * compile time error.  In contrast, this method silently drops
0294             * the backslash.  Therefore, this method treats the two character
0295             * sequence <code>"\b"</code> as equivalent to the single
0296             * character <code>'b'</code>.
0297             *
0298             * <li> Escapes are not necessary for single and double quotes;
0299             * however, by the rule above, single and double quote characters
0300             * preceded by a backslash still yield single and double quote
0301             * characters, respectively.
0302             *
0303             * <li> Only a single 'u' character is allowed in a Uniocde escape
0304             * sequence.
0305             *
0306             * </ul>
0307             * <p>
0308             * The specified stream remains open after this method returns.
0309             *
0310             * @param   reader   the input character stream.
0311             * @throws  IOException  if an error occurred when reading from the
0312             *          input stream.
0313             * @throws  IllegalArgumentException if a malformed Unicode escape
0314             *          appears in the input.
0315             * @since   1.6
0316             */
0317            public synchronized void load(Reader reader) throws IOException {
0318                load0(new LineReader(reader));
0319            }
0320
0321            /**
0322             * Reads a property list (key and element pairs) from the input
0323             * byte stream. The input stream is in a simple line-oriented
0324             * format as specified in
0325             * {@link #load(java.io.Reader) load(Reader)} and is assumed to use
0326             * the ISO 8859-1 character encoding; that is each byte is one Latin1
0327             * character. Characters not in Latin1, and certain special characters,
0328             * are represented in keys and elements using
0329             * <a href="http://java.sun.com/docs/books/jls/third_edition/html/lexical.html#3.3">Unicode escapes</a>.
0330             * <p>
0331             * The specified stream remains open after this method returns.
0332             *
0333             * @param      inStream   the input stream.
0334             * @exception  IOException  if an error occurred when reading from the
0335             *             input stream.
0336             * @throws	   IllegalArgumentException if the input stream contains a
0337             * 		   malformed Unicode escape sequence.
0338             * @since 1.2
0339             */
0340            public synchronized void load(InputStream inStream)
0341                    throws IOException {
0342                load0(new LineReader(inStream));
0343            }
0344
0345            private void load0(LineReader lr) throws IOException {
0346                char[] convtBuf = new char[1024];
0347                int limit;
0348                int keyLen;
0349                int valueStart;
0350                char c;
0351                boolean hasSep;
0352                boolean precedingBackslash;
0353
0354                while ((limit = lr.readLine()) >= 0) {
0355                    c = 0;
0356                    keyLen = 0;
0357                    valueStart = limit;
0358                    hasSep = false;
0359
0360                    //System.out.println("line=<" + new String(lineBuf, 0, limit) + ">");
0361                    precedingBackslash = false;
0362                    while (keyLen < limit) {
0363                        c = lr.lineBuf[keyLen];
0364                        //need check if escaped.
0365                        if ((c == '=' || c == ':') && !precedingBackslash) {
0366                            valueStart = keyLen + 1;
0367                            hasSep = true;
0368                            break;
0369                        } else if ((c == ' ' || c == '\t' || c == '\f')
0370                                && !precedingBackslash) {
0371                            valueStart = keyLen + 1;
0372                            break;
0373                        }
0374                        if (c == '\\') {
0375                            precedingBackslash = !precedingBackslash;
0376                        } else {
0377                            precedingBackslash = false;
0378                        }
0379                        keyLen++;
0380                    }
0381                    while (valueStart < limit) {
0382                        c = lr.lineBuf[valueStart];
0383                        if (c != ' ' && c != '\t' && c != '\f') {
0384                            if (!hasSep && (c == '=' || c == ':')) {
0385                                hasSep = true;
0386                            } else {
0387                                break;
0388                            }
0389                        }
0390                        valueStart++;
0391                    }
0392                    String key = loadConvert(lr.lineBuf, 0, keyLen, convtBuf);
0393                    String value = loadConvert(lr.lineBuf, valueStart, limit
0394                            - valueStart, convtBuf);
0395                    put(key, value);
0396                }
0397            }
0398
0399            /* Read in a "logical line" from an InputStream/Reader, skip all comment
0400             * and blank lines and filter out those leading whitespace characters 
0401             * (\u0020, \u0009 and \u000c) from the beginning of a "natural line". 
0402             * Method returns the char length of the "logical line" and stores 
0403             * the line in "lineBuf". 
0404             */
0405            class LineReader {
0406                public LineReader(InputStream inStream) {
0407                    this .inStream = inStream;
0408                    inByteBuf = new byte[8192];
0409                }
0410
0411                public LineReader(Reader reader) {
0412                    this .reader = reader;
0413                    inCharBuf = new char[8192];
0414                }
0415
0416                byte[] inByteBuf;
0417                char[] inCharBuf;
0418                char[] lineBuf = new char[1024];
0419                int inLimit = 0;
0420                int inOff = 0;
0421                InputStream inStream;
0422                Reader reader;
0423
0424                int readLine() throws IOException {
0425                    int len = 0;
0426                    char c = 0;
0427
0428                    boolean skipWhiteSpace = true;
0429                    boolean isCommentLine = false;
0430                    boolean isNewLine = true;
0431                    boolean appendedLineBegin = false;
0432                    boolean precedingBackslash = false;
0433                    boolean skipLF = false;
0434
0435                    while (true) {
0436                        if (inOff >= inLimit) {
0437                            inLimit = (inStream == null) ? reader
0438                                    .read(inCharBuf) : inStream.read(inByteBuf);
0439                            inOff = 0;
0440                            if (inLimit <= 0) {
0441                                if (len == 0 || isCommentLine) {
0442                                    return -1;
0443                                }
0444                                return len;
0445                            }
0446                        }
0447                        if (inStream != null) {
0448                            //The line below is equivalent to calling a 
0449                            //ISO8859-1 decoder.
0450                            c = (char) (0xff & inByteBuf[inOff++]);
0451                        } else {
0452                            c = inCharBuf[inOff++];
0453                        }
0454                        if (skipLF) {
0455                            skipLF = false;
0456                            if (c == '\n') {
0457                                continue;
0458                            }
0459                        }
0460                        if (skipWhiteSpace) {
0461                            if (c == ' ' || c == '\t' || c == '\f') {
0462                                continue;
0463                            }
0464                            if (!appendedLineBegin && (c == '\r' || c == '\n')) {
0465                                continue;
0466                            }
0467                            skipWhiteSpace = false;
0468                            appendedLineBegin = false;
0469                        }
0470                        if (isNewLine) {
0471                            isNewLine = false;
0472                            if (c == '#' || c == '!') {
0473                                isCommentLine = true;
0474                                continue;
0475                            }
0476                        }
0477
0478                        if (c != '\n' && c != '\r') {
0479                            lineBuf[len++] = c;
0480                            if (len == lineBuf.length) {
0481                                int newLength = lineBuf.length * 2;
0482                                if (newLength < 0) {
0483                                    newLength = Integer.MAX_VALUE;
0484                                }
0485                                char[] buf = new char[newLength];
0486                                System.arraycopy(lineBuf, 0, buf, 0,
0487                                        lineBuf.length);
0488                                lineBuf = buf;
0489                            }
0490                            //flip the preceding backslash flag
0491                            if (c == '\\') {
0492                                precedingBackslash = !precedingBackslash;
0493                            } else {
0494                                precedingBackslash = false;
0495                            }
0496                        } else {
0497                            // reached EOL
0498                            if (isCommentLine || len == 0) {
0499                                isCommentLine = false;
0500                                isNewLine = true;
0501                                skipWhiteSpace = true;
0502                                len = 0;
0503                                continue;
0504                            }
0505                            if (inOff >= inLimit) {
0506                                inLimit = (inStream == null) ? reader
0507                                        .read(inCharBuf) : inStream
0508                                        .read(inByteBuf);
0509                                inOff = 0;
0510                                if (inLimit <= 0) {
0511                                    return len;
0512                                }
0513                            }
0514                            if (precedingBackslash) {
0515                                len -= 1;
0516                                //skip the leading whitespace characters in following line
0517                                skipWhiteSpace = true;
0518                                appendedLineBegin = true;
0519                                precedingBackslash = false;
0520                                if (c == '\r') {
0521                                    skipLF = true;
0522                                }
0523                            } else {
0524                                return len;
0525                            }
0526                        }
0527                    }
0528                }
0529            }
0530
0531            /*
0532             * Converts encoded &#92;uxxxx to unicode chars
0533             * and changes special saved chars to their original forms
0534             */
0535            private String loadConvert(char[] in, int off, int len,
0536                    char[] convtBuf) {
0537                if (convtBuf.length < len) {
0538                    int newLen = len * 2;
0539                    if (newLen < 0) {
0540                        newLen = Integer.MAX_VALUE;
0541                    }
0542                    convtBuf = new char[newLen];
0543                }
0544                char aChar;
0545                char[] out = convtBuf;
0546                int outLen = 0;
0547                int end = off + len;
0548
0549                while (off < end) {
0550                    aChar = in[off++];
0551                    if (aChar == '\\') {
0552                        aChar = in[off++];
0553                        if (aChar == 'u') {
0554                            // Read the xxxx
0555                            int value = 0;
0556                            for (int i = 0; i < 4; i++) {
0557                                aChar = in[off++];
0558                                switch (aChar) {
0559                                case '0':
0560                                case '1':
0561                                case '2':
0562                                case '3':
0563                                case '4':
0564                                case '5':
0565                                case '6':
0566                                case '7':
0567                                case '8':
0568                                case '9':
0569                                    value = (value << 4) + aChar - '0';
0570                                    break;
0571                                case 'a':
0572                                case 'b':
0573                                case 'c':
0574                                case 'd':
0575                                case 'e':
0576                                case 'f':
0577                                    value = (value << 4) + 10 + aChar - 'a';
0578                                    break;
0579                                case 'A':
0580                                case 'B':
0581                                case 'C':
0582                                case 'D':
0583                                case 'E':
0584                                case 'F':
0585                                    value = (value << 4) + 10 + aChar - 'A';
0586                                    break;
0587                                default:
0588                                    throw new IllegalArgumentException(
0589                                            "Malformed \\uxxxx encoding.");
0590                                }
0591                            }
0592                            out[outLen++] = (char) value;
0593                        } else {
0594                            if (aChar == 't')
0595                                aChar = '\t';
0596                            else if (aChar == 'r')
0597                                aChar = '\r';
0598                            else if (aChar == 'n')
0599                                aChar = '\n';
0600                            else if (aChar == 'f')
0601                                aChar = '\f';
0602                            out[outLen++] = aChar;
0603                        }
0604                    } else {
0605                        out[outLen++] = (char) aChar;
0606                    }
0607                }
0608                return new String(out, 0, outLen);
0609            }
0610
0611            /*
0612             * Converts unicodes to encoded &#92;uxxxx and escapes
0613             * special characters with a preceding slash
0614             */
0615            private String saveConvert(String theString, boolean escapeSpace,
0616                    boolean escapeUnicode) {
0617                int len = theString.length();
0618                int bufLen = len * 2;
0619                if (bufLen < 0) {
0620                    bufLen = Integer.MAX_VALUE;
0621                }
0622                StringBuffer outBuffer = new StringBuffer(bufLen);
0623
0624                for (int x = 0; x < len; x++) {
0625                    char aChar = theString.charAt(x);
0626                    // Handle common case first, selecting largest block that
0627                    // avoids the specials below
0628                    if ((aChar > 61) && (aChar < 127)) {
0629                        if (aChar == '\\') {
0630                            outBuffer.append('\\');
0631                            outBuffer.append('\\');
0632                            continue;
0633                        }
0634                        outBuffer.append(aChar);
0635                        continue;
0636                    }
0637                    switch (aChar) {
0638                    case ' ':
0639                        if (x == 0 || escapeSpace)
0640                            outBuffer.append('\\');
0641                        outBuffer.append(' ');
0642                        break;
0643                    case '\t':
0644                        outBuffer.append('\\');
0645                        outBuffer.append('t');
0646                        break;
0647                    case '\n':
0648                        outBuffer.append('\\');
0649                        outBuffer.append('n');
0650                        break;
0651                    case '\r':
0652                        outBuffer.append('\\');
0653                        outBuffer.append('r');
0654                        break;
0655                    case '\f':
0656                        outBuffer.append('\\');
0657                        outBuffer.append('f');
0658                        break;
0659                    case '=': // Fall through
0660                    case ':': // Fall through
0661                    case '#': // Fall through
0662                    case '!':
0663                        outBuffer.append('\\');
0664                        outBuffer.append(aChar);
0665                        break;
0666                    default:
0667                        if (((aChar < 0x0020) || (aChar > 0x007e))
0668                                & escapeUnicode) {
0669                            outBuffer.append('\\');
0670                            outBuffer.append('u');
0671                            outBuffer.append(toHex((aChar >> 12) & 0xF));
0672                            outBuffer.append(toHex((aChar >> 8) & 0xF));
0673                            outBuffer.append(toHex((aChar >> 4) & 0xF));
0674                            outBuffer.append(toHex(aChar & 0xF));
0675                        } else {
0676                            outBuffer.append(aChar);
0677                        }
0678                    }
0679                }
0680                return outBuffer.toString();
0681            }
0682
0683            private static void writeComments(BufferedWriter bw, String comments)
0684                    throws IOException {
0685                bw.write("#");
0686                int len = comments.length();
0687                int current = 0;
0688                int last = 0;
0689                char[] uu = new char[6];
0690                uu[0] = '\\';
0691                uu[1] = 'u';
0692                while (current < len) {
0693                    char c = comments.charAt(current);
0694                    if (c > '\u00ff' || c == '\n' || c == '\r') {
0695                        if (last != current)
0696                            bw.write(comments.substring(last, current));
0697                        if (c > '\u00ff') {
0698                            uu[2] = toHex((c >> 12) & 0xf);
0699                            uu[3] = toHex((c >> 8) & 0xf);
0700                            uu[4] = toHex((c >> 4) & 0xf);
0701                            uu[5] = toHex(c & 0xf);
0702                            bw.write(new String(uu));
0703                        } else {
0704                            bw.newLine();
0705                            if (c == '\r' && current != len - 1
0706                                    && comments.charAt(current + 1) == '\n') {
0707                                current++;
0708                            }
0709                            if (current == len - 1
0710                                    || (comments.charAt(current + 1) != '#' && comments
0711                                            .charAt(current + 1) != '!'))
0712                                bw.write("#");
0713                        }
0714                        last = current + 1;
0715                    }
0716                    current++;
0717                }
0718                if (last != current)
0719                    bw.write(comments.substring(last, current));
0720                bw.newLine();
0721            }
0722
0723            /**
0724             * Calls the <code>store(OutputStream out, String comments)</code> method
0725             * and suppresses IOExceptions that were thrown.
0726             *
0727             * @deprecated This method does not throw an IOException if an I/O error
0728             * occurs while saving the property list.  The preferred way to save a
0729             * properties list is via the <code>store(OutputStream out, 
0730             * String comments)</code> method or the 
0731             * <code>storeToXML(OutputStream os, String comment)</code> method.
0732             *
0733             * @param   out      an output stream.
0734             * @param   comments   a description of the property list.
0735             * @exception  ClassCastException  if this <code>Properties</code> object
0736             *             contains any keys or values that are not 
0737             *             <code>Strings</code>.
0738             */
0739            @Deprecated
0740            public synchronized void save(OutputStream out, String comments) {
0741                try {
0742                    store(out, comments);
0743                } catch (IOException e) {
0744                }
0745            }
0746
0747            /**
0748             * Writes this property list (key and element pairs) in this
0749             * <code>Properties</code> table to the output character stream in a 
0750             * format suitable for using the {@link #load(java.io.Reader) load(Reader)}
0751             * method.
0752             * <p>
0753             * Properties from the defaults table of this <code>Properties</code>
0754             * table (if any) are <i>not</i> written out by this method.
0755             * <p>
0756             * If the comments argument is not null, then an ASCII <code>#</code>
0757             * character, the comments string, and a line separator are first written
0758             * to the output stream. Thus, the <code>comments</code> can serve as an
0759             * identifying comment. Any one of a line feed ('\n'), a carriage
0760             * return ('\r'), or a carriage return followed immediately by a line feed
0761             * in comments is replaced by a line separator generated by the <code>Writer</code>
0762             * and if the next character in comments is not character <code>#</code> or 
0763             * character <code>!</code> then an ASCII <code>#</code> is written out 
0764             * after that line separator.
0765             * <p>
0766             * Next, a comment line is always written, consisting of an ASCII
0767             * <code>#</code> character, the current date and time (as if produced
0768             * by the <code>toString</code> method of <code>Date</code> for the
0769             * current time), and a line separator as generated by the <code>Writer</code>.
0770             * <p>
0771             * Then every entry in this <code>Properties</code> table is
0772             * written out, one per line. For each entry the key string is
0773             * written, then an ASCII <code>=</code>, then the associated
0774             * element string. For the key, all space characters are
0775             * written with a preceding <code>\</code> character.  For the
0776             * element, leading space characters, but not embedded or trailing
0777             * space characters, are written with a preceding <code>\</code>
0778             * character. The key and element characters <code>#</code>,
0779             * <code>!</code>, <code>=</code>, and <code>:</code> are written
0780             * with a preceding backslash to ensure that they are properly loaded.
0781             * <p>
0782             * After the entries have been written, the output stream is flushed.  
0783             * The output stream remains open after this method returns.
0784             * <p>
0785             *
0786             * @param   writer      an output character stream writer.
0787             * @param   comments   a description of the property list.
0788             * @exception  IOException if writing this property list to the specified
0789             *             output stream throws an <tt>IOException</tt>.
0790             * @exception  ClassCastException  if this <code>Properties</code> object
0791             *             contains any keys or values that are not <code>Strings</code>.
0792             * @exception  NullPointerException  if <code>writer</code> is null.
0793             * @since 1.6
0794             */
0795            public void store(Writer writer, String comments)
0796                    throws IOException {
0797                store0(
0798                        (writer instanceof  BufferedWriter) ? (BufferedWriter) writer
0799                                : new BufferedWriter(writer), comments, false);
0800            }
0801
0802            /**
0803             * Writes this property list (key and element pairs) in this
0804             * <code>Properties</code> table to the output stream in a format suitable
0805             * for loading into a <code>Properties</code> table using the
0806             * {@link #load(InputStream) load(InputStream)} method.
0807             * <p>
0808             * Properties from the defaults table of this <code>Properties</code>
0809             * table (if any) are <i>not</i> written out by this method.
0810             * <p>
0811             * This method outputs the comments, properties keys and values in 
0812             * the same format as specified in
0813             * {@link #store(java.io.Writer, java.lang.String) store(Writer)},
0814             * with the following differences:
0815             * <ul>
0816             * <li>The stream is written using the ISO 8859-1 character encoding.
0817             *
0818             * <li>Characters not in Latin-1 in the comments are written as 
0819             * <code>&#92;u</code><i>xxxx</i> for their appropriate unicode 
0820             * hexadecimal value <i>xxxx</i>. 
0821             * 
0822             * <li>Characters less than <code>&#92;u0020</code> and characters greater
0823             * than <code>&#92;u007E</code> in property keys or values are written
0824             * as <code>&#92;u</code><i>xxxx</i> for the appropriate hexadecimal
0825             * value <i>xxxx</i>. 
0826             * </ul>
0827             * <p>
0828             * After the entries have been written, the output stream is flushed.  
0829             * The output stream remains open after this method returns.
0830             * <p>
0831             * @param   out      an output stream.
0832             * @param   comments   a description of the property list.
0833             * @exception  IOException if writing this property list to the specified
0834             *             output stream throws an <tt>IOException</tt>.
0835             * @exception  ClassCastException  if this <code>Properties</code> object
0836             *             contains any keys or values that are not <code>Strings</code>.
0837             * @exception  NullPointerException  if <code>out</code> is null.
0838             * @since 1.2
0839             */
0840            public void store(OutputStream out, String comments)
0841                    throws IOException {
0842                store0(
0843                        new BufferedWriter(
0844                                new OutputStreamWriter(out, "8859_1")),
0845                        comments, true);
0846            }
0847
0848            private void store0(BufferedWriter bw, String comments,
0849                    boolean escUnicode) throws IOException {
0850                if (comments != null) {
0851                    writeComments(bw, comments);
0852                }
0853                bw.write("#" + new Date().toString());
0854                bw.newLine();
0855                synchronized (this ) {
0856                    for (Enumeration e = keys(); e.hasMoreElements();) {
0857                        String key = (String) e.nextElement();
0858                        String val = (String) get(key);
0859                        key = saveConvert(key, true, escUnicode);
0860                        /* No need to escape embedded and trailing spaces for value, hence
0861                         * pass false to flag.
0862                         */
0863                        val = saveConvert(val, false, escUnicode);
0864                        bw.write(key + "=" + val);
0865                        bw.newLine();
0866                    }
0867                }
0868                bw.flush();
0869            }
0870
0871            /**
0872             * Loads all of the properties represented by the XML document on the
0873             * specified input stream into this properties table.
0874             *
0875             * <p>The XML document must have the following DOCTYPE declaration:
0876             * <pre>
0877             * &lt;!DOCTYPE properties SYSTEM "http://java.sun.com/dtd/properties.dtd"&gt;
0878             * </pre>
0879             * Furthermore, the document must satisfy the properties DTD described
0880             * above.
0881             *
0882             * <p>The specified stream is closed after this method returns.
0883             *
0884             * @param in the input stream from which to read the XML document.
0885             * @throws IOException if reading from the specified input stream
0886             *         results in an <tt>IOException</tt>.
0887             * @throws InvalidPropertiesFormatException Data on input stream does not
0888             *         constitute a valid XML document with the mandated document type.
0889             * @throws NullPointerException if <code>in</code> is null.
0890             * @see    #storeToXML(OutputStream, String, String)
0891             * @since 1.5
0892             */
0893            public synchronized void loadFromXML(InputStream in)
0894                    throws IOException, InvalidPropertiesFormatException {
0895                if (in == null)
0896                    throw new NullPointerException();
0897                XMLUtils.load(this , in);
0898                in.close();
0899            }
0900
0901            /**
0902             * Emits an XML document representing all of the properties contained
0903             * in this table.
0904             *
0905             * <p> An invocation of this method of the form <tt>props.storeToXML(os,
0906             * comment)</tt> behaves in exactly the same way as the invocation
0907             * <tt>props.storeToXML(os, comment, "UTF-8");</tt>.
0908             *
0909             * @param os the output stream on which to emit the XML document.
0910             * @param comment a description of the property list, or <code>null</code>
0911             *        if no comment is desired.
0912             * @throws IOException if writing to the specified output stream
0913             *         results in an <tt>IOException</tt>.
0914             * @throws NullPointerException if <code>os</code> is null.
0915             * @throws ClassCastException  if this <code>Properties</code> object
0916             *         contains any keys or values that are not 
0917             *         <code>Strings</code>.
0918             * @see    #loadFromXML(InputStream)
0919             * @since 1.5
0920             */
0921            public synchronized void storeToXML(OutputStream os, String comment)
0922                    throws IOException {
0923                if (os == null)
0924                    throw new NullPointerException();
0925                storeToXML(os, comment, "UTF-8");
0926            }
0927
0928            /**
0929             * Emits an XML document representing all of the properties contained
0930             * in this table, using the specified encoding.
0931             *
0932             * <p>The XML document will have the following DOCTYPE declaration:
0933             * <pre>
0934             * &lt;!DOCTYPE properties SYSTEM "http://java.sun.com/dtd/properties.dtd"&gt;
0935             * </pre>
0936             *
0937             *<p>If the specified comment is <code>null</code> then no comment
0938             * will be stored in the document.
0939             *
0940             * <p>The specified stream remains open after this method returns.
0941             *
0942             * @param os the output stream on which to emit the XML document.
0943             * @param comment a description of the property list, or <code>null</code>
0944             *        if no comment is desired.
0945             * @throws IOException if writing to the specified output stream
0946             *         results in an <tt>IOException</tt>.
0947             * @throws NullPointerException if <code>os</code> is <code>null</code>,
0948             *         or if <code>encoding</code> is <code>null</code>.
0949             * @throws ClassCastException  if this <code>Properties</code> object
0950             *         contains any keys or values that are not 
0951             *         <code>Strings</code>.
0952             * @see    #loadFromXML(InputStream)
0953             * @since 1.5
0954             */
0955            public synchronized void storeToXML(OutputStream os,
0956                    String comment, String encoding) throws IOException {
0957                if (os == null)
0958                    throw new NullPointerException();
0959                XMLUtils.save(this , os, comment, encoding);
0960            }
0961
0962            /**
0963             * Searches for the property with the specified key in this property list.
0964             * If the key is not found in this property list, the default property list,
0965             * and its defaults, recursively, are then checked. The method returns
0966             * <code>null</code> if the property is not found.
0967             *
0968             * @param   key   the property key.
0969             * @return  the value in this property list with the specified key value.
0970             * @see     #setProperty
0971             * @see     #defaults
0972             */
0973            public String getProperty(String key) {
0974                Object oval = super .get(key);
0975                String sval = (oval instanceof  String) ? (String) oval : null;
0976                return ((sval == null) && (defaults != null)) ? defaults
0977                        .getProperty(key) : sval;
0978            }
0979
0980            /**
0981             * Searches for the property with the specified key in this property list.
0982             * If the key is not found in this property list, the default property list,
0983             * and its defaults, recursively, are then checked. The method returns the
0984             * default value argument if the property is not found.
0985             *
0986             * @param   key            the hashtable key.
0987             * @param   defaultValue   a default value.
0988             *
0989             * @return  the value in this property list with the specified key value.
0990             * @see     #setProperty
0991             * @see     #defaults
0992             */
0993            public String getProperty(String key, String defaultValue) {
0994                String val = getProperty(key);
0995                return (val == null) ? defaultValue : val;
0996            }
0997
0998            /**
0999             * Returns an enumeration of all the keys in this property list,
1000             * including distinct keys in the default property list if a key
1001             * of the same name has not already been found from the main
1002             * properties list.
1003             *
1004             * @return  an enumeration of all the keys in this property list, including
1005             *          the keys in the default property list.
1006             * @throws  ClassCastException if any key in this property list
1007             *          is not a string. 
1008             * @see     java.util.Enumeration
1009             * @see     java.util.Properties#defaults
1010             * @see     #stringPropertyNames
1011             */
1012            public Enumeration<?> propertyNames() {
1013                Hashtable h = new Hashtable();
1014                enumerate(h);
1015                return h.keys();
1016            }
1017
1018            /**
1019             * Returns a set of keys in this property list where
1020             * the key and its corresponding value are strings,
1021             * including distinct keys in the default property list if a key
1022             * of the same name has not already been found from the main
1023             * properties list.  Properties whose key or value is not 
1024             * of type <tt>String</tt> are omitted.
1025             * <p>
1026             * The returned set is not backed by the <tt>Properties</tt> object.
1027             * Changes to this <tt>Properties</tt> are not reflected in the set,
1028             * or vice versa.
1029             *
1030             * @return  a set of keys in this property list where
1031             *          the key and its corresponding value are strings,
1032             *          including the keys in the default property list.
1033             * @see     java.util.Properties#defaults
1034             * @since   1.6
1035             */
1036            public Set<String> stringPropertyNames() {
1037                Hashtable<String, String> h = new Hashtable<String, String>();
1038                enumerateStringProperties(h);
1039                return h.keySet();
1040            }
1041
1042            /**
1043             * Prints this property list out to the specified output stream.
1044             * This method is useful for debugging.
1045             *
1046             * @param   out   an output stream.
1047             * @throws  ClassCastException if any key in this property list
1048             *          is not a string. 
1049             */
1050            public void list(PrintStream out) {
1051                out.println("-- listing properties --");
1052                Hashtable h = new Hashtable();
1053                enumerate(h);
1054                for (Enumeration e = h.keys(); e.hasMoreElements();) {
1055                    String key = (String) e.nextElement();
1056                    String val = (String) h.get(key);
1057                    if (val.length() > 40) {
1058                        val = val.substring(0, 37) + "...";
1059                    }
1060                    out.println(key + "=" + val);
1061                }
1062            }
1063
1064            /**
1065             * Prints this property list out to the specified output stream.
1066             * This method is useful for debugging.
1067             *
1068             * @param   out   an output stream.
1069             * @throws  ClassCastException if any key in this property list
1070             *          is not a string. 
1071             * @since   JDK1.1
1072             */
1073            /*
1074             * Rather than use an anonymous inner class to share common code, this
1075             * method is duplicated in order to ensure that a non-1.1 compiler can
1076             * compile this file.
1077             */
1078            public void list(PrintWriter out) {
1079                out.println("-- listing properties --");
1080                Hashtable h = new Hashtable();
1081                enumerate(h);
1082                for (Enumeration e = h.keys(); e.hasMoreElements();) {
1083                    String key = (String) e.nextElement();
1084                    String val = (String) h.get(key);
1085                    if (val.length() > 40) {
1086                        val = val.substring(0, 37) + "...";
1087                    }
1088                    out.println(key + "=" + val);
1089                }
1090            }
1091
1092            /**
1093             * Enumerates all key/value pairs in the specified hashtable.
1094             * @param h the hashtable
1095             * @throws ClassCastException if any of the property keys
1096             *         is not of String type.
1097             */
1098            private synchronized void enumerate(Hashtable h) {
1099                if (defaults != null) {
1100                    defaults.enumerate(h);
1101                }
1102                for (Enumeration e = keys(); e.hasMoreElements();) {
1103                    String key = (String) e.nextElement();
1104                    h.put(key, get(key));
1105                }
1106            }
1107
1108            /**
1109             * Enumerates all key/value pairs in the specified hashtable
1110             * and omits the property if the key or value is not a string.
1111             * @param h the hashtable
1112             */
1113            private synchronized void enumerateStringProperties(
1114                    Hashtable<String, String> h) {
1115                if (defaults != null) {
1116                    defaults.enumerateStringProperties(h);
1117                }
1118                for (Enumeration e = keys(); e.hasMoreElements();) {
1119                    Object k = e.nextElement();
1120                    Object v = get(k);
1121                    if (k instanceof  String && v instanceof  String) {
1122                        h.put((String) k, (String) v);
1123                    }
1124                }
1125            }
1126
1127            /**
1128             * Convert a nibble to a hex character
1129             * @param	nibble	the nibble to convert.
1130             */
1131            private static char toHex(int nibble) {
1132                return hexDigit[(nibble & 0xF)];
1133            }
1134
1135            /** A table of hex digits */
1136            private static final char[] hexDigit = { '0', '1', '2', '3', '4',
1137                    '5', '6', '7', '8', '9', 'A', 'B', 'C', 'D', 'E', 'F' };
1138        }
www.java2java.com | Contact Us
Copyright 2009 - 12 Demo Source and Support. All rights reserved.
All other trademarks are property of their respective owners.