Save This Page
Home » openjdk-7 » javax » naming » [javadoc | source]
    1   /*
    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   
   26   package javax.naming;
   27   
   28   import java.util.Enumeration;
   29   import java.util.Properties;
   30   
   31   /**
   32    * This class represents a compound name -- a name from
   33    * a hierarchical name space.
   34    * Each component in a compound name is an atomic name.
   35    * <p>
   36    * The components of a compound name are numbered.  The indexes of a
   37    * compound name with N components range from 0 up to, but not including, N.
   38    * This range may be written as [0,N).
   39    * The most significant component is at index 0.
   40    * An empty compound name has no components.
   41    *<p>
   42    * <h4>Compound Name Syntax</h4>
   43    * The syntax of a compound name is specified using a set of properties:
   44    *<dl>
   45    *  <dt>jndi.syntax.direction
   46    *  <dd>Direction for parsing ("right_to_left", "left_to_right", "flat").
   47    *      If unspecified, defaults to "flat", which means the namespace is flat
   48    *      with no hierarchical structure.
   49    *
   50    *  <dt>jndi.syntax.separator
   51    *  <dd>Separator between atomic name components.
   52    *      Required unless direction is "flat".
   53    *
   54    *  <dt>jndi.syntax.ignorecase
   55    *  <dd>If present, "true" means ignore the case when comparing name
   56    *      components. If its value is not "true", or if the property is not
   57    *      present, case is considered when comparing name components.
   58    *
   59    *  <dt>jndi.syntax.escape
   60    *  <dd>If present, specifies the escape string for overriding separator,
   61    *      escapes and quotes.
   62    *
   63    *  <dt>jndi.syntax.beginquote
   64    *  <dd>If present, specifies the string delimiting start of a quoted string.
   65    *
   66    *  <dt>jndi.syntax.endquote
   67    *  <dd>String delimiting end of quoted string.
   68    *      If present, specifies the string delimiting the end of a quoted string.
   69    *      If not present, use syntax.beginquote as end quote.
   70    *  <dt>jndi.syntax.beginquote2
   71    *  <dd>Alternative set of begin/end quotes.
   72    *
   73    *  <dt>jndi.syntax.endquote2
   74    *  <dd>Alternative set of begin/end quotes.
   75    *
   76    *  <dt>jndi.syntax.trimblanks
   77    *  <dd>If present, "true" means trim any leading and trailing whitespaces
   78    *      in a name component for comparison purposes. If its value is not
   79    *      "true", or if the property is not present, blanks are significant.
   80    *  <dt>jndi.syntax.separator.ava
   81    *  <dd>If present, specifies the string that separates
   82    *      attribute-value-assertions when specifying multiple attribute/value
   83    *      pairs. (e.g. ","  in age=65,gender=male).
   84    *  <dt>jndi.syntax.separator.typeval
   85    *  <dd>If present, specifies the string that separators attribute
   86    *              from value (e.g. "=" in "age=65")
   87    *</dl>
   88    * These properties are interpreted according to the following rules:
   89    *<ol>
   90    *<li>
   91    * In a string without quotes or escapes, any instance of the
   92    * separator delimits two atomic names. Each atomic name is referred
   93    * to as a <em>component</em>.
   94    *<li>
   95    * A separator, quote or escape is escaped if preceded immediately
   96    * (on the left) by the escape.
   97    *<li>
   98    * If there are two sets of quotes, a specific begin-quote must be matched
   99    * by its corresponding end-quote.
  100    *<li>
  101    * A non-escaped begin-quote which precedes a component must be
  102    * matched by a non-escaped end-quote at the end of the component.
  103    * A component thus quoted is referred to as a
  104    * <em>quoted component</em>. It is parsed by
  105    * removing the being- and end- quotes, and by treating the intervening
  106    * characters as ordinary characters unless one of the rules involving
  107    * quoted components listed below applies.
  108    *<li>
  109    * Quotes embedded in non-quoted components are treated as ordinary strings
  110    * and need not be matched.
  111    *<li>
  112    * A separator that is escaped or appears between non-escaped
  113    * quotes is treated as an ordinary string and not a separator.
  114    *<li>
  115    * An escape string within a quoted component acts as an escape only when
  116    * followed by the corresponding end-quote string.
  117    * This can be used to embed an escaped quote within a quoted component.
  118    *<li>
  119    * An escaped escape string is not treated as an escape string.
  120    *<li>
  121    * An escape string that does not precede a meta string (quotes or separator)
  122    * and is not at the end of a component is treated as an ordinary string.
  123    *<li>
  124    * A leading separator (the compound name string begins with
  125    * a separator) denotes a leading empty atomic component (consisting
  126    * of an empty string).
  127    * A trailing separator (the compound name string ends with
  128    * a separator) denotes a trailing empty atomic component.
  129    * Adjacent separators denote an empty atomic component.
  130    *</ol>
  131    * <p>
  132    * The string form of the compound name follows the syntax described above.
  133    * When the components of the compound name are turned into their
  134    * string representation, the reserved syntax rules described above are
  135    * applied (e.g. embedded separators are escaped or quoted)
  136    * so that when the same string is parsed, it will yield the same components
  137    * of the original compound name.
  138    *<p>
  139    *<h4>Multithreaded Access</h4>
  140    * A <tt>CompoundName</tt> instance is not synchronized against concurrent
  141    * multithreaded access. Multiple threads trying to access and modify a
  142    * <tt>CompoundName</tt> should lock the object.
  143    *
  144    * @author Rosanna Lee
  145    * @author Scott Seligman
  146    * @since 1.3
  147    */
  148   
  149   public class CompoundName implements Name {
  150   
  151       /**
  152         * Implementation of this compound name.
  153         * This field is initialized by the constructors and cannot be null.
  154         * It should be treated as a read-only variable by subclasses.
  155         */
  156       protected transient NameImpl impl;
  157       /**
  158         * Syntax properties for this compound name.
  159         * This field is initialized by the constructors and cannot be null.
  160         * It should be treated as a read-only variable by subclasses.
  161         * Any necessary changes to mySyntax should be made within constructors
  162         * and not after the compound name has been instantiated.
  163         */
  164       protected transient Properties mySyntax;
  165   
  166       /**
  167         * Constructs a new compound name instance using the components
  168         * specified in comps and syntax. This protected method is intended to be
  169         * to be used by subclasses of CompoundName when they override
  170         * methods such as clone(), getPrefix(), getSuffix().
  171         *
  172         * @param comps  A non-null enumeration of the components to add.
  173         *   Each element of the enumeration is of class String.
  174         *               The enumeration will be consumed to extract its
  175         *               elements.
  176         * @param syntax   A non-null properties that specify the syntax of
  177         *                 this compound name. See class description for
  178         *                 contents of properties.
  179         */
  180       protected CompoundName(Enumeration<String> comps, Properties syntax) {
  181           if (syntax == null) {
  182               throw new NullPointerException();
  183           }
  184           mySyntax = syntax;
  185           impl = new NameImpl(syntax, comps);
  186       }
  187   
  188       /**
  189         * Constructs a new compound name instance by parsing the string n
  190         * using the syntax specified by the syntax properties supplied.
  191         *
  192         * @param  n       The non-null string to parse.
  193         * @param syntax   A non-null list of properties that specify the syntax of
  194         *                 this compound name.  See class description for
  195         *                 contents of properties.
  196         * @exception      InvalidNameException If 'n' violates the syntax specified
  197         *                 by <code>syntax</code>.
  198         */
  199       public CompoundName(String n, Properties syntax) throws InvalidNameException {
  200           if (syntax == null) {
  201               throw new NullPointerException();
  202           }
  203           mySyntax = syntax;
  204           impl = new NameImpl(syntax, n);
  205       }
  206   
  207       /**
  208         * Generates the string representation of this compound name, using
  209         * the syntax rules of the compound name. The syntax rules
  210         * are described in the class description.
  211         * An empty component is represented by an empty string.
  212         *
  213         * The string representation thus generated can be passed to
  214         * the CompoundName constructor with the same syntax properties
  215         * to create a new equivalent compound name.
  216         *
  217         * @return A non-null string representation of this compound name.
  218         */
  219       public String toString() {
  220           return (impl.toString());
  221       }
  222   
  223       /**
  224         * Determines whether obj is syntactically equal to this compound name.
  225         * If obj is null or not a CompoundName, false is returned.
  226         * Two compound names are equal if each component in one is "equal"
  227         * to the corresponding component in the other.
  228         *<p>
  229         * Equality is also defined in terms of the syntax of this compound name.
  230         * The default implementation of CompoundName uses the syntax properties
  231         * jndi.syntax.ignorecase and jndi.syntax.trimblanks when comparing
  232         * two components for equality.  If case is ignored, two strings
  233         * with the same sequence of characters but with different cases
  234         * are considered equal. If blanks are being trimmed, leading and trailing
  235         * blanks are ignored for the purpose of the comparison.
  236         *<p>
  237         * Both compound names must have the same number of components.
  238         *<p>
  239         * Implementation note: Currently the syntax properties of the two compound
  240         * names are not compared for equality. They might be in the future.
  241         *
  242         * @param  obj     The possibly null object to compare against.
  243         * @return true if obj is equal to this compound name, false otherwise.
  244         * @see #compareTo(java.lang.Object obj)
  245         */
  246       public boolean equals(Object obj) {
  247           // %%% check syntax too?
  248           return (obj != null &&
  249                   obj instanceof CompoundName &&
  250                   impl.equals(((CompoundName)obj).impl));
  251       }
  252   
  253       /**
  254         * Computes the hash code of this compound name.
  255         * The hash code is the sum of the hash codes of the "canonicalized"
  256         * forms of individual components of this compound name.
  257         * Each component is "canonicalized" according to the
  258         * compound name's syntax before its hash code is computed.
  259         * For a case-insensitive name, for example, the uppercased form of
  260         * a name has the same hash code as its lowercased equivalent.
  261         *
  262         * @return An int representing the hash code of this name.
  263         */
  264       public int hashCode() {
  265           return impl.hashCode();
  266       }
  267   
  268       /**
  269         * Creates a copy of this compound name.
  270         * Changes to the components of this compound name won't
  271         * affect the new copy and vice versa.
  272         * The clone and this compound name share the same syntax.
  273         *
  274         * @return A non-null copy of this compound name.
  275         */
  276       public Object clone() {
  277           return (new CompoundName(getAll(), mySyntax));
  278       }
  279   
  280       /**
  281        * Compares this CompoundName with the specified Object for order.
  282        * Returns a
  283        * negative integer, zero, or a positive integer as this Name is less
  284        * than, equal to, or greater than the given Object.
  285        * <p>
  286        * If obj is null or not an instance of CompoundName, ClassCastException
  287        * is thrown.
  288        * <p>
  289        * See equals() for what it means for two compound names to be equal.
  290        * If two compound names are equal, 0 is returned.
  291        *<p>
  292        * Ordering of compound names depend on the syntax of the compound name.
  293        * By default, they follow lexicographical rules for string comparison
  294        * with the extension that this applies to all the components in the
  295        * compound name and that comparison of individual components is
  296        * affected by the jndi.syntax.ignorecase and jndi.syntax.trimblanks
  297        * properties, identical to how they affect equals().
  298        * If this compound name is "lexicographically" lesser than obj,
  299        * a negative number is returned.
  300        * If this compound name is "lexicographically" greater than obj,
  301        * a positive number is returned.
  302        *<p>
  303        * Implementation note: Currently the syntax properties of the two compound
  304        * names are not compared when checking order. They might be in the future.
  305        * @param   obj     The non-null object to compare against.
  306        * @return  a negative integer, zero, or a positive integer as this Name
  307        *          is less than, equal to, or greater than the given Object.
  308        * @exception ClassCastException if obj is not a CompoundName.
  309        * @see #equals(java.lang.Object)
  310        */
  311       public int compareTo(Object obj) {
  312           if (!(obj instanceof CompoundName)) {
  313               throw new ClassCastException("Not a CompoundName");
  314           }
  315           return impl.compareTo(((CompoundName)obj).impl);
  316       }
  317   
  318       /**
  319         * Retrieves the number of components in this compound name.
  320         *
  321         * @return The nonnegative number of components in this compound name.
  322         */
  323       public int size() {
  324           return (impl.size());
  325       }
  326   
  327       /**
  328         * Determines whether this compound name is empty.
  329         * A compound name is empty if it has zero components.
  330         *
  331         * @return true if this compound name is empty, false otherwise.
  332         */
  333       public boolean isEmpty() {
  334           return (impl.isEmpty());
  335       }
  336   
  337       /**
  338         * Retrieves the components of this compound name as an enumeration
  339         * of strings.
  340         * The effects of updates to this compound name on this enumeration
  341         * is undefined.
  342         *
  343         * @return A non-null enumeration of the components of this
  344         * compound name. Each element of the enumeration is of class String.
  345         */
  346       public Enumeration<String> getAll() {
  347           return (impl.getAll());
  348       }
  349   
  350       /**
  351         * Retrieves a component of this compound name.
  352         *
  353         * @param  posn    The 0-based index of the component to retrieve.
  354         *                 Must be in the range [0,size()).
  355         * @return The component at index posn.
  356         * @exception ArrayIndexOutOfBoundsException if posn is outside the
  357         *         specified range.
  358         */
  359       public String get(int posn) {
  360           return (impl.get(posn));
  361       }
  362   
  363       /**
  364         * Creates a compound name whose components consist of a prefix of the
  365         * components in this compound name.
  366         * The result and this compound name share the same syntax.
  367         * Subsequent changes to
  368         * this compound name does not affect the name that is returned and
  369         * vice versa.
  370         *
  371         * @param  posn    The 0-based index of the component at which to stop.
  372         *                 Must be in the range [0,size()].
  373         * @return A compound name consisting of the components at indexes in
  374         *         the range [0,posn).
  375         * @exception ArrayIndexOutOfBoundsException
  376         *         If posn is outside the specified range.
  377         */
  378       public Name getPrefix(int posn) {
  379           Enumeration comps = impl.getPrefix(posn);
  380           return (new CompoundName(comps, mySyntax));
  381       }
  382   
  383       /**
  384         * Creates a compound name whose components consist of a suffix of the
  385         * components in this compound name.
  386         * The result and this compound name share the same syntax.
  387         * Subsequent changes to
  388         * this compound name does not affect the name that is returned.
  389         *
  390         * @param  posn    The 0-based index of the component at which to start.
  391         *                 Must be in the range [0,size()].
  392         * @return A compound name consisting of the components at indexes in
  393         *         the range [posn,size()).  If posn is equal to
  394         *         size(), an empty compound name is returned.
  395         * @exception ArrayIndexOutOfBoundsException
  396         *         If posn is outside the specified range.
  397         */
  398       public Name getSuffix(int posn) {
  399           Enumeration comps = impl.getSuffix(posn);
  400           return (new CompoundName(comps, mySyntax));
  401       }
  402   
  403       /**
  404         * Determines whether a compound name is a prefix of this compound name.
  405         * A compound name 'n' is a prefix if it is equal to
  406         * getPrefix(n.size())--in other words, this compound name
  407         * starts with 'n'.
  408         * If n is null or not a compound name, false is returned.
  409         *<p>
  410         * Implementation note: Currently the syntax properties of n
  411         *  are not used when doing the comparison. They might be in the future.
  412         * @param  n       The possibly null compound name to check.
  413         * @return true if n is a CompoundName and
  414         *                 is a prefix of this compound name, false otherwise.
  415         */
  416       public boolean startsWith(Name n) {
  417           if (n instanceof CompoundName) {
  418               return (impl.startsWith(n.size(), n.getAll()));
  419           } else {
  420               return false;
  421           }
  422       }
  423   
  424       /**
  425         * Determines whether a compound name is a suffix of this compound name.
  426         * A compound name 'n' is a suffix if it it is equal to
  427         * getSuffix(size()-n.size())--in other words, this
  428         * compound name ends with 'n'.
  429         * If n is null or not a compound name, false is returned.
  430         *<p>
  431         * Implementation note: Currently the syntax properties of n
  432         *  are not used when doing the comparison. They might be in the future.
  433         * @param  n       The possibly null compound name to check.
  434         * @return true if n is a CompoundName and
  435         *         is a suffix of this compound name, false otherwise.
  436         */
  437       public boolean endsWith(Name n) {
  438           if (n instanceof CompoundName) {
  439               return (impl.endsWith(n.size(), n.getAll()));
  440           } else {
  441               return false;
  442           }
  443       }
  444   
  445       /**
  446         * Adds the components of a compound name -- in order -- to the end of
  447         * this compound name.
  448         *<p>
  449         * Implementation note: Currently the syntax properties of suffix
  450         *  is not used or checked. They might be in the future.
  451         * @param suffix   The non-null components to add.
  452         * @return The updated CompoundName, not a new one. Cannot be null.
  453         * @exception InvalidNameException If suffix is not a compound name,
  454         *            or if the addition of the components violates the syntax
  455         *            of this compound name (e.g. exceeding number of components).
  456         */
  457       public Name addAll(Name suffix) throws InvalidNameException {
  458           if (suffix instanceof CompoundName) {
  459               impl.addAll(suffix.getAll());
  460               return this;
  461           } else {
  462               throw new InvalidNameException("Not a compound name: " +
  463                   suffix.toString());
  464           }
  465       }
  466   
  467       /**
  468         * Adds the components of a compound name -- in order -- at a specified
  469         * position within this compound name.
  470         * Components of this compound name at or after the index of the first
  471         * new component are shifted up (away from index 0)
  472         * to accommodate the new components.
  473         *<p>
  474         * Implementation note: Currently the syntax properties of suffix
  475         *  is not used or checked. They might be in the future.
  476         *
  477         * @param n        The non-null components to add.
  478         * @param posn     The index in this name at which to add the new
  479         *                 components.  Must be in the range [0,size()].
  480         * @return The updated CompoundName, not a new one. Cannot be null.
  481         * @exception ArrayIndexOutOfBoundsException
  482         *         If posn is outside the specified range.
  483         * @exception InvalidNameException If n is not a compound name,
  484         *            or if the addition of the components violates the syntax
  485         *            of this compound name (e.g. exceeding number of components).
  486         */
  487       public Name addAll(int posn, Name n) throws InvalidNameException {
  488           if (n instanceof CompoundName) {
  489               impl.addAll(posn, n.getAll());
  490               return this;
  491           } else {
  492               throw new InvalidNameException("Not a compound name: " +
  493                   n.toString());
  494           }
  495       }
  496   
  497       /**
  498         * Adds a single component to the end of this compound name.
  499         *
  500         * @param comp     The non-null component to add.
  501         * @return The updated CompoundName, not a new one. Cannot be null.
  502         * @exception InvalidNameException If adding comp at end of the name
  503         *                         would violate the compound name's syntax.
  504         */
  505       public Name add(String comp) throws InvalidNameException{
  506           impl.add(comp);
  507           return this;
  508       }
  509   
  510       /**
  511         * Adds a single component at a specified position within this
  512         * compound name.
  513         * Components of this compound name at or after the index of the new
  514         * component are shifted up by one (away from index 0)
  515         * to accommodate the new component.
  516         *
  517         * @param  comp    The non-null component to add.
  518         * @param  posn    The index at which to add the new component.
  519         *                 Must be in the range [0,size()].
  520         * @exception ArrayIndexOutOfBoundsException
  521         *         If posn is outside the specified range.
  522         * @return The updated CompoundName, not a new one. Cannot be null.
  523         * @exception InvalidNameException If adding comp at the specified position
  524         *                         would violate the compound name's syntax.
  525         */
  526       public Name add(int posn, String comp) throws InvalidNameException{
  527           impl.add(posn, comp);
  528           return this;
  529       }
  530   
  531       /**
  532         * Deletes a component from this compound name.
  533         * The component of this compound name at position 'posn' is removed,
  534         * and components at indices greater than 'posn'
  535         * are shifted down (towards index 0) by one.
  536         *
  537         * @param  posn    The index of the component to delete.
  538         *                 Must be in the range [0,size()).
  539         * @return The component removed (a String).
  540         * @exception ArrayIndexOutOfBoundsException
  541         *         If posn is outside the specified range (includes case where
  542         *         compound name is empty).
  543         * @exception InvalidNameException If deleting the component
  544         *                         would violate the compound name's syntax.
  545         */
  546       public Object remove(int posn) throws InvalidNameException {
  547           return impl.remove(posn);
  548       }
  549   
  550       /**
  551        * Overridden to avoid implementation dependency.
  552        * @serialData The syntax <tt>Properties</tt>, followed by
  553        * the number of components (an <tt>int</tt>), and the individual
  554        * components (each a <tt>String</tt>).
  555        */
  556       private void writeObject(java.io.ObjectOutputStream s)
  557               throws java.io.IOException {
  558           s.writeObject(mySyntax);
  559           s.writeInt(size());
  560           Enumeration comps = getAll();
  561           while (comps.hasMoreElements()) {
  562               s.writeObject(comps.nextElement());
  563           }
  564       }
  565   
  566       /**
  567        * Overridden to avoid implementation dependency.
  568        */
  569       private void readObject(java.io.ObjectInputStream s)
  570               throws java.io.IOException, ClassNotFoundException {
  571           mySyntax = (Properties)s.readObject();
  572           impl = new NameImpl(mySyntax);
  573           int n = s.readInt();    // number of components
  574           try {
  575               while (--n >= 0) {
  576                   add((String)s.readObject());
  577               }
  578           } catch (InvalidNameException e) {
  579               throw (new java.io.StreamCorruptedException("Invalid name"));
  580           }
  581       }
  582   
  583       /**
  584        * Use serialVersionUID from JNDI 1.1.1 for interoperability
  585        */
  586       private static final long serialVersionUID = 3513100557083972036L;
  587   
  588   /*
  589   //   For testing
  590   
  591       public static void main(String[] args) {
  592           Properties dotSyntax = new Properties();
  593           dotSyntax.put("jndi.syntax.direction", "right_to_left");
  594           dotSyntax.put("jndi.syntax.separator", ".");
  595           dotSyntax.put("jndi.syntax.ignorecase", "true");
  596           dotSyntax.put("jndi.syntax.escape", "\\");
  597   //      dotSyntax.put("jndi.syntax.beginquote", "\"");
  598   //      dotSyntax.put("jndi.syntax.beginquote2", "'");
  599   
  600           Name first = null;
  601           try {
  602               for (int i = 0; i < args.length; i++) {
  603                   Name name;
  604                   Enumeration e;
  605                   System.out.println("Given name: " + args[i]);
  606                   name = new CompoundName(args[i], dotSyntax);
  607                   if (first == null) {
  608                       first = name;
  609                   }
  610                   e = name.getComponents();
  611                   while (e.hasMoreElements()) {
  612                       System.out.println("Element: " + e.nextElement());
  613                   }
  614                   System.out.println("Constructed name: " + name.toString());
  615   
  616                   System.out.println("Compare " + first.toString() + " with "
  617                       + name.toString() + " = " + first.compareTo(name));
  618               }
  619           } catch (Exception ne) {
  620               ne.printStackTrace();
  621           }
  622       }
  623   */
  624   }

Save This Page
Home » openjdk-7 » javax » naming » [javadoc | source]