Source Code Cross Referenced for CompoundName.java in  » Apache-Harmony-Java-SE » javax-package » javax » naming » 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 » Apache Harmony Java SE » javax package » javax.naming 
Source Cross Referenced  Class Diagram Java Document (Java Doc) 


0001:        /* 
0002:         * Licensed to the Apache Software Foundation (ASF) under one or more
0003:         * contributor license agreements.  See the NOTICE file distributed with
0004:         * this work for additional information regarding copyright ownership.
0005:         * The ASF licenses this file to You under the Apache License, Version 2.0
0006:         * (the "License"); you may not use this file except in compliance with
0007:         * the License.  You may obtain a copy of the License at
0008:         * 
0009:         *     http://www.apache.org/licenses/LICENSE-2.0
0010:         * 
0011:         * Unless required by applicable law or agreed to in writing, software
0012:         * distributed under the License is distributed on an "AS IS" BASIS,
0013:         * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
0014:         * See the License for the specific language governing permissions and
0015:         * limitations under the License.
0016:         */
0017:
0018:        package javax.naming;
0019:
0020:        import java.io.IOException;
0021:        import java.io.ObjectInputStream;
0022:        import java.io.ObjectOutputStream;
0023:        import java.util.Enumeration;
0024:        import java.util.Properties;
0025:        import java.util.Vector;
0026:
0027:        import org.apache.harmony.jndi.internal.nls.Messages;
0028:
0029:        /**
0030:         * A <code>CompoundName</code> is a series of string elements, and it
0031:         * represents a name in a naming service within a single namespace. Typically
0032:         * these names have a structure which is hierarchical.
0033:         * <p>
0034:         * A <code>CompoundName</code> has a sequence of zero or more elements
0035:         * delimited by the char specified in the property "jndi.syntax.separator". This
0036:         * property is required except when the direction of the name is "flat" (see
0037:         * jndi.syntax.direction). The property "jndi.syntax.separator2" allows for the
0038:         * specification of an additional separator. A separator string will be treated
0039:         * as normal characters if it is preceded by the escape string or is within
0040:         * quotes.
0041:         * </p>
0042:         * <p>
0043:         * The property "jndi.syntax.direction" specifies the direction in which the
0044:         * name is read. Permitted values are "right_to_left", "left_to_right" and
0045:         * "flat". A flat name does not have a hierarchical structure. If this property
0046:         * is not specified then the default is "flat". If this property is specified
0047:         * with an invalid value then an <code>IllegalArgumentException</code> should
0048:         * be raised.
0049:         * </p>
0050:         * <p>
0051:         * Each element can be accessed using its position. The first element is at
0052:         * position 0. The direction of the name is important. When direction is
0053:         * "left_to_right" then the leftmost element is at position 0. Conversely when
0054:         * the direction is "right_to_left" then the rightmost element is at position 0.
0055:         * </p>
0056:         * <p>
0057:         * There are other properties which affect the syntax of a
0058:         * <code>CompoundName</code>. The following properties are all optional:
0059:         * <ul>
0060:         * <li> jndi.syntax.escape - Escape sequence,The escape sequence is used to
0061:         * escape a quote, separator or escape. When preceded itself by the escape
0062:         * sequence it is treated as ordinary characters. When it is followed by chars
0063:         * which are not quote or separator strings then it is treated as ordinary
0064:         * characters</li>
0065:         * <li> jndi.syntax.beginquote - Used as start of quoted string (Defaults to
0066:         * endquote)</li>
0067:         * <li> jndi.syntax.endquote - Used as end of quoted string (Defaults to
0068:         * beginquote)</li>
0069:         * <li> jndi.syntax.beginquote2 - Additionally used as start of quoted string
0070:         * (Defaults to endquote2)</li>
0071:         * <li> jndi.syntax.endquote2 - Additionally used as end of quoted string
0072:         * (Defaults to beginquote2)</li>
0073:         * </ul>
0074:         * <p>
0075:         * When a non-escaped quote appears at the start of an element it must be
0076:         * matched at the end. That element can then be said to be quoted. When an
0077:         * escape sequence appears within a quoted element then it is treated as normal
0078:         * characters unless it precedes an occurrence of the quote in which case it is
0079:         * assumed that the quoted element contains a quote which is escaped.
0080:         * </p>
0081:         * <p>
0082:         * If the element does not start with a quote, then any quote strings within
0083:         * that element are just normal characters.
0084:         * </p>
0085:         * <p>
0086:         * <ul>
0087:         * <li> jndi.syntax.ignorecase - If 'true' then ignore case when name elements
0088:         * are compared. If false or not set then case is important.</li>
0089:         * <li> jndi.syntax.trimblanks - If 'true' then ignore leading & trailing blanks
0090:         * when name elements are compared. If false or not set then blanks are
0091:         * important.</li>
0092:         * </ul>
0093:         * </p>
0094:         * <p>
0095:         * These 2 properties relate to names where the syntax includes
0096:         * attribute/content pairs.
0097:         * <ul>
0098:         * <li>jndi.syntax.separator.ava</li>
0099:         * <li>jndi.syntax.separator.typeval</li>
0100:         * </ul>
0101:         * For example the LDAP name, "CN=Mandy Jennings, O=Apache, C=UK". In this
0102:         * example the pair separator jndi.syntax.separator.ava is ',', and the
0103:         * character that separates pairs jndi.syntax.separator.typeval is '='. See
0104:         * RFC1779 for LDAP naming conventions.
0105:         * </p>
0106:         * <p>
0107:         * The jndi.syntax.separator.ava is not used when manipulating
0108:         * <code>CompoundName</code>. The jndi.syntax.separator is still used to
0109:         * separate elements.
0110:         * </p>
0111:         * <p>
0112:         * The <code>CompoundName</code> needs to be aware of the
0113:         * jndi.syntax.separator.typeval in case of the instance where a quoted string
0114:         * is used to provide the content of a pair.
0115:         * </p>
0116:         * <p>
0117:         * Consider the string "CN=$Mandy Jennings, O=Apache, C=UK" with
0118:         * <ul>
0119:         * <li> jndi.syntax.direction set to "right_to_left"</li>
0120:         * <li> jndi.syntax.separator set to ","</li>
0121:         * <li> jndi.syntax.separator.typeval set to "="</li>
0122:         * </ul>
0123:         * When no jndi.syntax.beginquote is set then this creates a valid
0124:         * <code>CompoundName</code> with 3 elements.
0125:         * </p>
0126:         * <p>
0127:         * If jndi.syntax.beginquote is then set to "$" the name becomes invalid as the
0128:         * content part of the pair CN=$Mandy Jennings has a mismatched quote.
0129:         * </p>
0130:         * <p>
0131:         * The string "CN=$Mandy Jennings$, O=Apache, C=UK" would be fine as the $
0132:         * quotes round Mandy Jennings now balance.
0133:         * </p>
0134:         * <p>
0135:         * A <code>CompoundName</code> may be empty. An empty
0136:         * <code>CompoundName</code> has no elements. Elements may also be empty.
0137:         * </p>
0138:         * 
0139:         * <pre>
0140:         * Some Examples:
0141:         * ==============
0142:         * 
0143:         * Consider the following compound name from the file system namespace:
0144:         *     &quot;home/jenningm-abc/.profile&quot; 
0145:         * 
0146:         * jndi.syntax.separator is set to '/' as in the UNIX filesystem.
0147:         * This name has 3 elements:
0148:         *     home jenningm-abc and .profile
0149:         * The direction should be left_to_right as in the UNIX filesystem
0150:         * The element at position 0 would be home.
0151:         * 
0152:         * Consider if jndi.syntax.separator had been set to '-' then this name 
0153:         * would have 2 elements:
0154:         *     home/jenningm and abc/.profile
0155:         * If the direction was right_to_left then the element at position 0
0156:         * would be abc/.profile.
0157:         * 
0158:         * Consider the name &quot;&lt;ab&lt;cd&gt;ef&gt;&quot; where jndi.syntax.beginquote is &lt;
0159:         * and jndi.syntax.endquote is &gt;. This will give rise to an 
0160:         * InvalidNameException because a close quote was encountered before
0161:         * the end of an element. The same is also true for &quot;&lt;abcd&gt;ef&gt;&quot;.
0162:         * If the name was &quot;ab&lt;cd&gt;ef&quot; then this would be valid and there would
0163:         * be one element ab&lt;cd&gt;ef.
0164:         * However if the name was &quot;&lt;abcdef&gt;&quot; there would be one element abcdef.
0165:         * 
0166:         * An empty
0167:         * <code>
0168:         * CompoundName
0169:         * </code>
0170:         *  is the name &quot;&quot; and has no elements.
0171:         * 
0172:         * When jndi.syntax.beginquote is set to &quot; and beginquote2 is set to '
0173:         * the behaviour is similar to CompositeName - 
0174:         * The name &quot;\&quot;abcd&quot; gives an InvalidNameException as there is no closing quote.
0175:         * The name &quot;'\&quot;abcd'&quot; gives one element of value &quot;abcd.
0176:         * The name &quot;\\abcd&quot; gives one element of value \abcd. 
0177:         *  
0178:         * Assuming:
0179:         *     jndi.syntax.separator is &quot;/&quot;
0180:         *     jndi.syntax.direction is &quot;left_to_right&quot;
0181:         * then
0182:         *     &quot;&quot; is empty. It has no elements.
0183:         *     &quot;/&quot; has one empty element.
0184:         *     &quot;//&quot; has 2 empty elements.
0185:         *     &quot;/a/&quot; has 3 elements the middle one is set to a.
0186:         *     &quot;///&quot; has 3 empty elements.
0187:         *     &quot;//a/&quot; has 4 elements, the last but one is set to a.
0188:         * 
0189:         * 
0190:         * Assuming the only properties set are: 
0191:         *     jndi.syntax.separator is &quot;/&quot;
0192:         *     jndi.syntax.direction is &quot;left_to_right&quot;
0193:         * then the String
0194:         *     &quot;\&quot;&quot; has one element with the value &quot;
0195:         *     &quot;\\\&quot;&quot; has one element with the value \&quot;
0196:         *     &quot;\\\&quot;'&quot; has one element with the value \&quot;'
0197:         * 
0198:         * Assuming the only properties set are:
0199:         *     jndi.syntax.separator is &quot;/&quot;
0200:         *     jndi.syntax.direction is &quot;left_to_right&quot;
0201:         *     jndi.syntax.beginquote is &quot;\&quot;&quot;
0202:         * 
0203:         * then the String
0204:         *     &quot;\&quot;&quot; is invalid because of no closing quote
0205:         *     &quot;\\\&quot;&quot; has one element with the value \&quot;
0206:         *     &quot;\\\&quot;'&quot; has one element with the value \&quot;'
0207:         * 
0208:         * Assuming the only properties set are:
0209:         *     jndi.syntax.separator is &quot;/&quot;
0210:         *     jndi.syntax.direction is &quot;left_to_right&quot;
0211:         *     jndi.syntax.beginquote is &quot;\&quot;&quot;
0212:         *     jndi.syntax.beginquote2 is &quot;\'&quot;
0213:         * then the String
0214:         *     &quot;\&quot;&quot; is invalid because of no closing quote
0215:         *     &quot;\\\&quot;&quot; has one element with the value \&quot;
0216:         *     &quot;\\\&quot;'&quot; has one element with the value \&quot;'
0217:         *     &quot;'\\&quot; is invalid because of no closing quote
0218:         * </pre>
0219:         */
0220:        public class CompoundName implements  Name {
0221:
0222:            /*
0223:             * Note: For serialization purposes, the specified serialVersionUID must be
0224:             * used. This class does not have serializable fields specified. Instead the
0225:             * readObject and writeObject methods are overridden.
0226:             */
0227:            private static final long serialVersionUID = 3513100557083972036L;
0228:
0229:            // const for property key
0230:            private static final String SEPARATOR = "jndi.syntax.separator"; //$NON-NLS-1$
0231:
0232:            private static final String SEPARATOR_AVA = "jndi.syntax.separator.ava"; //$NON-NLS-1$
0233:
0234:            private static final String SEPARATOR_TYPEVAL = "jndi.syntax.separator.typeval"; //$NON-NLS-1$
0235:
0236:            private static final String ESCAPE = "jndi.syntax.escape"; //$NON-NLS-1$
0237:
0238:            private static final String BEGIN_QUOTE = "jndi.syntax.beginquote"; //$NON-NLS-1$
0239:
0240:            private static final String END_QUOTE = "jndi.syntax.endquote"; //$NON-NLS-1$
0241:
0242:            private static final String BEGIN_QUOTE2 = "jndi.syntax.beginquote2"; //$NON-NLS-1$
0243:
0244:            private static final String END_QUOTE2 = "jndi.syntax.endquote2"; //$NON-NLS-1$
0245:
0246:            private static final String IGNORE_CASE = "jndi.syntax.ignorecase"; //$NON-NLS-1$
0247:
0248:            private static final String TRIM_BLANKS = "jndi.syntax.trimblanks"; //$NON-NLS-1$
0249:
0250:            private static final String DIRECTION = "jndi.syntax.direction"; //$NON-NLS-1$
0251:
0252:            private static final String SEPARATOR2 = "jndi.syntax.separator2"; //$NON-NLS-1$
0253:
0254:            // const for direction
0255:            private static final String LEFT_TO_RIGHT = "left_to_right"; //$NON-NLS-1$
0256:
0257:            private static final String RIGHT_TO_LEFT = "right_to_left"; //$NON-NLS-1$
0258:
0259:            private static final String FLAT = "flat"; //$NON-NLS-1$
0260:
0261:            // alphabets consts
0262:            private static final String NULL_STRING = ""; //$NON-NLS-1$
0263:
0264:            // states consts
0265:            private static final int NORMAL_STATUS = 0;
0266:
0267:            private static final int QUOTE1_STATUS = 1;
0268:
0269:            private static final int QUOTE2_STATUS = 2;
0270:
0271:            private static final int INIT_STATUS = 3;
0272:
0273:            private static final int QUOTEEND_STATUS = 4;
0274:
0275:            // properties variables
0276:            private transient String separatorString;
0277:
0278:            private transient String separatorString2;
0279:
0280:            private transient String escapeString;
0281:
0282:            private transient String endQuoteString;
0283:
0284:            private transient String endQuoteString2;
0285:
0286:            private transient String beginQuoteString;
0287:
0288:            private transient String beginQuoteString2;
0289:
0290:            private transient String sepAvaString;
0291:
0292:            private transient String sepTypeValString;
0293:
0294:            private transient String direction;
0295:
0296:            private transient boolean trimBlanks;
0297:
0298:            private transient boolean ignoreCase;
0299:
0300:            private transient boolean flat;
0301:
0302:            // elements of compound name
0303:            private transient Vector<String> elem;
0304:
0305:            // property setting
0306:            protected transient Properties mySyntax;
0307:
0308:            /*
0309:             * The specification calls for a protected variable called 'impl' which is
0310:             * of a non-API type. I believe this is an error in the spec, but to be
0311:             * complaint we have implemented this as a useless class (below).
0312:             */
0313:            protected transient javax.naming.NameImpl impl = new NameImpl();
0314:
0315:            /**
0316:             * Constructs a <code>CompoundName</code> with supplied
0317:             * <code>Enumeration</code> and <code>Properties</code>
0318:             * 
0319:             * @param elements
0320:             *            an enumeration of name elements, cannot be null
0321:             * @param props
0322:             *            the properties, cannot be null but may be empty. If empty, the
0323:             *            direction defaults to flat and no other properties are
0324:             *            required.
0325:             */
0326:            protected CompoundName(Enumeration<String> elements,
0327:                    Properties props) {
0328:                if (null == props || null == elements) {
0329:                    throw new NullPointerException();
0330:                }
0331:                init(props);
0332:                this .elem = new Vector<String>();
0333:                while (elements.hasMoreElements()) {
0334:                    this .elem.add(elements.nextElement());
0335:                }
0336:            }
0337:
0338:            /**
0339:             * Constructs a <code>CompoundName</code> with supplied
0340:             * <code>String</code> and <code>Properties</code>, taking the supplied
0341:             * <code>s</code> and breaking it down into its elements.
0342:             * 
0343:             * @param s
0344:             *            a string containing the full compound name
0345:             * @param props
0346:             *            the properties, cannot be null but may be empty for a flat
0347:             *            name
0348:             * @throws InvalidNameException
0349:             *             thrown if the supplied <code>String s</code> is invalid
0350:             * @throws NullPointerException
0351:             *             thrown if the supplied <code>String s</code> is null
0352:             */
0353:            public CompoundName(String s, Properties props)
0354:                    throws InvalidNameException {
0355:                if (null == s || null == props) {
0356:                    throw new NullPointerException();
0357:                }
0358:                init(props);
0359:                parseName(s);
0360:            }
0361:
0362:            /**
0363:             * init instance variables
0364:             */
0365:            private void init(Properties props) {
0366:                trimBlanks = false;
0367:                ignoreCase = false;
0368:                this .mySyntax = props;
0369:                String property;
0370:
0371:                // read property settings
0372:                // direction's default value is FLAT
0373:                direction = null == (property = props.getProperty(DIRECTION)) ? FLAT
0374:                        : property;
0375:                // if direction value must equals to one of FLAT, LEFT_TO_RIGHT and
0376:                // RIGHT_TO_LEFT, exception threw
0377:                if (!LEFT_TO_RIGHT.equals(direction)
0378:                        && !RIGHT_TO_LEFT.equals(direction)
0379:                        && !FLAT.equals(direction)) {
0380:                    // jndi.04=Illegal direction property value, which must be one of
0381:                    // right_to_left, left_to_right or flat
0382:                    throw new IllegalArgumentException(Messages
0383:                            .getString("jndi.04")); //$NON-NLS-1$
0384:                }
0385:                flat = FLAT.equals(direction);
0386:
0387:                separatorString = flat ? NULL_STRING : props
0388:                        .getProperty(SEPARATOR);
0389:                // if direction is not FLAT, separator must be set
0390:                if (null == separatorString && !flat) {
0391:                    // jndi.05=jndi.syntax.separator property must be set when
0392:                    // jndi.syntax.direction is not flat
0393:                    throw new IllegalArgumentException(Messages
0394:                            .getString("jndi.05")); //$NON-NLS-1$
0395:                }
0396:                separatorString2 = (flat || null == (property = props
0397:                        .getProperty(SEPARATOR2))) ? NULL_STRING : property;
0398:
0399:                // ignorecase default value is false
0400:                ignoreCase = null == (property = props.getProperty(IGNORE_CASE)) ? false
0401:                        : Boolean.valueOf(property).booleanValue();
0402:                // trimblanks default value is false
0403:                trimBlanks = null == (property = props.getProperty(TRIM_BLANKS)) ? false
0404:                        : Boolean.valueOf(property).booleanValue();
0405:                escapeString = null == (property = props.getProperty(ESCAPE)) ? NULL_STRING
0406:                        : property;
0407:                beginQuoteString = null == (property = props
0408:                        .getProperty(BEGIN_QUOTE)) ? NULL_STRING : property;
0409:                beginQuoteString2 = null == (property = props
0410:                        .getProperty(BEGIN_QUOTE2)) ? NULL_STRING : property;
0411:                // end quote string default value is begin quote string
0412:                endQuoteString = null == (property = props
0413:                        .getProperty(END_QUOTE)) ? beginQuoteString : property;
0414:                // begin quote string default value is end quote string
0415:                if (NULL_STRING.equals(beginQuoteString)) {
0416:                    beginQuoteString = endQuoteString;
0417:                }
0418:                // end quote string2 default value is begin quote string2
0419:                endQuoteString2 = null == (property = props
0420:                        .getProperty(END_QUOTE2)) ? beginQuoteString2
0421:                        : property;
0422:                // begin quote string2 default value is end quote string2
0423:                if (NULL_STRING.equals(beginQuoteString2)) {
0424:                    beginQuoteString2 = endQuoteString2;
0425:                }
0426:
0427:                sepTypeValString = null == (property = props
0428:                        .getProperty(SEPARATOR_TYPEVAL)) ? NULL_STRING
0429:                        : property;
0430:                sepAvaString = null == (property = props
0431:                        .getProperty(SEPARATOR_AVA)) ? NULL_STRING : property;
0432:            }
0433:
0434:            /*
0435:             * parse name from string to elements
0436:             */
0437:            private void parseName(String s) throws InvalidNameException {
0438:                this .elem = new Vector<String>();
0439:                if ("".equals(s)) { //$NON-NLS-1$
0440:                    // if empty string, return empty vector
0441:                    return;
0442:                }
0443:
0444:                // init variables
0445:                int status = INIT_STATUS;
0446:                StringBuilder element = new StringBuilder();
0447:                int pos = 0;
0448:                int length = s.length();
0449:                boolean hasNotNullElement = false;
0450:                boolean includeQuote = false;
0451:
0452:                // scan name
0453:                while (pos < length) {
0454:                    if (startsWithFromPos(s, pos, endQuoteString)
0455:                            && status == QUOTE1_STATUS) {
0456:                        status = QUOTEEND_STATUS;
0457:                        pos += addBuffer(element, endQuoteString, includeQuote);
0458:                    } else if (startsWithFromPos(s, pos, endQuoteString2)
0459:                            && status == QUOTE2_STATUS) {
0460:                        status = QUOTEEND_STATUS;
0461:                        pos += addBuffer(element, endQuoteString2, includeQuote);
0462:                    } else if (startsWithFromPos(s, pos, beginQuoteString)
0463:                            && status == INIT_STATUS) {
0464:                        hasNotNullElement = true;
0465:                        status = QUOTE1_STATUS;
0466:                        pos += addBuffer(element, beginQuoteString,
0467:                                includeQuote);
0468:                    } else if (startsWithFromPos(s, pos, beginQuoteString2)
0469:                            && status == INIT_STATUS) {
0470:                        hasNotNullElement = true;
0471:                        status = QUOTE2_STATUS;
0472:                        pos += addBuffer(element, beginQuoteString2,
0473:                                includeQuote);
0474:                    } else if (startsWithFromPos(s, pos, separatorString)
0475:                            && (!flat)
0476:                            && (status == INIT_STATUS
0477:                                    || status == QUOTEEND_STATUS || status == NORMAL_STATUS)) {
0478:                        hasNotNullElement = hasNotNullElement
0479:                                || element.length() > 0;
0480:                        addElement(element);
0481:                        status = INIT_STATUS;
0482:                        pos += separatorString.length();
0483:                        includeQuote = false;
0484:                    } else if (startsWithFromPos(s, pos, separatorString2)
0485:                            && (!flat)
0486:                            && (status == INIT_STATUS
0487:                                    || status == QUOTEEND_STATUS || status == NORMAL_STATUS)) {
0488:                        hasNotNullElement = hasNotNullElement
0489:                                || element.length() > 0;
0490:                        addElement(element);
0491:                        status = INIT_STATUS;
0492:                        pos += separatorString2.length();
0493:                        includeQuote = false;
0494:                    } else if (startsWithFromPos(s, pos, escapeString)) {
0495:                        pos += escapeString.length();
0496:                        if (pos == s.length()) {
0497:                            // if this escape char is last character, throw exception
0498:                            // jndi.06=The {0} cannot be at end of the component
0499:                            throw new InvalidNameException(Messages.getString(
0500:                                    "jndi.06", escapeString)); //$NON-NLS-1$
0501:                        }
0502:                        // if one escape char followed by a special char, append the
0503:                        // special char to current element
0504:                        String str = extractEscapedString(s, pos, status);
0505:                        if (null == str) {
0506:                            pos -= escapeString.length();
0507:                            element.append(s.charAt(pos++));
0508:                        } else {
0509:                            pos += str.length();
0510:                            element.append(str);
0511:                        }
0512:
0513:                    } else if (startsWithFromPos(s, pos, sepTypeValString)
0514:                            && (status == INIT_STATUS || status == NORMAL_STATUS)) {
0515:                        includeQuote = true;
0516:                        pos += addBuffer(element, sepTypeValString, true);
0517:                        status = INIT_STATUS;
0518:                    } else if (startsWithFromPos(s, pos, sepAvaString)
0519:                            && (status == INIT_STATUS || status == NORMAL_STATUS)) {
0520:                        includeQuote = true;
0521:                        pos += addBuffer(element, sepAvaString, true);
0522:                        status = INIT_STATUS;
0523:                    } else if (status == QUOTEEND_STATUS) {
0524:                        // jndi.07={0}: close quote must appears at end of component in
0525:                        // quoted string
0526:                        throw new InvalidNameException(Messages.getString(
0527:                                "jndi.07", s)); //$NON-NLS-1$
0528:                    } else {
0529:                        status = status == INIT_STATUS ? NORMAL_STATUS : status;
0530:                        element.append(s.charAt(pos++));
0531:                    }
0532:                }
0533:                if (QUOTE1_STATUS != status && QUOTE2_STATUS != status) {
0534:                    hasNotNullElement = hasNotNullElement
0535:                            || element.length() > 0;
0536:                    addElement(element);
0537:                } else {
0538:                    // jndi.08={0}: close quote is required for quoted string
0539:                    throw new InvalidNameException(Messages.getString(
0540:                            "jndi.08", s)); //$NON-NLS-1$
0541:                }
0542:                if (!hasNotNullElement) {
0543:                    elem.remove(elem.size() - 1);
0544:                }
0545:            }
0546:
0547:            /*
0548:             * add des parameter to StringBuilder if include is true
0549:             */
0550:            private int addBuffer(StringBuilder buffer, String des,
0551:                    boolean include) {
0552:                if (include) {
0553:                    buffer.append(des);
0554:                }
0555:                return des.length();
0556:            }
0557:
0558:            /*
0559:             * add current content of supplied string buffer as one element of this
0560:             * CompoundName and reset the string buffer to empty
0561:             */
0562:            private void addElement(StringBuilder element) {
0563:                if (LEFT_TO_RIGHT == direction) {
0564:                    elem.add(element.toString());
0565:                } else {
0566:                    elem.add(0, element.toString());
0567:                }
0568:                element.setLength(0);
0569:            }
0570:
0571:            /*
0572:             * find string to be escaped, if cannot find special string(which means,
0573:             * quote, separator and escape), return null
0574:             */
0575:            private String extractEscapedString(String s, int pos, int status) {
0576:                String result = null;
0577:                if (status == QUOTE1_STATUS
0578:                        && startsWithFromPos(s, pos, endQuoteString)) {
0579:                    result = endQuoteString;
0580:                } else if (status == QUOTE2_STATUS
0581:                        && startsWithFromPos(s, pos, endQuoteString2)) {
0582:                    result = endQuoteString2;
0583:                } else if (status != QUOTE1_STATUS && status != QUOTE2_STATUS) {
0584:                    if (startsWithFromPos(s, pos, beginQuoteString)) {
0585:                        result = beginQuoteString;
0586:                    } else if (startsWithFromPos(s, pos, beginQuoteString2)) {
0587:                        result = beginQuoteString2;
0588:                    } else if (startsWithFromPos(s, pos, endQuoteString)) {
0589:                        result = endQuoteString;
0590:                    } else if (startsWithFromPos(s, pos, endQuoteString2)) {
0591:                        result = endQuoteString2;
0592:                    } else if (startsWithFromPos(s, pos, separatorString)) {
0593:                        result = separatorString;
0594:                    } else if (startsWithFromPos(s, pos, separatorString2)) {
0595:                        result = separatorString2;
0596:                    } else if (startsWithFromPos(s, pos, escapeString)) {
0597:                        result = escapeString;
0598:                    }
0599:                }
0600:                return result;
0601:            }
0602:
0603:            /*
0604:             * justify if string src start with des from position pos
0605:             */
0606:            private boolean startsWithFromPos(String src, int pos, String des) {
0607:                if (null == src || null == des || NULL_STRING.equals(des)
0608:                        || src.length() - pos < des.length()) {
0609:                    return false;
0610:                }
0611:                int length = des.length();
0612:                int i = -1;
0613:                while (++i < length && src.charAt(pos + i) == des.charAt(i)) {
0614:                    // empty body
0615:                }
0616:                return i == length;
0617:            }
0618:
0619:            public Enumeration<String> getAll() {
0620:                return this .elem.elements();
0621:            }
0622:
0623:            public String get(int index) {
0624:                validateIndex(index, false);
0625:                return elem.elementAt(index);
0626:            }
0627:
0628:            /*
0629:             * validate the index, if isInclude is true, index which equals to
0630:             * this.size() is considered as valid, otherwise invalid
0631:             */
0632:            private void validateIndex(int index, boolean isInclude) {
0633:                if (0 > index || index > elem.size()
0634:                        || (!isInclude && index == elem.size())) {
0635:                    throw new ArrayIndexOutOfBoundsException();
0636:                }
0637:            }
0638:
0639:            public Name getPrefix(int index) {
0640:                validateIndex(index, true);
0641:                return new CompoundName(new Vector<String>(elem.subList(0,
0642:                        index)).elements(), mySyntax);
0643:            }
0644:
0645:            public Name getSuffix(int index) {
0646:                validateIndex(index, false);
0647:                return new CompoundName(new Vector<String>(elem.subList(index,
0648:                        elem.size())).elements(), mySyntax);
0649:            }
0650:
0651:            public Name addAll(Name name) throws InvalidNameException {
0652:                return addAll(elem.size(), name);
0653:            }
0654:
0655:            public Name addAll(int index, Name name)
0656:                    throws InvalidNameException {
0657:                if (name == null) {
0658:                    // jndi.00=name must not be null
0659:                    throw new NullPointerException(Messages
0660:                            .getString("jndi.00")); //$NON-NLS-1$
0661:                }
0662:                if (!(name instanceof  CompoundName)) {
0663:                    // jndi.09={0} is not a compound name.
0664:                    throw new InvalidNameException(Messages.getString(
0665:                            "jndi.09", name.toString())); //$NON-NLS-1$
0666:                }
0667:                if (FLAT.equals(direction) && (this .size() + name.size() > 1)) {
0668:                    // jndi.0A=A flat name can only have a single component
0669:                    throw new InvalidNameException(Messages
0670:                            .getString("jndi.0A")); //$NON-NLS-1$
0671:                }
0672:                validateIndex(index, true);
0673:                Enumeration<String> enumeration = name.getAll();
0674:                while (enumeration.hasMoreElements()) {
0675:                    elem.add(index++, enumeration.nextElement());
0676:                }
0677:                return this ;
0678:            }
0679:
0680:            public Name add(String element) throws InvalidNameException {
0681:                if (element == null) {
0682:                    // jndi.8C=component must not be null
0683:                    throw new IllegalArgumentException(Messages
0684:                            .getString("jndi.8C")); //$NON-NLS-1$
0685:                }
0686:                if (FLAT.equals(direction) && (size() > 0)) {
0687:                    // jndi.0A=A flat name can only have a single component
0688:                    throw new InvalidNameException(Messages
0689:                            .getString("jndi.0A")); //$NON-NLS-1$
0690:                }
0691:                elem.add(element);
0692:                return this ;
0693:            }
0694:
0695:            /**
0696:             * Insert an element within this CompoundName at the specified index.
0697:             * 
0698:             * @return this <code>CompoundName</code>.
0699:             * @param element
0700:             *            the String to insert
0701:             * @param index
0702:             *            the index of the element to insert - must be greater than or
0703:             *            equal to 0 and less than size().
0704:             * @throws ArrayIndexOutOfBoundsException
0705:             *             thrown when the index is invalid.
0706:             * @throws InvalidNameException
0707:             *             thrown if the insertion of the element results in this
0708:             *             <code>CompoundName</code> becoming invalid.
0709:             */
0710:            public Name add(int index, String element)
0711:                    throws InvalidNameException {
0712:                if (element == null) {
0713:                    // jndi.8C=component must not be null
0714:                    throw new IllegalArgumentException(Messages
0715:                            .getString("jndi.8C")); //$NON-NLS-1$
0716:                }
0717:                if (FLAT.equals(direction) && (size() > 0)) {
0718:                    // jndi.0A=A flat name can only have a single component
0719:                    throw new InvalidNameException(Messages
0720:                            .getString("jndi.0A")); //$NON-NLS-1$
0721:                }
0722:                validateIndex(index, true);
0723:                elem.add(index, element);
0724:                return this ;
0725:            }
0726:
0727:            /**
0728:             * Delete an element from this <code>CompoundName</code>.
0729:             * 
0730:             * @return the deleted element
0731:             * @param index
0732:             *            the index of the element to delete - must be greater than or
0733:             *            equal to 0 and less than size().
0734:             * @throws ArrayIndexOutOfBoundsException
0735:             *             thrown when the index is invalid.
0736:             * @throws InvalidNameException
0737:             *             thrown if the deletion of the element results in this
0738:             *             <code>CompoundName</code> becoming invalid.
0739:             */
0740:            public Object remove(int index) throws InvalidNameException {
0741:                validateIndex(index, false);
0742:                return elem.remove(index);
0743:            }
0744:
0745:            @Override
0746:            public Object clone() {
0747:                return new CompoundName(getAll(), mySyntax);
0748:            }
0749:
0750:            public int size() {
0751:                return elem.size();
0752:            }
0753:
0754:            public boolean isEmpty() {
0755:                return elem.isEmpty();
0756:            }
0757:
0758:            public boolean startsWith(Name name) {
0759:                if (!(name instanceof  CompoundName)) {
0760:                    return false;
0761:                }
0762:                return equals(name, 0, name.size());
0763:            }
0764:
0765:            public boolean endsWith(Name name) {
0766:                if (!(name instanceof  CompoundName)) {
0767:                    return false;
0768:                }
0769:                return equals(name, this .size() - name.size(), name.size());
0770:            }
0771:
0772:            /**
0773:             * preprocess string according to trimblank and ignorecase properties
0774:             */
0775:            private String preProcess(String string, boolean caseInsensitive,
0776:                    boolean removeBlanks) {
0777:                String result = string;
0778:                if (null != string && !"".equals(string)) { //$NON-NLS-1$
0779:                    result = caseInsensitive ? result.toLowerCase() : result;
0780:                    result = removeBlanks ? result.trim() : result;
0781:                }
0782:                return result;
0783:            }
0784:
0785:            /**
0786:             * Writes a serialized representation of the CompoundName. It starts with
0787:             * the properties, followed by an int which is the number of elements in the
0788:             * name, and is followed by a String for each element.
0789:             * 
0790:             * @throws java.io.IOException
0791:             *             if an error is encountered writing to the stream.
0792:             */
0793:            private void writeObject(ObjectOutputStream oos) throws IOException {
0794:                oos.defaultWriteObject();
0795:                oos.writeObject(mySyntax);
0796:                oos.writeInt(elem.size());
0797:                for (int i = 0; i < elem.size(); i++) {
0798:                    String element = elem.elementAt(i);
0799:                    oos.writeObject(element);
0800:                }
0801:            }
0802:
0803:            /**
0804:             * Recreate a CompoundName from the data in the supplied stream.
0805:             * Additionally there are 2 protected fields which are not serializable. One
0806:             * of them is of a type which is a private class and cannot therefore be
0807:             * specified or implemented and so will be excluded from our deliverable.
0808:             * The one protected field which we can spec and implement is as follows:
0809:             * protected Properties mySyntax - The properties associated with a
0810:             * CompoundName.
0811:             * 
0812:             * @throws java.io.IOException
0813:             *             if an error is encountered reading from the stream.
0814:             * @throws ClassNotFoundException.
0815:             */
0816:            private void readObject(ObjectInputStream ois)
0817:                    throws ClassNotFoundException, IOException {
0818:                ois.defaultReadObject();
0819:                init(((Properties) ois.readObject()));
0820:                int size = ois.readInt();
0821:                elem = new Vector<String>();
0822:                for (int i = 0; i < size; i++) {
0823:                    elem.add((String) ois.readObject());
0824:                }
0825:            }
0826:
0827:            /**
0828:             * Compare this <code>CompoundName</code> with the one supplied as a
0829:             * param.
0830:             * <p>
0831:             * See the definition of the <code>equals()</code> method to see how the
0832:             * direction, ignorecase and trimblanks properties affect the comparison of
0833:             * a <code>CompoundName</code>. Other than that the comparison is the
0834:             * same as that for a <code>CompositeName</code>.
0835:             * </p>
0836:             * 
0837:             * @return a negative number means this is less than the supplied Object
0838:             *         <code>o</code>. a positive number means this is greater than
0839:             *         the supplied Object <code>o</code>. zero means the two objects
0840:             *         are equal.
0841:             * @param o
0842:             *            the object to compare - cannot be null.
0843:             * @throws ClassCastException
0844:             *             when <code>o</code> is not a compatible class that can be
0845:             *             compared or if the object to compare <code>o</code> is
0846:             *             null.
0847:             */
0848:            public int compareTo(Object o) {
0849:                if (!(o instanceof  CompoundName)) {
0850:                    throw new ClassCastException();
0851:                }
0852:                int result = -1;
0853:                CompoundName otherName = (CompoundName) o;
0854:                Enumeration<String> otherEnum = otherName.getAll();
0855:                String this Element;
0856:                String otherElement;
0857:                int i;
0858:                for (i = 0; i < size() && otherEnum.hasMoreElements(); i++) {
0859:                    this Element = preProcess(elem.get(i), ignoreCase,
0860:                            trimBlanks);
0861:                    otherElement = preProcess(otherEnum.nextElement(),
0862:                            ignoreCase, trimBlanks);
0863:                    result = (null == this Element ? (null == otherElement ? 0
0864:                            : -1) : this Element.compareTo(otherElement));
0865:                    if (0 != result) {
0866:                        return result;
0867:                    }
0868:                }
0869:                if (i < size()) {
0870:                    result = 1;
0871:                } else if (otherEnum.hasMoreElements()) {
0872:                    result = -1;
0873:                }
0874:                return result;
0875:            }
0876:
0877:            /**
0878:             * Calculate the hashcode of this <code>CompoundName</code> by summing the
0879:             * hashcodes of all of its elements.
0880:             * <p>
0881:             * If jndi.syntax.trimblanks is set to true then remove any leading and
0882:             * trailing blanks from the elements before calculating the hashcode.
0883:             * </p>
0884:             * <p>
0885:             * If jndi.syntax.ignorecase is set to true then use the lowercase version
0886:             * of the element to calculate its hashcode.
0887:             * </p>
0888:             * 
0889:             * @return the hashcode of this object.
0890:             */
0891:            @Override
0892:            public int hashCode() {
0893:                int result = 0;
0894:                Enumeration<String> enumeration = elem.elements();
0895:                while (enumeration.hasMoreElements()) {
0896:                    result += preProcess(enumeration.nextElement(), ignoreCase,
0897:                            trimBlanks).hashCode();
0898:                }
0899:                return result;
0900:            }
0901:
0902:            /**
0903:             * Gets the string representation of this <code>CompoundName</code>.
0904:             * <p>
0905:             * This is generated by concatenating the elements together with the
0906:             * separator string added as the separator between each of them. It may be
0907:             * necessary to add quotes and escape string to preserve the meaning. The
0908:             * resulting string should produce an equivalent <code>CompoundName</code>
0909:             * when used to create a new instance.
0910:             * </p>
0911:             * 
0912:             * @return the string representation of this <code>CompoundName</code>.
0913:             */
0914:            @Override
0915:            public String toString() {
0916:                StringBuilder sb = new StringBuilder();
0917:                String begin = NULL_STRING.equals(beginQuoteString) ? beginQuoteString2
0918:                        : beginQuoteString;
0919:                String end = NULL_STRING.equals(endQuoteString) ? endQuoteString2
0920:                        : endQuoteString;
0921:                String separator = NULL_STRING.equals(separatorString) ? separatorString2
0922:                        : separatorString;
0923:                if (RIGHT_TO_LEFT.equals(direction)) {
0924:                    for (int i = elem.size() - 1; i >= 0; i--) {
0925:                        addElement(sb, i, separator, begin, end);
0926:                    }
0927:                } else {
0928:                    for (int i = 0; i < elem.size(); i++) {
0929:                        addElement(sb, i, separator, begin, end);
0930:                    }
0931:                }
0932:                if (size() * separator.length() < sb.length()) {
0933:                    // if the name contains non-empty element, delete the last separator
0934:                    // char, which is abundant
0935:                    sb.setLength(sb.length() - separator.length());
0936:                }
0937:                return sb.toString();
0938:            }
0939:
0940:            private void addElement(StringBuilder sb, int index,
0941:                    String separator, String begin, String end) {
0942:                String elemString = elem.get(index);
0943:                if (0 == elemString.length()) {
0944:                    // if empty element, append a separator and continue
0945:                    sb.append(separator);
0946:                    return;
0947:                }
0948:                int pos = sb.length();
0949:                sb.append(elemString);
0950:                if (!NULL_STRING.equals(begin) && !NULL_STRING.equals(end)
0951:                        && !NULL_STRING.equals(separator)
0952:                        && (0 <= elemString.indexOf(separator))) {
0953:                    // if contains separator string, quoted it
0954:                    sb.insert(pos, begin);
0955:                    pos += begin.length();
0956:                    // if quoted, then every endquote char must be escaped
0957:                    for (int i = 0, j = 0; 0 <= (j = elemString.indexOf(end, i)); i = j
0958:                            + end.length()) {
0959:                        sb.insert(pos + j, escapeString);
0960:                        pos += escapeString.length();
0961:                    }
0962:                    sb.append(end);
0963:                } else {
0964:                    if (startsWithFromPos(elemString, 0, beginQuoteString)
0965:                            || startsWithFromPos(elemString, 0,
0966:                                    beginQuoteString2)) {
0967:                        // if not quoted and start with begin quote string, escape it
0968:                        sb.insert(pos, escapeString);
0969:                        pos += escapeString.length();
0970:                    }
0971:                    // if not quoted, escape all separator string and all escape string
0972:                    for (int i = 0; i < elemString.length();) {
0973:                        if (startsWithFromPos(elemString, i, separatorString)) {
0974:                            sb.insert(pos + i, escapeString);
0975:                            pos += escapeString.length();
0976:                            i += separatorString.length();
0977:                        } else if (startsWithFromPos(elemString, i,
0978:                                separatorString2)) {
0979:                            sb.insert(pos + i, escapeString);
0980:                            pos += escapeString.length();
0981:                            i += separatorString2.length();
0982:                        } else if (startsWithFromPos(elemString, i,
0983:                                escapeString)) {
0984:                            sb.insert(pos + i, escapeString);
0985:                            pos += escapeString.length();
0986:                            i += escapeString.length();
0987:                        } else {
0988:                            i++;
0989:                        }
0990:                    }
0991:                }
0992:                sb.append(separator);
0993:            }
0994:
0995:            /**
0996:             * Check if the supplied object <code>o</code> is equal to this
0997:             * <code>CompoundName</code>.
0998:             * <p>
0999:             * The supplied <code>Object o</code> may be null but that will cause
1000:             * false to be returned.
1001:             * </p>
1002:             * <p>
1003:             * The supplied <code>Object o</code> may be something other than a
1004:             * <code>CompoundName</code> but that will cause false to be returned.
1005:             * </p>
1006:             * <p>
1007:             * To be equal the supplied <code>CompoundName</code> must have the same
1008:             * number of elements and each element must match the corresponding element
1009:             * of this <code>CompoundName</code>. The properties
1010:             * jndi.syntax.ignorecase and jndi.syntax.trimblanks need to be considered
1011:             * if they have been set.
1012:             * </p>
1013:             * <p>
1014:             * The properties associated with the <code>CompoundName</code> must be
1015:             * taken into account but do not have to match. For example
1016:             * "home/jenningm-abc/.profile" with a direction of left to right is equal
1017:             * to ".profile/jenningm-abc/home" with a direction of right to left.
1018:             * </p>
1019:             * 
1020:             * @param o
1021:             *            the object to be compared
1022:             * @return true if supplied object <code>o</code> is equals to this
1023:             *         <code>CompoundName</code>, false otherwise
1024:             */
1025:            @Override
1026:            public boolean equals(Object o) {
1027:                if (!(o instanceof  CompoundName)) {
1028:                    return false;
1029:                }
1030:
1031:                // compare size
1032:                CompoundName otherName = (CompoundName) o;
1033:                final int size = otherName.size();
1034:                if (size != this .size()) {
1035:                    return false;
1036:                }
1037:
1038:                // compare every element
1039:                return equals(otherName, 0, size);
1040:            }
1041:
1042:            /**
1043:             * compare this name to the supplied <code>name</code> from position
1044:             * <code>start</code> to position <code>start</code>+
1045:             * <code>length</code>-1
1046:             */
1047:            private boolean equals(Name name, int start, int length) {
1048:                if (length > this .size()) {
1049:                    return false;
1050:                }
1051:                CompoundName otherName = (CompoundName) name;
1052:                Enumeration<String> otherEnum = otherName.getAll();
1053:                String this Element;
1054:                String otherElement;
1055:                for (int i = 0; i < length; i++) {
1056:                    this Element = preProcess(elem.get(i + start), ignoreCase,
1057:                            trimBlanks);
1058:                    otherElement = preProcess(otherEnum.nextElement(),
1059:                            ignoreCase, trimBlanks);
1060:                    if (!(null == this Element ? null == otherElement
1061:                            : this Element.equals(otherElement))) {
1062:                        return false;
1063:                    }
1064:                }
1065:                return true;
1066:            }
1067:
1068:        }
www.java2java.com | Contact Us
Copyright 2009 - 12 Demo Source and Support. All rights reserved.
All other trademarks are property of their respective owners.