blob: 4180a266d325a5388d0acdf5ae58e87e49e46d5e [file] [log] [blame]
J. Duke319a3b92007-12-01 00:00:00 +00001/*
2 * Copyright 1999-2004 Sun Microsystems, Inc. All Rights Reserved.
3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
4 *
5 * This code is free software; you can redistribute it and/or modify it
6 * under the terms of the GNU General Public License version 2 only, as
7 * published by the Free Software Foundation. Sun designates this
8 * particular file as subject to the "Classpath" exception as provided
9 * by Sun in the LICENSE file that accompanied this code.
10 *
11 * This code is distributed in the hope that it will be useful, but WITHOUT
12 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
13 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
14 * version 2 for more details (a copy is included in the LICENSE file that
15 * accompanied this code).
16 *
17 * You should have received a copy of the GNU General Public License version
18 * 2 along with this work; if not, write to the Free Software Foundation,
19 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
20 *
21 * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
22 * CA 95054 USA or visit www.sun.com if you need additional information or
23 * have any questions.
24 */
25
26package javax.naming;
27
28import java.util.Enumeration;
29import java.util.Properties;
30
31/**
32 * This class represents a composite name -- a sequence of
33 * component names spanning multiple namespaces.
34 * Each component is a string name from the namespace of a
35 * naming system. If the component comes from a hierarchical
36 * namespace, that component can be further parsed into
37 * its atomic parts by using the CompoundName class.
38 *<p>
39 * The components of a composite name are numbered. The indexes of a
40 * composite name with N components range from 0 up to, but not including, N.
41 * This range may be written as [0,N).
42 * The most significant component is at index 0.
43 * An empty composite name has no components.
44 *<p>
45 * <h4>JNDI Composite Name Syntax</h4>
46 * JNDI defines a standard string representation for composite names. This
47 * representation is the concatenation of the components of a composite name
48 * from left to right using the component separator (a forward
49 * slash character (/)) to separate each component.
50 * The JNDI syntax defines the following meta characters:
51 * <ul>
52 * <li>escape (backward slash \),
53 * <li>quote characters (single (') and double quotes (")), and
54 * <li>component separator (forward slash character (/)).
55 * </ul>
56 * Any occurrence of a leading quote, an escape preceding any meta character,
57 * an escape at the end of a component, or a component separator character
58 * in an unquoted component must be preceded by an escape character when
59 * that component is being composed into a composite name string.
60 * Alternatively, to avoid adding escape characters as described,
61 * the entire component can be quoted using matching single quotes
62 * or matching double quotes. A single quote occurring within a double-quoted
63 * component is not considered a meta character (and need not be escaped),
64 * and vice versa.
65 *<p>
66 * When two composite names are compared, the case of the characters
67 * is significant.
68 *<p>
69 * A leading component separator (the composite name string begins with
70 * a separator) denotes a leading empty component (a component consisting
71 * of an empty string).
72 * A trailing component separator (the composite name string ends with
73 * a separator) denotes a trailing empty component.
74 * Adjacent component separators denote an empty component.
75 *<p>
76 *<h4>Composite Name Examples</h4>
77 *This table shows examples of some composite names. Each row shows
78 *the string form of a composite name and its corresponding structural form
79 *(<tt>CompositeName</tt>).
80 *<p>
81<table border="1" cellpadding=3 width="70%" summary="examples showing string form of composite name and its corresponding structural form (CompositeName)">
82
83<tr>
84<th>String Name</th>
85<th>CompositeName</th>
86</tr>
87
88<tr>
89<td>
90""
91</td>
92<td>{} (the empty name == new CompositeName("") == new CompositeName())
93</td>
94</tr>
95
96<tr>
97<td>
98"x"
99</td>
100<td>{"x"}
101</td>
102</tr>
103
104<tr>
105<td>
106"x/y"
107</td>
108<td>{"x", "y"}</td>
109</tr>
110
111<tr>
112<td>"x/"</td>
113<td>{"x", ""}</td>
114</tr>
115
116<tr>
117<td>"/x"</td>
118<td>{"", "x"}</td>
119</tr>
120
121<tr>
122<td>"/"</td>
123<td>{""}</td>
124</tr>
125
126<tr>
127<td>"//"</td>
128<td>{"", ""}</td>
129</tr>
130
131<tr><td>"/x/"</td>
132<td>{"", "x", ""}</td>
133</tr>
134
135<tr><td>"x//y"</td>
136<td>{"x", "", "y"}</td>
137</tr>
138</table>
139 * <p>
140 *<h4>Composition Examples</h4>
141 * Here are some composition examples. The right column shows composing
142 * string composite names while the left column shows composing the
143 * corresponding <tt>CompositeName</tt>s. Notice that composing the
144 * string forms of two composite names simply involves concatenating
145 * their string forms together.
146
147<p> <table border="1" cellpadding=3 width="70%" summary="composition examples showing string names and composite names">
148
149<tr>
150<th>String Names</th>
151<th>CompositeNames</th>
152</tr>
153
154<tr>
155<td>
156"x/y" + "/" = x/y/
157</td>
158<td>
159{"x", "y"} + {""} = {"x", "y", ""}
160</td>
161</tr>
162
163<tr>
164<td>
165"" + "x" = "x"
166</td>
167<td>
168{} + {"x"} = {"x"}
169</td>
170</tr>
171
172<tr>
173<td>
174"/" + "x" = "/x"
175</td>
176<td>
177{""} + {"x"} = {"", "x"}
178</td>
179</tr>
180
181<tr>
182<td>
183"x" + "" + "" = "x"
184</td>
185<td>
186{"x"} + {} + {} = {"x"}
187</td>
188</tr>
189
190</table>
191 *<p>
192 *<h4>Multithreaded Access</h4>
193 * A <tt>CompositeName</tt> instance is not synchronized against concurrent
194 * multithreaded access. Multiple threads trying to access and modify a
195 * <tt>CompositeName</tt> should lock the object.
196 *
197 * @author Rosanna Lee
198 * @author Scott Seligman
199 * @since 1.3
200 */
201
202
203public class CompositeName implements Name {
204
205 private transient NameImpl impl;
206 /**
207 * Constructs a new composite name instance using the components
208 * specified by 'comps'. This protected method is intended to be
209 * to be used by subclasses of CompositeName when they override
210 * methods such as clone(), getPrefix(), getSuffix().
211 *
212 * @param comps A non-null enumeration containing the components for the new
213 * composite name. Each element is of class String.
214 * The enumeration will be consumed to extract its
215 * elements.
216 */
217 protected CompositeName(Enumeration<String> comps) {
218 impl = new NameImpl(null, comps); // null means use default syntax
219 }
220
221 /**
222 * Constructs a new composite name instance by parsing the string n
223 * using the composite name syntax (left-to-right, slash separated).
224 * The composite name syntax is described in detail in the class
225 * description.
226 *
227 * @param n The non-null string to parse.
228 * @exception InvalidNameException If n has invalid composite name syntax.
229 */
230 public CompositeName(String n) throws InvalidNameException {
231 impl = new NameImpl(null, n); // null means use default syntax
232 }
233
234 /**
235 * Constructs a new empty composite name. Such a name returns true
236 * when <code>isEmpty()</code> is invoked on it.
237 */
238 public CompositeName() {
239 impl = new NameImpl(null); // null means use default syntax
240 }
241
242 /**
243 * Generates the string representation of this composite name.
244 * The string representation consists of enumerating in order
245 * each component of the composite name and separating
246 * each component by a forward slash character. Quoting and
247 * escape characters are applied where necessary according to
248 * the JNDI syntax, which is described in the class description.
249 * An empty component is represented by an empty string.
250 *
251 * The string representation thus generated can be passed to
252 * the CompositeName constructor to create a new equivalent
253 * composite name.
254 *
255 * @return A non-null string representation of this composite name.
256 */
257 public String toString() {
258 return impl.toString();
259 }
260
261 /**
262 * Determines whether two composite names are equal.
263 * If obj is null or not a composite name, false is returned.
264 * Two composite names are equal if each component in one is equal
265 * to the corresponding component in the other. This implies
266 * both have the same number of components, and each component's
267 * equals() test against the corresponding component in the other name
268 * returns true.
269 *
270 * @param obj The possibly null object to compare against.
271 * @return true if obj is equal to this composite name, false otherwise.
272 * @see #hashCode
273 */
274 public boolean equals(Object obj) {
275 return (obj != null &&
276 obj instanceof CompositeName &&
277 impl.equals(((CompositeName)obj).impl));
278 }
279
280 /**
281 * Computes the hash code of this composite name.
282 * The hash code is the sum of the hash codes of individual components
283 * of this composite name.
284 *
285 * @return An int representing the hash code of this name.
286 * @see #equals
287 */
288 public int hashCode() {
289 return impl.hashCode();
290 }
291
292
293 /**
294 * Compares this CompositeName with the specified Object for order.
295 * Returns a
296 * negative integer, zero, or a positive integer as this Name is less
297 * than, equal to, or greater than the given Object.
298 * <p>
299 * If obj is null or not an instance of CompositeName, ClassCastException
300 * is thrown.
301 * <p>
302 * See equals() for what it means for two composite names to be equal.
303 * If two composite names are equal, 0 is returned.
304 * <p>
305 * Ordering of composite names follows the lexicographical rules for
306 * string comparison, with the extension that this applies to all
307 * the components in the composite name. The effect is as if all the
308 * components were lined up in their specified ordered and the
309 * lexicographical rules applied over the two line-ups.
310 * If this composite name is "lexicographically" lesser than obj,
311 * a negative number is returned.
312 * If this composite name is "lexicographically" greater than obj,
313 * a positive number is returned.
314 * @param obj The non-null object to compare against.
315 *
316 * @return a negative integer, zero, or a positive integer as this Name
317 * is less than, equal to, or greater than the given Object.
318 * @exception ClassCastException if obj is not a CompositeName.
319 */
320 public int compareTo(Object obj) {
321 if (!(obj instanceof CompositeName)) {
322 throw new ClassCastException("Not a CompositeName");
323 }
324 return impl.compareTo(((CompositeName)obj).impl);
325 }
326
327 /**
328 * Generates a copy of this composite name.
329 * Changes to the components of this composite name won't
330 * affect the new copy and vice versa.
331 *
332 * @return A non-null copy of this composite name.
333 */
334 public Object clone() {
335 return (new CompositeName(getAll()));
336 }
337
338 /**
339 * Retrieves the number of components in this composite name.
340 *
341 * @return The nonnegative number of components in this composite name.
342 */
343 public int size() {
344 return (impl.size());
345 }
346
347 /**
348 * Determines whether this composite name is empty. A composite name
349 * is empty if it has zero components.
350 *
351 * @return true if this composite name is empty, false otherwise.
352 */
353 public boolean isEmpty() {
354 return (impl.isEmpty());
355 }
356
357 /**
358 * Retrieves the components of this composite name as an enumeration
359 * of strings.
360 * The effects of updates to this composite name on this enumeration
361 * is undefined.
362 *
363 * @return A non-null enumeration of the components of
364 * this composite name. Each element of the enumeration is of
365 * class String.
366 */
367 public Enumeration<String> getAll() {
368 return (impl.getAll());
369 }
370
371 /**
372 * Retrieves a component of this composite name.
373 *
374 * @param posn The 0-based index of the component to retrieve.
375 * Must be in the range [0,size()).
376 * @return The non-null component at index posn.
377 * @exception ArrayIndexOutOfBoundsException if posn is outside the
378 * specified range.
379 */
380 public String get(int posn) {
381 return (impl.get(posn));
382 }
383
384 /**
385 * Creates a composite name whose components consist of a prefix of the
386 * components in this composite name. Subsequent changes to
387 * this composite name does not affect the name that is returned.
388 *
389 * @param posn The 0-based index of the component at which to stop.
390 * Must be in the range [0,size()].
391 * @return A composite name consisting of the components at indexes in
392 * the range [0,posn).
393 * @exception ArrayIndexOutOfBoundsException
394 * If posn is outside the specified range.
395 */
396 public Name getPrefix(int posn) {
397 Enumeration comps = impl.getPrefix(posn);
398 return (new CompositeName(comps));
399 }
400
401 /**
402 * Creates a composite name whose components consist of a suffix of the
403 * components in this composite name. Subsequent changes to
404 * this composite name does not affect the name that is returned.
405 *
406 * @param posn The 0-based index of the component at which to start.
407 * Must be in the range [0,size()].
408 * @return A composite name consisting of the components at indexes in
409 * the range [posn,size()). If posn is equal to
410 * size(), an empty composite name is returned.
411 * @exception ArrayIndexOutOfBoundsException
412 * If posn is outside the specified range.
413 */
414 public Name getSuffix(int posn) {
415 Enumeration comps = impl.getSuffix(posn);
416 return (new CompositeName(comps));
417 }
418
419 /**
420 * Determines whether a composite name is a prefix of this composite name.
421 * A composite name 'n' is a prefix if it is equal to
422 * getPrefix(n.size())--in other words, this composite name
423 * starts with 'n'. If 'n' is null or not a composite name, false is returned.
424 *
425 * @param n The possibly null name to check.
426 * @return true if n is a CompositeName and
427 * is a prefix of this composite name, false otherwise.
428 */
429 public boolean startsWith(Name n) {
430 if (n instanceof CompositeName) {
431 return (impl.startsWith(n.size(), n.getAll()));
432 } else {
433 return false;
434 }
435 }
436
437 /**
438 * Determines whether a composite name is a suffix of this composite name.
439 * A composite name 'n' is a suffix if it it is equal to
440 * getSuffix(size()-n.size())--in other words, this
441 * composite name ends with 'n'.
442 * If n is null or not a composite name, false is returned.
443 *
444 * @param n The possibly null name to check.
445 * @return true if n is a CompositeName and
446 * is a suffix of this composite name, false otherwise.
447 */
448 public boolean endsWith(Name n) {
449 if (n instanceof CompositeName) {
450 return (impl.endsWith(n.size(), n.getAll()));
451 } else {
452 return false;
453 }
454 }
455
456 /**
457 * Adds the components of a composite name -- in order -- to the end of
458 * this composite name.
459 *
460 * @param suffix The non-null components to add.
461 * @return The updated CompositeName, not a new one. Cannot be null.
462 * @exception InvalidNameException If suffix is not a composite name.
463 */
464 public Name addAll(Name suffix)
465 throws InvalidNameException
466 {
467 if (suffix instanceof CompositeName) {
468 impl.addAll(suffix.getAll());
469 return this;
470 } else {
471 throw new InvalidNameException("Not a composite name: " +
472 suffix.toString());
473 }
474 }
475
476 /**
477 * Adds the components of a composite name -- in order -- at a specified
478 * position within this composite name.
479 * Components of this composite name at or after the index of the first
480 * new component are shifted up (away from index 0)
481 * to accommodate the new components.
482 *
483 * @param n The non-null components to add.
484 * @param posn The index in this name at which to add the new
485 * components. Must be in the range [0,size()].
486 * @return The updated CompositeName, not a new one. Cannot be null.
487 * @exception InvalidNameException If n is not a composite name.
488 * @exception ArrayIndexOutOfBoundsException
489 * If posn is outside the specified range.
490 */
491 public Name addAll(int posn, Name n)
492 throws InvalidNameException
493 {
494 if (n instanceof CompositeName) {
495 impl.addAll(posn, n.getAll());
496 return this;
497 } else {
498 throw new InvalidNameException("Not a composite name: " +
499 n.toString());
500 }
501 }
502
503 /**
504 * Adds a single component to the end of this composite name.
505 *
506 * @param comp The non-null component to add.
507 * @return The updated CompositeName, not a new one. Cannot be null.
508 * @exception InvalidNameException If adding comp at end of the name
509 * would violate the name's syntax.
510 */
511 public Name add(String comp) throws InvalidNameException {
512 impl.add(comp);
513 return this;
514 }
515
516 /**
517 * Adds a single component at a specified position within this
518 * composite name.
519 * Components of this composite name at or after the index of the new
520 * component are shifted up by one (away from index 0) to accommodate
521 * the new component.
522 *
523 * @param comp The non-null component to add.
524 * @param posn The index at which to add the new component.
525 * Must be in the range [0,size()].
526 * @return The updated CompositeName, not a new one. Cannot be null.
527 * @exception ArrayIndexOutOfBoundsException
528 * If posn is outside the specified range.
529 * @exception InvalidNameException If adding comp at the specified position
530 * would violate the name's syntax.
531 */
532 public Name add(int posn, String comp)
533 throws InvalidNameException
534 {
535 impl.add(posn, comp);
536 return this;
537 }
538
539 /**
540 * Deletes a component from this composite name.
541 * The component of this composite name at position 'posn' is removed,
542 * and components at indices greater than 'posn'
543 * are shifted down (towards index 0) by one.
544 *
545 * @param posn The index of the component to delete.
546 * Must be in the range [0,size()).
547 * @return The component removed (a String).
548 * @exception ArrayIndexOutOfBoundsException
549 * If posn is outside the specified range (includes case where
550 * composite name is empty).
551 * @exception InvalidNameException If deleting the component
552 * would violate the name's syntax.
553 */
554 public Object remove(int posn) throws InvalidNameException{
555 return impl.remove(posn);
556 }
557
558 /**
559 * Overridden to avoid implementation dependency.
560 * @serialData The number of components (an <tt>int</tt>) followed by
561 * the individual components (each a <tt>String</tt>).
562 */
563 private void writeObject(java.io.ObjectOutputStream s)
564 throws java.io.IOException {
565 s.writeInt(size());
566 Enumeration comps = getAll();
567 while (comps.hasMoreElements()) {
568 s.writeObject(comps.nextElement());
569 }
570 }
571
572 /**
573 * Overridden to avoid implementation dependency.
574 */
575 private void readObject(java.io.ObjectInputStream s)
576 throws java.io.IOException, ClassNotFoundException {
577 impl = new NameImpl(null); // null means use default syntax
578 int n = s.readInt(); // number of components
579 try {
580 while (--n >= 0) {
581 add((String)s.readObject());
582 }
583 } catch (InvalidNameException e) {
584 throw (new java.io.StreamCorruptedException("Invalid name"));
585 }
586 }
587
588 /**
589 * Use serialVersionUID from JNDI 1.1.1 for interoperability
590 */
591 private static final long serialVersionUID = 1667768148915813118L;
592
593/*
594 // %%% Test code for serialization.
595 public static void main(String[] args) throws Exception {
596 CompositeName c = new CompositeName("aaa/bbb");
597 java.io.FileOutputStream f1 = new java.io.FileOutputStream("/tmp/ser");
598 java.io.ObjectOutputStream s1 = new java.io.ObjectOutputStream(f1);
599 s1.writeObject(c);
600 s1.close();
601 java.io.FileInputStream f2 = new java.io.FileInputStream("/tmp/ser");
602 java.io.ObjectInputStream s2 = new java.io.ObjectInputStream(f2);
603 c = (CompositeName)s2.readObject();
604
605 System.out.println("Size: " + c.size());
606 System.out.println("Size: " + c.snit);
607 }
608*/
609
610/*
611 %%% Testing code
612 public static void main(String[] args) {
613 try {
614 for (int i = 0; i < args.length; i++) {
615 Name name;
616 Enumeration e;
617 System.out.println("Given name: " + args[i]);
618 name = new CompositeName(args[i]);
619 e = name.getComponents();
620 while (e.hasMoreElements()) {
621 System.out.println("Element: " + e.nextElement());
622 }
623 System.out.println("Constructed name: " + name.toString());
624 }
625 } catch (Exception ne) {
626 ne.printStackTrace();
627 }
628 }
629*/
630}