2003-12-26 Guilhem Lavaux <guilhem@kaffe.org>
[official-gcc.git] / libjava / javax / naming / CompoundName.java
blob4df89e9af95127672b7e322ef10adccd79550a5a
1 /* CompoundName.java --
2 Copyright (C) 2001 Free Software Foundation, Inc.
4 This file is part of GNU Classpath.
6 GNU Classpath is free software; you can redistribute it and/or modify
7 it under the terms of the GNU General Public License as published by
8 the Free Software Foundation; either version 2, or (at your option)
9 any later version.
11 GNU Classpath is distributed in the hope that it will be useful, but
12 WITHOUT ANY WARRANTY; without even the implied warranty of
13 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14 General Public License for more details.
16 You should have received a copy of the GNU General Public License
17 along with GNU Classpath; see the file COPYING. If not, write to the
18 Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
19 02111-1307 USA.
21 Linking this library statically or dynamically with other modules is
22 making a combined work based on this library. Thus, the terms and
23 conditions of the GNU General Public License cover the whole
24 combination.
26 As a special exception, the copyright holders of this library give you
27 permission to link this library with independent modules to produce an
28 executable, regardless of the license terms of these independent
29 modules, and to copy and distribute the resulting executable under
30 terms of your choice, provided that you also meet, for each linked
31 independent module, the terms and conditions of the license of that
32 module. An independent module is a module which is not derived from
33 or based on this library. If you modify this library, you may extend
34 this exception to your version of the library, but you are not
35 obligated to do so. If you do not wish to do so, delete this
36 exception statement from your version. */
39 package javax.naming;
41 import java.io.Serializable;
42 import java.util.Enumeration;
43 import java.util.Properties;
44 import java.util.NoSuchElementException;
45 import java.util.Vector;
47 /**
48 * @author Tom Tromey <tromey@redhat.com>
49 * @date May 16, 2001
51 * FIXME: must write readObject and writeObject to conform to
52 * serialization spec.
54 * FIXME: this class is underspecified. For instance, the `flat'
55 * direction is never described. If it means that the CompoundName
56 * can only have a single element, then the Enumeration-based
57 * constructor ought to throw InvalidNameException.
59 public class CompoundName implements Name, Cloneable, Serializable
61 private static final long serialVersionUID = 3513100557083972036L;
63 private CompoundName (Properties syntax)
65 elts = new Vector ();
66 mySyntax = syntax;
67 initializeSyntax ();
70 protected CompoundName (Enumeration comps, Properties syntax)
72 elts = new Vector ();
73 mySyntax = syntax;
74 initializeSyntax ();
75 try
77 while (comps.hasMoreElements ())
78 elts.add (comps.nextElement ());
80 catch (NoSuchElementException ignore)
85 public CompoundName (String n, Properties syntax)
86 throws InvalidNameException
88 elts = new Vector ();
89 mySyntax = syntax;
90 initializeSyntax ();
92 StringBuffer new_element = new StringBuffer ();
93 int i = 0;
94 // QUOTE==null means no quoting right now. When it is set it is
95 // the value of the closing quote.
96 String quote = null;
97 while (i < n.length ())
99 String special = isSpecial (n, i);
101 if (special == escape && escape != null)
103 if (n.length () == i + special.length ())
105 // A trailing escape is treated as itself.
106 new_element.append (special);
107 i += special.length ();
109 else
111 String eSpecial = isSpecial (n, i + special.length ());
112 if (eSpecial != null)
114 // Treat the escape as an escape.
115 new_element.append (eSpecial);
116 i += special.length () + eSpecial.length ();
118 else
120 // Treat the escape as itself.
121 new_element.append (special);
122 i += special.length ();
124 continue;
127 else if (quote != null)
129 // It is safe to use == here.
130 if (quote == special)
132 // Quotes must surround a complete component.
133 if (i + quote.length () < n.length ()
134 && ! n.startsWith (separator, i + quote.length ()))
135 throw new InvalidNameException ("close quote before end of component");
136 elts.add (new_element.toString ());
137 new_element.setLength (0);
138 i += quote.length ();
139 quote = null;
140 continue;
142 // Otherwise, fall through.
144 // Quotes are only special at the start of a component.
145 else if (new_element.length () == 0
146 && special == beginQuote
147 && beginQuote != null)
149 quote = endQuote;
150 i += special.length ();
151 continue;
153 else if (new_element.length () == 0
154 && special == beginQuote2
155 && beginQuote2 != null)
157 quote = endQuote2;
158 i += special.length ();
159 continue;
161 else if (special == separator)
163 elts.add (new_element.toString ());
164 new_element.setLength (0);
165 i += special.length ();
166 continue;
169 // Nothing in particular, so try the next character.
170 new_element.append (n.charAt (i));
171 ++i;
174 if (new_element.length () != 0)
175 elts.add (new_element.toString ());
177 if (direction == RIGHT_TO_LEFT)
179 // Reverse the order of the elements.
180 int len = elts.size ();
181 for (i = 0; i < len / 2; ++i)
183 Object t = elts.set (i, elts.get (len - i - 1));
184 elts.set (len - i - 1, t);
188 // Error checking.
189 if (quote != null)
190 throw new InvalidNameException ("unterminated quote");
193 public Name add (int posn, String comp) throws InvalidNameException
195 elts.add (posn, comp);
196 return this;
199 public Name add (String comp) throws InvalidNameException
201 elts.add (comp);
202 return this;
205 public Name addAll (int posn, Name n) throws InvalidNameException
207 Enumeration e = n.getAll ();
210 while (e.hasMoreElements ())
212 elts.add (posn, e.nextElement ());
213 ++posn;
216 catch (NoSuchElementException ignore)
219 return this;
222 public Name addAll (Name suffix) throws InvalidNameException
224 Enumeration e = suffix.getAll ();
227 while (e.hasMoreElements ())
228 elts.add (e.nextElement ());
230 catch (NoSuchElementException ignore)
233 return this;
236 public Object clone ()
238 return new CompoundName (elts.elements (), mySyntax);
241 public int compareTo (Object obj)
243 if (! (obj instanceof CompoundName))
244 throw new ClassCastException ("CompoundName.compareTo() expected CompoundName");
245 CompoundName cn = (CompoundName) obj;
246 int last = Math.min (cn.elts.size (), elts.size ());
247 for (int i = 0; i < last; ++i)
249 String f = canonicalize ((String) elts.get (i));
250 int comp = f.compareTo (canonicalize ((String) cn.elts.get (i)));
251 if (comp != 0)
252 return comp;
254 return elts.size () - cn.elts.size ();
257 public boolean endsWith (Name n)
259 if (! (n instanceof CompoundName))
260 return false;
261 CompoundName cn = (CompoundName) n;
262 if (cn.elts.size () > elts.size ())
263 return false;
264 int delta = elts.size () - cn.elts.size ();
265 for (int i = 0; i < cn.elts.size (); ++i)
267 String f = canonicalize ((String) elts.get (i));
268 if (! f.equals (canonicalize ((String) cn.elts.get (i))))
269 return false;
271 return true;
274 public boolean equals (Object obj)
276 if (! (obj instanceof CompoundName))
277 return false;
278 return compareTo (obj) == 0;
281 public String get (int posn)
283 return (String) elts.get (posn);
286 public Enumeration getAll ()
288 return elts.elements ();
291 public Name getPrefix (int posn)
293 CompoundName cn = new CompoundName (mySyntax);
294 for (int i = 0; i < posn; ++i)
295 cn.elts.add (elts.get (i));
296 return cn;
299 public Name getSuffix (int posn)
301 if (posn > elts.size ())
302 throw new ArrayIndexOutOfBoundsException (posn);
303 CompoundName cn = new CompoundName (mySyntax);
304 for (int i = posn; i < elts.size (); ++i)
305 cn.elts.add (elts.get (i));
306 return cn;
309 public int hashCode ()
311 int h = 0;
312 for (int i = 0; i < elts.size (); ++i)
313 h += canonicalize ((String) elts.get (i)).hashCode ();
314 return h;
317 public boolean isEmpty ()
319 return elts.isEmpty ();
322 public Object remove (int posn) throws InvalidNameException
324 return elts.remove (posn);
327 public int size ()
329 return elts.size ();
332 public boolean startsWith (Name n)
334 if (! (n instanceof CompoundName))
335 return false;
336 CompoundName cn = (CompoundName) n;
337 if (cn.elts.size () > elts.size ())
338 return false;
339 for (int i = 0; i < cn.elts.size (); ++i)
341 String f = canonicalize ((String) elts.get (i));
342 if (! f.equals (canonicalize ((String) cn.elts.get (i))))
343 return false;
345 return true;
348 // If ELEMENT starts with some meta-sequence at OFFSET, then return
349 // the string representing the meta-sequence. Otherwise return
350 // null.
351 private String isSpecial (String element, int offset)
353 String special = null;
354 if (separator != null && element.startsWith (separator, offset))
355 special = separator;
356 else if (escape != null && element.startsWith (escape, offset))
357 special = escape;
358 else if (beginQuote != null && element.startsWith (beginQuote, offset))
359 special = beginQuote;
360 else if (endQuote != null && element.startsWith (endQuote, offset))
361 special = endQuote;
362 else if (beginQuote2 != null
363 && element.startsWith (beginQuote2, offset))
364 special = beginQuote2;
365 else if (endQuote2 != null && element.startsWith (endQuote2, offset))
366 special = endQuote2;
368 return special;
371 public String toString ()
373 StringBuffer result = new StringBuffer ();
374 int size = elts.size ();
375 for (int i = 0; i < size; ++i)
377 // Find the appropriate element. FIXME: not clear what FLAT
378 // means.
379 int offset = (direction == RIGHT_TO_LEFT) ? (size - i - 1) : i;
380 String element = (String) elts.get (offset);
381 if (i > 0
382 || (i == size - 1 && element.equals ("")))
383 result.append (separator);
385 int k = 0;
386 while (k < element.length ())
388 String special = isSpecial (element, k);
389 if (special != null)
391 result.append (escape);
392 result.append (special);
393 k += special.length ();
395 else
397 result.append (element.charAt (k));
398 ++k;
403 return result.toString ();
406 // This canonicalizes a String, based on the syntax, for comparison
407 // or other similar purposes.
408 private String canonicalize (String element)
410 String ret = element;
412 if (ignoreCase)
413 ret = ret.toLowerCase ();
415 if (trimBlanks)
417 int first = 0;
418 while (first < ret.length ()
419 && Character.isWhitespace (ret.charAt (first)))
420 ++first;
422 int last = ret.length () - 1;
423 while (last >= first
424 && Character.isWhitespace (ret.charAt (last)))
425 --last;
427 ret = ret.substring (first, last);
430 return ret;
433 // This initializes all the syntax variables. This seems easier
434 // than re-querying the properties every time. We're allowed to do
435 // this because the spec says that subclasses should consider the
436 // syntax as being read-only.
437 private void initializeSyntax ()
439 String t = mySyntax.getProperty ("jndi.syntax.direction", "flat");
440 if (t.equals ("right_to_left"))
441 this.direction = RIGHT_TO_LEFT;
442 else if (t.equals ("left_to_right"))
443 this.direction = LEFT_TO_RIGHT;
444 else
446 // If we don't recognize it, default to flat.
447 this.direction = FLAT;
450 // This is required unless the direction is FLAT. Unfortunately
451 // there is no way to report this error.
452 this.separator = mySyntax.getProperty ("jndi.syntax.separator", "");
454 this.ignoreCase
455 = Boolean.valueOf (mySyntax.getProperty ("jndi.syntax.ignorecase",
456 "false")).booleanValue ();
457 this.escape = mySyntax.getProperty ("jndi.syntax.escape", null);
458 this.beginQuote = mySyntax.getProperty ("jndi.syntax.beginquote", null);
459 this.endQuote = mySyntax.getProperty ("jndi.syntax.endquote",
460 this.beginQuote);
461 this.beginQuote2 = mySyntax.getProperty ("jndi.syntax.beginquote2",
462 null);
463 this.endQuote2 = mySyntax.getProperty ("jndi.syntax.endquote2",
464 this.beginQuote2);
465 this.trimBlanks
466 = Boolean.valueOf (mySyntax.getProperty ("jndi.syntax.trimblanks",
467 "false")).booleanValue ();
470 // The spec specifies this but does not document it in any way (it
471 // is a package-private class). It is useless as far as I can tell.
472 // So we ignore it.
473 // protected transient NameImpl impl;
474 protected transient Properties mySyntax;
476 // The actual elements.
477 private transient Vector elts;
479 // The following are all used for syntax.
480 private transient int direction;
481 private transient String separator;
482 private transient boolean ignoreCase;
483 private transient String escape;
484 private transient String beginQuote;
485 private transient String endQuote;
486 private transient String beginQuote2;
487 private transient String endQuote2;
488 private transient boolean trimBlanks;
489 // We didn't need these for parsing, so they are gone.
490 // private transient String avaSeparator;
491 // private transient String typevalSeparator;
493 private static final int RIGHT_TO_LEFT = -1;
494 private static final int LEFT_TO_RIGHT = 1;
495 private static final int FLAT = 0;