diff options
Diffstat (limited to 'javax/naming/CompoundName.java')
-rw-r--r-- | javax/naming/CompoundName.java | 490 |
1 files changed, 490 insertions, 0 deletions
diff --git a/javax/naming/CompoundName.java b/javax/naming/CompoundName.java new file mode 100644 index 000000000..686a3a3d3 --- /dev/null +++ b/javax/naming/CompoundName.java @@ -0,0 +1,490 @@ +/* CompoundName.java -- + Copyright (C) 2001 Free Software Foundation, Inc. + +This file is part of GNU Classpath. + +GNU Classpath is free software; you can redistribute it and/or modify +it under the terms of the GNU General Public License as published by +the Free Software Foundation; either version 2, or (at your option) +any later version. + +GNU Classpath is distributed in the hope that it will be useful, but +WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +General Public License for more details. + +You should have received a copy of the GNU General Public License +along with GNU Classpath; see the file COPYING. If not, write to the +Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA +02111-1307 USA. + +Linking this library statically or dynamically with other modules is +making a combined work based on this library. Thus, the terms and +conditions of the GNU General Public License cover the whole +combination. + +As a special exception, the copyright holders of this library give you +permission to link this library with independent modules to produce an +executable, regardless of the license terms of these independent +modules, and to copy and distribute the resulting executable under +terms of your choice, provided that you also meet, for each linked +independent module, the terms and conditions of the license of that +module. An independent module is a module which is not derived from +or based on this library. If you modify this library, you may extend +this exception to your version of the library, but you are not +obligated to do so. If you do not wish to do so, delete this +exception statement from your version. */ + + +package javax.naming; + +import java.io.Serializable; +import java.util.Enumeration; +import java.util.Properties; +import java.util.NoSuchElementException; +import java.util.Vector; + +/** + * @author Tom Tromey <tromey@redhat.com> + * @date May 16, 2001 + * + * FIXME: must write readObject and writeObject to conform to + * serialization spec. + * + * FIXME: this class is underspecified. For instance, the `flat' + * direction is never described. If it means that the CompoundName + * can only have a single element, then the Enumeration-based + * constructor ought to throw InvalidNameException. + */ +public class CompoundName implements Name, Cloneable, Serializable +{ + private CompoundName (Properties syntax) + { + elts = new Vector (); + mySyntax = syntax; + initializeSyntax (); + } + + protected CompoundName (Enumeration comps, Properties syntax) + { + elts = new Vector (); + mySyntax = syntax; + initializeSyntax (); + try + { + while (comps.hasMoreElements ()) + elts.add (comps.nextElement ()); + } + catch (NoSuchElementException ignore) + { + } + } + + public CompoundName (String n, Properties syntax) + throws InvalidNameException + { + elts = new Vector (); + mySyntax = syntax; + initializeSyntax (); + + StringBuffer new_element = new StringBuffer (); + int i = 0; + // QUOTE==null means no quoting right now. When it is set it is + // the value of the closing quote. + String quote = null; + while (i < n.length ()) + { + String special = isSpecial (n, i); + + if (special == escape && escape != null) + { + if (n.length () == i + special.length ()) + { + // A trailing escape is treated as itself. + new_element.append (special); + i += special.length (); + } + else + { + String eSpecial = isSpecial (n, i + special.length ()); + if (eSpecial != null) + { + // Treat the escape as an escape. + new_element.append (eSpecial); + i += special.length () + eSpecial.length (); + } + else + { + // Treat the escape as itself. + new_element.append (special); + i += special.length (); + } + continue; + } + } + else if (quote != null) + { + // It is safe to use == here. + if (quote == special) + { + // Quotes must surround a complete component. + if (i + quote.length () < n.length () + && ! n.startsWith (separator, i + quote.length ())) + throw new InvalidNameException ("close quote before end of component"); + elts.add (new_element.toString ()); + new_element.setLength (0); + i += quote.length (); + quote = null; + continue; + } + // Otherwise, fall through. + } + // Quotes are only special at the start of a component. + else if (new_element.length () == 0 && special == beginQuote) + { + quote = endQuote; + i += special.length (); + continue; + } + else if (new_element.length () == 0 && special == beginQuote2) + { + quote = endQuote2; + i += special.length (); + continue; + } + else if (special == separator) + { + elts.add (new_element.toString ()); + new_element.setLength (0); + i += special.length (); + continue; + } + + // Nothing in particular, so try the next character. + new_element.append (n.charAt (i)); + ++i; + } + + if (new_element.length () != 0) + elts.add (new_element.toString ()); + + if (direction == RIGHT_TO_LEFT) + { + // Reverse the order of the elements. + int len = elts.size (); + for (i = 0; i < len / 2; ++i) + { + Object t = elts.set (i, elts.get (len - i - 1)); + elts.set (len - i - 1, t); + } + } + + // Error checking. + if (quote != null) + throw new InvalidNameException ("unterminated quote"); + } + + public Name add (int posn, String comp) throws InvalidNameException + { + elts.add (posn, comp); + return this; + } + + public Name add (String comp) throws InvalidNameException + { + elts.add (comp); + return this; + } + + public Name addAll (int posn, Name n) throws InvalidNameException + { + Enumeration e = n.getAll (); + try + { + while (e.hasMoreElements ()) + { + elts.add (posn, e.nextElement ()); + ++posn; + } + } + catch (NoSuchElementException ignore) + { + } + return this; + } + + public Name addAll (Name suffix) throws InvalidNameException + { + Enumeration e = suffix.getAll (); + try + { + while (e.hasMoreElements ()) + elts.add (e.nextElement ()); + } + catch (NoSuchElementException ignore) + { + } + return this; + } + + public Object clone () + { + return new CompoundName (elts.elements (), mySyntax); + } + + public int compareTo (Object obj) + { + if (obj == null || ! (obj instanceof CompoundName)) + throw new ClassCastException ("CompoundName.compareTo() expected CompoundName"); + CompoundName cn = (CompoundName) obj; + int last = Math.min (cn.elts.size (), elts.size ()); + for (int i = 0; i < last; ++i) + { + String f = canonicalize ((String) elts.get (i)); + int comp = f.compareTo (canonicalize ((String) cn.elts.get (i))); + if (comp != 0) + return comp; + } + return elts.size () - cn.elts.size (); + } + + public boolean endsWith (Name n) + { + if (! (n instanceof CompoundName)) + return false; + CompoundName cn = (CompoundName) n; + if (cn.elts.size () > elts.size ()) + return false; + int delta = elts.size () - cn.elts.size (); + for (int i = 0; i < cn.elts.size (); ++i) + { + String f = canonicalize ((String) elts.get (i)); + if (! f.equals (canonicalize ((String) cn.elts.get (i)))) + return false; + } + return true; + } + + public boolean equals (Object obj) + { + if (! (obj instanceof CompoundName)) + return false; + return compareTo (obj) == 0; + } + + public String get (int posn) + { + return (String) elts.get (posn); + } + + public Enumeration getAll () + { + return elts.elements (); + } + + public Name getPrefix (int posn) + { + CompoundName cn = new CompoundName (mySyntax); + for (int i = 0; i < posn; ++i) + cn.elts.add (elts.get (i)); + return cn; + } + + public Name getSuffix (int posn) + { + if (posn > elts.size ()) + throw new ArrayIndexOutOfBoundsException (posn); + CompoundName cn = new CompoundName (mySyntax); + for (int i = posn; i < elts.size (); ++i) + cn.elts.add (elts.get (i)); + return cn; + } + + public int hashCode () + { + int h = 0; + for (int i = 0; i < elts.size (); ++i) + h += canonicalize ((String) elts.get (i)).hashCode (); + return h; + } + + public boolean isEmpty () + { + return elts.isEmpty (); + } + + public Object remove (int posn) throws InvalidNameException + { + return elts.remove (posn); + } + + public int size () + { + return elts.size (); + } + + public boolean startsWith (Name n) + { + if (! (n instanceof CompoundName)) + return false; + CompoundName cn = (CompoundName) n; + if (cn.elts.size () > elts.size ()) + return false; + for (int i = 0; i < cn.elts.size (); ++i) + { + String f = canonicalize ((String) elts.get (i)); + if (! f.equals (canonicalize ((String) cn.elts.get (i)))) + return false; + } + return true; + } + + // If ELEMENT starts with some meta-sequence at OFFSET, then return + // the string representing the meta-sequence. Otherwise return + // null. + private String isSpecial (String element, int offset) + { + String special = null; + if (separator != null && element.startsWith (separator, offset)) + special = separator; + else if (escape != null && element.startsWith (escape, offset)) + special = escape; + else if (beginQuote != null && element.startsWith (beginQuote, offset)) + special = beginQuote; + else if (endQuote != null && element.startsWith (endQuote, offset)) + special = endQuote; + else if (beginQuote2 != null + && element.startsWith (beginQuote2, offset)) + special = beginQuote2; + else if (endQuote2 != null && element.startsWith (endQuote2, offset)) + special = endQuote2; + + return special; + } + + public String toString () + { + StringBuffer result = new StringBuffer (); + int size = elts.size (); + for (int i = 0; i < size; ++i) + { + // Find the appropriate element. FIXME: not clear what FLAT + // means. + int offset = (direction == RIGHT_TO_LEFT) ? (size - i - 1) : i; + String element = (String) elts.get (offset); + if (i > 0 + || (i == size - 1 && element.equals (""))) + result.append (separator); + + int k = 0; + while (k < element.length ()) + { + String special = isSpecial (element, k); + if (special != null) + { + result.append (escape); + result.append (special); + k += special.length (); + } + else + { + result.append (element.charAt (k)); + ++k; + } + } + } + + return result.toString (); + } + + // This canonicalizes a String, based on the syntax, for comparison + // or other similar purposes. + private String canonicalize (String element) + { + String ret = element; + + if (ignoreCase) + ret = ret.toLowerCase (); + + if (trimBlanks) + { + int first = 0; + while (first < ret.length () + && Character.isWhitespace (ret.charAt (first))) + ++first; + + int last = ret.length () - 1; + while (last >= first + && Character.isWhitespace (ret.charAt (last))) + --last; + + ret = ret.substring (first, last); + } + + return ret; + } + + // This initializes all the syntax variables. This seems easier + // than re-querying the properties every time. We're allowed to do + // this because the spec says that subclasses should consider the + // syntax as being read-only. + private void initializeSyntax () + { + String t = mySyntax.getProperty ("jndi.syntax.direction", "flat"); + if (t.equals ("right_to_left")) + this.direction = RIGHT_TO_LEFT; + else if (t.equals ("left_to_right")) + this.direction = LEFT_TO_RIGHT; + else + { + // If we don't recognize it, default to flat. + this.direction = FLAT; + } + + // This is required unless the direction is FLAT. Unfortunately + // there is no way to report this error. + this.separator = mySyntax.getProperty ("jndi.syntax.separator", ""); + + this.ignoreCase + = Boolean.valueOf (mySyntax.getProperty ("jndi.syntax.ignorecase", + "false")).booleanValue (); + this.escape = mySyntax.getProperty ("jndi.syntax.escape", null); + this.beginQuote = mySyntax.getProperty ("jndi.syntax.beginquote", null); + this.endQuote = mySyntax.getProperty ("jndi.syntax.endquote", + this.beginQuote); + this.beginQuote2 = mySyntax.getProperty ("jndi.syntax.beginquote2", + null); + this.endQuote2 = mySyntax.getProperty ("jndi.syntax.endquote2", + this.beginQuote2); + this.trimBlanks + = Boolean.valueOf (mySyntax.getProperty ("jndi.syntax.trimblanks", + "false")).booleanValue (); + } + + // The spec specifies this but does not document it in any way (it + // is a package-private class). It is useless as far as I can tell. + // So we ignore it. + // protected transient NameImpl impl; + protected transient Properties mySyntax; + + // The actual elements. + private transient Vector elts; + + // The following are all used for syntax. + private transient int direction; + private transient String separator; + private transient boolean ignoreCase; + private transient String escape; + private transient String beginQuote; + private transient String endQuote; + private transient String beginQuote2; + private transient String endQuote2; + private transient boolean trimBlanks; + // We didn't need these for parsing, so they are gone. + // private transient String avaSeparator; + // private transient String typevalSeparator; + + private static final int RIGHT_TO_LEFT = -1; + private static final int LEFT_TO_RIGHT = 1; + private static final int FLAT = 0; +} |