Source Code Cross Referenced for SuperProperties.java in  » J2EE » openejb3 » org » apache » openejb » 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 » J2EE » openejb3 » org.apache.openejb.util 
Source Cross Referenced  Class Diagram Java Document (Java Doc) 


0001:        /**
0002:         *
0003:         * Licensed to the Apache Software Foundation (ASF) under one or more
0004:         * contributor license agreements.  See the NOTICE file distributed with
0005:         * this work for additional information regarding copyright ownership.
0006:         * The ASF licenses this file to You under the Apache License, Version 2.0
0007:         * (the "License"); you may not use this file except in compliance with
0008:         * the License.  You may obtain a copy of the License at
0009:         *
0010:         *     http://www.apache.org/licenses/LICENSE-2.0
0011:         *
0012:         *  Unless required by applicable law or agreed to in writing, software
0013:         *  distributed under the License is distributed on an "AS IS" BASIS,
0014:         *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
0015:         *  See the License for the specific language governing permissions and
0016:         *  limitations under the License.
0017:         */package org.apache.openejb.util;
0018:
0019:        import java.io.ByteArrayInputStream;
0020:        import java.io.IOException;
0021:        import java.io.InputStream;
0022:        import java.io.OutputStream;
0023:        import java.io.OutputStreamWriter;
0024:        import java.io.PrintStream;
0025:        import java.io.PrintWriter;
0026:        import java.io.StringReader;
0027:        import java.util.Arrays;
0028:        import java.util.Collection;
0029:        import java.util.Collections;
0030:        import java.util.Enumeration;
0031:        import java.util.Hashtable;
0032:        import java.util.InvalidPropertiesFormatException;
0033:        import java.util.LinkedHashMap;
0034:        import java.util.Map;
0035:        import java.util.Properties;
0036:        import java.util.Set;
0037:        import javax.xml.parsers.DocumentBuilder;
0038:        import javax.xml.parsers.DocumentBuilderFactory;
0039:        import javax.xml.parsers.ParserConfigurationException;
0040:
0041:        import org.w3c.dom.Comment;
0042:        import org.w3c.dom.Document;
0043:        import org.w3c.dom.Element;
0044:        import org.w3c.dom.Node;
0045:        import org.w3c.dom.NodeList;
0046:        import org.xml.sax.EntityResolver;
0047:        import org.xml.sax.ErrorHandler;
0048:        import org.xml.sax.InputSource;
0049:        import org.xml.sax.SAXException;
0050:        import org.xml.sax.SAXParseException;
0051:
0052:        /**
0053:         * Properties is a Hashtable where the keys and values must be Strings. Each Properties can have a default
0054:         * Properties which specifies the default values which are used if the key is not in this Properties.
0055:         *
0056:         * @see Hashtable
0057:         * @see java.lang.System#getProperties
0058:         */
0059:        public class SuperProperties extends Properties {
0060:
0061:            private static final String PROP_DTD_NAME = "http://java.sun.com/dtd/properties.dtd";
0062:
0063:            private static final String PROP_DTD = "<?xml version=\"1.0\" encoding=\"UTF-8\"?>"
0064:                    + "    <!ELEMENT properties (comment?, entry*) >"
0065:                    + "    <!ATTLIST properties version CDATA #FIXED \"1.0\" >"
0066:                    + "    <!ELEMENT comment (#PCDATA) >"
0067:                    + "    <!ELEMENT entry (#PCDATA) >"
0068:                    + "    <!ATTLIST entry key CDATA #REQUIRED >";
0069:
0070:            /**
0071:             * Actual property values.
0072:             */
0073:            protected LinkedHashMap<Object, Object> properties = new LinkedHashMap<Object, Object>();
0074:
0075:            /**
0076:             * Comments for the properties.
0077:             */
0078:            protected LinkedHashMap<String, String> comments = new LinkedHashMap<String, String>();
0079:
0080:            /**
0081:             * Attributes for the properties.
0082:             */
0083:            protected LinkedHashMap<String, LinkedHashMap<String, String>> attributes = new LinkedHashMap<String, LinkedHashMap<String, String>>();
0084:
0085:            /**
0086:             * The default property values.
0087:             */
0088:            protected Properties defaults;
0089:
0090:            /**
0091:             * Are lookups case insensitive?
0092:             */
0093:            protected boolean caseInsensitive;
0094:
0095:            /**
0096:             * The text between a key and the value.
0097:             */
0098:            protected String keyValueSeparator = "=";
0099:
0100:            /**
0101:             * The line separator to use when storing.  Defaults to system line separator.
0102:             */
0103:            protected String lineSeparator = System
0104:                    .getProperty("line.separator");
0105:
0106:            /**
0107:             * Number of spaces to indent each line of the properties file.
0108:             */
0109:            protected String indent = "";
0110:
0111:            /**
0112:             * Number of spaces to indent comment after '#' character.
0113:             */
0114:            protected String commentIndent = " ";
0115:
0116:            /**
0117:             * Should there be a blank line between properties.
0118:             */
0119:            protected boolean spaceBetweenProperties = true;
0120:
0121:            /**
0122:             * Should there be a blank line between a comment and the property.
0123:             */
0124:            protected boolean spaceAfterComment = false;
0125:
0126:            /**
0127:             * Used for loadFromXML.
0128:             */
0129:            private DocumentBuilder builder = null;
0130:
0131:            /**
0132:             * Constructs a new Properties object.
0133:             */
0134:            public SuperProperties() {
0135:                super ();
0136:            }
0137:
0138:            /**
0139:             * Constructs a new Properties object using the specified default properties.
0140:             *
0141:             * @param properties the default properties
0142:             */
0143:            public SuperProperties(Properties properties) {
0144:                super (properties);
0145:                defaults = properties;
0146:            }
0147:
0148:            /**
0149:             * Are lookups case insensitive?
0150:             * @return true if lookups are insensitive
0151:             */
0152:            public boolean isCaseInsensitive() {
0153:                return caseInsensitive;
0154:            }
0155:
0156:            /**
0157:             * Sets the sensitive of lookups.
0158:             * @param caseInsensitive if looks are insensitive
0159:             */
0160:            public void setCaseInsensitive(boolean caseInsensitive) {
0161:                this .caseInsensitive = caseInsensitive;
0162:            }
0163:
0164:            /**
0165:             * Gets the text that separates keys and values.
0166:             * The default is "=".
0167:             * @return the text that separates keys and values
0168:             */
0169:            public String getKeyValueSeparator() {
0170:                return keyValueSeparator;
0171:            }
0172:
0173:            /**
0174:             * Sets the text that separates keys and values.
0175:             * @param keyValueSeparator the text that separates keys and values
0176:             */
0177:            public void setKeyValueSeparator(String keyValueSeparator) {
0178:                if (keyValueSeparator == null)
0179:                    throw new NullPointerException("keyValueSeparator is null");
0180:                if (keyValueSeparator.length() == 0)
0181:                    throw new NullPointerException("keyValueSeparator is empty");
0182:                this .keyValueSeparator = keyValueSeparator;
0183:            }
0184:
0185:            /**
0186:             * Gets the text that separates lines while storing.
0187:             * The default is the system line.separator.
0188:             * @return the text that separates keys and values
0189:             */
0190:            public String getLineSeparator() {
0191:                return lineSeparator;
0192:            }
0193:
0194:            /**
0195:             * Sets the text that separates lines while storing
0196:             * @param lineSeparator the text that separates lines
0197:             */
0198:            public void setLineSeparator(String lineSeparator) {
0199:                if (lineSeparator == null)
0200:                    throw new NullPointerException("lineSeparator is null");
0201:                if (lineSeparator.length() == 0)
0202:                    throw new NullPointerException("lineSeparator is empty");
0203:                this .lineSeparator = lineSeparator;
0204:            }
0205:
0206:            /**
0207:             * Gets the number of spaces to indent each line of the properties file.
0208:             * @return the number of spaces to indent each line of the properties file
0209:             */
0210:            public int getIndent() {
0211:                return indent.length();
0212:            }
0213:
0214:            /**
0215:             * Sets the number of spaces to indent each line of the properties file.
0216:             * @param  indent the number of spaces to indent each line of the properties file
0217:             */
0218:            public void setIndent(int indent) {
0219:                char[] chars = new char[indent];
0220:                Arrays.fill(chars, ' ');
0221:                this .indent = new String(chars);
0222:            }
0223:
0224:            /**
0225:             * Gets the number of spaces to indent comment after '#' character.
0226:             * @return the number of spaces to indent comment after '#' character
0227:             */
0228:            public int getCommentIndent() {
0229:                return commentIndent.length();
0230:            }
0231:
0232:            /**
0233:             * Sets the number of spaces to indent comment after '#' character.
0234:             * @param commentIndent the number of spaces to indent comment after '#' character
0235:             */
0236:            public void setCommentIndent(int commentIndent) {
0237:                char[] chars = new char[commentIndent];
0238:                Arrays.fill(chars, ' ');
0239:                this .commentIndent = new String(chars);
0240:            }
0241:
0242:            /**
0243:             * Should a blank line be added between properties?
0244:             * @return true if a blank line should be added between properties; false otherwise
0245:             */
0246:            public boolean isSpaceBetweenProperties() {
0247:                return spaceBetweenProperties;
0248:            }
0249:
0250:            /**
0251:             * If true a blank line will be added between properties.
0252:             * @param spaceBetweenProperties if true a blank line will be added between properties
0253:             */
0254:            public void setSpaceBetweenProperties(boolean spaceBetweenProperties) {
0255:                this .spaceBetweenProperties = spaceBetweenProperties;
0256:            }
0257:
0258:            /**
0259:             * Should there be a blank line between a comment and the property?
0260:             * @return true if a blank line should be added between a comment and the property
0261:             */
0262:            public boolean isSpaceAfterComment() {
0263:                return spaceAfterComment;
0264:            }
0265:
0266:            /**
0267:             * If true a blank line will be added between a comment and the property.
0268:             * @param spaceAfterComment if true a blank line will be added between a comment and the property
0269:             */
0270:            public void setSpaceAfterComment(boolean spaceAfterComment) {
0271:                this .spaceAfterComment = spaceAfterComment;
0272:            }
0273:
0274:            public String getProperty(String name) {
0275:                Object result = get(name);
0276:                String property = result instanceof  String ? (String) result
0277:                        : null;
0278:                if (property == null && defaults != null) {
0279:                    property = defaults.getProperty(name);
0280:                }
0281:                return property;
0282:            }
0283:
0284:            public String getProperty(String name, String defaultValue) {
0285:                Object result = get(name);
0286:                String property = result instanceof  String ? (String) result
0287:                        : null;
0288:                if (property == null && defaults != null) {
0289:                    property = defaults.getProperty(name);
0290:                }
0291:                if (property == null) {
0292:                    return defaultValue;
0293:                }
0294:                return property;
0295:            }
0296:
0297:            public synchronized Object setProperty(String name, String value) {
0298:                return put(name, value);
0299:            }
0300:
0301:            /**
0302:             * Searches for the comment associated with the specified property. If the property is not found, look
0303:             * in the default properties. If the property is not found in the default properties, answer null.
0304:             *
0305:             * @param name the name of the property to find
0306:             * @return the named property value
0307:             */
0308:            public String getComment(String name) {
0309:                name = normalize(name);
0310:                String comment = comments.get(name);
0311:                if (comment == null && defaults instanceof  SuperProperties) {
0312:                    comment = ((SuperProperties) defaults).getComment(name);
0313:                }
0314:                return comment;
0315:            }
0316:
0317:            /**
0318:             * Sets the comment associated with a property.
0319:             * @param name the property name; not null
0320:             * @param comment the comment; not null
0321:             */
0322:            public void setComment(String name, String comment) {
0323:                if (name == null)
0324:                    throw new NullPointerException("name is null");
0325:                if (comment == null)
0326:                    throw new NullPointerException("comment is null");
0327:
0328:                name = normalize(name);
0329:                comments.put(name, comment);
0330:            }
0331:
0332:            /**
0333:             * Searches for the attributes associated with the specified property. If the property is not found, look
0334:             * in the default properties. If the property is not found in the default properties, answer null.
0335:             *
0336:             * @param name the name of the property to find
0337:             * @return the attributes for an existing property (not null); null for non-existant properties
0338:             */
0339:            public Map<String, String> getAttributes(String name) {
0340:                if (name == null)
0341:                    throw new NullPointerException("name is null");
0342:
0343:                name = normalize(name);
0344:                Map<String, String> attributes = this .attributes.get(name);
0345:                if (attributes == null && defaults instanceof  SuperProperties) {
0346:                    attributes = ((SuperProperties) defaults)
0347:                            .getAttributes(name);
0348:                }
0349:                return attributes;
0350:            }
0351:
0352:            public void list(PrintStream out) {
0353:                if (out == null) {
0354:                    throw new NullPointerException();
0355:                }
0356:                StringBuffer buffer = new StringBuffer(80);
0357:                Enumeration<?> keys = propertyNames();
0358:                while (keys.hasMoreElements()) {
0359:                    String key = (String) keys.nextElement();
0360:                    buffer.append(key);
0361:                    buffer.append('=');
0362:                    String property = (String) get(key);
0363:                    if (property == null) {
0364:                        property = defaults.getProperty(key);
0365:                    }
0366:                    if (property.length() > 40) {
0367:                        buffer.append(property.substring(0, 37));
0368:                        buffer.append("...");
0369:                    } else {
0370:                        buffer.append(property);
0371:                    }
0372:                    out.println(buffer.toString());
0373:                    buffer.setLength(0);
0374:                }
0375:            }
0376:
0377:            public void list(PrintWriter writer) {
0378:                if (writer == null) {
0379:                    throw new NullPointerException();
0380:                }
0381:                StringBuffer buffer = new StringBuffer(80);
0382:                Enumeration<?> keys = propertyNames();
0383:                while (keys.hasMoreElements()) {
0384:                    String key = (String) keys.nextElement();
0385:                    buffer.append(key);
0386:                    buffer.append('=');
0387:                    String property = (String) get(key);
0388:                    while (property == null) {
0389:                        property = defaults.getProperty(key);
0390:                    }
0391:                    if (property.length() > 40) {
0392:                        buffer.append(property.substring(0, 37));
0393:                        buffer.append("...");
0394:                    } else {
0395:                        buffer.append(property);
0396:                    }
0397:                    writer.println(buffer.toString());
0398:                    buffer.setLength(0);
0399:                }
0400:            }
0401:
0402:            public synchronized void load(InputStream in) throws IOException {
0403:                // never null, when empty we are processing the white space at the beginning of the line
0404:                StringBuilder key = new StringBuilder();
0405:                // null when processing key
0406:                StringBuilder value = null;
0407:                // never null, contains the comment for the property or nothing if no comment
0408:                StringBuilder comment = new StringBuilder();
0409:                // never null, contains attributes for a property
0410:                LinkedHashMap<String, String> attributes = new LinkedHashMap<String, String>();
0411:
0412:                int indent = 0;
0413:                boolean globalIndentSet = false;
0414:
0415:                int commentIndent = -1;
0416:                boolean globalCommentIndentSet = false;
0417:
0418:                // true when processing the separator between a key and value
0419:                boolean inSeparator = false;
0420:
0421:                while (true) {
0422:                    int nextByte = decodeNextCharacter(in);
0423:                    if (nextByte == EOF)
0424:                        break;
0425:                    char nextChar = (char) (nextByte & 0xff);
0426:
0427:                    switch (nextByte) {
0428:                    case ' ':
0429:                    case '\t':
0430:                        //
0431:                        // End of key if parsing key
0432:                        //
0433:                        // if parsing the key, this is the end of the key
0434:                        if (key.length() > 0 && value == null) {
0435:                            inSeparator = true;
0436:                            value = new StringBuilder();
0437:                            continue;
0438:                        }
0439:                        break;
0440:                    case ':':
0441:                    case '=':
0442:                        //
0443:                        // End of key
0444:                        //
0445:                        if (inSeparator) {
0446:                            inSeparator = false;
0447:                            continue;
0448:                        }
0449:                        if (value == null) {
0450:                            value = new StringBuilder();
0451:                            continue;
0452:                        }
0453:                        break;
0454:                    case LINE_ENDING:
0455:                        //
0456:                        // End of Line
0457:                        //
0458:                        if (key.length() > 0) {
0459:                            // add property
0460:                            put(key.toString(), value == null ? "" : value
0461:                                    .toString());
0462:                            // add comment
0463:                            if (comment.length() > 0) {
0464:                                setComment(key.toString(), comment.toString());
0465:                                comment = new StringBuilder();
0466:                            }
0467:                            // add attributes
0468:                            this .attributes.put(normalize(key.toString()),
0469:                                    attributes);
0470:                            attributes = new LinkedHashMap<String, String>();
0471:                            // set line indent
0472:                            if (!globalIndentSet) {
0473:                                setIndent(indent);
0474:                                globalIndentSet = true;
0475:                            }
0476:                            indent = 0;
0477:                        }
0478:                        key = new StringBuilder();
0479:                        value = null;
0480:                        continue;
0481:                    case '#':
0482:                    case '!':
0483:                        //
0484:                        // Comment
0485:                        //
0486:                        if (key.length() == 0) {
0487:                            // set global line indent
0488:                            if (!globalIndentSet) {
0489:                                setIndent(indent);
0490:                                globalIndentSet = true;
0491:                            }
0492:                            indent = 0;
0493:
0494:                            // read comment Line
0495:                            StringBuilder commentLine = new StringBuilder();
0496:                            int commentLineIndent = 0;
0497:                            boolean inIndent = true;
0498:                            while (true) {
0499:                                nextByte = in.read();
0500:                                if (nextByte < 0)
0501:                                    break;
0502:                                nextChar = (char) nextByte; // & 0xff
0503:
0504:                                if (inIndent && nextChar == ' ') {
0505:                                    commentLineIndent++;
0506:                                    commentLine.append(' ');
0507:                                } else if (inIndent && nextChar == '\t') {
0508:                                    commentLineIndent += 4;
0509:                                    commentLine.append("    ");
0510:                                } else if (nextChar == '\r' || nextChar == '\n') {
0511:                                    break;
0512:                                } else {
0513:                                    inIndent = false;
0514:                                    commentLine.append(nextChar);
0515:                                }
0516:                            }
0517:
0518:                            // Determine indent
0519:                            if (comment.length() == 0) {
0520:                                // if this is a new comment block, the comment indent size for this
0521:                                // block is based the first line of the comment
0522:                                commentIndent = commentLineIndent;
0523:                                if (!globalCommentIndentSet) {
0524:                                    setCommentIndent(commentIndent);
0525:                                    globalCommentIndentSet = true;
0526:                                }
0527:                            }
0528:                            commentLineIndent = Math.min(commentIndent,
0529:                                    commentLineIndent);
0530:
0531:                            if (commentLine.toString().trim().startsWith("@")) {
0532:                                // process property attribute
0533:                                String attribute = commentLine.toString()
0534:                                        .trim().substring(1);
0535:                                String[] parts = attribute.split("=", 2);
0536:                                String attributeName = parts[0].trim();
0537:                                String attributeValue = parts.length == 2 ? parts[1]
0538:                                        .trim()
0539:                                        : "";
0540:                                attributes.put(attributeName, attributeValue);
0541:                            } else {
0542:                                // append comment
0543:                                if (comment.length() != 0) {
0544:                                    comment.append(lineSeparator);
0545:                                }
0546:                                comment.append(commentLine.toString()
0547:                                        .substring(commentLineIndent));
0548:                            }
0549:                            continue;
0550:                        }
0551:                        break;
0552:                    }
0553:
0554:                    if (nextByte >= 0 && Character.isWhitespace(nextChar)) {
0555:                        // count leading white space
0556:                        if (key.length() == 0) {
0557:                            if (nextChar == '\t') {
0558:                                indent += 4;
0559:                            } else {
0560:                                indent++;
0561:                            }
0562:                        }
0563:
0564:                        // if key length == 0 or value length == 0
0565:                        if (key.length() == 0 || value == null
0566:                                || value.length() == 0) {
0567:                            continue;
0568:                        }
0569:                    }
0570:
0571:                    // Decode encoded separator characters
0572:                    switch (nextByte) {
0573:                    case ENCODED_EQUALS:
0574:                        nextChar = '=';
0575:                        break;
0576:                    case ENCODED_COLON:
0577:                        nextChar = ':';
0578:                        break;
0579:                    case ENCODED_SPACE:
0580:                        nextChar = ' ';
0581:                        break;
0582:                    case ENCODED_TAB:
0583:                        nextChar = '\t';
0584:                        break;
0585:                    case ENCODED_NEWLINE:
0586:                        nextChar = '\n';
0587:                        break;
0588:                    case ENCODED_CARRIAGE_RETURN:
0589:                        nextChar = '\r';
0590:                        break;
0591:                    }
0592:
0593:                    inSeparator = false;
0594:                    if (value == null) {
0595:                        key.append(nextChar);
0596:                    } else {
0597:                        value.append(nextChar);
0598:                    }
0599:                }
0600:
0601:                // if buffer has data, there is a property we still need toadd
0602:                if (key.length() > 0) {
0603:                    // add property
0604:                    put(key.toString(), value == null ? "" : value.toString());
0605:                    // add comment
0606:                    if (comment.length() > 0) {
0607:                        setComment(key.toString(), comment.toString());
0608:                    }
0609:                    // add attributes
0610:                    this .attributes.put(normalize(key.toString()), attributes);
0611:                    // set line indent
0612:                    if (!globalIndentSet) {
0613:                        setIndent(indent);
0614:                    }
0615:                }
0616:            }
0617:
0618:            private static final int EOF = -1;
0619:            private static final int LINE_ENDING = -4200;
0620:            private static final int ENCODED_EQUALS = -5000;
0621:            private static final int ENCODED_COLON = -5001;
0622:            private static final int ENCODED_SPACE = -5002;
0623:            private static final int ENCODED_TAB = -5003;
0624:            private static final int ENCODED_NEWLINE = -5004;
0625:            private static final int ENCODED_CARRIAGE_RETURN = -5005;
0626:
0627:            private int decodeNextCharacter(InputStream in) throws IOException {
0628:                boolean lineContinuation = false;
0629:                boolean carriageReturnLineContinuation = false;
0630:                boolean encoded = false;
0631:                while (true) {
0632:                    // read character
0633:                    int nextByte = in.read();
0634:                    if (nextByte < 0)
0635:                        return EOF;
0636:                    char nextChar = (char) (nextByte & 0xff);
0637:
0638:                    // if line continuation character was '\r', we need to ignore an optional '\n'
0639:                    // immediately following the \r
0640:                    if (carriageReturnLineContinuation) {
0641:                        carriageReturnLineContinuation = false;
0642:                        if (nextChar == '\n') {
0643:                            continue;
0644:                        }
0645:                    }
0646:
0647:                    // If escape sequence \x or line continuation, decode it
0648:                    if (nextChar == '\\') {
0649:                        // next character is the escaped character
0650:                        nextByte = in.read();
0651:                        if (nextByte < 0) {
0652:                            // line continuation to end of stream
0653:                            // sun vm returns 0 character for this case
0654:                            nextChar = '\u0000';
0655:                        } else {
0656:                            nextChar = (char) (nextByte & 0xff);
0657:                        }
0658:
0659:                        switch (nextChar) {
0660:                        case '\r':
0661:                            // line continuation using '\r', which optionally can have a following '\n'
0662:                            carriageReturnLineContinuation = true;
0663:                            // fall through
0664:                        case '\n':
0665:                            // line continuation
0666:                            lineContinuation = true;
0667:                            continue;
0668:                        case 'u':
0669:                            nextChar = readUnicode(in);
0670:                            break;
0671:                        default:
0672:                            encoded = true;
0673:                            nextChar = decodeEscapeChar(nextChar);
0674:                            break;
0675:                        }
0676:                    } else {
0677:                        // if line ending character, we return the special value LINE_ENDING so
0678:                        // caller can differentiate between an encoded "\n" sequence and a real
0679:                        // line ending character in the file
0680:                        if (nextChar == '\n' || nextChar == '\r') {
0681:                            return LINE_ENDING;
0682:                        }
0683:                    }
0684:
0685:                    // in a line continuation we ignore spaces and tabs until the first real character
0686:                    if (lineContinuation
0687:                            && (nextChar == ' ' || nextChar == '\t')) {
0688:                        continue;
0689:                    }
0690:
0691:                    if (encoded) {
0692:                        switch (nextChar) {
0693:                        case '=':
0694:                            return ENCODED_EQUALS;
0695:                        case ':':
0696:                            return ENCODED_COLON;
0697:                        case ' ':
0698:                            return ENCODED_SPACE;
0699:                        case '\t':
0700:                            return ENCODED_TAB;
0701:                        case '\n':
0702:                            return ENCODED_NEWLINE;
0703:                        case '\r':
0704:                            return ENCODED_CARRIAGE_RETURN;
0705:                        }
0706:                    }
0707:                    return nextChar;
0708:                }
0709:            }
0710:
0711:            private char decodeEscapeChar(char nextChar) {
0712:                switch (nextChar) {
0713:                case 'b':
0714:                    return '\b';
0715:                case 'f':
0716:                    return '\f';
0717:                case 'n':
0718:                    return '\n';
0719:                case 'r':
0720:                    return '\r';
0721:                case 't':
0722:                    return '\t';
0723:                case 'u':
0724:                    throw new IllegalArgumentException(
0725:                            "decodeEscapeChar can not decode an unicode sequence");
0726:                default:
0727:                    return nextChar;
0728:                }
0729:            }
0730:
0731:            private char readUnicode(InputStream in) throws IOException {
0732:                char[] buf = new char[4];
0733:                int unicode = 0;
0734:                for (int i = 0; i < buf.length; i++) {
0735:                    int nextByte = in.read();
0736:
0737:                    // we must get exactally 4 bytes
0738:                    if (nextByte < 0) {
0739:                        throw new IllegalArgumentException(
0740:                                "Invalid unicode sequence: expected format \\uxxxx, but got \\u"
0741:                                        + new String(buf, 0, i));
0742:                    }
0743:
0744:                    // convert to character
0745:                    char nextChar = (char) (nextByte & 0xff);
0746:                    buf[i] = nextChar;
0747:
0748:                    // convert to digit
0749:                    int nextDigit = Character.digit(nextChar, 16);
0750:
0751:                    // all bytes must be valid hex digits
0752:                    if (nextDigit < 0) {
0753:                        throw new IllegalArgumentException("Illegal character "
0754:                                + nextChar + " in unicode sequence \\u"
0755:                                + new String(buf, 0, i + 1));
0756:                    }
0757:
0758:                    unicode = (unicode << 4) + nextDigit;
0759:                }
0760:
0761:                return (char) unicode;
0762:            }
0763:
0764:            public Enumeration<?> propertyNames() {
0765:                if (defaults == null) {
0766:                    return keys();
0767:                }
0768:
0769:                Hashtable<Object, Object> set = new Hashtable<Object, Object>(
0770:                        defaults.size() + size());
0771:                Enumeration<?> keys = defaults.propertyNames();
0772:                while (keys.hasMoreElements()) {
0773:                    set.put(keys.nextElement(), set);
0774:                }
0775:                keys = keys();
0776:                while (keys.hasMoreElements()) {
0777:                    set.put(keys.nextElement(), set);
0778:                }
0779:                return set.keys();
0780:            }
0781:
0782:            @SuppressWarnings({"deprecation"})
0783:            public void save(OutputStream out, String comment) {
0784:                try {
0785:                    store(out, comment);
0786:                } catch (IOException e) {
0787:                }
0788:            }
0789:
0790:            public synchronized void store(OutputStream out, String headComment)
0791:                    throws IOException {
0792:                OutputStreamWriter writer = new OutputStreamWriter(out,
0793:                        "ISO8859_1");
0794:                if (headComment != null) {
0795:                    writer.write(indent);
0796:                    writer.write("#");
0797:                    writer.write(commentIndent);
0798:                    writer.write(headComment);
0799:                    writer.write(lineSeparator);
0800:                }
0801:
0802:                boolean firstProperty = true;
0803:                StringBuilder buffer = new StringBuilder(200);
0804:                for (Map.Entry<Object, Object> entry : entrySet()) {
0805:                    String key = (String) entry.getKey();
0806:                    String value = (String) entry.getValue();
0807:
0808:                    if (!firstProperty && spaceBetweenProperties) {
0809:                        buffer.append(lineSeparator);
0810:                    }
0811:
0812:                    String comment = comments.get(key);
0813:                    Map<String, String> attributes = this .attributes.get(key);
0814:                    if (comment != null || !attributes.isEmpty()) {
0815:                        dumpComment(buffer, comment, attributes, "#");
0816:                        if (spaceAfterComment) {
0817:                            buffer.append(lineSeparator);
0818:                        }
0819:                    }
0820:
0821:                    // ${indent}${key}=${value}
0822:                    buffer.append(indent);
0823:                    dumpString(buffer, key, true);
0824:                    if (value != null && value.length() > 0) {
0825:                        buffer.append(keyValueSeparator);
0826:                        dumpString(buffer, value, false);
0827:                    }
0828:                    buffer.append(lineSeparator);
0829:
0830:                    writer.write(buffer.toString());
0831:                    buffer.setLength(0);
0832:
0833:                    firstProperty = false;
0834:                }
0835:                writer.flush();
0836:            }
0837:
0838:            private void dumpString(StringBuilder buffer, String string,
0839:                    boolean key) {
0840:                int i = 0;
0841:                if (!key && i < string.length() && string.charAt(i) == ' ') {
0842:                    buffer.append("\\ ");
0843:                    i++;
0844:                }
0845:
0846:                for (; i < string.length(); i++) {
0847:                    char ch = string.charAt(i);
0848:                    switch (ch) {
0849:                    case '\t':
0850:                        buffer.append("\\t");
0851:                        break;
0852:                    case '\n':
0853:                        buffer.append("\\n");
0854:                        break;
0855:                    case '\f':
0856:                        buffer.append("\\f");
0857:                        break;
0858:                    case '\r':
0859:                        buffer.append("\\r");
0860:                        break;
0861:                    default:
0862:                        if ("\\".indexOf(ch) >= 0
0863:                                || (key && "#!=: ".indexOf(ch) >= 0)) {
0864:                            buffer.append('\\');
0865:                        }
0866:                        if (ch >= ' ' && ch <= '~') {
0867:                            buffer.append(ch);
0868:                        } else {
0869:                            String hex = Integer.toHexString(ch);
0870:                            buffer.append("\\u");
0871:                            for (int j = 0; j < 4 - hex.length(); j++) {
0872:                                buffer.append("0");
0873:                            }
0874:                            buffer.append(hex);
0875:                        }
0876:                    }
0877:                }
0878:            }
0879:
0880:            private void dumpComment(StringBuilder buffer, String comment,
0881:                    Map<String, String> attributes, String commentToken) {
0882:                if (comment != null) {
0883:                    boolean startOfLine = true;
0884:
0885:                    char ch = 0;
0886:                    for (int i = 0; i < comment.length(); i++) {
0887:                        ch = comment.charAt(i);
0888:
0889:                        if (startOfLine) {
0890:                            buffer.append(indent);
0891:                            buffer.append(commentToken);
0892:                            buffer.append(commentIndent);
0893:                            startOfLine = false;
0894:                        }
0895:
0896:                        switch (ch) {
0897:                        case '\r':
0898:                            // if next character is not \n, this is the line break
0899:                            if (i + 1 < comment.length()
0900:                                    && comment.charAt(i + 1) != '\n') {
0901:                                buffer.append(lineSeparator);
0902:                                startOfLine = true;
0903:                            }
0904:                            break;
0905:                        case '\n':
0906:                            buffer.append(lineSeparator);
0907:                            startOfLine = true;
0908:                            break;
0909:                        default:
0910:                            buffer.append(ch);
0911:                        }
0912:                    }
0913:
0914:                    // if the last character written was not a line break, write one now
0915:                    if (ch != '\r' && ch != '\n') {
0916:                        buffer.append(lineSeparator);
0917:                    }
0918:                }
0919:
0920:                // ${indent}#${commentIndent}@${attributeName}=${attributeValue}
0921:                for (Map.Entry<String, String> entry : attributes.entrySet()) {
0922:                    buffer.append(indent);
0923:                    buffer.append("#");
0924:                    buffer.append(commentIndent);
0925:                    buffer.append("@");
0926:                    buffer.append(entry.getKey());
0927:                    if (entry.getValue() != null
0928:                            && entry.getValue().length() > 0) {
0929:                        buffer.append("=");
0930:                        buffer.append(entry.getValue());
0931:                    }
0932:                    buffer.append(lineSeparator);
0933:                }
0934:            }
0935:
0936:            public synchronized void loadFromXML(InputStream in)
0937:                    throws IOException {
0938:                if (in == null) {
0939:                    throw new NullPointerException();
0940:                }
0941:
0942:                DocumentBuilder builder = getDocumentBuilder();
0943:
0944:                try {
0945:                    Document doc = builder.parse(in);
0946:                    NodeList entries = doc.getElementsByTagName("entry");
0947:                    if (entries == null) {
0948:                        return;
0949:                    }
0950:
0951:                    int entriesListLength = entries.getLength();
0952:                    for (int i = 0; i < entriesListLength; i++) {
0953:                        Element entry = (Element) entries.item(i);
0954:                        String key = entry.getAttribute("key");
0955:                        String value = entry.getTextContent();
0956:                        put(key, value);
0957:
0958:                        // search backwards for a comment
0959:                        for (Node node = entry.getPreviousSibling(); node != null
0960:                                && !(node instanceof  Element); node = node
0961:                                .getPreviousSibling()) {
0962:                            if (node instanceof  Comment) {
0963:                                InputStream cin = new ByteArrayInputStream(
0964:                                        ((Comment) node).getData().getBytes());
0965:
0966:                                // read comment line by line
0967:                                StringBuilder comment = new StringBuilder();
0968:                                LinkedHashMap<String, String> attributes = new LinkedHashMap<String, String>();
0969:
0970:                                int nextByte;
0971:                                char nextChar;
0972:                                boolean firstLine = true;
0973:                                int commentIndent = Integer.MAX_VALUE;
0974:                                do {
0975:                                    // read one line
0976:                                    StringBuilder commentLine = new StringBuilder();
0977:                                    int commentLineIndent = 0;
0978:                                    boolean inIndent = true;
0979:                                    while (true) {
0980:                                        nextByte = cin.read();
0981:                                        if (nextByte < 0)
0982:                                            break;
0983:                                        nextChar = (char) nextByte; // & 0xff
0984:                                        if (inIndent && nextChar == ' ') {
0985:                                            commentLineIndent++;
0986:                                            commentLine.append(' ');
0987:                                        } else if (inIndent && nextChar == '\t') {
0988:                                            commentLineIndent += 4;
0989:                                            commentLine.append("    ");
0990:                                        } else if (nextChar == '\r'
0991:                                                || nextChar == '\n') {
0992:                                            break;
0993:                                        } else {
0994:                                            inIndent = false;
0995:                                            commentLine.append(nextChar);
0996:                                        }
0997:                                    }
0998:
0999:                                    // Determine indent
1000:                                    if (!firstLine
1001:                                            && commentIndent == Integer.MAX_VALUE
1002:                                            && commentLine.length() > 0) {
1003:                                        // if this is a new comment block, the comment indent size for this
1004:                                        // block is based the first full line of the comment (ignoring the
1005:                                        // line with the <!--
1006:                                        commentIndent = commentLineIndent;
1007:                                    }
1008:                                    commentLineIndent = Math.min(commentIndent,
1009:                                            commentLineIndent);
1010:
1011:                                    if (commentLine.toString().trim()
1012:                                            .startsWith("@")) {
1013:                                        // process property attribute
1014:                                        String attribute = commentLine
1015:                                                .toString().trim().substring(1);
1016:                                        String[] parts = attribute
1017:                                                .split("=", 2);
1018:                                        String attributeName = parts[0].trim();
1019:                                        String attributeValue = parts.length == 2 ? parts[1]
1020:                                                .trim()
1021:                                                : "";
1022:                                        attributes.put(attributeName,
1023:                                                attributeValue);
1024:                                    } else {
1025:                                        // append comment
1026:                                        if (comment.length() != 0) {
1027:                                            comment.append(lineSeparator);
1028:                                        }
1029:                                        comment.append(commentLine.toString()
1030:                                                .substring(commentLineIndent));
1031:                                    }
1032:
1033:                                    firstLine = false;
1034:                                } while (nextByte > 0);
1035:
1036:                                if (comment.length() > 0) {
1037:                                    setComment(key, comment.toString());
1038:                                }
1039:                                this .attributes.put(normalize(key), attributes);
1040:
1041:                                break;
1042:                            }
1043:                        }
1044:
1045:                    }
1046:                } catch (SAXException e) {
1047:                    throw new InvalidPropertiesFormatException(e);
1048:                }
1049:            }
1050:
1051:            private DocumentBuilder getDocumentBuilder() {
1052:                if (builder == null) {
1053:                    DocumentBuilderFactory factory = DocumentBuilderFactory
1054:                            .newInstance();
1055:                    factory.setValidating(true);
1056:
1057:                    try {
1058:                        builder = factory.newDocumentBuilder();
1059:                    } catch (ParserConfigurationException e) {
1060:                        throw new Error(e);
1061:                    }
1062:
1063:                    builder.setErrorHandler(new ErrorHandler() {
1064:                        public void warning(SAXParseException e)
1065:                                throws SAXException {
1066:                            throw e;
1067:                        }
1068:
1069:                        public void error(SAXParseException e)
1070:                                throws SAXException {
1071:                            throw e;
1072:                        }
1073:
1074:                        public void fatalError(SAXParseException e)
1075:                                throws SAXException {
1076:                            throw e;
1077:                        }
1078:                    });
1079:
1080:                    builder.setEntityResolver(new EntityResolver() {
1081:                        public InputSource resolveEntity(String publicId,
1082:                                String systemId) throws SAXException,
1083:                                IOException {
1084:                            if (systemId.equals(PROP_DTD_NAME)) {
1085:                                InputSource result = new InputSource(
1086:                                        new StringReader(PROP_DTD));
1087:                                result.setSystemId(PROP_DTD_NAME);
1088:                                return result;
1089:                            }
1090:                            throw new SAXException(
1091:                                    "Invalid DOCTYPE declaration: " + systemId);
1092:                        }
1093:                    });
1094:                }
1095:                return builder;
1096:            }
1097:
1098:            public void storeToXML(OutputStream os, String comment)
1099:                    throws IOException {
1100:                storeToXML(os, comment, "UTF-8");
1101:            }
1102:
1103:            public synchronized void storeToXML(OutputStream os,
1104:                    String headComment, String encoding) throws IOException {
1105:                if (os == null || encoding == null) {
1106:                    throw new NullPointerException();
1107:                }
1108:
1109:                // for somereason utf-8 is always used
1110:                String encodingCanonicalName = "UTF-8";
1111:
1112:                // header
1113:                OutputStreamWriter osw = new OutputStreamWriter(os,
1114:                        encodingCanonicalName);
1115:                StringBuilder buf = new StringBuilder(200);
1116:                buf.append("<?xml version=\"1.0\" encoding=\"").append(
1117:                        encodingCanonicalName).append("\"?>").append(
1118:                        lineSeparator);
1119:                buf.append(
1120:                        "<!DOCTYPE properties SYSTEM \"" + PROP_DTD_NAME
1121:                                + "\">").append(lineSeparator);
1122:                buf.append("<properties>").append(lineSeparator);
1123:
1124:                // comment
1125:                if (headComment != null) {
1126:                    buf.append(indent);
1127:                    buf.append("<comment>");
1128:                    buf.append(substitutePredefinedEntries(headComment));
1129:                    buf.append("</comment>");
1130:                    buf.append(lineSeparator);
1131:
1132:                    if (!isEmpty()
1133:                            && (spaceBetweenProperties || spaceAfterComment)) {
1134:                        buf.append(lineSeparator);
1135:                    }
1136:                }
1137:
1138:                // properties
1139:                boolean firstProperty = true;
1140:                for (Map.Entry<Object, Object> entry : entrySet()) {
1141:                    String key = (String) entry.getKey();
1142:                    String value = (String) entry.getValue();
1143:
1144:                    if (!firstProperty && spaceBetweenProperties) {
1145:                        buf.append(lineSeparator);
1146:                    }
1147:
1148:                    // property comment
1149:                    String comment = comments.get(key);
1150:                    Map<String, String> attributes = this .attributes.get(key);
1151:                    if (comment != null || !attributes.isEmpty()) {
1152:                        buf.append(indent);
1153:                        buf.append("<!--");
1154:                        buf.append(lineSeparator);
1155:
1156:                        // comments can't contain "--" so we shrink all sequences of them to a single "-"
1157:                        comment = comment.replaceAll("--*", "-");
1158:                        dumpComment(buf, comment, attributes, "");
1159:
1160:                        buf.append(indent);
1161:                        buf.append("-->");
1162:                        buf.append(lineSeparator);
1163:
1164:                        if (spaceAfterComment) {
1165:                            buf.append(lineSeparator);
1166:                        }
1167:                    }
1168:
1169:                    // property
1170:                    buf.append(indent);
1171:                    buf.append("<entry key=\"");
1172:                    buf.append(substitutePredefinedEntries(key));
1173:                    buf.append("\">");
1174:                    buf.append(substitutePredefinedEntries(value));
1175:                    buf.append("</entry>");
1176:                    buf.append(lineSeparator);
1177:
1178:                    firstProperty = false;
1179:                }
1180:
1181:                buf.append("</properties>").append(lineSeparator);
1182:
1183:                osw.write(buf.toString());
1184:                osw.flush();
1185:            }
1186:
1187:            private String substitutePredefinedEntries(String s) {
1188:                /*
1189:                 * substitution for predefined character entities
1190:                 * to use them safely in XML
1191:                 */
1192:                return s.replaceAll("&", "&amp;").replaceAll("<", "&lt;")
1193:                        .replaceAll(">", "&gt;").replaceAll("\u0027", "&apos;")
1194:                        .replaceAll("\"", "&quot;");
1195:            }
1196:
1197:            //
1198:            // Delegate all remaining methods to the properties object
1199:            //
1200:
1201:            public boolean isEmpty() {
1202:                return properties.isEmpty();
1203:            }
1204:
1205:            public int size() {
1206:                return properties.size();
1207:            }
1208:
1209:            public Object get(Object key) {
1210:                key = normalize(key);
1211:                return properties.get(key);
1212:            }
1213:
1214:            public Object put(Object key, Object value) {
1215:                key = normalize(key);
1216:                if (key instanceof  String) {
1217:                    String name = (String) key;
1218:                    if (!attributes.containsKey(name)) {
1219:                        attributes.put(name,
1220:                                new LinkedHashMap<String, String>());
1221:                    }
1222:                }
1223:                return properties.put(key, value);
1224:            }
1225:
1226:            public Object remove(Object key) {
1227:                key = normalize(key);
1228:                comments.remove(key);
1229:                attributes.remove(key);
1230:                return properties.remove(key);
1231:            }
1232:
1233:            public void putAll(Map<?, ?> t) {
1234:                for (Map.Entry<?, ?> entry : t.entrySet()) {
1235:                    put(entry.getKey(), entry.getValue());
1236:                }
1237:                if (t instanceof  SuperProperties) {
1238:                    SuperProperties super Properties = (SuperProperties) t;
1239:                    for (Map.Entry<String, String> entry : super Properties.comments
1240:                            .entrySet()) {
1241:                        comments.put(normalize(entry.getKey()), entry
1242:                                .getValue());
1243:                    }
1244:                    for (Map.Entry<String, LinkedHashMap<String, String>> entry : super Properties.attributes
1245:                            .entrySet()) {
1246:                        attributes.put(normalize(entry.getKey()), entry
1247:                                .getValue());
1248:                    }
1249:                }
1250:            }
1251:
1252:            /**
1253:             * Returns an unmodifiable view of the keys.
1254:             * @return an unmodifiable view of the keys
1255:             */
1256:            public Set<Object> keySet() {
1257:                return Collections.unmodifiableSet(properties.keySet());
1258:            }
1259:
1260:            public Enumeration<Object> keys() {
1261:                return Collections.enumeration(properties.keySet());
1262:            }
1263:
1264:            /**
1265:             * Returns an unmodifiable view of the values.
1266:             * @return an unmodifiable view of the values
1267:             */
1268:            public Collection<Object> values() {
1269:                return Collections.unmodifiableCollection(properties.values());
1270:            }
1271:
1272:            /**
1273:             * Returns an unmodifiable view of the entries.
1274:             * @return an unmodifiable view of the entries
1275:             */
1276:            public Set<Map.Entry<Object, Object>> entrySet() {
1277:                return Collections.unmodifiableSet(properties.entrySet());
1278:            }
1279:
1280:            public Enumeration<Object> elements() {
1281:                return Collections.enumeration(properties.values());
1282:            }
1283:
1284:            public boolean containsKey(Object key) {
1285:                key = normalize(key);
1286:                return properties.containsKey(key);
1287:            }
1288:
1289:            public boolean containsValue(Object value) {
1290:                return properties.containsValue(value);
1291:            }
1292:
1293:            public boolean contains(Object value) {
1294:                return properties.containsValue(value);
1295:            }
1296:
1297:            public void clear() {
1298:                properties.clear();
1299:                comments.clear();
1300:                attributes.clear();
1301:            }
1302:
1303:            @SuppressWarnings({"unchecked"})
1304:            public Object clone() {
1305:                SuperProperties clone = (SuperProperties) super .clone();
1306:                clone.properties = (LinkedHashMap<Object, Object>) properties
1307:                        .clone();
1308:                clone.comments = (LinkedHashMap<String, String>) comments
1309:                        .clone();
1310:                clone.attributes = (LinkedHashMap<String, LinkedHashMap<String, String>>) attributes
1311:                        .clone();
1312:                for (Map.Entry<String, LinkedHashMap<String, String>> entry : clone.attributes
1313:                        .entrySet()) {
1314:                    entry.setValue((LinkedHashMap<String, String>) entry
1315:                            .getValue().clone());
1316:                }
1317:                return clone;
1318:            }
1319:
1320:            @SuppressWarnings({"EqualsWhichDoesntCheckParameterClass"})
1321:            public boolean equals(Object o) {
1322:                return properties.equals(o);
1323:            }
1324:
1325:            public int hashCode() {
1326:                return properties.hashCode();
1327:            }
1328:
1329:            public String toString() {
1330:                return properties.toString();
1331:            }
1332:
1333:            protected void rehash() {
1334:            }
1335:
1336:            private Object normalize(Object key) {
1337:                if (key instanceof  String) {
1338:                    return normalize((String) key);
1339:                }
1340:                return key;
1341:            }
1342:
1343:            private String normalize(String property) {
1344:                if (!caseInsensitive) {
1345:                    return property;
1346:                }
1347:
1348:                if (super .containsKey(property)) {
1349:                    return property;
1350:                }
1351:
1352:                for (Object o : keySet()) {
1353:                    if (o instanceof  String) {
1354:                        String key = (String) o;
1355:                        if (key.equalsIgnoreCase(property))
1356:                            return key;
1357:                    }
1358:                }
1359:
1360:                if (defaults != null) {
1361:                    for (Object o : defaults.keySet()) {
1362:                        if (o instanceof  String) {
1363:                            String key = (String) o;
1364:                            if (key.equalsIgnoreCase(property))
1365:                                return key;
1366:                        }
1367:                    }
1368:                }
1369:
1370:                return property;
1371:            }
1372:        }
www.java2java.com | Contact Us
Copyright 2009 - 12 Demo Source and Support. All rights reserved.
All other trademarks are property of their respective owners.