OSDN Git Service

4e9f5bd8a000490223990e0bbfcf7c643d8e8acc
[pf3gnuchains/gcc-fork.git] / libjava / javax / naming / CompoundName.java
1 /* Copyright (C) 2001 Free Software Foundation
2
3    This file is part of libgcj.
4
5 This software is copyrighted work licensed under the terms of the
6 Libgcj License.  Please consult the file "LIBGCJ_LICENSE" for
7 details.  */
8
9 package javax.naming;
10
11 import java.io.Serializable;
12 import java.util.Enumeration;
13 import java.util.Properties;
14 import java.util.NoSuchElementException;
15 import java.util.Vector;
16
17 /**
18  * @author Tom Tromey <tromey@redhat.com>
19  * @date May 16, 2001
20  *
21  * FIXME: must write readObject and writeObject to conform to
22  * serialization spec.
23  *
24  * FIXME: this class is underspecified.  For instance, the `flat'
25  * direction is never described.  If it means that the CompoundName
26  * can only have a single element, then the Enumeration-based
27  * constructor ought to throw InvalidNameException.
28  */
29 public class CompoundName implements Name, Cloneable, Serializable
30 {
31   private CompoundName (Properties syntax)
32   {
33     elts = new Vector ();
34     mySyntax = syntax;
35     initializeSyntax ();
36   }
37
38   protected CompoundName (Enumeration comps, Properties syntax)
39   {
40     elts = new Vector ();
41     mySyntax = syntax;
42     initializeSyntax ();
43     try
44       {
45         while (comps.hasMoreElements ())
46           elts.add (comps.nextElement ());
47       }
48     catch (NoSuchElementException ignore)
49       {
50       }
51   }
52
53   public CompoundName (String n, Properties syntax)
54     throws InvalidNameException
55   {
56     elts = new Vector ();
57     mySyntax = syntax;
58     initializeSyntax ();
59
60     StringBuffer new_element = new StringBuffer ();
61     int i = 0;
62     // QUOTE==null means no quoting right now.  When it is set it is
63     // the value of the closing quote.
64     String quote = null;
65     while (i < n.length ())
66       {
67         String special = isSpecial (n, i);
68
69         if (special == escape && escape != null)
70           {
71             if (n.length () == i + special.length ())
72               {
73                 // A trailing escape is treated as itself.
74                 new_element.append (special);
75                 i += special.length ();
76               }
77             else
78               {
79                 String eSpecial = isSpecial (n, i + special.length ());
80                 if (eSpecial != null)
81                   {
82                     // Treat the escape as an escape.
83                     new_element.append (eSpecial);
84                     i += special.length () + eSpecial.length ();
85                   }
86                 else
87                   {
88                     // Treat the escape as itself.
89                     new_element.append (special);
90                     i += special.length ();
91                   }
92                 continue;
93               }
94           }
95         else if (quote != null)
96           {
97             // It is safe to use == here.
98             if (quote == special)
99               {
100                 // Quotes must surround a complete component.
101                 if (i + quote.length () < n.length ()
102                     && ! n.startsWith (separator, i + quote.length ()))
103                   throw new InvalidNameException ("close quote before end of component");
104                 elts.add (new_element.toString ());
105                 new_element.setLength (0);
106                 i += quote.length ();
107                 quote = null;
108                 continue;
109               }
110             // Otherwise, fall through.
111           }
112         // Quotes are only special at the start of a component.
113         else if (new_element.length () == 0 && special == beginQuote)
114           {
115             quote = endQuote;
116             i += special.length ();
117             continue;
118           }
119         else if (new_element.length () == 0 && special == beginQuote2)
120           {
121             quote = endQuote2;
122             i += special.length ();
123             continue;
124           }
125         else if (special == separator)
126           {
127             elts.add (new_element.toString ());
128             new_element.setLength (0);
129             i += special.length ();
130             continue;
131           }
132
133         // Nothing in particular, so try the next character.
134         new_element.append (n.charAt (i));
135         ++i;
136       }
137
138     if (new_element.length () != 0)
139       elts.add (new_element.toString ());
140
141     if (direction == RIGHT_TO_LEFT)
142       {
143         // Reverse the order of the elements.
144         int len = elts.size ();
145         for (i = 0; i < len / 2; ++i)
146           {
147             Object t = elts.set (i, elts.get (len - i - 1));
148             elts.set (len - i - 1, t);
149           }
150       }
151
152     // Error checking.
153     if (quote != null)
154       throw new InvalidNameException ("unterminated quote");
155   }
156
157   public Name add (int posn, String comp) throws InvalidNameException
158   {
159     elts.add (posn, comp);
160     return this;
161   }
162
163   public Name add (String comp) throws InvalidNameException
164   {
165     elts.add (comp);
166     return this;
167   }
168
169   public Name addAll (int posn, Name n) throws InvalidNameException
170   {
171     Enumeration e = n.getAll ();
172     try
173       {
174         while (e.hasMoreElements ())
175           {
176             elts.add (posn, e.nextElement ());
177             ++posn;
178           }
179       }
180     catch (NoSuchElementException ignore)
181       {
182       }
183     return this;
184   }
185
186   public Name addAll (Name suffix) throws InvalidNameException
187   {
188     Enumeration e = suffix.getAll ();
189     try
190       {
191         while (e.hasMoreElements ())
192           elts.add (e.nextElement ());
193       }
194     catch (NoSuchElementException ignore)
195       {
196       }
197     return this;
198   }
199
200   public Object clone ()
201   {
202     return new CompoundName (elts.elements (), mySyntax);
203   }
204
205   public int compareTo (Object obj)
206   {
207     if (obj == null || ! (obj instanceof CompoundName))
208       throw new ClassCastException ("CompoundName.compareTo() expected CompoundName");
209     CompoundName cn = (CompoundName) obj;
210     int last = Math.min (cn.elts.size (), elts.size ());
211     for (int i = 0; i < last; ++i)
212       {
213         String f = canonicalize ((String) elts.get (i));
214         int comp = f.compareTo (canonicalize ((String) cn.elts.get (i)));
215         if (comp != 0)
216           return comp;
217       }
218     return elts.size () - cn.elts.size ();
219   }
220
221   public boolean endsWith (Name n)
222   {
223     if (! (n instanceof CompoundName))
224       return false;
225     CompoundName cn = (CompoundName) n;
226     if (cn.elts.size () > elts.size ())
227       return false;
228     int delta = elts.size () - cn.elts.size ();
229     for (int i = 0; i < cn.elts.size (); ++i)
230       {
231         String f = canonicalize ((String) elts.get (i));
232         if (! f.equals (canonicalize ((String) cn.elts.get (i))))
233           return false;
234       }
235     return true;
236   }
237
238   public boolean equals (Object obj)
239   {
240     if (! (obj instanceof CompoundName))
241       return false;
242     return compareTo (obj) == 0;
243   }
244
245   public String get (int posn)
246   {
247     return (String) elts.get (posn);
248   }
249
250   public Enumeration getAll ()
251   {
252     return elts.elements ();
253   }
254
255   public Name getPrefix (int posn)
256   {
257     CompoundName cn = new CompoundName (mySyntax);
258     for (int i = 0; i < posn; ++i)
259       cn.elts.add (elts.get (i));
260     return cn;
261   }
262
263   public Name getSuffix (int posn)
264   {
265     if (posn > elts.size ())
266       throw new ArrayIndexOutOfBoundsException (posn);
267     CompoundName cn = new CompoundName (mySyntax);
268     for (int i = posn; i < elts.size (); ++i)
269       cn.elts.add (elts.get (i));
270     return cn;
271   }
272
273   public int hashCode ()
274   {
275     int h = 0;
276     for (int i = 0; i < elts.size (); ++i)
277       h += canonicalize ((String) elts.get (i)).hashCode ();
278     return h;
279   }
280
281   public boolean isEmpty ()
282   {
283     return elts.isEmpty ();
284   }
285
286   public Object remove (int posn) throws InvalidNameException
287   {
288     return elts.remove (posn);
289   }
290
291   public int size ()
292   {
293     return elts.size ();
294   }
295
296   public boolean startsWith (Name n)
297   {
298     if (! (n instanceof CompoundName))
299       return false;
300     CompoundName cn = (CompoundName) n;
301     if (cn.elts.size () > elts.size ())
302       return false;
303     for (int i = 0; i < cn.elts.size (); ++i)
304       {
305         String f = canonicalize ((String) elts.get (i));
306         if (! f.equals (canonicalize ((String) cn.elts.get (i))))
307           return false;
308       }
309     return true;
310   }
311
312   // If ELEMENT starts with some meta-sequence at OFFSET, then return
313   // the string representing the meta-sequence.  Otherwise return
314   // null.
315   private String isSpecial (String element, int offset)
316   {
317     String special = null;
318     if (separator != null && element.startsWith (separator, offset))
319       special = separator;
320     else if (escape != null && element.startsWith (escape, offset))
321       special = escape;
322     else if (beginQuote != null && element.startsWith (beginQuote, offset))
323       special = beginQuote;
324     else if (endQuote != null && element.startsWith (endQuote, offset))
325       special = endQuote;
326     else if (beginQuote2 != null
327              && element.startsWith (beginQuote2, offset))
328       special = beginQuote2;
329     else if (endQuote2 != null && element.startsWith (endQuote2, offset))
330       special = endQuote2;
331
332     return special;
333   }
334
335   public String toString ()
336   {
337     StringBuffer result = new StringBuffer ();
338     int size = elts.size ();
339     for (int i = 0; i < size; ++i)
340       {
341         // Find the appropriate element.  FIXME: not clear what FLAT
342         // means.
343         int offset = (direction == RIGHT_TO_LEFT) ? (size - i - 1) : i;
344         String element = (String) elts.get (offset);
345         if (i > 0
346             || (i == size - 1 && element.equals ("")))
347           result.append (separator);
348
349         int k = 0;
350         while (k < element.length ())
351           {
352             String special = isSpecial (element, k);
353             if (special != null)
354               {
355                 result.append (escape);
356                 result.append (special);
357                 k += special.length ();
358               }
359             else
360               {
361                 result.append (element.charAt (k));
362                 ++k;
363               }
364           }
365       }
366
367     return result.toString ();
368   }
369
370   // This canonicalizes a String, based on the syntax, for comparison
371   // or other similar purposes.
372   private String canonicalize (String element)
373   {
374     String ret = element;
375
376     if (ignoreCase)
377       ret = ret.toLowerCase ();
378
379     if (trimBlanks)
380       {
381         int first = 0;
382         while (first < ret.length ()
383                && Character.isWhitespace (ret.charAt (first)))
384           ++first;
385
386         int last = ret.length () - 1;
387         while (last >= first
388                && Character.isWhitespace (ret.charAt (last)))
389           --last;
390
391         ret = ret.substring (first, last);
392       }
393
394     return ret;
395   }
396
397   // This initializes all the syntax variables.  This seems easier
398   // than re-querying the properties every time.  We're allowed to do
399   // this because the spec says that subclasses should consider the
400   // syntax as being read-only.
401   private void initializeSyntax ()
402   {
403     String t = mySyntax.getProperty ("jndi.syntax.direction", "flat");
404     if (t.equals ("right_to_left"))
405       this.direction = RIGHT_TO_LEFT;
406     else if (t.equals ("left_to_right"))
407       this.direction = LEFT_TO_RIGHT;
408     else
409       {
410         // If we don't recognize it, default to flat.
411         this.direction = FLAT;
412       }
413
414     // This is required unless the direction is FLAT.  Unfortunately
415     // there is no way to report this error.
416     this.separator = mySyntax.getProperty ("jndi.syntax.separator", "");
417
418     this.ignoreCase
419       = Boolean.valueOf (mySyntax.getProperty ("jndi.syntax.ignorecase",
420                                                "false")).booleanValue ();
421     this.escape = mySyntax.getProperty ("jndi.syntax.escape", null);
422     this.beginQuote = mySyntax.getProperty ("jndi.syntax.beginquote", null);
423     this.endQuote = mySyntax.getProperty ("jndi.syntax.endquote",
424                                           this.beginQuote);
425     this.beginQuote2 = mySyntax.getProperty ("jndi.syntax.beginquote2",
426                                              null);
427     this.endQuote2 = mySyntax.getProperty ("jndi.syntax.endquote2",
428                                            this.beginQuote2);
429     this.trimBlanks
430       = Boolean.valueOf (mySyntax.getProperty ("jndi.syntax.trimblanks",
431                                                "false")).booleanValue ();
432   }
433
434   // The spec specifies this but does not document it in any way (it
435   // is a package-private class).  It is useless as far as I can tell.
436   // So we ignore it.
437   // protected transient NameImpl impl;
438   protected transient Properties mySyntax;
439
440   // The actual elements.
441   private transient Vector elts;
442
443   // The following are all used for syntax.
444   private transient int direction;
445   private transient String separator;
446   private transient boolean ignoreCase;
447   private transient String escape;
448   private transient String beginQuote;
449   private transient String endQuote;
450   private transient String beginQuote2;
451   private transient String endQuote2;
452   private transient boolean trimBlanks;
453   // We didn't need these for parsing, so they are gone.
454   // private transient String avaSeparator;
455   // private transient String typevalSeparator;
456
457   private static final int RIGHT_TO_LEFT = -1;
458   private static final int LEFT_TO_RIGHT = 1;
459   private static final int FLAT = 0;
460 }