Source Code Cross Referenced for UberProperties.java in  » Template-Engine » ostermillerutils » com » Ostermiller » 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
Photoshop Tutorials
Maya Tutorials
Flash Tutorials
3ds-Max Tutorials
Illustrator Tutorials
GIMP Tutorials
C# / C Sharp
C# / CSharp Tutorial
C# / CSharp Open Source
ASP.Net
ASP.NET Tutorial
JavaScript DHTML
JavaScript Tutorial
JavaScript Reference
HTML / CSS
HTML CSS Reference
C / ANSI-C
C Tutorial
C++
C++ Tutorial
Ruby
PHP
Python
Python Tutorial
Python Open Source
SQL Server / T-SQL
SQL Server / T-SQL Tutorial
Oracle PL / SQL
Oracle PL/SQL Tutorial
PostgreSQL
SQL / MySQL
MySQL Tutorial
VB.Net
VB.Net Tutorial
Flash / Flex / ActionScript
VBA / Excel / Access / Word
XML
XML Tutorial
Microsoft Office PowerPoint 2007 Tutorial
Microsoft Office Excel 2007 Tutorial
Microsoft Office Word 2007 Tutorial
Java Source Code / Java Documentation » Template Engine » ostermillerutils » com.Ostermiller.util 
Source Cross Referenced  Class Diagram Java Document (Java Doc) 


0001:        /*
0002:         * Copyright (C) 2002-2007 Stephen Ostermiller
0003:         * http://ostermiller.org/contact.pl?regarding=Java+Utilities
0004:         *
0005:         * Copyright (C) 2003 Carlo Magnaghi <software at tecnosoft dot net>
0006:         *
0007:         * This program is free software; you can redistribute it and/or modify
0008:         * it under the terms of the GNU General Public License as published by
0009:         * the Free Software Foundation; either version 2 of the License, or
0010:         * (at your option) any later version.
0011:         *
0012:         * This program is distributed in the hope that it will be useful,
0013:         * but WITHOUT ANY WARRANTY; without even the implied warranty of
0014:         * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
0015:         * GNU General Public License for more details.
0016:         *
0017:         * See COPYING.TXT for details.
0018:         */
0019:        package com.Ostermiller.util;
0020:
0021:        import java.io.*;
0022:        import java.util.*;
0023:
0024:        /**
0025:         * The Properties class represents a persistent set of properties. The
0026:         * Properties can be saved to a stream or loaded from a stream. Each key and
0027:         * its corresponding value in the property list is a string.
0028:         * More information about this class is available from <a target="_top" href=
0029:         * "http://ostermiller.org/utils/UberProperties.html">ostermiller.org</a>.
0030:         * <p>
0031:         * A property list can contain another property list as its "defaults"; this
0032:         * second property list is searched if the property key is not found in the
0033:         * original property list.
0034:         * <p>
0035:         * When saving properties to a stream or loading them from a stream, the ISO
0036:         * 8859-1 character encoding is used. For characters that cannot be directly
0037:         * represented in this encoding, Unicode escapes are used; however, only a
0038:         * single 'u' character is allowed in an escape sequence. The native2ascii tool
0039:         * can be used to convert property files to and from other character encodings.
0040:         * <p>
0041:         * Unlike the java.util.Properties, UberProperties does not inherit from
0042:         * java.util.Hashtable, so Objects other than strings cannot be stored in it.
0043:         * Also, comments from a files are preserved, and there can be several
0044:         * properties for a given name.
0045:         * <p>
0046:         * This class is not synchronized, so it should not be used in a
0047:         * multi-threaded environment without external synchronization.
0048:         * <p>
0049:         * The file format that UberProperties uses is as follows:
0050:         * <blockquote>
0051:         * The file is assumed to be using the ISO 8859-1 character encoding. All of the
0052:         * comment lines (starting with a '#' or '!') at the beginning of the file before the
0053:         * first line that is not a comment, are the comment associated with the file.
0054:         * After that, each comment will be associated with the next property.  If there
0055:         * is more than one property with the same name, the first comment will be the
0056:         * only one that is loaded.
0057:         * <p>
0058:         * Every property occupies one line of the input stream. Each line is terminated
0059:         * by a line terminator (\n or \r or \r\n).
0060:         * <p>
0061:         * A line that contains only whitespace or whose first non-whitespace character
0062:         * is an ASCII # or ! is ignored (thus, # or ! indicate comment lines).
0063:         * <p>
0064:         * Every line other than a blank line or a comment line describes one property
0065:         * to be added to the table (except that if a line ends with \, then the
0066:         * following line, if it exists, is treated as a continuation line,
0067:         * as described below). The key consists of all the characters in the line
0068:         * starting with the first non-whitespace character and up to, but not
0069:         * including, the first ASCII =, :, or whitespace character. All of the key
0070:         * termination characters may be included in the key by preceding them with a \.
0071:         * Any whitespace after the key is skipped; if the first non-whitespace
0072:         * character after the key is = or :, then it is ignored and any whitespace
0073:         * characters after it are also skipped. All remaining characters on the line
0074:         * become part of the associated element string. Within the element string, the
0075:         * ASCII escape sequences \t, \n, \r, \\, \", \', \ (a backslash and a space),
0076:         * and \\uxxxx are recognized and converted to single characters. Moreover, if
0077: * the last character on the line is \, then the next line is treated as a
0078: * continuation of the current line; the \ and line terminator are simply
0079: * discarded, and any leading whitespace characters on the continuation line are
0080: * also discarded and are not part of the element string.
0081: * <p>
0082: * As an example, each of the following four lines specifies the key "Truth"
0083: * and the associated element value "Beauty":<br>
0084: * <pre>Truth = Beauty
0085: * 	   Truth:Beauty
0086: *   Truth			:Beauty</pre>
0087: * <p>
0088: * As another example, the following three lines specify a single property:<br>
0089: * <pre>fruits				apple, banana, pear, \
0090: *                                cantaloupe, watermelon, \
0091: *                                kiwi, mango</pre>
0092: * <p>
0093: * The key is "fruits" and the associated element is:<br>
0094: * "apple,&nbsp;banana,&nbsp;pear,&nbsp;cantaloupe,&nbsp;watermelon,&nbsp;kiwi,&nbsp;mango"<br>
0095: * Note that a space appears before each \ so that a space will appear after
0096: * each comma in the final result; the \, line terminator, and leading
0097: * whitespace on the continuation line are merely discarded and are not replaced
0098: * by one or more other characters.
0099: * <p>
0100: * As a third example, the line:<br>
0101: * cheeses<br>
0102: * specifies that the key is "cheeses" and the associated element is the empty
0103: * string.
0104: * </blockquote>
0105: *
0106: * @author Stephen Ostermiller http://ostermiller.org/contact.pl?regarding=Java+Utilities
0107: * @since ostermillerutils 1.00.00
0108: */
0109:        public class UberProperties {
0110:
0111:            /**
0112:             * A hash map that contains all the properties.
0113:             * This should never be null, but may be empty.
0114:             * This should hold objects of type Property.
0115:             *
0116:             * @since ostermillerutils 1.00.00
0117:             */
0118:            private HashMap<String, Property> properties = new HashMap<String, Property>();
0119:
0120:            /**
0121:             * Comment for this set of properties.
0122:             * This may be either null or empty.
0123:             *
0124:             * @since ostermillerutils 1.00.00
0125:             */
0126:            private String comment = null;
0127:
0128:            /**
0129:             * The object type that goes in the HashMap.
0130:             *
0131:             * @since ostermillerutils 1.00.00
0132:             */
0133:            private class Property {
0134:
0135:                /**
0136:                 * List of values for this property.
0137:                 * This should never be null or empty.
0138:                 *
0139:                 * @since ostermillerutils 1.00.00
0140:                 */
0141:                private ArrayList<String> list;
0142:
0143:                /**
0144:                 * Comment for this set of properties.
0145:                 * This may be either null or empty.
0146:                 *
0147:                 * @since ostermillerutils 1.00.00
0148:                 */
0149:                private String comment = null;
0150:
0151:                /**
0152:                 * Set the comment associated with this property.
0153:                 *
0154:                 * @param comment the comment for this property, or null to clear.
0155:                 *
0156:                 * @since ostermillerutils 1.00.00
0157:                 */
0158:                public void setComment(String comment) {
0159:                    this .comment = comment;
0160:                }
0161:
0162:                /**
0163:                 * Get the comment associated with this property.
0164:                 *
0165:                 * @return comment for this property, or null if none is set.
0166:                 *
0167:                 * @since ostermillerutils 1.00.00
0168:                 */
0169:                public String getComment() {
0170:                    return this .comment;
0171:                }
0172:
0173:                /**
0174:                 * Construct a new property with the given value.
0175:                 *
0176:                 * @param value initial value for this property.
0177:                 *
0178:                 * @since ostermillerutils 1.00.00
0179:                 */
0180:                public Property(String value) {
0181:                    list = new ArrayList<String>(1);
0182:                    add(value);
0183:                }
0184:
0185:                /**
0186:                 * Construct a new property with the given values.
0187:                 *
0188:                 * @param values initial values for this property.
0189:                 *
0190:                 * @since ostermillerutils 1.00.00
0191:                 */
0192:                public Property(String[] values) {
0193:                    list = new ArrayList<String>(values.length);
0194:                    add(values);
0195:                }
0196:
0197:                /**
0198:                 * Set this property to have this single value.
0199:                 *
0200:                 * @param value lone value for this property.
0201:                 *
0202:                 * @since ostermillerutils 1.00.00
0203:                 */
0204:                public void set(String value) {
0205:                    list.clear();
0206:                    add(value);
0207:                }
0208:
0209:                /**
0210:                 * Set this property to have only these values.
0211:                 *
0212:                 * @param values lone values for this property.
0213:                 *
0214:                 * @since ostermillerutils 1.00.00
0215:                 */
0216:                public void set(String[] values) {
0217:                    list.clear();
0218:                    add(values);
0219:                }
0220:
0221:                /**
0222:                 * Add this value to the list of values for this property.
0223:                 *
0224:                 * @param value another value for this property.
0225:                 *
0226:                 * @since ostermillerutils 1.00.00
0227:                 */
0228:                public void add(String value) {
0229:                    list.add(value);
0230:                }
0231:
0232:                /**
0233:                 * Add these values to the list of values for this property.
0234:                 *
0235:                 * @param values other values for this property.
0236:                 *
0237:                 * @since ostermillerutils 1.00.00
0238:                 */
0239:                public void add(String[] values) {
0240:                    list.ensureCapacity(list.size() + values.length);
0241:                    for (String element : values) {
0242:                        add(element);
0243:                    }
0244:                }
0245:
0246:                /**
0247:                 * Get the last value for this property.
0248:                 *
0249:                 * @return the last value.
0250:                 *
0251:                 * @since ostermillerutils 1.00.00
0252:                 */
0253:                public String getValue() {
0254:                    return list.get(list.size() - 1);
0255:                }
0256:
0257:                /**
0258:                 * Get all the values for this property.
0259:                 *
0260:                 * @return a list of all the values.
0261:                 *
0262:                 * @since ostermillerutils 1.00.00
0263:                 */
0264:                public String[] getValues() {
0265:                    return list.toArray(new String[list.size()]);
0266:                }
0267:            }
0268:
0269:            /**
0270:             * Creates an empty property list with no default values.
0271:             *
0272:             * @since ostermillerutils 1.00.00
0273:             */
0274:            public UberProperties() {
0275:                // Create empty properties
0276:            }
0277:
0278:            /**
0279:             * Creates an empty property list with the specified defaults.
0280:             *
0281:             * @param defaults the defaults.
0282:             * @throws NullPointerException if defaults is null.
0283:             *
0284:             * @since ostermillerutils 1.00.00
0285:             */
0286:            public UberProperties(UberProperties defaults) {
0287:                merge(defaults);
0288:            }
0289:
0290:            /**
0291:             * Put all the properties from the defaults in this.
0292:             * Calling this from a constructor will clone (deep)
0293:             * the default properties.
0294:             *
0295:             * @since ostermillerutils 1.00.00
0296:             */
0297:            private void merge(UberProperties defaults) {
0298:                setComment(defaults.getComment());
0299:                String[] names = defaults.propertyNames();
0300:                for (String element : names) {
0301:                    setProperties(element, defaults.getProperties(element));
0302:                    setComment(element, defaults.getComment(element));
0303:                }
0304:            }
0305:
0306:            /**
0307:             * Test to see if a property with the given name exists.
0308:             *
0309:             * @param name the name of the property.
0310:             * @return true if the property existed and was removed, false if it did not exist.
0311:             * @throws NullPointerException if name is null.
0312:             *
0313:             * @since ostermillerutils 1.00.00
0314:             */
0315:            public boolean contains(String name) {
0316:                if (name == null)
0317:                    throw new NullPointerException();
0318:                return properties.containsKey(name);
0319:            }
0320:
0321:            /**
0322:             * Remove any property with the given name.
0323:             *
0324:             * @param name the name of the property.
0325:             * @return true if the property existed and was removed, false if it did not exist.
0326:             * @throws NullPointerException if name is null.
0327:             *
0328:             * @since ostermillerutils 1.00.00
0329:             */
0330:            public boolean remove(String name) {
0331:                if (!contains(name))
0332:                    return false;
0333:                properties.remove(name);
0334:                return true;
0335:            }
0336:
0337:            /**
0338:             * Replaces all properties of the given name with
0339:             * a single property with the given value.
0340:             *
0341:             * @param name the name of the property.
0342:             * @param value the value of the property, or null to remove it.
0343:             * @throws NullPointerException if name is null.
0344:             *
0345:             * @since ostermillerutils 1.00.00
0346:             */
0347:            public void setProperty(String name, String value) {
0348:                if (name == null)
0349:                    throw new NullPointerException();
0350:                if (value == null) {
0351:                    properties.remove(name);
0352:                } else {
0353:                    Property property;
0354:                    if (properties.containsKey(name)) {
0355:                        property = properties.get(name);
0356:                        property.set(value);
0357:                    } else {
0358:                        property = new Property(value);
0359:                        properties.put(name, property);
0360:                    }
0361:                }
0362:            }
0363:
0364:            /**
0365:             * Replaces all properties of the given name with
0366:             * properties with the given values.
0367:             *
0368:             * @param name the name of the property.
0369:             * @param values for the property.
0370:             * @throws NullPointerException if name is null.
0371:             * @throws NullPointerException if values is null.
0372:             * @throws IllegalArgumentException if values is empty.
0373:             *
0374:             * @since ostermillerutils 1.00.00
0375:             */
0376:            public void setProperties(String name, String[] values) {
0377:                if (name == null)
0378:                    throw new NullPointerException();
0379:                if (values.length == 0)
0380:                    throw new IllegalArgumentException();
0381:                Property property;
0382:                if (properties.containsKey(name)) {
0383:                    property = properties.get(name);
0384:                    property.set(values);
0385:                } else {
0386:                    property = new Property(values);
0387:                    properties.put(name, property);
0388:                }
0389:            }
0390:
0391:            /**
0392:             * Replaces all properties of the given name with
0393:             * a single property with the given value.
0394:             *
0395:             * @param name the name of the property.
0396:             * @param value the value of the property or null to remove it.
0397:             * @param comment the comment for the property, or null to remove it.
0398:             * @throws NullPointerException if name is null.
0399:             * @throws NullPointerException if comment is null.
0400:             *
0401:             * @since ostermillerutils 1.00.00
0402:             */
0403:            public void setProperty(String name, String value, String comment) {
0404:                if (name == null)
0405:                    throw new NullPointerException();
0406:                if (value == null) {
0407:                    properties.remove(name);
0408:                } else {
0409:                    setProperty(name, value);
0410:                    setComment(name, comment);
0411:                }
0412:            }
0413:
0414:            /**
0415:             * Replaces all properties of the given name with
0416:             * properties with the given values.
0417:             *
0418:             * @param name the name of the property.
0419:             * @param values value of the property.
0420:             * @param comment the comment for the property, or null to remove it.
0421:             * @throws NullPointerException if name is null.
0422:             * @throws NullPointerException if values is null.
0423:             * @throws IllegalArgumentException if values is empty.
0424:             *
0425:             * @since ostermillerutils 1.00.00
0426:             */
0427:            public void setProperties(String name, String[] values,
0428:                    String comment) {
0429:                if (name == null)
0430:                    throw new NullPointerException();
0431:                if (values.length == 0)
0432:                    throw new IllegalArgumentException();
0433:                setProperties(name, values);
0434:                setComment(name, comment);
0435:            }
0436:
0437:            /**
0438:             * Set the comment on the property of the given name.
0439:             * The property must exist before this method is called.
0440:             *
0441:             * @param name the name of the property.
0442:             * @param comment the comment for the property.
0443:             * @param comment the comment for the property, or null to remove it.
0444:             * @throws NullPointerException if name is null.
0445:             * @throws IllegalArgumentException if name is not a known key.
0446:             *
0447:             * @since ostermillerutils 1.00.00
0448:             */
0449:            private void setComment(String name, String comment) {
0450:                if (name == null)
0451:                    throw new NullPointerException();
0452:                if (!properties.containsKey(name))
0453:                    throw new IllegalArgumentException();
0454:                (properties.get(name)).setComment(comment);
0455:            }
0456:
0457:            /**
0458:             * Adds a value to the list of properties with the
0459:             * given name.
0460:             *
0461:             * @param name the name of the property.
0462:             * @param value the values for the property, or null to remove.
0463:             * @param comment the comment for the property, or null to remove it.
0464:             * @throws NullPointerException if name is null.
0465:             * @throws NullPointerException if value is null.
0466:             *
0467:             * @since ostermillerutils 1.00.00
0468:             */
0469:            public void addProperty(String name, String value, String comment) {
0470:                if (name == null)
0471:                    throw new NullPointerException();
0472:                if (value == null)
0473:                    throw new NullPointerException();
0474:                addProperty(name, value);
0475:                setComment(name, comment);
0476:            }
0477:
0478:            /**
0479:             * Adds the values to the list of properties with the
0480:             * given name.
0481:             *
0482:             * @param name the name of the property.
0483:             * @param values the values for the property.
0484:             * @param comment the comment for the property, or null to remove it.
0485:             * @throws NullPointerException if name is null.
0486:             * @throws NullPointerException if values is null.
0487:             *
0488:             * @since ostermillerutils 1.00.00
0489:             */
0490:            public void addProperties(String name, String[] values,
0491:                    String comment) {
0492:                if (name == null)
0493:                    throw new NullPointerException();
0494:                if (values == null)
0495:                    throw new NullPointerException();
0496:                addProperties(name, values);
0497:                setComment(name, comment);
0498:            }
0499:
0500:            /**
0501:             * Adds a value to the list of properties with the
0502:             * given name.
0503:             *
0504:             * @param name the name of the property.
0505:             * @param value the values for the property.
0506:             * @throws NullPointerException if name is null.
0507:             * @throws NullPointerException if value is null.
0508:             *
0509:             * @since ostermillerutils 1.00.00
0510:             */
0511:            public void addProperty(String name, String value) {
0512:                if (name == null)
0513:                    throw new NullPointerException();
0514:                if (value == null)
0515:                    throw new NullPointerException();
0516:                Property property;
0517:                if (properties.containsKey(name)) {
0518:                    property = properties.get(name);
0519:                    property.add(value);
0520:                } else {
0521:                    property = new Property(value);
0522:                    properties.put(name, property);
0523:                }
0524:            }
0525:
0526:            /**
0527:             * Adds the values to the list of properties with the
0528:             * given name.
0529:             *
0530:             * @param name the name of the property.
0531:             * @param values the values for the property.
0532:             * @throws NullPointerException if name is null.
0533:             * @throws NullPointerException if values is null.
0534:             *
0535:             * @since ostermillerutils 1.00.00
0536:             */
0537:            public void addProperties(String name, String[] values) {
0538:                if (name == null)
0539:                    throw new NullPointerException();
0540:                if (values == null)
0541:                    throw new NullPointerException();
0542:                Property property;
0543:                if (properties.containsKey(name)) {
0544:                    property = properties.get(name);
0545:                    property.add(values);
0546:                } else {
0547:                    property = new Property(values);
0548:                    properties.put(name, property);
0549:                }
0550:            }
0551:
0552:            private static int hexDigitValue(char c) {
0553:                switch (c) {
0554:                case '0':
0555:                    return 0;
0556:                case '1':
0557:                    return 1;
0558:                case '2':
0559:                    return 2;
0560:                case '3':
0561:                    return 3;
0562:                case '4':
0563:                    return 4;
0564:                case '5':
0565:                    return 5;
0566:                case '6':
0567:                    return 6;
0568:                case '7':
0569:                    return 7;
0570:                case '8':
0571:                    return 8;
0572:                case '9':
0573:                    return 9;
0574:                case 'a':
0575:                case 'A':
0576:                    return 10;
0577:                case 'b':
0578:                case 'B':
0579:                    return 11;
0580:                case 'c':
0581:                case 'C':
0582:                    return 12;
0583:                case 'd':
0584:                case 'D':
0585:                    return 13;
0586:                case 'e':
0587:                case 'E':
0588:                    return 14;
0589:                case 'f':
0590:                case 'F':
0591:                    return 15;
0592:                default:
0593:                    return -1;
0594:                }
0595:            }
0596:
0597:            private static String unescape(String s) {
0598:                StringBuffer sb = new StringBuffer(s.length());
0599:                for (int i = 0; i < s.length(); i++) {
0600:                    char c = s.charAt(i);
0601:                    if (c == '\\') {
0602:                        i++;
0603:                        if (i < s.length()) {
0604:                            c = s.charAt(i);
0605:                            switch (c) {
0606:                            case 'n': {
0607:                                sb.append('\n');
0608:                            }
0609:                                break;
0610:                            case 'r': {
0611:                                sb.append('\r');
0612:                            }
0613:                                break;
0614:                            case 't': {
0615:                                sb.append('\t');
0616:                            }
0617:                                break;
0618:                            case 'f': {
0619:                                sb.append('\f');
0620:                            }
0621:                                break;
0622:                            case 'u': {
0623:                                boolean foundUnicode = false;
0624:                                if (i + 4 < s.length()) {
0625:                                    int unicodeValue = 0;
0626:                                    for (int j = 3; unicodeValue >= 0 && j >= 0; j--) {
0627:                                        int val = hexDigitValue(s.charAt(i
0628:                                                + (4 - j)));
0629:                                        if (val == -1) {
0630:                                            unicodeValue = -1;
0631:                                        } else {
0632:                                            unicodeValue |= (val << (j << 2));
0633:                                        }
0634:                                    }
0635:                                    if (unicodeValue >= 0) {
0636:                                        i += 4;
0637:                                        foundUnicode = true;
0638:                                        sb.append((char) unicodeValue);
0639:                                    }
0640:                                }
0641:                                if (!foundUnicode)
0642:                                    sb.append(c);
0643:                            }
0644:                                break;
0645:                            default: {
0646:                                sb.append(c);
0647:                            }
0648:                                break;
0649:                            }
0650:                        }
0651:                    } else {
0652:                        sb.append(c);
0653:                    }
0654:                }
0655:                return sb.toString();
0656:            }
0657:
0658:            /**
0659:             * Load these properties from a user file with default properties
0660:             * from a system resource.
0661:             * <p>
0662:             * Example:
0663:             * <pre>load(
0664:             *     new String(){".java","tld","company","package","component.properties"}
0665:             *     "tld/company/package/component.properties",
0666:             * )</pre>
0667:             * This will load the properties file relative to the classpath as the
0668:             * defaults and the file &lt;%userhome%&gt;/.java/tld/company/package/component.properties
0669:             * if the file exists.  The .java directory is recommended as it is a common,
0670:             * possibly hidden, directory in the users home directory commonly used by
0671:             * Java programs.
0672:             *
0673:             * This method is meant to be used with the save(String systemResource) method
0674:             * which will save modified properties back to the user directory.
0675:             *
0676:             * @param userFile array of Strings representing a path and file name relative to the user home directory.
0677:             * @param systemResource name relative to classpath of default properties, or null to ignore.
0678:             * @throws IOException if an error occurs when reading.
0679:             * @throws NullPointerException if userFile is null.
0680:             * @throws IllegalArgumentException if userFile is empty.
0681:             *
0682:             * @since ostermillerutils 1.00.00
0683:             */
0684:            public void load(String[] userFile, String systemResource)
0685:                    throws IOException {
0686:                int length = userFile.length;
0687:                if (userFile.length == 0)
0688:                    throw new IllegalArgumentException();
0689:                InputStream in = ClassLoader
0690:                        .getSystemResourceAsStream(systemResource);
0691:                if (in == null)
0692:                    throw new FileNotFoundException(systemResource);
0693:                if (systemResource != null)
0694:                    load(in);
0695:                File f = new File(System.getProperty("user.home"));
0696:                for (int i = 0; f.exists() && i < length; i++) {
0697:                    f = new File(f, userFile[i]);
0698:                }
0699:                if (f.exists())
0700:                    load(new FileInputStream(f));
0701:            }
0702:
0703:            /**
0704:             * Add the properties from the input stream to this
0705:             * UberProperties.
0706:             *
0707:             * @param in InputStream containing properties.
0708:             * @param add whether parameters should add to parameters with the same name or replace them.
0709:             * @throws IOException if an error occurs when reading.
0710:             *
0711:             * @since ostermillerutils 1.00.00
0712:             */
0713:            public void load(InputStream in, boolean add) throws IOException {
0714:                PropertiesLexer lex = new PropertiesLexer(
0715:                        new InputStreamReader(in, "ISO-8859-1"));
0716:                PropertiesToken t;
0717:                HashSet<String> names = new HashSet<String>();
0718:                StringBuffer comment = new StringBuffer();
0719:                boolean foundComment = false;
0720:                StringBuffer name = new StringBuffer();
0721:                StringBuffer value = new StringBuffer();
0722:                boolean atStart = true;
0723:                String lastSeparator = null;
0724:                while ((t = lex.getNextToken()) != null) {
0725:                    if (t.getID() == PropertiesToken.COMMENT) {
0726:                        int start = 1;
0727:                        String commentText = t.getContents();
0728:                        if (commentText.startsWith("# "))
0729:                            start = 2;
0730:                        comment.append(commentText.substring(start, commentText
0731:                                .length()));
0732:                        comment.append("\n");
0733:                        lex.getNextToken();
0734:                        foundComment = true;
0735:                    } else if (t.getID() == PropertiesToken.NAME) {
0736:                        if (atStart) {
0737:                            setComment(comment.toString());
0738:                            comment.setLength(0);
0739:                            atStart = false;
0740:                        }
0741:                        name.append(t.getContents());
0742:                    } else if (t.getID() == PropertiesToken.VALUE) {
0743:                        if (atStart) {
0744:                            setComment(comment.toString());
0745:                            comment.setLength(0);
0746:                            atStart = false;
0747:                        }
0748:                        value.append(t.getContents());
0749:                    } else if (t.getID() == PropertiesToken.SEPARATOR) {
0750:                        lastSeparator = t.getContents();
0751:                    } else if (t.getID() == PropertiesToken.END_LINE_WHITE_SPACE) {
0752:                        if (atStart) {
0753:                            setComment(comment.toString());
0754:                            comment.setLength(0);
0755:                            atStart = false;
0756:                        }
0757:                        String stName = unescape(name.toString());
0758:                        String stValue = unescape(value.toString());
0759:                        if (lastSeparator != null || stName.length() > 0
0760:                                || stValue.length() > 0) {
0761:                            if (add || names.contains(stName)) {
0762:                                addProperty(stName, stValue);
0763:                            } else {
0764:                                setProperty(stName, stValue);
0765:                                names.add(stName);
0766:                            }
0767:                            if (foundComment)
0768:                                setComment(stName, unescape(comment.toString()));
0769:                        }
0770:                        comment.setLength(0);
0771:                        name.setLength(0);
0772:                        value.setLength(0);
0773:                        foundComment = false;
0774:                        lastSeparator = null;
0775:                    }
0776:                }
0777:            }
0778:
0779:            /**
0780:             * Add the properties from the input stream to this
0781:             * UberProperties.
0782:             * <p>
0783:             * Properties that are found replace any properties that
0784:             * were there before.
0785:             *
0786:             * @param in InputStream containing properties.
0787:             * @throws IOException if an error occurs when reading.
0788:             *
0789:             * @since ostermillerutils 1.00.00
0790:             */
0791:            public void load(InputStream in) throws IOException {
0792:                load(in, false);
0793:            }
0794:
0795:            /**
0796:             * Save these properties from a user file.
0797:             * <p>
0798:             * Example:
0799:             * <pre>save(
0800:             *     new String(){"tld","company","package","component.properties"}
0801:             * )</pre>
0802:             * This will save the properties file relative to the user directory:
0803:             * &lt;%userhome%&gt;/tld/company/package/component.properties
0804:             * Directories will be created as needed.
0805:             *
0806:             * @param userFile array of Strings representing a path and file name relative to the user home directory.
0807:             * @throws IOException if an error occurs when reading.
0808:             * @throws NullPointerException if userFile is null.
0809:             * @throws IllegalArgumentException if userFile is empty.
0810:             *
0811:             * @since ostermillerutils 1.00.00
0812:             */
0813:            public void save(String[] userFile) throws IOException {
0814:                int length = userFile.length;
0815:                if (length == 0)
0816:                    throw new IllegalArgumentException();
0817:                File f = new File(System.getProperty("user.home"));
0818:                for (int i = 0; i < length; i++) {
0819:                    f = new File(f, userFile[i]);
0820:                    if (i == length - 2 && !f.exists()) {
0821:                        f.mkdirs();
0822:                    }
0823:                }
0824:                OutputStream out = new FileOutputStream(f);
0825:                save(out);
0826:                out.close();
0827:            }
0828:
0829:            /**
0830:             * Save these properties to the given stream.
0831:             *
0832:             * @param out OutputStream to which these properties should be written.
0833:             * @throws IOException if an error occurs when writing.
0834:             *
0835:             * @since ostermillerutils 1.00.00
0836:             */
0837:            public void save(OutputStream out) throws IOException {
0838:                writeComment(out, comment);
0839:                out.write('\n');
0840:                String[] names = propertyNames();
0841:                Arrays.sort(names);
0842:                for (String element : names) {
0843:                    writeComment(out, getComment(element));
0844:                    String[] values = getProperties(element);
0845:                    for (String element2 : values) {
0846:                        writeProperty(out, element, element2);
0847:                    }
0848:                }
0849:                out.flush();
0850:            }
0851:
0852:            private static void writeProperty(OutputStream out, String name,
0853:                    String value) throws IOException {
0854:                writeEscapedISO88591(out, name, TYPE_NAME);
0855:                out.write('=');
0856:                writeEscapedISO88591(out, value, TYPE_VALUE);
0857:                out.write('\n');
0858:
0859:            }
0860:
0861:            private static void writeComment(OutputStream out, String comment)
0862:                    throws IOException {
0863:                if (comment != null) {
0864:                    java.util.StringTokenizer tok = new java.util.StringTokenizer(
0865:                            comment, "\r\n");
0866:                    while (tok.hasMoreTokens()) {
0867:                        out.write('#');
0868:                        out.write(' ');
0869:                        writeEscapedISO88591(out, tok.nextToken(), TYPE_COMMENT);
0870:                        out.write('\n');
0871:                    }
0872:                }
0873:            }
0874:
0875:            private static final int TYPE_COMMENT = 0;
0876:            private static final int TYPE_NAME = 1;
0877:            private static final int TYPE_VALUE = 2;
0878:
0879:            private static void writeEscapedISO88591(OutputStream out,
0880:                    String s, int type) throws IOException {
0881:                for (int i = 0; i < s.length(); i++) {
0882:                    int c = s.charAt(i);
0883:                    if (c < 0x100) {
0884:                        boolean escape = false;
0885:                        if (c == '\r' || c == '\n' || c == '\\') {
0886:                            escape = true;
0887:                        } else if (c == ' ' || c == '\t' || c == '\f') {
0888:                            if (type == TYPE_NAME) {
0889:                                escape = true;
0890:                            } else if (type == TYPE_VALUE
0891:                                    && (i == 0 || i == s.length() - 1)) {
0892:                                escape = true;
0893:                            }
0894:                        } else if (type == TYPE_NAME && (c == '=' || c == ':')) {
0895:                            escape = true;
0896:                        }
0897:                        if (escape) {
0898:                            switch (c) {
0899:                            case '\n': {
0900:                                switch (type) {
0901:                                case TYPE_COMMENT: {
0902:                                    out.write('\n');
0903:                                    out.write('#');
0904:                                    out.write(' ');
0905:                                }
0906:                                    break;
0907:                                case TYPE_NAME: {
0908:                                    out.write('\\');
0909:                                    out.write('n');
0910:                                    out.write('\\');
0911:                                    out.write('\n');
0912:                                    out.write('\t');
0913:                                }
0914:                                    break;
0915:                                case TYPE_VALUE: {
0916:                                    out.write('\\');
0917:                                    out.write('n');
0918:                                    out.write('\\');
0919:                                    out.write('\n');
0920:                                    out.write('\t');
0921:                                    out.write('\t');
0922:                                }
0923:                                    break;
0924:                                }
0925:                            }
0926:                                break;
0927:                            case '\\': {
0928:                                out.write('\\');
0929:                                out.write('\\');
0930:                            }
0931:                                break;
0932:                            case '\r': {
0933:                                out.write('\\');
0934:                                out.write('r');
0935:                            }
0936:                                break;
0937:                            case '\t': {
0938:                                out.write('\\');
0939:                                out.write('t');
0940:                            }
0941:                                break;
0942:                            case '\f': {
0943:                                out.write('\\');
0944:                                out.write('f');
0945:                            }
0946:                                break;
0947:                            default: {
0948:                                out.write('\\');
0949:                                out.write((byte) c);
0950:                            }
0951:                                break;
0952:                            }
0953:                        } else {
0954:                            out.write((byte) c);
0955:                        }
0956:                    } else {
0957:                        out.write('\\');
0958:                        out.write('u');
0959:                        out.write(StringHelper.prepad(Integer.toHexString(c),
0960:                                4, '0').getBytes("ISO-8859-1"));
0961:                    }
0962:                }
0963:            }
0964:
0965:            /**
0966:             * Get the first property with the given name.
0967:             * If the property is not specified in this UberProperties
0968:             * but it is in the default UberProperties, the default is
0969:             * used.  If no default is found, null is returned.
0970:             *
0971:             * @param name Parameter name
0972:             * @return the first value of this property, or null if the property does not exist.
0973:             *
0974:             * @since ostermillerutils 1.00.00
0975:             */
0976:            public String getProperty(String name) {
0977:                String value = null;
0978:                if (properties.containsKey(name)) {
0979:                    value = (properties.get(name)).getValue();
0980:                }
0981:                return value;
0982:            }
0983:
0984:            /**
0985:             * Get the first property with the given name.
0986:             * If the property is not specified in this UberProperties
0987:             * but it is in the default UberProperties, the default
0988:             * UberProperties is consulted, otherwise, the supplied
0989:             * default is used.
0990:             *
0991:             * @param name Parameter name
0992:             * @param defaultValue Value to use when property not present
0993:             * @return the first value of this property.
0994:             *
0995:             * @since ostermillerutils 1.00.00
0996:             */
0997:            public String getProperty(String name, String defaultValue) {
0998:                String value = getProperty(name);
0999:                if (value == null)
1000:                    value = defaultValue;
1001:                return value;
1002:            }
1003:
1004:            /**
1005:             * Get the values for a property.
1006:             * Properties returned in the same order in which
1007:             * they were added.
1008:             * <p>
1009:             * If the property is not specified in this UberProperties
1010:             * but it is in the default UberProperties, the default is
1011:             * used.  If no default is found, null is returned.
1012:             *
1013:             * @param name Parameter name
1014:             * @return all the values associated with the given key, or null if the property does not exist.
1015:             *
1016:             * @since ostermillerutils 1.00.00
1017:             */
1018:            public String[] getProperties(String name) {
1019:                String[] values = null;
1020:                if (properties.containsKey(name)) {
1021:                    values = (properties.get(name)).getValues();
1022:                }
1023:                return values;
1024:            }
1025:
1026:            /**
1027:             * Get the values for a property.
1028:             * Properties returned in the same order in which
1029:             * they were added.
1030:             * <p>
1031:             * If the property is not specified in this UberProperties
1032:             * but it is in the default UberProperties, the default
1033:             * UberProperties is consulted, otherwise, the supplied
1034:             * defaults are used.
1035:             *
1036:             * @param name Parameter name
1037:             * @param defaultValues Values to use when property not present
1038:             * @return all the values associated with the given key, or null if the property does not exist.
1039:             *
1040:             * @since ostermillerutils 1.00.00
1041:             */
1042:            public String[] getProperties(String name, String[] defaultValues) {
1043:                String[] values = getProperties(name);
1044:                if (values == null)
1045:                    values = defaultValues;
1046:                return values;
1047:            }
1048:
1049:            /**
1050:             * Get the comment associated with this property.
1051:             * <p>
1052:             * If the property is not specified in this UberProperties
1053:             * but it is in the default UberProperties, the default is
1054:             * used.  If no default is found, null is returned.
1055:             *
1056:             * @param name Parameter name
1057:             * @return the comment for this property, or null if there is no comment or the property does not exist.
1058:             *
1059:             * @since ostermillerutils 1.00.00
1060:             */
1061:            public String getComment(String name) {
1062:                String comment = null;
1063:                if (properties.containsKey(name)) {
1064:                    comment = (properties.get(name)).getComment();
1065:                }
1066:                return comment;
1067:            }
1068:
1069:            /**
1070:             * Returns an enumeration of all the keys in this property list, including
1071:             * distinct keys in the default property list if a key of the same name has
1072:             * not already been found from the main properties list.
1073:             *
1074:             * @return an enumeration of all the keys in this property list, including the keys in the default property list.
1075:             *
1076:             * @since ostermillerutils 1.00.00
1077:             */
1078:            public String[] propertyNames() {
1079:                Set<String> names = properties.keySet();
1080:                return names.toArray(new String[names.size()]);
1081:            }
1082:
1083:            /**
1084:             * Set the comment associated with this set of properties.
1085:             *
1086:             * @param comment the comment for entire set of properties, or null to clear.
1087:             *
1088:             * @since ostermillerutils 1.00.00
1089:             */
1090:            public void setComment(String comment) {
1091:                this .comment = comment;
1092:            }
1093:
1094:            /**
1095:             * Get the comment associated with this set of properties.
1096:             *
1097:             * @return comment for entire set of properties, or null if there is no comment.
1098:             *
1099:             * @since ostermillerutils 1.00.00
1100:             */
1101:            public String getComment() {
1102:                return this .comment;
1103:            }
1104:
1105:            /**
1106:             * Get the number of unique names for properties stored
1107:             * in this UberProperties.
1108:             *
1109:             * @return number of names.
1110:             *
1111:             * @since ostermillerutils 1.00.00
1112:             */
1113:            public int getPropertyNameCount() {
1114:                return properties.keySet().size();
1115:            }
1116:
1117:            /**
1118:             * Save these properties to a string.
1119:             *
1120:             * @return Serialized String version of these properties.
1121:             *
1122:             * @since ostermillerutils 1.02.23
1123:             */
1124:            @Override
1125:            public String toString() {
1126:                ByteArrayOutputStream out = new ByteArrayOutputStream();
1127:                try {
1128:                    this .save(out);
1129:                } catch (IOException iox) {
1130:                    throw new Error(
1131:                            "IO constructed on memory, this shouldn't happen.",
1132:                            iox);
1133:                }
1134:                String s = null;
1135:                try {
1136:                    s = new String(out.toByteArray(), "ISO-8859-1");
1137:                } catch (UnsupportedEncodingException uee) {
1138:                    throw new Error("ISO-8859-1 should be recognized.", uee);
1139:                }
1140:                return s;
1141:            }
1142:        }
www.java2java.com | Contact Us
Copyright 2009 - 12 Demo Source and Support. All rights reserved.
All other trademarks are property of their respective owners.