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

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 geronimo
26. EJB Server GlassFish
27. EJB Server JBoss 4.2.1
28. EJB Server resin 3.1.5
29. ERP CRM Financial
30. ESB
31. Forum
32. GIS
33. Graphic Library
34. Groupware
35. HTML Parser
36. IDE
37. IDE Eclipse
38. IDE Netbeans
39. Installer
40. Internationalization Localization
41. Inversion of Control
42. Issue Tracking
43. J2EE
44. JBoss
45. JMS
46. JMX
47. Library
48. Mail Clients
49. Net
50. Parser
51. PDF
52. Portal
53. Profiler
54. Project Management
55. Report
56. RSS RDF
57. Rule Engine
58. Science
59. Scripting
60. Search Engine
61. Security
62. Sevlet Container
63. Source Control
64. Swing Library
65. Template Engine
66. Test Coverage
67. Testing
68. UML
69. Web Crawler
70. Web Framework
71. Web Mail
72. Web Server
73. Web Services
74. Web Services apache cxf 2.0.1
75. Web Services AXIS2
76. Wiki Engine
77. Workflow Engines
78. XML
79. XML UI
Java
Java Tutorial
Java Open Source
Jar File Download
Java Articles
Java Products
Java by API
C# / C Sharp
C# / CSharp Tutorial
ASP.Net
JavaScript DHTML
JavaScript Tutorial
JavaScript Reference
HTML / CSS
HTML CSS Reference
C / ANSI-C
C Tutorial
C++
C++ Tutorial
PHP
Python
SQL Server / T-SQL
Oracle PL / SQL
Oracle PL/SQL Tutorial
PostgreSQL
SQL / MySQL
MySQL Tutorial
VB.Net
VB.Net Tutorial
Flash / Flex / ActionScript
VBA / Excel / Access / Word
Microsoft Office PowerPoint 2007 Tutorial
Microsoft Office Excel 2007 Tutorial
Microsoft Office Word 2007 Tutorial
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:        }
w__w_w__.__j_av___a__2_s___.__c__o_m__ | Contact Us
Copyright 2003 - 08 Demo Source and Support. All rights reserved.
All other trademarks are property of their respective owners.