1
25
26 package javax.naming;
27
28 import java.util.Locale;
29 import java.util.Vector;
30 import java.util.Enumeration;
31 import java.util.Properties;
32 import java.util.NoSuchElementException;
33
34
43
44 class NameImpl {
45 private static final byte LEFT_TO_RIGHT = 1;
46 private static final byte RIGHT_TO_LEFT = 2;
47 private static final byte FLAT = 0;
48
49 private Vector<String> components;
50
51 private byte syntaxDirection = LEFT_TO_RIGHT;
52 private String syntaxSeparator = "/";
53 private String syntaxSeparator2 = null;
54 private boolean syntaxCaseInsensitive = false;
55 private boolean syntaxTrimBlanks = false;
56 private String syntaxEscape = "\\";
57 private String syntaxBeginQuote1 = "\"";
58 private String syntaxEndQuote1 = "\"";
59 private String syntaxBeginQuote2 = "'";
60 private String syntaxEndQuote2 = "'";
61 private String syntaxAvaSeparator = null;
62 private String syntaxTypevalSeparator = null;
63
64
65
66
67
68 private static final int STYLE_NONE = 0;
69 private static final int STYLE_QUOTE1 = 1;
70 private static final int STYLE_QUOTE2 = 2;
71 private static final int STYLE_ESCAPE = 3;
72 private int escapingStyle = STYLE_NONE;
73
74
75
76 private final boolean isA(String n, int i, String match) {
77 return (match != null && n.startsWith(match, i));
78 }
79
80 private final boolean isMeta(String n, int i) {
81 return (isA(n, i, syntaxEscape) ||
82 isA(n, i, syntaxBeginQuote1) ||
83 isA(n, i, syntaxBeginQuote2) ||
84 isSeparator(n, i));
85 }
86
87 private final boolean isSeparator(String n, int i) {
88 return (isA(n, i, syntaxSeparator) ||
89 isA(n, i, syntaxSeparator2));
90 }
91
92 private final int skipSeparator(String name, int i) {
93 if (isA(name, i, syntaxSeparator)) {
94 i += syntaxSeparator.length();
95 } else if (isA(name, i, syntaxSeparator2)) {
96 i += syntaxSeparator2.length();
97 }
98 return (i);
99 }
100
101 private final int extractComp(String name, int i, int len, Vector<String> comps)
102 throws InvalidNameException {
103 String beginQuote;
104 String endQuote;
105 boolean start = true;
106 boolean one = false;
107 StringBuffer answer = new StringBuffer(len);
108
109 while (i < len) {
110
111 if (start && ((one = isA(name, i, syntaxBeginQuote1)) ||
112 isA(name, i, syntaxBeginQuote2))) {
113
114
115 beginQuote = one ? syntaxBeginQuote1 : syntaxBeginQuote2;
116 endQuote = one ? syntaxEndQuote1 : syntaxEndQuote2;
117 if (escapingStyle == STYLE_NONE) {
118 escapingStyle = one ? STYLE_QUOTE1 : STYLE_QUOTE2;
119 }
120
121
122 for (i += beginQuote.length();
123 ((i < len) && !name.startsWith(endQuote, i));
124 i++) {
125
126
127 if (isA(name, i, syntaxEscape) &&
128 isA(name, i + syntaxEscape.length(), endQuote)) {
129 i += syntaxEscape.length();
130 }
131 answer.append(name.charAt(i));
132 }
133
134
135 if (i >= len)
136 throw
137 new InvalidNameException(name + ": no close quote");
138
139
140 i += endQuote.length();
141
142
143 if (i == len || isSeparator(name, i)) {
144 break;
145 }
146
147 throw (new InvalidNameException(name +
148 ": close quote appears before end of component"));
149
150 } else if (isSeparator(name, i)) {
151 break;
152
153 } else if (isA(name, i, syntaxEscape)) {
154 if (isMeta(name, i + syntaxEscape.length())) {
155
156
157 i += syntaxEscape.length();
158 if (escapingStyle == STYLE_NONE) {
159 escapingStyle = STYLE_ESCAPE;
160 }
161 } else if (i + syntaxEscape.length() >= len) {
162 throw (new InvalidNameException(name +
163 ": unescaped " + syntaxEscape + " at end of component"));
164 }
165 } else if (isA(name, i, syntaxTypevalSeparator) &&
166 ((one = isA(name, i+syntaxTypevalSeparator.length(), syntaxBeginQuote1)) ||
167 isA(name, i+syntaxTypevalSeparator.length(), syntaxBeginQuote2))) {
168
169 beginQuote = one ? syntaxBeginQuote1 : syntaxBeginQuote2;
170 endQuote = one ? syntaxEndQuote1 : syntaxEndQuote2;
171
172 i += syntaxTypevalSeparator.length();
173 answer.append(syntaxTypevalSeparator+beginQuote);
174
175
176 for (i += beginQuote.length();
177 ((i < len) && !name.startsWith(endQuote, i));
178 i++) {
179
180
181 if (isA(name, i, syntaxEscape) &&
182 isA(name, i + syntaxEscape.length(), endQuote)) {
183 i += syntaxEscape.length();
184 }
185 answer.append(name.charAt(i));
186 }
187
188
189 if (i >= len)
190 throw
191 new InvalidNameException(name + ": typeval no close quote");
192
193 i += endQuote.length();
194 answer.append(endQuote);
195
196
197 if (i == len || isSeparator(name, i)) {
198 break;
199 }
200 throw (new InvalidNameException(name.substring(i) +
201 ": typeval close quote appears before end of component"));
202 }
203
204 answer.append(name.charAt(i++));
205 start = false;
206 }
207
208 if (syntaxDirection == RIGHT_TO_LEFT)
209 comps.insertElementAt(answer.toString(), 0);
210 else
211 comps.addElement(answer.toString());
212 return i;
213 }
214
215 private static boolean getBoolean(Properties p, String name) {
216 return toBoolean(p.getProperty(name));
217 }
218
219 private static boolean toBoolean(String name) {
220 return ((name != null) &&
221 name.toLowerCase(Locale.ENGLISH).equals("true"));
222 }
223
224 private final void recordNamingConvention(Properties p) {
225 String syntaxDirectionStr =
226 p.getProperty("jndi.syntax.direction", "flat");
227 if (syntaxDirectionStr.equals("left_to_right")) {
228 syntaxDirection = LEFT_TO_RIGHT;
229 } else if (syntaxDirectionStr.equals("right_to_left")) {
230 syntaxDirection = RIGHT_TO_LEFT;
231 } else if (syntaxDirectionStr.equals("flat")) {
232 syntaxDirection = FLAT;
233 } else {
234 throw new IllegalArgumentException(syntaxDirectionStr +
235 "is not a valid value for the jndi.syntax.direction property");
236 }
237
238 if (syntaxDirection != FLAT) {
239 syntaxSeparator = p.getProperty("jndi.syntax.separator");
240 syntaxSeparator2 = p.getProperty("jndi.syntax.separator2");
241 if (syntaxSeparator == null) {
242 throw new IllegalArgumentException(
243 "jndi.syntax.separator property required for non-flat syntax");
244 }
245 } else {
246 syntaxSeparator = null;
247 }
248 syntaxEscape = p.getProperty("jndi.syntax.escape");
249
250 syntaxCaseInsensitive = getBoolean(p, "jndi.syntax.ignorecase");
251 syntaxTrimBlanks = getBoolean(p, "jndi.syntax.trimblanks");
252
253 syntaxBeginQuote1 = p.getProperty("jndi.syntax.beginquote");
254 syntaxEndQuote1 = p.getProperty("jndi.syntax.endquote");
255 if (syntaxEndQuote1 == null && syntaxBeginQuote1 != null)
256 syntaxEndQuote1 = syntaxBeginQuote1;
257 else if (syntaxBeginQuote1 == null && syntaxEndQuote1 != null)
258 syntaxBeginQuote1 = syntaxEndQuote1;
259 syntaxBeginQuote2 = p.getProperty("jndi.syntax.beginquote2");
260 syntaxEndQuote2 = p.getProperty("jndi.syntax.endquote2");
261 if (syntaxEndQuote2 == null && syntaxBeginQuote2 != null)
262 syntaxEndQuote2 = syntaxBeginQuote2;
263 else if (syntaxBeginQuote2 == null && syntaxEndQuote2 != null)
264 syntaxBeginQuote2 = syntaxEndQuote2;
265
266 syntaxAvaSeparator = p.getProperty("jndi.syntax.separator.ava");
267 syntaxTypevalSeparator =
268 p.getProperty("jndi.syntax.separator.typeval");
269 }
270
271 NameImpl(Properties syntax) {
272 if (syntax != null) {
273 recordNamingConvention(syntax);
274 }
275 components = new Vector<>();
276 }
277
278 NameImpl(Properties syntax, String n) throws InvalidNameException {
279 this(syntax);
280
281 boolean rToL = (syntaxDirection == RIGHT_TO_LEFT);
282 boolean compsAllEmpty = true;
283 int len = n.length();
284
285 for (int i = 0; i < len; ) {
286 i = extractComp(n, i, len, components);
287
288 String comp = rToL
289 ? components.firstElement()
290 : components.lastElement();
291 if (comp.length() >= 1) {
292 compsAllEmpty = false;
293 }
294
295 if (i < len) {
296 i = skipSeparator(n, i);
297 if ((i == len) && !compsAllEmpty) {
298
299 if (rToL) {
300 components.insertElementAt("", 0);
301 } else {
302 components.addElement("");
303 }
304 }
305 }
306 }
307 }
308
309 NameImpl(Properties syntax, Enumeration<String> comps) {
310 this(syntax);
311
312
313 while (comps.hasMoreElements())
314 components.addElement(comps.nextElement());
315 }
316
340 private final String stringifyComp(String comp) {
341 int len = comp.length();
342 boolean escapeSeparator = false, escapeSeparator2 = false;
343 String beginQuote = null, endQuote = null;
344 StringBuffer strbuf = new StringBuffer(len);
345
346
347
348 if (syntaxSeparator != null &&
349 comp.indexOf(syntaxSeparator) >= 0) {
350 if (syntaxBeginQuote1 != null) {
351 beginQuote = syntaxBeginQuote1;
352 endQuote = syntaxEndQuote1;
353 } else if (syntaxBeginQuote2 != null) {
354 beginQuote = syntaxBeginQuote2;
355 endQuote = syntaxEndQuote2;
356 } else if (syntaxEscape != null)
357 escapeSeparator = true;
358 }
359 if (syntaxSeparator2 != null &&
360 comp.indexOf(syntaxSeparator2) >= 0) {
361 if (syntaxBeginQuote1 != null) {
362 if (beginQuote == null) {
363 beginQuote = syntaxBeginQuote1;
364 endQuote = syntaxEndQuote1;
365 }
366 } else if (syntaxBeginQuote2 != null) {
367 if (beginQuote == null) {
368 beginQuote = syntaxBeginQuote2;
369 endQuote = syntaxEndQuote2;
370 }
371 } else if (syntaxEscape != null)
372 escapeSeparator2 = true;
373 }
374
375
376 if (beginQuote != null) {
377
378
379 strbuf = strbuf.append(beginQuote);
380
381
382
383 for (int i = 0; i < len; ) {
384 if (comp.startsWith(endQuote, i)) {
385
386 strbuf.append(syntaxEscape).append(endQuote);
387 i += endQuote.length();
388 } else {
389
390 strbuf.append(comp.charAt(i++));
391 }
392 }
393
394
395 strbuf.append(endQuote);
396
397 } else {
398
399
400
401
402
403
404
405
406 boolean start = true;
407 for (int i = 0; i < len; ) {
408
409 if (start && isA(comp, i, syntaxBeginQuote1)) {
410 strbuf.append(syntaxEscape).append(syntaxBeginQuote1);
411 i += syntaxBeginQuote1.length();
412 } else if (start && isA(comp, i, syntaxBeginQuote2)) {
413 strbuf.append(syntaxEscape).append(syntaxBeginQuote2);
414 i += syntaxBeginQuote2.length();
415 } else
416
417
418
419 if (isA(comp, i, syntaxEscape)) {
420 if (i + syntaxEscape.length() >= len) {
421
422 strbuf.append(syntaxEscape);
423 } else if (isMeta(comp, i + syntaxEscape.length())) {
424
425 strbuf.append(syntaxEscape);
426 }
427 strbuf.append(syntaxEscape);
428 i += syntaxEscape.length();
429 } else
430
431
432 if (escapeSeparator && comp.startsWith(syntaxSeparator, i)) {
433
434 strbuf.append(syntaxEscape).append(syntaxSeparator);
435 i += syntaxSeparator.length();
436 } else if (escapeSeparator2 &&
437 comp.startsWith(syntaxSeparator2, i)) {
438
439 strbuf.append(syntaxEscape).append(syntaxSeparator2);
440 i += syntaxSeparator2.length();
441 } else {
442
443 strbuf.append(comp.charAt(i++));
444 }
445 start = false;
446 }
447 }
448 return (strbuf.toString());
449 }
450
451 public String toString() {
452 StringBuffer answer = new StringBuffer();
453 String comp;
454 boolean compsAllEmpty = true;
455 int size = components.size();
456
457 for (int i = 0; i < size; i++) {
458 if (syntaxDirection == RIGHT_TO_LEFT) {
459 comp =
460 stringifyComp(components.elementAt(size - 1 - i));
461 } else {
462 comp = stringifyComp(components.elementAt(i));
463 }
464 if ((i != 0) && (syntaxSeparator != null))
465 answer.append(syntaxSeparator);
466 if (comp.length() >= 1)
467 compsAllEmpty = false;
468 answer = answer.append(comp);
469 }
470 if (compsAllEmpty && (size >= 1) && (syntaxSeparator != null))
471 answer = answer.append(syntaxSeparator);
472 return (answer.toString());
473 }
474
475 public boolean equals(Object obj) {
476 if ((obj != null) && (obj instanceof NameImpl)) {
477 NameImpl target = (NameImpl)obj;
478 if (target.size() == this.size()) {
479 Enumeration<String> mycomps = getAll();
480 Enumeration<String> comps = target.getAll();
481 while (mycomps.hasMoreElements()) {
482
483 String my = mycomps.nextElement();
484 String his = comps.nextElement();
485 if (syntaxTrimBlanks) {
486 my = my.trim();
487 his = his.trim();
488 }
489 if (syntaxCaseInsensitive) {
490 if (!(my.equalsIgnoreCase(his)))
491 return false;
492 } else {
493 if (!(my.equals(his)))
494 return false;
495 }
496 }
497 return true;
498 }
499 }
500 return false;
501 }
502
503
511 public int compareTo(NameImpl obj) {
512 if (this == obj) {
513 return 0;
514 }
515
516 int len1 = size();
517 int len2 = obj.size();
518 int n = Math.min(len1, len2);
519
520 int index1 = 0, index2 = 0;
521
522 while (n-- != 0) {
523 String comp1 = get(index1++);
524 String comp2 = obj.get(index2++);
525
526
527 if (syntaxTrimBlanks) {
528 comp1 = comp1.trim();
529 comp2 = comp2.trim();
530 }
531
532 int local;
533 if (syntaxCaseInsensitive) {
534 local = comp1.compareToIgnoreCase(comp2);
535 } else {
536 local = comp1.compareTo(comp2);
537 }
538
539 if (local != 0) {
540 return local;
541 }
542 }
543
544 return len1 - len2;
545 }
546
547 public int size() {
548 return (components.size());
549 }
550
551 public Enumeration<String> getAll() {
552 return components.elements();
553 }
554
555 public String get(int posn) {
556 return components.elementAt(posn);
557 }
558
559 public Enumeration<String> getPrefix(int posn) {
560 if (posn < 0 || posn > size()) {
561 throw new ArrayIndexOutOfBoundsException(posn);
562 }
563 return new NameImplEnumerator(components, 0, posn);
564 }
565
566 public Enumeration<String> getSuffix(int posn) {
567 int cnt = size();
568 if (posn < 0 || posn > cnt) {
569 throw new ArrayIndexOutOfBoundsException(posn);
570 }
571 return new NameImplEnumerator(components, posn, cnt);
572 }
573
574 public boolean isEmpty() {
575 return (components.isEmpty());
576 }
577
578 public boolean startsWith(int posn, Enumeration<String> prefix) {
579 if (posn < 0 || posn > size()) {
580 return false;
581 }
582 try {
583 Enumeration<String> mycomps = getPrefix(posn);
584 while (mycomps.hasMoreElements()) {
585 String my = mycomps.nextElement();
586 String his = prefix.nextElement();
587 if (syntaxTrimBlanks) {
588 my = my.trim();
589 his = his.trim();
590 }
591 if (syntaxCaseInsensitive) {
592 if (!(my.equalsIgnoreCase(his)))
593 return false;
594 } else {
595 if (!(my.equals(his)))
596 return false;
597 }
598 }
599 } catch (NoSuchElementException e) {
600 return false;
601 }
602 return true;
603 }
604
605 public boolean endsWith(int posn, Enumeration<String> suffix) {
606
607
608
609
610 int startIndex = size() - posn;
611 if (startIndex < 0 || startIndex > size()) {
612 return false;
613 }
614 try {
615 Enumeration<String> mycomps = getSuffix(startIndex);
616 while (mycomps.hasMoreElements()) {
617 String my = mycomps.nextElement();
618 String his = suffix.nextElement();
619 if (syntaxTrimBlanks) {
620 my = my.trim();
621 his = his.trim();
622 }
623 if (syntaxCaseInsensitive) {
624 if (!(my.equalsIgnoreCase(his)))
625 return false;
626 } else {
627 if (!(my.equals(his)))
628 return false;
629 }
630 }
631 } catch (NoSuchElementException e) {
632 return false;
633 }
634 return true;
635 }
636
637 public boolean addAll(Enumeration<String> comps) throws InvalidNameException {
638 boolean added = false;
639 while (comps.hasMoreElements()) {
640 try {
641 String comp = comps.nextElement();
642 if (size() > 0 && syntaxDirection == FLAT) {
643 throw new InvalidNameException(
644 "A flat name can only have a single component");
645 }
646 components.addElement(comp);
647 added = true;
648 } catch (NoSuchElementException e) {
649 break;
650 }
651 }
652 return added;
653 }
654
655 public boolean addAll(int posn, Enumeration<String> comps)
656 throws InvalidNameException {
657 boolean added = false;
658 for (int i = posn; comps.hasMoreElements(); i++) {
659 try {
660 String comp = comps.nextElement();
661 if (size() > 0 && syntaxDirection == FLAT) {
662 throw new InvalidNameException(
663 "A flat name can only have a single component");
664 }
665 components.insertElementAt(comp, i);
666 added = true;
667 } catch (NoSuchElementException e) {
668 break;
669 }
670 }
671 return added;
672 }
673
674 public void add(String comp) throws InvalidNameException {
675 if (size() > 0 && syntaxDirection == FLAT) {
676 throw new InvalidNameException(
677 "A flat name can only have a single component");
678 }
679 components.addElement(comp);
680 }
681
682 public void add(int posn, String comp) throws InvalidNameException {
683 if (size() > 0 && syntaxDirection == FLAT) {
684 throw new InvalidNameException(
685 "A flat name can only zero or one component");
686 }
687 components.insertElementAt(comp, posn);
688 }
689
690 public Object remove(int posn) {
691 Object r = components.elementAt(posn);
692 components.removeElementAt(posn);
693 return r;
694 }
695
696 public int hashCode() {
697 int hash = 0;
698 for (Enumeration<String> e = getAll(); e.hasMoreElements();) {
699 String comp = e.nextElement();
700 if (syntaxTrimBlanks) {
701 comp = comp.trim();
702 }
703 if (syntaxCaseInsensitive) {
704 comp = comp.toLowerCase(Locale.ENGLISH);
705 }
706
707 hash += comp.hashCode();
708 }
709 return hash;
710 }
711 }
712
713 final
714 class NameImplEnumerator implements Enumeration<String> {
715 Vector<String> vector;
716 int count;
717 int limit;
718
719 NameImplEnumerator(Vector<String> v, int start, int lim) {
720 vector = v;
721 count = start;
722 limit = lim;
723 }
724
725 public boolean hasMoreElements() {
726 return count < limit;
727 }
728
729 public String nextElement() {
730 if (count < limit) {
731 return vector.elementAt(count++);
732 }
733 throw new NoSuchElementException("NameImplEnumerator");
734 }
735 }
736