You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@harmony.apache.org by te...@apache.org on 2006/03/15 15:57:17 UTC

svn commit: r386087 [3/45] - in /incubator/harmony/enhanced/classlib/trunk: make/ make/patternsets/ modules/jndi/ modules/jndi/META-INF/ modules/jndi/make/ modules/jndi/make/common/ modules/jndi/src/ modules/jndi/src/main/ modules/jndi/src/main/java/ m...

Added: incubator/harmony/enhanced/classlib/trunk/modules/jndi/src/main/java/javax/naming/CompoundName.java
URL: http://svn.apache.org/viewcvs/incubator/harmony/enhanced/classlib/trunk/modules/jndi/src/main/java/javax/naming/CompoundName.java?rev=386087&view=auto
==============================================================================
--- incubator/harmony/enhanced/classlib/trunk/modules/jndi/src/main/java/javax/naming/CompoundName.java (added)
+++ incubator/harmony/enhanced/classlib/trunk/modules/jndi/src/main/java/javax/naming/CompoundName.java Wed Mar 15 06:55:38 2006
@@ -0,0 +1,1024 @@
+/* Copyright 2004 The Apache Software Foundation or its licensors, as applicable
+ * 
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ * 
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ * 
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+
+package javax.naming;
+
+import java.io.IOException;
+import java.io.ObjectInputStream;
+import java.io.ObjectOutputStream;
+import java.util.Enumeration;
+import java.util.Properties;
+import java.util.Vector;
+
+/**
+ * A <code>CompoundName</code> is a series of string elements, and it represents 
+ * a name in a naming service within a single namespace. Typically these 
+ * names have a structure which is hierarchical. 
+ * <p>
+ * A <code>CompoundName</code> has a sequence of zero or more elements delimited 
+ * by the char specified in the property "jndi.syntax.separator". This property 
+ * is required except when the direction of the name is "flat" 
+ * (see jndi.syntax.direction). The property "jndi.syntax.separator2" allows for 
+ * the specification of an additional separator. A separator string will be 
+ * treated as normal characters if it is preceded by the escape string or is 
+ * within quotes.</p>
+ * <p>
+ * The property "jndi.syntax.direction" specifies the direction in which the name
+ * is read. Permitted values are "right_to_left", "left_to_right" and "flat". A 
+ * flat name does not have a hierarchical structure. If this property is not 
+ * specified then the default is "flat". If this property is specified with an 
+ * invalid value then an <code>IllegalArgumentException</code> should be raised.</p>
+ * <p>
+ * Each element can be accessed using its position. The first element is at 
+ * position 0. The direction of the name is important. When direction is 
+ * "left_to_right" then the leftmost element is at position 0. Conversely when 
+ * the direction is "right_to_left" then the rightmost element is at position 0.</p>
+ * <p>
+ * There are other properties which affect the syntax of a <code>CompoundName</code>. 
+ * The following properties are all optional:
+ * <ul>
+ * <li>
+ * jndi.syntax.escape -		Escape sequence,The escape sequence is used to escape 
+ * 							a quote, separator or escape. When preceded itself by 
+ * 							the escape sequence it is treated as ordinary characters.
+ * 							When it is followed by chars which are not quote or 
+ * 							separator strings then it is treated as ordinary characters</li>
+ * <li>
+ * jndi.syntax.beginquote -	Used as start of quoted string (Defaults to endquote)</li>
+ * <li>
+ * jndi.syntax.endquote - 	Used as end of quoted string (Defaults to beginquote)</li>
+ * <li>
+ * jndi.syntax.beginquote2 -	Additionally used as start of quoted string 
+ * 							(Defaults to endquote2)</li>
+ * <li>
+ * jndi.syntax.endquote2 - 	Additionally used as end of quoted string 
+ * 							(Defaults to beginquote2)</li>
+ * </ul>
+ * <p>
+ * When a non-escaped quote appears at the start of an element it must be matched at the
+ * end. That element can then be said to be quoted. When an escape sequence appears
+ * within a quoted element then it is treated as normal characters unless it precedes
+ * an occurence of the quote in which case it is assumed that the quoted element
+ * contains a quote which is escaped.</p>
+ * <p>
+ * If the element does not start with a quote, then any quote strings within that
+ * element are just normal characters.</p>
+ * <p>
+ * <ul>
+ * <li>
+ * jndi.syntax.ignorecase -	If 'true' then ignore case when name elements are compared.
+ *  						If false or not set then case is important.</li>
+ * <li>
+ * jndi.syntax.trimblanks -	If 'true' then ignore leading & trailing blanks when name elements are compared.
+ * 							If false or not set then blanks are important.</li>
+ * </ul></p>
+ * <p>
+ * These 2 properties relate to names where the syntax includes attribute/content 
+ * pairs.
+ * <ul>
+ * <li>jndi.syntax.separator.ava</li>
+ * <li>jndi.syntax.separator.typeval</li>
+ * </ul>
+ * For example the LDAP name, "CN=Mandy Jennings, O=Apache, C=UK".
+ * In this example the pair separator jndi.syntax.separator.ava is ',', and the 
+ * character that separates pairs jndi.syntax.separator.typeval is '='. See 
+ * RFC1779 for LDAP naming conventions.</p>
+ * <p>
+ * The jndi.syntax.separator.ava is not used when manipulating <code>CompoundName</code>. 
+ * The jndi.syntax.separator is still used to separate elements.</p>
+ * <p>
+ * The <code>CompoundName</code> needs to be aware of the jndi.syntax.separator.typeval
+ * in case of the instance where a quoted string is used to provide the content
+ * of a pair.</p>
+ * <p>
+ * Consider the string "CN=$Mandy Jennings, O=Apache, C=UK" with
+ * <ul>
+ * <li>
+ * jndi.syntax.direction         set to "right_to_left"</li>
+ * <li>
+ * jndi.syntax.separator         set to ","</li>
+ * <li>
+ * jndi.syntax.separator.typeval set to "="</li>
+ * </ul>
+ * When no jndi.syntax.beginquote is set then this creates a valid <code>CompoundName</code>
+ * with 3 elements.</p>
+ * <p>
+ * If jndi.syntax.beginquote is then set to "$" the name becomes invalid as the
+ * content part of the pair CN=$Mandy Jennings has a mismatched quote.</p>
+ * <p>
+ * The string "CN=$Mandy Jennings$, O=Apache, C=UK" would be fine as the $ quotes
+ * round Mandy Jennings now balance.</p>
+ * <p>
+ * A <code>CompoundName</code> may be empty. An empty <code>CompoundName</code> has no elements.
+ * Elements may also be empty.</p> 
+ * 
+ * <pre>
+ * Some Examples:
+ * ==============
+ * 
+ * Consider the following compound name from the file system namespace:
+ *     "home/jenningm-abc/.profile" 
+ * 
+ * jndi.syntax.separator is set to '/' as in the UNIX filesystem.
+ * This name has 3 elements:
+ *     home jenningm-abc and .profile
+ * The direction should be left_to_right as in the UNIX filesystem
+ * The element at position 0 would be home.
+ * 
+ * 
+ * Consider if jndi.syntax.separator had been set to '-' then this name 
+ * would have 2 elements:
+ *     home/jenningm and abc/.profile
+ * If the direction was right_to_left then the element at position 0
+ * would be abc/.profile.
+ * 
+ * Consider the name "&lt;ab&lt;cd&gt;ef&gt;" where jndi.syntax.beginquote is &lt;
+ * and jndi.syntax.endquote is &gt;. This will give rise to an 
+ * InvalidNameException because a close quote was encountered before
+ * the end of an element. The same is also true for "&lt;abcd&gt;ef&gt;".
+ * If the name was "ab&lt;cd&gt;ef" then this would be valid and there would
+ * be one element ab&lt;cd&gt;ef.
+ * However if the name was "&lt;abcdef&gt;" there would be one element abcdef.
+ * 
+ * An empty <code>CompoundName</code> is the name "" and has no elements.
+ * 
+ * When jndi.syntax.beginquote is set to " and beginquote2 is set to '
+ * the behaviour is simliar to CompositeName - 
+ * The name "\"abcd" gives an InvalidNameException as there is no closing quote.
+ * The name "'\"abcd'" gives one element of value "abcd.
+ * The name "\\abcd" gives one element of value \abcd. 
+ *  
+ * Assuming:
+ *     jndi.syntax.separator is "/"
+ *     jndi.syntax.direction is "left_to_right"
+ * then
+ *     "" is empty. It has no elements.
+ *     "/" has one empty element.
+ *     "//" has 2 empty elements.
+ *     "/a/" has 3 elements the middle one is set to a.
+ *     "///" has 3 empty elements.
+ *     "//a/" has 4 elements, the last but one is set to a.
+ * 
+ *
+ * Assuming the only properties set are: 
+ *     jndi.syntax.separator is "/"
+ *     jndi.syntax.direction is "left_to_right"
+ * then the String
+ *     "\"" has one element with the value "
+ *     "\\\"" has one element with the value \"
+ *     "\\\"'" has one element with the value \"'
+ * 
+ * Assuming the only properties set are:
+ *     jndi.syntax.separator is "/"
+ *     jndi.syntax.direction is "left_to_right"
+ *     jndi.syntax.beginquote is "\""
+ * 
+ * then the String
+ *     "\"" is invalid because of no closing quote
+ *     "\\\"" has one element with the value \"
+ *     "\\\"'" has one element with the value \"'
+ * 
+ * 
+ * Assuming the only properties set are:
+ *     jndi.syntax.separator is "/"
+ *     jndi.syntax.direction is "left_to_right"
+ *     jndi.syntax.beginquote is "\""
+ *     jndi.syntax.beginquote2 is "\'"
+ * then the String
+ *     "\"" is invalid because of no closing quote
+ *     "\\\"" has one element with the value \"
+ *     "\\\"'" has one element with the value \"'
+ *     "'\\" is invalid because of no closing quote
+ * </pre>
+ * 
+ * 
+ */
+
+public class CompoundName implements Name {
+
+    /*
+     * -------------------------------------------------------------------
+     * Constants
+     * -------------------------------------------------------------------
+     */
+
+    /*
+     *=============
+     *Serialization
+     *=============
+     *
+     *Note: For serialization purposes, the specified serialVersionUID must be used.
+     *This class does not have serializable fields specified. Instead the readObject
+     *and writeObject methods are overidden.
+     */
+    static final long serialVersionUID = 3513100557083972036L; // J2SE 1.4.2
+
+    //const for property key
+    private static final String SEPARATOR = "jndi.syntax.separator"; //$NON-NLS-1$
+
+    private static final String SEPARATOR_AVA = "jndi.syntax.separator.ava"; //$NON-NLS-1$
+
+    private static final String SEPARATOR_TYPEVAL = "jndi.syntax.separator.typeval"; //$NON-NLS-1$
+
+    private static final String ESCAPE = "jndi.syntax.escape"; //$NON-NLS-1$
+
+    private static final String BEGIN_QUOTE = "jndi.syntax.beginquote"; //$NON-NLS-1$
+
+    private static final String END_QUOTE = "jndi.syntax.endquote"; //$NON-NLS-1$
+
+    private static final String BEGIN_QUOTE2 = "jndi.syntax.beginquote2"; //$NON-NLS-1$
+
+    private static final String END_QUOTE2 = "jndi.syntax.endquote2"; //$NON-NLS-1$
+
+    private static final String IGNORE_CASE = "jndi.syntax.ignorecase"; //$NON-NLS-1$
+
+    private static final String TRIM_BLANKS = "jndi.syntax.trimblanks"; //$NON-NLS-1$
+
+    private static final String DIRECTION = "jndi.syntax.direction"; //$NON-NLS-1$
+
+    private static final String SEPARATOR2 = "jndi.syntax.separator2"; //$NON-NLS-1$
+
+    //const for direction
+    private static final String LEFT_TO_RIGHT = "left_to_right"; //$NON-NLS-1$
+
+    private static final String RIGHT_TO_LEFT = "right_to_left"; //$NON-NLS-1$
+
+    private static final String FLAT = "flat"; //$NON-NLS-1$
+
+    // alphabets consts
+    private static final String NULL_STRING = ""; //$NON-NLS-1$
+
+    //states consts
+    private static final int NORMAL_STATUS = 0;
+
+    private static final int QUOTE1_STATUS = 1;
+
+    private static final int QUOTE2_STATUS = 2;
+
+    private static final int INIT_STATUS = 3;
+
+    private static final int QUOTEEND_STATUS = 4;
+
+    /*
+     * ============
+     * Variables
+     * ============ 
+     */
+    //properties variables
+    private transient String separatorString;
+
+    private transient String separatorString2;
+
+    private transient String escapeString;
+
+    private transient String endQuoteString;
+
+    private transient String endQuoteString2;
+
+    private transient String beginQuoteString;
+
+    private transient String beginQuoteString2;
+
+    private transient String sepAvaString;
+
+    private transient String sepTypeValString;
+
+    private transient String direction;
+
+    private transient boolean trimBlanks;
+
+    private transient boolean ignoreCase;
+
+    private transient boolean flat;
+
+    //elements of compound name
+    private transient Vector elem;
+
+    //property setting
+    protected transient Properties mySyntax;
+    
+    /*
+     * The specification calls for a protected variable called 'impl' which is of a non-API
+     * type.  I believe this is an error in the spec, but to be compliant we have implemented
+     * this as a useless class (below).
+     */
+    protected transient javax.naming.NameImpl impl = new NameImpl();
+
+    /*
+     *============
+     *Constructors
+     *============ 
+     */
+
+    /**
+     * Constructs a <code>CompoundName</code> with supplied <code>Enumeration</code> 
+     * and <code>Properties</code>
+     * 
+     * @param elements		an enumeration of name elements, cannot be null
+     * @param props			the properties, cannot be null but may be empty. 
+     * 						If empty, the direction defaults to flat and no 
+     * 						other properties are required.
+     */
+    protected CompoundName(Enumeration elements, Properties props) {
+        if (null == props || null == elements) {
+            throw new NullPointerException();
+        }
+        init(props);
+        this.elem = new Vector();
+        while (elements.hasMoreElements()) {
+            this.elem.add(elements.nextElement());
+        }
+    }
+
+    /**
+     * Constructs a <code>CompoundName</code> with supplied <code>String</code> 
+     * and <code>Properties</code>,  taking the supplied <code>s</code> and 
+     * breaking it down into its elements. 
+     *
+     * @param s				a string containing the full compound name
+     * @param props			the properties, cannot be null but may be empty for a flat name
+     * @throws InvalidNameException 
+     * 						thrown if the supplied <code>String s</code> is invalid
+     * @throws NullPointerException 
+     * 						thrown if the supplied <code>String s</code> is null
+     */
+    public CompoundName(String s, Properties props) throws InvalidNameException {
+        if (null == s || null == props) {
+            throw new NullPointerException();
+        }
+        init(props);
+        parseName(s);
+    }
+
+    /*
+     * init instance variables
+     */
+    private void init(Properties props) {
+        trimBlanks = false;
+        ignoreCase = false;
+        this.mySyntax = (Properties) props.clone();
+        String property;
+
+        //read property settings
+        // direction's default value is FLAT
+        direction = null == (property = props.getProperty(DIRECTION)) ? FLAT
+                : property;
+        //if direction value must equals to one of FLAT, LEFT_TO_RIGHT and RIGHT_TO_LEFT, exception throwed 
+        if (!LEFT_TO_RIGHT.equals(direction)
+                && !RIGHT_TO_LEFT.equals(direction) && !FLAT.equals(direction)) {
+            throw new IllegalArgumentException(
+                    "Illegal direction property value, which must be one of right_to_left, left_to_right or flat"); //$NON-NLS-1$
+        }
+        flat = FLAT.equals(direction);
+
+        separatorString = flat ? NULL_STRING : props.getProperty(SEPARATOR);
+        //		if direction is not FLAT, separator must be set
+        if (null == separatorString && !flat) {
+            throw new IllegalArgumentException(
+                    "jndi.syntax.separator property must be set when jndi.syntax.direction is not flat"); //$NON-NLS-1$
+        }
+        separatorString2 = (flat || null == (property = props
+                .getProperty(SEPARATOR2))) ? NULL_STRING : property;
+
+        //ignorecase default value is false
+        ignoreCase = null == (property = props.getProperty(IGNORE_CASE)) ? false
+                : Boolean.valueOf(property).booleanValue();
+        //trimblanks default value is false
+        trimBlanks = null == (property = props.getProperty(TRIM_BLANKS)) ? false
+                : Boolean.valueOf(property).booleanValue();
+        escapeString = null == (property = props.getProperty(ESCAPE)) ? NULL_STRING
+                : property;
+        beginQuoteString = null == (property = props.getProperty(BEGIN_QUOTE)) ? NULL_STRING
+                : property;
+        beginQuoteString2 = null == (property = props.getProperty(BEGIN_QUOTE2)) ? NULL_STRING
+                : property;
+        //end quote string default value is begin quote string
+        endQuoteString = null == (property = props.getProperty(END_QUOTE)) ? beginQuoteString
+                : property;
+        //begin quote string default value is end quote string
+        if (NULL_STRING.equals(beginQuoteString)) {
+            beginQuoteString = endQuoteString;
+        }
+        //end quote string2 default value is begin quote string2
+        endQuoteString2 = null == (property = props.getProperty(END_QUOTE2)) ? beginQuoteString2
+                : property;
+        //begin quote string2 default value is end quote string2
+        if (NULL_STRING.equals(beginQuoteString2)) {
+            beginQuoteString2 = endQuoteString2;
+        }
+
+        sepTypeValString = null == (property = props
+                .getProperty(SEPARATOR_TYPEVAL)) ? NULL_STRING : property;
+        sepAvaString = null == (property = props.getProperty(SEPARATOR_AVA)) ? NULL_STRING
+                : property;
+    }
+
+    /*
+     * parse name from string to elements
+     */
+    private void parseName(String s) throws InvalidNameException {
+        this.elem = new Vector();
+        if ("".equals(s)) { //$NON-NLS-1$
+            // if empty string, return empty vector
+            return;
+        }
+
+        //init variables
+        int status = INIT_STATUS;
+        StringBuffer element = new StringBuffer();
+        int pos = 0;
+        int length = s.length();
+        boolean hasNotNullElement = false;
+        boolean includeQuote = false;
+
+        //scan name
+        while (pos < length) {
+            if (startsWithFromPos(s, pos, endQuoteString)
+                    && status == QUOTE1_STATUS) {
+                status = QUOTEEND_STATUS;
+                pos += addBuffer(element, endQuoteString, includeQuote);
+            } else if (startsWithFromPos(s, pos, endQuoteString2)
+                    && status == QUOTE2_STATUS) {
+                status = QUOTEEND_STATUS;
+                pos += addBuffer(element, endQuoteString2, includeQuote);
+            } else if (startsWithFromPos(s, pos, beginQuoteString)
+                    && status == INIT_STATUS) {
+                hasNotNullElement = true;
+                status = QUOTE1_STATUS;
+                pos += addBuffer(element, beginQuoteString, includeQuote);
+            } else if (startsWithFromPos(s, pos, beginQuoteString2)
+                    && status == INIT_STATUS) {
+                hasNotNullElement = true;
+                status = QUOTE2_STATUS;
+                pos += addBuffer(element, beginQuoteString2, includeQuote);
+            } else if (startsWithFromPos(s, pos, separatorString)
+                    && (!flat)
+                    && (status == INIT_STATUS || status == QUOTEEND_STATUS || status == NORMAL_STATUS)) {
+                hasNotNullElement = hasNotNullElement || element.length() > 0;
+                addElement(element);
+                status = INIT_STATUS;
+                pos += separatorString.length();
+                includeQuote = false;
+            } else if (startsWithFromPos(s, pos, separatorString2)
+                    && (!flat)
+                    && (status == INIT_STATUS || status == QUOTEEND_STATUS || status == NORMAL_STATUS)) {
+                hasNotNullElement = hasNotNullElement || element.length() > 0;
+                addElement(element);
+                status = INIT_STATUS;
+                pos += separatorString2.length();
+                includeQuote = false;
+            } else if (startsWithFromPos(s, pos, escapeString)) {
+                pos += escapeString.length();
+                if (pos == s.length()) {
+                    //if this escape char is last character, throw exception
+                    throw new InvalidNameException(new StringBuffer(50).append(
+                            "The ") //$NON-NLS-1$
+                            .append(escapeString).append(
+                                    " cannot be at end of the component") //$NON-NLS-1$
+                            .toString());
+                }
+                //if one escape char followed by a special char, append the special char to current element
+                String str = extractEscapedString(s, pos, status);
+                if (null == str) {
+                    pos -= escapeString.length();
+                    element.append(s.charAt(pos++));
+                } else {
+                    pos += str.length();
+                    element.append(str);
+                }
+
+            } else if (startsWithFromPos(s, pos, sepTypeValString)
+                    && (status == INIT_STATUS || status == NORMAL_STATUS)) {
+                includeQuote = true;
+                pos += addBuffer(element, sepTypeValString, true);
+                status = INIT_STATUS;
+            } else if (startsWithFromPos(s, pos, sepAvaString)
+                    && (status == INIT_STATUS || status == NORMAL_STATUS)) {
+                includeQuote = true;
+                pos += addBuffer(element, sepAvaString, true);
+                status = INIT_STATUS;
+            } else if (status == QUOTEEND_STATUS) {
+                throw new InvalidNameException(
+                        s
+                                + ": close quote must appears at end of component in quoted string"); //$NON-NLS-1$
+            } else {
+                status = status == INIT_STATUS ? NORMAL_STATUS : status;
+                element.append(s.charAt(pos++));
+            }
+        }
+        if (QUOTE1_STATUS != status && QUOTE2_STATUS != status) {
+            hasNotNullElement = hasNotNullElement || element.length() > 0;
+            addElement(element);
+        } else {
+            throw new InvalidNameException(s
+                    + ": close quote is required for quoted string"); //$NON-NLS-1$
+        }
+        if (!hasNotNullElement) {
+            elem.remove(elem.size() - 1);
+        }
+    }
+
+    /*
+     * add des parameter to stringbuffer if include is true
+     */
+    private int addBuffer(StringBuffer buffer, String des, boolean include) {
+        if (include) {
+            buffer.append(des);
+        }
+        return des.length();
+    }
+
+    /*
+     * add current content of supplied string buffer as one element of this 
+     * CompoundName and reset the string buffer to empty
+     */
+    private void addElement(StringBuffer element) {
+        if (LEFT_TO_RIGHT == direction) {
+            elem.add(element.toString());
+        } else {
+            elem.add(0, element.toString());
+        }
+        element.setLength(0);
+    }
+
+    /*
+     * find string to be escaped, if cannot find special string(which means, 
+     * quote, separator and escape), return null 
+     */
+    private String extractEscapedString(String s, int pos, int status) {
+        String result = null;
+        if (status == QUOTE1_STATUS
+                && startsWithFromPos(s, pos, endQuoteString)) {
+            result = endQuoteString;
+        } else if (status == QUOTE2_STATUS
+                && startsWithFromPos(s, pos, endQuoteString2)) {
+            result = endQuoteString2;
+        } else if (status != QUOTE1_STATUS && status != QUOTE2_STATUS) {
+            if (startsWithFromPos(s, pos, beginQuoteString)) {
+                result = beginQuoteString;
+            } else if (startsWithFromPos(s, pos, beginQuoteString2)) {
+                result = beginQuoteString2;
+            } else if (startsWithFromPos(s, pos, endQuoteString)) {
+                result = endQuoteString;
+            } else if (startsWithFromPos(s, pos, endQuoteString2)) {
+                result = endQuoteString2;
+            } else if (startsWithFromPos(s, pos, separatorString)) {
+                result = separatorString;
+            } else if (startsWithFromPos(s, pos, separatorString2)) {
+                result = separatorString2;
+            } else if (startsWithFromPos(s, pos, escapeString)) {
+                result = escapeString;
+            }
+        }
+        return result;
+    }
+
+    /*
+     * justify if string src start with des from position pos
+     * @param src
+     * @param pos
+     * @param des
+     * @return
+     */
+    private boolean startsWithFromPos(String src, int pos, String des) {
+        if (null == src || null == des || NULL_STRING.equals(des)
+                || src.length() - pos < des.length()) {
+            return false;
+        }
+        int length = des.length();
+        int i = -1;
+        while (++i < length && src.charAt(pos + i) == des.charAt(i)) {
+            //empty body
+        }
+        return i == length;
+    }
+
+    /*
+     * -------------------------------------------------------------------
+     * Methods of interface Name
+     * -------------------------------------------------------------------
+     */
+    public Enumeration getAll() {
+        return this.elem.elements();
+    }
+
+    public String get(int index) {
+        validateIndex(index, false);
+        return (String) elem.elementAt(index);
+    }
+
+    /*
+     * validate the index, if isInclude is true, index which equals to this.size() 
+     * is considered as valid, otherwise invalid
+     */
+    private void validateIndex(int index, boolean isInclude) {
+        if (0 > index || index > elem.size()
+                || (!isInclude && index == elem.size())) {
+            throw new ArrayIndexOutOfBoundsException();
+        }
+    }
+
+    public Name getPrefix(int index) {
+        validateIndex(index, true);
+        return new CompoundName(new Vector(elem.subList(0, index)).elements(),
+                mySyntax);
+    }
+
+    public Name getSuffix(int index) {
+        validateIndex(index, false);
+        return new CompoundName(new Vector(elem.subList(index, elem.size()))
+                .elements(), mySyntax);
+    }
+
+    public Name addAll(Name name) throws InvalidNameException {
+        return addAll(elem.size(), name);
+    }
+
+    public Name addAll(int index, Name name) throws InvalidNameException {
+        if (!(name instanceof CompoundName)) {
+            throw new InvalidNameException(name.toString()
+                    + " is not a compound name."); //$NON-NLS-1$
+        }
+        validateIndex(index, true);
+        Enumeration enumeration = name.getAll();
+        while (enumeration.hasMoreElements()) {
+            elem.add(index++, enumeration.nextElement());
+        }
+        return this;
+    }
+
+    public Name add(String element) throws InvalidNameException {
+        elem.add(element);
+        return this;
+    }
+
+    /**
+     * Insert an element within this CompoundName at the specified index.
+     * @return 				this <code>CompoundName</code>.
+     * @param element 		the String to insert
+     * @param index			the index of the element to insert - must be greater 
+     * 						than or equal to 0 and less than size().
+     * @throws ArrayIndexOutOfBoundsException 
+     * 						thrown when the index is invalid.
+     * @throws InvalidNameException 
+     * 						thrown if the insertion of the element results in 
+     * 						this <code>CompoundName</code> becoming invalid.
+     */
+    public Name add(int index, String element) throws InvalidNameException {
+        validateIndex(index, true);
+        elem.add(index, element);
+        return this;
+    }
+
+    /**
+     * Delete an element from this <code>CompoundName</code>.
+     * 
+     * @return 				the deleted element
+     * @param index			the index of the element to delete - must be greater 
+     * 						than or equal to 0 and less than size().
+     * @throws ArrayIndexOutOfBoundsException 
+     * 						thrown when the index is invalid.
+     * @throws InvalidNameException 
+     * 						thrown if the deletion of the element results in 
+     * 						this <code>CompoundName</code> becoming invalid.
+     */
+    public Object remove(int index) throws InvalidNameException {
+        validateIndex(index, false);
+        return elem.remove(index);
+    }
+
+    public Object clone() {
+        CompoundName newName = null;
+        try {
+            newName = (CompoundName) super.clone();
+        } catch (CloneNotSupportedException e) {
+            throw new Error("Failed to clone object of CompoundName class"); //$NON-NLS-1$
+        }
+        newName.mySyntax = (Properties) mySyntax.clone();
+        newName.elem = (Vector) elem.clone();
+        return newName;
+    }
+
+    public int size() {
+        return elem.size();
+    }
+
+    public boolean isEmpty() {
+        return elem.isEmpty();
+    }
+
+    public boolean startsWith(Name name) {
+        if (!(name instanceof CompoundName)) {
+            return false;
+        }
+        return equals(name, 0, name.size());
+    }
+
+    public boolean endsWith(Name name) {
+        if (!(name instanceof CompoundName)) {
+            return false;
+        }
+        return equals(name, this.size() - name.size(), name
+                .size());
+    }
+
+    /*
+     * preprocess string according to trimblank and ignorecase properties
+     */
+    private String preProcess(String string, boolean caseInsensitive,
+            boolean removeBlanks) {
+        String result = string;
+        if (null != string && !"".equals(string)) { //$NON-NLS-1$
+            result = caseInsensitive ? result.toLowerCase() : result;
+            result = removeBlanks ? result.trim() : result;
+        }
+        return result;
+    }
+
+    /*
+     * Writes a serialized representation of the CompoundName. It starts with
+     * the properties, followed by an int which is the number of elements 
+     * in the name, and is followed by a String for each element. 
+     * @throws java.io.IOException if an error is encountered writing to the stream.
+     */
+    private void writeObject(ObjectOutputStream oos) throws IOException {
+        oos.defaultWriteObject();
+        oos.writeObject(mySyntax);
+        oos.writeInt(elem.size());
+        for (int i = 0; i < elem.size(); i++) {
+            String element = (String) elem.elementAt(i);
+            oos.writeObject(element);
+        }
+    }
+
+    /*
+     * Recreate a CompoundName from the data in the supplied stream.
+     * Additionally there are 2 protected fields which are not serializable.
+     * One of them is of a type which is a private class and cannot therefore
+     * be specified or implemented and so will be excluded from our deliverable.
+     * The one protected field which we can spec and implement is as follows:
+     * 		protected Properties mySyntax - The properties associated with a CompoundName.
+     
+     
+     * 
+     * @throws java.io.IOException if an error is encountered reading from the stream.
+     * @throws ClassNotFoundException.
+     */
+    private void readObject(ObjectInputStream ois)
+            throws ClassNotFoundException, IOException {
+        ois.defaultReadObject();
+        init(((Properties) ois.readObject()));
+        int size = ois.readInt();
+        elem = new Vector();
+        for (int i = 0; i < size; i++) {
+            elem.add(ois.readObject());
+        }
+    }
+
+    /**
+     * Compare this <code>CompoundName</code> with the one supplied as a param.
+     * <p>
+     * See the definition of the <code>equals()</code> method to see how the 
+     * direction, ignorecase and trimblanks properties affect the comparison of 
+     * a <code>CompoundName</code>. Other than that the comparison is the same 
+     * as that for a <code>CompositeName</code>.</p>
+     * 
+     * @return  				a negative number means this is less than the 
+     *						supplied Object <code>o</code>. 
+     *						a positive number means this is greater than the 
+     *						supplied Object <code>o</code>.
+     *         				zero means the two objects are equal. 
+     * @param  o				the object to compare - cannot be null. 
+     * @throws ClassCastException 
+     *						when <code>o</code> is not a compatible class that 
+     *						can be compared or if the object to compare 
+     *						<code>o</code> is null.
+     */
+    public int compareTo(Object o) {
+        if (!(o instanceof CompoundName)) {
+            throw new ClassCastException();
+        }
+        int result = -1;
+        CompoundName otherName = (CompoundName) o;
+        Enumeration otherEnum = otherName.getAll();
+        String thisElement;
+        String otherElement;
+        int i;
+        for (i = 0; i < size() && otherEnum.hasMoreElements(); i++) {
+            thisElement = preProcess((String) elem.get(i), ignoreCase,
+                    trimBlanks);
+            otherElement = preProcess((String) otherEnum.nextElement(),
+                    ignoreCase, trimBlanks);
+            result = (null == thisElement ? (null == otherElement ? 0 : -1)
+                    : thisElement.compareTo(otherElement));
+            if (0 != result) {
+                return result;
+            }
+        }
+        if (i < size()) {
+            result = 1;
+        } else if (otherEnum.hasMoreElements()) {
+            result = -1;
+        }
+        return result;
+    }
+
+    /*
+     * -------------------------------------------------------------------
+     * Methods override parent class Object
+     * -------------------------------------------------------------------
+     */
+
+    /**
+     * Calculate the hashcode of this <code>CompoundName</code> by summing 
+     * the hashcodes of all of its elements. 
+     * <p>
+     * If jndi.syntax.trimblanks is set to true then remove any leading and 
+     * trailing blanks from the elements before calculating the hashcode. </p>
+     * <p>
+     * If jndi.syntax.ignorecase is set to true then use the lowercase version 
+     * of the element to calculate its hashcode.</p>
+     * 
+     * @return 				the hashcode of this object.
+     */
+    public int hashCode() {
+        int result = 0;
+        Enumeration enumeration = elem.elements();
+        while (enumeration.hasMoreElements()) {
+            result += preProcess((String) enumeration.nextElement(),
+                    ignoreCase, trimBlanks).hashCode();
+        }
+        return result;
+    }
+
+    /**
+     * Gets the string representation of this <code>CompoundName</code>.
+     * <p>
+     * This is generated by concatenating the elements together with the 
+     * separator string added as the separator between each of them. It may be 
+     * necessary to add quotes and escape string to preserve the meaning. 
+     * The resulting string should produce an equivalent <code>CompoundName</code> 
+     * when used to create a new instance.</p>
+     * 
+     * @return the string representation of this <code>CompoundName</code>. 
+     */
+    public String toString() {
+        StringBuffer sb = new StringBuffer();
+        Enumeration enums = elem.elements();
+        String begin = NULL_STRING.equals(beginQuoteString) ? beginQuoteString2
+                : beginQuoteString;
+        String end = NULL_STRING.equals(endQuoteString) ? endQuoteString2
+                : endQuoteString;
+        String separator = NULL_STRING.equals(separatorString) ? separatorString2
+                : separatorString;
+        while (enums.hasMoreElements()) {
+            String elemString = (String) enums.nextElement();
+            if (0 == elemString.length()) {
+                // if empty element, append a separator and continue
+                sb.append(separator);
+                continue;
+            }
+            int pos = sb.length();
+            sb.append(elemString);
+
+            if (!NULL_STRING.equals(begin) && !NULL_STRING.equals(end)
+                    && !NULL_STRING.equals(separator)
+                    && (0 <= elemString.indexOf(separator))) {
+                // if contains separator string, quoted it
+                sb.insert(pos, begin);
+                pos += begin.length();
+                // if quoted, then every endquote char must be escaped
+                for (int i = 0, j = 0; 0 <= (j = elemString.indexOf(end, i)); i = j
+                        + end.length()) {
+                    sb.insert(pos + j, escapeString);
+                    pos += escapeString.length();
+                }
+                sb.append(end);
+            } else {
+                if (startsWithFromPos(elemString, 0, beginQuoteString)
+                        || startsWithFromPos(elemString, 0, beginQuoteString2)) {
+                    //if not quoted and start with begin quote string, escape it
+                    sb.insert(pos, escapeString);
+                    pos += escapeString.length();
+                }
+                //if not quoted, escape all separator string and all escape string
+                for (int i = 0; i < elemString.length();) {
+                    if (startsWithFromPos(elemString, i, separatorString)) {
+                        sb.insert(pos + i, escapeString);
+                        pos += escapeString.length();
+                        i += separatorString.length();
+                    } else if (startsWithFromPos(elemString, i,
+                            separatorString2)) {
+                        sb.insert(pos + i, escapeString);
+                        pos += escapeString.length();
+                        i += separatorString2.length();
+                    } else if (startsWithFromPos(elemString, i, escapeString)) {
+                        sb.insert(pos + i, escapeString);
+                        pos += escapeString.length();
+                        i += escapeString.length();
+                    } else {
+                        i++;
+                    }
+                }
+            }
+            sb.append(separator);
+        }
+        if (size() * separator.length() < sb.length()) {
+            //if the name contains non-empty element, delete the last separator char, which is abundant
+            sb.setLength(sb.length() - separator.length());
+        }
+        return sb.toString();
+    }
+
+    /**
+     * Check if the supplied object <code>o</code> is equal to this 
+     * <code>CompoundName</code>.
+     * <p>
+     * The supplied <code>Object o</code> may be null but that will cause false 
+     * to be returned.</p>
+     * <p>
+     * The supplied <code>Object o</code> may be something other than a 
+     * <code>CompoundName</code> but that will cause false to be returned.</p>
+     * <p>
+     * To be equal the supplied <code>CompoundName</code> must have the same 
+     * number of elements and each element must match the corresponding element 
+     * of this <code>CompoundName</code>. The properties jndi.syntax.ignorecase 
+     * and jndi.syntax.trimblanks need to be considered if they have been set.</p>
+     * <p>
+     * The properties associated with the <code>CompoundName</code> must be taken 
+     * into account but do not have to match. For example "home/jenningm-abc/.profile" 
+     * with a direction of left to right is equal to ".profile/jenningm-abc/home" with 
+     * a direction of right to left. </p>
+     * 
+     * @param o				the object to be compared
+     * @return 				true if supplied object <code>o</code> is equals to 
+     * 						this <code>CompoundName</code>, false otherwise
+     */
+    public boolean equals(Object o) {
+        if (!(o instanceof CompoundName)) {
+            return false;
+        }
+
+        //compare size
+        CompoundName otherName = (CompoundName) o;
+        final int size = otherName.size();
+        if (size != this.size()) {
+            return false;
+        }
+
+        //compare every element
+        return equals(otherName, 0, size);
+    }
+
+    /*
+     * compare this name to the supplied <code>name</code> from position 
+     * <code>start</code> to position <code>start</code>+
+     * <code>length</code>-1 
+     *
+     */
+    private boolean equals(Name name, int start, int length) {
+        if (length > this.size()) {
+            return false;
+        }
+        CompoundName otherName = (CompoundName) name;
+        Enumeration otherEnum = otherName.getAll();
+        String thisElement;
+        String otherElement;
+        for (int i = 0; i < length; i++) {
+            thisElement = preProcess((String) elem.get(i + start), ignoreCase,
+                    trimBlanks);
+            otherElement = preProcess((String) otherEnum.nextElement(),
+                    ignoreCase, trimBlanks);
+            if (!(null == thisElement ? null == otherElement : thisElement
+                    .equals(otherElement))) {
+                return false;
+            }
+        }
+        return true;
+    }
+}
+
+/*
+ * A useless class requied to satisfy the requirement for an 'impl'
+ * field (see above).
+ */
+class NameImpl {
+	protected NameImpl() {
+		super();
+	}
+}
+
+

Added: incubator/harmony/enhanced/classlib/trunk/modules/jndi/src/main/java/javax/naming/ConfigurationException.java
URL: http://svn.apache.org/viewcvs/incubator/harmony/enhanced/classlib/trunk/modules/jndi/src/main/java/javax/naming/ConfigurationException.java?rev=386087&view=auto
==============================================================================
--- incubator/harmony/enhanced/classlib/trunk/modules/jndi/src/main/java/javax/naming/ConfigurationException.java (added)
+++ incubator/harmony/enhanced/classlib/trunk/modules/jndi/src/main/java/javax/naming/ConfigurationException.java Wed Mar 15 06:55:38 2006
@@ -0,0 +1,55 @@
+/* Copyright 2004 The Apache Software Foundation or its licensors, as applicable
+ * 
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ * 
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ * 
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+
+package javax.naming;
+
+/**
+ * This is the <code>NamingException</code> used when there is a problem
+ * encountered with the configuration.
+ * <p>
+ * Multithreaded access to an instance is only safe when client code locks the
+ * object first.</p>
+ * 
+ */
+public class ConfigurationException extends NamingException{
+
+    /*
+     * This constant is used during deserialization to check the J2SE version
+     * which created the serialized object.
+     */
+	static final long serialVersionUID = -2535156726228855704L; // J2SE 1.4.2
+	
+    /**
+     * Constructs a <code>ConfigurationException</code> instance 
+     * with all data initialized to null.
+     */
+    public ConfigurationException() {
+        super();
+    }
+    
+    /**
+     * Constructs a <code>ConfigurationException</code> instance 
+     * with the specified message.
+     * 
+     * @param s The detail message for the exception. It may be null.
+     */
+    public ConfigurationException(String s){
+    	super(s);
+    }
+
+}
+
+

Added: incubator/harmony/enhanced/classlib/trunk/modules/jndi/src/main/java/javax/naming/Context.java
URL: http://svn.apache.org/viewcvs/incubator/harmony/enhanced/classlib/trunk/modules/jndi/src/main/java/javax/naming/Context.java?rev=386087&view=auto
==============================================================================
--- incubator/harmony/enhanced/classlib/trunk/modules/jndi/src/main/java/javax/naming/Context.java (added)
+++ incubator/harmony/enhanced/classlib/trunk/modules/jndi/src/main/java/javax/naming/Context.java Wed Mar 15 06:55:38 2006
@@ -0,0 +1,843 @@
+/* Copyright 2004 The Apache Software Foundation or its licensors, as applicable
+ * 
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ * 
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ * 
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+ 
+package javax.naming;
+
+import java.util.Hashtable;
+
+/**
+ * The <code>Context</code> interface describes a naming context comprising a 
+ * collection of bindings (see <code>javax.naming.Binding</code>) and methods 
+ * for manipulating them. This interface is extended by interfaces 
+ * <code>javax.naming.directory.DirContext</code> and
+ * <code>javax.naming.event.EventContext</code>. The class 
+ * <code>javax.naming.InitialContext</code> implements the <code>Context</code> 
+ * interface.
+ * <p>
+ * Any of the methods may throw a <code>NamingException</code> or one of its 
+ * subclasses. The specifications for those exceptions explain the 
+ * circumstances in which they may be thrown.</p>
+ * <p>
+ * Name parameters to context methods are each relative to the context. Name
+ * parameters cannot be null. The empty name, whether of type <code>Name</code> 
+ * or <code>String</code>, is the name of the initial context. Names may be 
+ * composed of multiple components; for example, in the filesystem name 
+ * "usr/include/stdio.h", each of the components "usr", "include", "stdio.h" 
+ * is an atomic component, but only "stdio.h" is the terminal atomic component. 
+ * The example name may be used in context operations providing the intervening 
+ * parent contexts for "usr" and "include" already exist. Finally, if the 
+ * current context has name "usr/include", then the example name could be the 
+ * result of <code>composeName("stdio.h","usr/include")</code>.</p>
+ * <p>
+ * Depending on whether a naming system supports federation, that is, names
+ * that may include components from different naming systems, name parameters
+ * to context methods may be considered differently as described below.</p>
+ * <p>
+ * In systems supporting federation, String name parameters are treated as
+ * composite names. When <code>Name</code> parameters are not instances of 
+ * <code>CompositeName</code>, they are deemed to be compound names 
+ * (<code>CompoundName</code> instances or subclasses of them). Also, when 
+ * using <code>list()</code> or <code>listBindings()</code> to obtain a
+ * <code>NamingEnumeration</code>, all names in the enumeration are string 
+ * representations of composite names.</p>
+ * <p>
+ * Where systems do not support federation, a service provider may treat name
+ * parameters to context methods and names found using 
+ * <code>NamingEnumeration</code> may either as composite names or as compound
+ * names. See service provider documentation for details.</p>
+ * <p>
+ * Any <code>Name</code> parameter specified to a context method is owned by 
+ * the caller and will remain unchanged, but applications should avoid 
+ * modifying these <code>Name</code> objects while the operation has not 
+ * completed. Any <code>Name</code> object returned by a context operation 
+ * becomes owned by the caller.</p>
+ * <p>
+ * JNDI applications can provide preferences and configuration information,
+ * such as security details for authentication to a service, using JNDI
+ * environment properties. JNDI environment properties nearly all begin with
+ * "java.naming." except for provider-specific properties (explained below).
+ * All specified JNDI environment properties together comprise the context
+ * environment and methods are available for examining and manipulating that
+ * environment. The environment of a context may not necessarily contain all
+ * possible JNDI properties; for example, one or more may remain unspecified.</p>
+ * <p>
+ * The set of standard JNDI environment properties is:
+ * <pre>
+ * Property name                       Value type    Notes
+ * -------------                       ----------    -----
+ * java.naming.applet                  F
+ * java.naming.authoritative           F
+ * java.naming.batchsize               F
+ * java.naming.dns.url                 F
+ * java.naming.factory.control         C             see LdapContext
+ * java.naming.factory.initial         F
+ * java.naming.factory.object          C
+ * java.naming.factory.state           C
+ * java.naming.factory.url.pkgs        C
+ * java.naming.language                F
+ * java.naming.provider.url            F
+ * java.naming.referral                F
+ * java.naming.security.authentication F
+ * java.naming.security.credentials    F
+ * java.naming.security.principal      F
+ * java.naming.security.protocol       F
+ * </pre></p>
+ * <p>
+ * For each property above marked with "C" for "concatenate", when encountered
+ * while searching sources of environment properties, values are combined into
+ * a single list separated by colons and becomes the resulting value of that
+ * property.</p>
+ * <p>
+ * For each property above marked with "F" for "first occurrence", when
+ * encountered while searching sources of environment properties, the first
+ * value encountered is the resulting value of that property. In the latter
+ * case, and with additional JNDI environment properties explained further
+ * below, the type and syntax of acceptable property values should be
+ * described in the corresponding documentation for the property. In
+ * particular, a property may accept a value consisting of several pieces of
+ * relevant information, but the search order and precedence for environment
+ * properties ensures that the entire value of the first occurrence of a given
+ * property is deemed the value to be used.</p>
+ * <p>
+ * Additional JNDI environment properties may be defined according to the
+ * needs of the particular service and/or service providers and a few
+ * guidelines should be followed when choosing appropriate names for them.
+ * Such additional properties comprise service-specific, feature-specific,
+ * or provider-specific properties.</p>
+ * <p>
+ * Service-specific JNDI properties may be used by all service providers that
+ * offer implementations for a given service and would include the service
+ * type in the property name prefix. For example, JNDI service providers for
+ * Java RMI should name their service-specific JNDI properties using prefix
+ * "java.naming.rmi.", or LDAP service providers should use prefix
+ * "java.naming.ldap.".</p>
+ * <p>
+ * Feature-specific JNDI properties may be used by all service providers
+ * offering implementations using a particular flavour of a feature and would
+ * include the feature name and the particular flavour name in the property
+ * name prefix. A common example is SASL used by several service providers for
+ * security; appropriate SASL feature-specific properties would use prefix
+ * "java.naming.security.sasl.".</p>
+ * <p>
+ * Provider-specific JNDI properties are used by only a single provider though
+ * a provider may offer more than one service provider implementation. The
+ * provider should ensure uniqueness of their provider properties, for example,
+ * an LDAP service provider from mycom might use a service provider package
+ * name such as "com.mycom.jndi.ldap." as their provider-specific prefix.</p>
+ * <p>
+ * JNDI environment properties can be specified in a <code>Hashtable</code> 
+ * and passed as the environment parameter when creating an initial context.</p>
+ * <p>
+ * Two other important sources of JNDI environment properties are resource
+ * files provided by applications and applet parameters (each is considered as
+ * an application resource file) and by service provider implementations
+ * (provider resource files) in the format of Java properties files - see
+ * <code>java.util.Properties</code> class for details.</p>
+ * <p>
+ * At runtime, the application classpath and, where appropriate, the applet
+ * codebase attribute is used to locate the classes to run; when creating the
+ * first initial context, the JNDI also searches the same path for all files
+ * (application resource files) called "jndi.properties"; it is the classpath
+ * associated with the context <code>ClassLoader</code> (for example, the 
+ * return value from <code>Thread.getContextClassLoader()</code> or from 
+ * <code>ClassLoader.getSystemClassLoader()</code>) which is searched to get 
+ * the resource files. Further, a path comprising the value of the "java.home" 
+ * system property followed by "lib/jndi.properties" is checked for a readable 
+ * file; if one exists, then that file is used as another application resource 
+ * file. All application resource files found in the application classpath are 
+ * examined, but JNDI properties set in a file found early will override the 
+ * same properties also set in a file found later in the classpath.</p>
+ * <p>
+ * Provider resource files are located according to the package prefix for the
+ * service provider's initial context factory and context implementation class
+ * in which dot separator characters are converted into slash path separator
+ * characters to construct a filepath appended with "jndiprovider.properties".
+ * Consider the example where you have a service provider which supplies
+ * a context <code>com.ibm.jndi.example.exampleCtx</code>.
+ * In this case the package prefix is <code>com.ibm.jndi.example</code>. 
+ * Substituting slash chars for dots & appending "jndiprovider.properties" 
+ * gives you <code>com/ibm/jndi/example/jndiprovider.properties</code>.</p>
+ * <p>
+ * An important part of service provider implementation is to specify certain
+ * standard JNDI properties that are using to locate any of the various
+ * factory classes needed for the implementation; these are:
+ * <pre>
+ * java.naming.factory.control
+ * java.naming.factory.object
+ * java.naming.factory.state
+ * java.naming.factory.url.pkgs - package prefixes used for URL contexts
+ * </pre></p>
+ * <p>
+ * When searching for the above 4 properties only provider resource files
+ * should be examined. Although other properties may be specified in them for
+ * use by the service provider implementation, the JNDI ignores properties
+ * from these files other than those related to factories.</p>
+ * <p>
+ * It should be noted that a provider resource file's properties differ from
+ * those in application resource files in that their values are not 
+ * incorporated into the environment. Instead, they are read when the 
+ * following methods are invoked with <code>Context</code> and 
+ * <code>Hashtable</code> parameters:
+ * <pre>
+ * ControlFactory.getControlInstance    - uses java.naming.factory.control
+ * DirectoryManager.getObjectInstance   - uses java.naming.factory.object
+ * DirectoryManager.getStateToBind      - uses java.naming.factory.state
+ * NamingManager.getObjectInstance      - uses java.naming.factory.object
+ * NamingManager.getStateToBind         - uses java.naming.factory.state
+ * </pre></p>
+ * <p>
+ * These methods use their <code>Hashtable</code> parameter to get the 
+ * environment properties. Then they use the class loader of the 
+ * <code>Context</code> parameter to look for the provider resource file. 
+ * If the file is found, then the value of the required property is appended 
+ * to the value of the required property in the environment. Note that it is 
+ * appended for use by this method but the environment itself is unaffected.</p>
+ * <p>
+ * The <code>jndiprovider.properties</code> files may specify additional 
+ * properties, but documentation for the service provider should clearly 
+ * describe which properties are valid in this file and under what 
+ * circumstances.</p>
+ * <p>
+ * To summarize the search order and precedence for JNDI environment
+ * properties, the earliest having highest precedence:
+ * <pre>
+ * 1. environment parameter used to initialize an initial context,
+ * 2. applet parameters, (only used if that environment param does not exist)
+ * 3. system properties, (only used if that environment and applet parameter 
+ *    do not exist)
+ * 4. application resource files.
+ * </pre></p>
+ * <p>
+ * It should be noted that in the case of applet parameters and system 
+ * properties only a subset of the properties are read. These are the 
+ * following 7:
+ * <pre>
+ * java.naming.dns.url
+ * java.naming.factory.control
+ * java.naming.factory.initial
+ * java.naming.factory.object
+ * java.naming.factory.state
+ * java.naming.factory.url.pkgs
+ * java.naming.provider.url
+ * </pre></p>
+ * <p>
+ * For a JNDI property found in more than one of those sources, if it is one
+ * of the JNDI factory list properties then values are joined into a
+ * colon-separated list, otherwise the first instance of a property defines
+ * the value to be used.</p>
+ * <p>
+ * The above search order and precedence applies when creating contexts for
+ * any class implementing the <code>Context</code> interface.</p>
+ * <p>
+ * Although a subcontext inherits the environment of its parent context,
+ * subsequent changes to either's environment has no direct effect on the
+ * other. However, applications should avoid dependency on when JNDI properties
+ * are used or verified as this depends on the service provider implementation.
+ * As the environment of a context can be examined by any object that has a
+ * reference to the context, care should be taken to assess the risk to
+ * any security details stored in the environment.</p>
+ * <p>
+ * Multithreaded access to a single <code>Context</code> instance is only safe 
+ * when client code uses appropriate synchronization and locking.</p>
+ * <p>
+ * When a <code>NamingEnumeration</code> is returned by a <code>Context</code> 
+ * method, the operation should not be considered complete, for concurrency 
+ * purposes, if the NamingEnumeration is still being used or if any referrals 
+ * are still being followed resulting from that operation.</p>
+ * 
+ */
+public interface Context {
+
+    /*
+     * -------------------------------------------------------------------
+     * Constants
+     * -------------------------------------------------------------------
+     */
+
+    /**
+     * A constant containing environment property name "java.naming.applet". 
+     * The property may remain unspecified or may be specified within the 
+     * environment parameter used when creating an initial context. When 
+     * this environment property is specified, its value must be the currently 
+     * executing instance of <code>java.applet.Applet</code> to enable the 
+     * operation of initial context creation to search applet parameters first 
+     * for other environment properties which may have been specified, before 
+     * searching for properties in the constructor environment parameter, 
+     * system properties, and application resource files.
+     */
+    public static final String APPLET = "java.naming.applet"; //$NON-NLS-1$
+
+    /**
+     * A constant containing environment property name 
+     * "java.naming.authoritative". An application specifies this property to 
+     * indicate whether naming requests must be made to the most authoritative 
+     * naming service instance or not. The property may remain unspecified or 
+     * may be specified with a string value. If unspecified, the property 
+     * value is considered to be "false". A value of "true" means requests 
+     * should be made to the most authoritative naming service replicas or 
+     * caches that may be available. Any value other than "true" means 
+     * requests may be made to any instance of the naming service which need 
+     * not be, but may include, the most authoritative.
+     */
+    public static final String AUTHORITATIVE = "java.naming.authoritative"; //$NON-NLS-1$
+
+    /**
+     * A constant containing environment property name "java.naming.batchsize".
+     * An application specifies this property to indicate a preference to 
+     * receive operation results in batches of the given size from the service 
+     * provider. The property may remain unspecified or may be specified with 
+     * an integer expressed as a string value. If unspecified, the batch size 
+     * of operation results is determined by the service provider. The service 
+     * provider implementation may use or ignore the specified value.
+     */
+    public static final String BATCHSIZE = "java.naming.batchsize"; //$NON-NLS-1$
+
+    /**
+     * A constant containing environment property name "java.naming.dns.url". 
+     * The property specifies a DNS-scheme URL including the DNS host 
+     * including domain names, if any; for example, "dns://9.28.36.7/apache.org". 
+     * If the application uses any JNDI URL with DNS names and a search for 
+     * this property fails, then the naming operation will throw a 
+     * <code>ConfigurationException</code>.
+     */
+    public static final String DNS_URL = "java.naming.dns.url"; //$NON-NLS-1$
+
+    /**
+     * A constant containing environment property name
+     * "java.naming.factory.initial". The property specifies the name of the
+     * factory class, fully-qualified, that will be used to create an initial
+     * context; for example, "mycom.jndi.testing.spi.DazzleContextFactory". 
+     * If the property is not specified, any operation requiring an initial 
+     * context will throw a <code>NoInitialContextException</code>.
+     */
+    public static final String INITIAL_CONTEXT_FACTORY =
+        "java.naming.factory.initial"; //$NON-NLS-1$
+
+    /**
+     * A constant containing environment property name "java.naming.language". 
+     * The property indicates the preferred language for operations with the 
+     * service provider. The property may remain unspecified or should be a 
+     * string comprising a list of language tags according to RFC 1766 
+     * separated by colons. When not specified, the language preference is 
+     * selected by the service provider.
+     */
+    public static final String LANGUAGE = "java.naming.language"; //$NON-NLS-1$
+
+    /**
+     * A constant containing environment property name 
+     * "java.naming.factory.object". The property specifies a list of object 
+     * factories to be used when the application requests an instance of a 
+     * specified object. The value is a string comprising a list of fully 
+     * qualified object factory class names separated by colons.
+     */
+    public static final String OBJECT_FACTORIES = "java.naming.factory.object"; //$NON-NLS-1$
+
+    /**
+     * A constant containing environment property name 
+     * "java.naming.provider.url". The property specifies configuration 
+     * options for use by the a service provider. The property may remain 
+     * unspecified or should be a URL string; for example, 
+     * "ldap://ahost.myfirm.com:389". If not specified, the service provider 
+     * selects its default configuration.
+     */
+    public static final String PROVIDER_URL = "java.naming.provider.url"; //$NON-NLS-1$
+
+    /**
+     * A constant containing environment property name "java.naming.referral".
+     * The property specifies how the service provider should process any 
+     * referrals encountered during a naming operation. The property may 
+     * remain unspecified or specified as one of the following strings:
+     * <ul>
+     * <li>"follow" service provider should always follow referrals</li>
+     * <li>"ignore" service provider should ignore referrals</li>
+     * <li>"throw"  service provider should throw ReferralException if it 
+     * encounters a referral</li>
+     *</ul>
+     * When not specified, the service provider selects a default value.
+     */
+    public static final String REFERRAL = "java.naming.referral"; //$NON-NLS-1$
+
+    /**
+     * A constant containing environment property name
+     * "java.naming.security.authentication". The property specifies the 
+     * security level to be used in naming operations. The property may remain
+     * unspecified or be one of the strings "none", "simple", "strong". When 
+     * not specified, the service provider selects a default value.
+     */
+    public static final String SECURITY_AUTHENTICATION =
+        "java.naming.security.authentication"; //$NON-NLS-1$
+
+    /**
+     * A constant containing environment property name
+     * "java.naming.security.credentials". The property specifies credentials 
+     * of the security principal so that the caller can be authenticated to 
+     * the naming service. The property may remain unspecified or be a value
+     * according to the authentication scheme controlling access to the 
+     * service. When not specified, the service provider determines how to 
+     * respond to service requests affected by the lack of security 
+     * credentials.
+     */
+    public static final String SECURITY_CREDENTIALS =
+        "java.naming.security.credentials"; //$NON-NLS-1$
+
+    /**
+     * A constant containing environment property name
+     * "java.naming.security.principal". The property the name of the security
+     * principal to be used when the caller needs to be authenticated to the
+     * naming service. The property may remain unspecified or be a value
+     * according to the authentication scheme controlling access to the 
+     * service. When not specified, the service provider determines how to 
+     * respond to service requests affected by the lack of a security 
+     * principal.
+     */
+    public static final String SECURITY_PRINCIPAL =
+        "java.naming.security.principal"; //$NON-NLS-1$
+
+    /**
+     * A constant containing environment property name
+     * "java.naming.security.protocol". The property the name of the security
+     * protocol to be used with the naming service. The property may remain
+     * unspecified or be specified as a string according to the service 
+     * provider implementation. When not specified, the service provider 
+     * determines how to respond to service requests.
+     */
+    public static final String SECURITY_PROTOCOL =
+        "java.naming.security.protocol"; //$NON-NLS-1$
+
+    /**
+     * A constant containing environment property name 
+     * "java.naming.factory.state". The property specifies a list of state 
+     * factories to be used when the application requests the state of a 
+     * specified object. The value is a string comprising a list of fully 
+     * qualified state factory class names separated by colons. The property 
+     * may remain unspecified.
+     */
+    public static final String STATE_FACTORIES = "java.naming.factory.state"; //$NON-NLS-1$
+
+    /**
+     * A constant containing environment property name
+     * "java.naming.factory.url.pkgs". The property specifies a list of 
+     * package prefixes that are used to load URL context factories. The value 
+     * is a string comprising a list of package prefixes for class names of 
+     * URL context factory classes separated by colons. The property may 
+     * remain unspecified. In any case, prefix "com.sun.jndi.url" is 
+     * automatically added to the list of specified package prefixes or used 
+     * as the only package prefix when the property is unspecified.
+     */
+    public static final String URL_PKG_PREFIXES =
+        "java.naming.factory.url.pkgs"; //$NON-NLS-1$
+
+    /*
+     * -------------------------------------------------------------------
+     * Methods
+     * -------------------------------------------------------------------
+     */
+
+    /**
+     * Adds or replaces the environment property specified by the non-null 
+     * string parameter into the environment of this context with the 
+     * specified object value. Returns the previous property value if 
+     * replaced, or null if the property did not exist in the environment.
+     * 
+     * @param s the name of the property to add
+     * @param o the value of the property to add
+     * @return  the previous property value if replaced, or null if the
+     *          property did not exist in the environment.
+     * @throws NamingException if an error occurs.
+     */
+    public Object addToEnvironment(String s, Object o) throws NamingException;
+
+    /**
+     * Binds the specified name to the specified object in this context. The
+     * specified name may not be null. The specified object may be null when 
+     * a name bound to a null object is meaningful in the semantics of the
+     * underlying naming system, otherwise a <code>NamingException</code> 
+     * is thrown.
+     * 
+     * @param n a <code>Name</code>, may not be null
+     * @param o an object to bind with the name, may be null
+     * @throws NamingException if an error occurs.
+     */
+    public void bind(Name n, Object o) throws NamingException;
+
+    /**
+     * Binds the specified name to the specified object in this context. The
+     * specified name may not be null. The specified object may be null when 
+     * a name bound to a null object is meaningful in the semantics of the
+     * underlying naming system, otherwise a <code>NamingException</code> 
+     * is thrown.
+     * 
+     * @param s a name in string, may not be null
+     * @param o an object to bind with the name, may be null
+     * @throws NamingException if an error occurs.
+     */
+    public void bind(String s, Object o) throws NamingException;
+
+    /**
+     * Closes this context. The result of any further operations on a closed
+     * context is undefined. 
+     * 
+     * @throws NamingException if an error occurs.
+     */
+    public void close() throws NamingException;
+
+    /**
+     * Combines two names into a composite name according to the syntax for 
+     * this context. The name <code>pfx</code> is expected to be the name of 
+     * one or more of the immediate parent contexts of this context. The name 
+     * <code>n</code> is a name relative to this context. Neither 
+     * <code>pfx</code> nor <code>n</code> may be null. The combined result 
+     * is a name which is relative to the specified parent context names.
+     * 
+     * @param n     a <code>Name</code>, may not be null
+     * @param pfx   a <code>Name</code> serves as perfix, may not be null
+     * @return      the combined name
+     * @throws NamingException if an error occurs.
+     */
+    public Name composeName(Name n, Name pfx) throws NamingException;
+
+    /**
+     * Combines two names into a composite name according to the syntax for 
+     * this context. The name <code>pfx</code> is expected to be the name of 
+     * one or more of the immediate parent contexts of this context. The name 
+     * <code>s</code> is a name relative to this context. Neither 
+     * <code>pfx</code> nor <code>s</code> may be null. The combined result 
+     * is a name which is relative to the specified parent context names.
+     * 
+     * @param s     a name in string, may not be null
+     * @param pfx   a name in string, serves as prefix, may not be null
+     * @return      the combined name in string
+     * @throws NamingException if an error occurs.
+     */
+    public String composeName(String s, String pfx) throws NamingException;
+
+    /**
+     * Creates a new context with the specified name as a child of this 
+     * context and creates a binding for the name with the new context 
+     * object in this context. This is analogous to creating a new lower 
+     * level in a hierarchical naming system.
+     * 
+     * @param n the name of the new subcontext
+     * @return  the created subcontext
+     * @throws NamingException if an error occurs.
+     */
+    public Context createSubcontext(Name n) throws NamingException;
+
+    /**
+     * Creates a new context with the specified name as a child of this 
+     * context and creates a binding for the name with the new context 
+     * object in this context. This is analogous to creating a new lower 
+     * level in a hierarchical naming system.
+     * 
+     * @param s the name of the new subcontext, in string
+     * @return  the created subcontext
+     * @throws NamingException if an error occurs.
+     */
+    public Context createSubcontext(String s) throws NamingException;
+
+    /**
+     * Removes a child context with the specified name from this context 
+     * together with any attributes associated with that name. If the 
+     * specified context does not exist, but intervening contexts do exist, 
+     * then the operation is is considered to succeed.
+     * <p>
+     * Care must be taken with composite names crossing multiple naming 
+     * systems. A composite name containing a name component which is bound 
+     * to an object in a different naming system cannot be used to destroy 
+     * that name subcontext because the subcontext is not of the same type 
+     * as the context containing the binding. <code>Unbind()</code> can be 
+     * used to destroy the binding of the specified name in this context to 
+     * the object in the other naming system. To remove the context object 
+     * in the other naming system, first obtain a context belonging to the 
+     * other naming system, then use <code>destroySubcontext()</code> on that 
+     * context.</p>
+     * 
+     * @param n the name of the subcontext to destroy
+     * @throws NamingException if an error occurs.
+     */
+    public void destroySubcontext(Name n) throws NamingException;
+
+    /**
+     * Removes a child context with the specified name from this context 
+     * together with any attributes associated with that name. If the 
+     * specified context does not exist, but intervening contexts do exist, 
+     * then the operation is considered to succeed.
+     * <p>
+     * Care must be taken with composite names crossing multiple naming 
+     * systems. A composite name containing a name component which is bound 
+     * to an object in a different naming system cannot be used to destroy 
+     * that name subcontext because the subcontext is not of the same type 
+     * as the context containing the binding. <code>Unbind()</code> can be 
+     * used to destroy the binding of the specified name in this context to 
+     * the object in the other naming system. To remove the context object 
+     * in the other naming system, first obtain a context belonging to the 
+     * other naming system, then use <code>destroySubcontext()</code> on that 
+     * context.</p>
+     * 
+     * @param s the name of the subcontext to destroy
+     * @throws NamingException if an error occurs.
+     */
+    public void destroySubcontext(String s) throws NamingException;
+
+    /**
+     * Returns a non-null reference to the current environment properties for 
+     * this context. The only proper ways to modify the properties for this 
+     * context are using the <code>addToEnvironment()</code> and 
+     * <code>removeFromEnvironment()</code> methods.
+     * 
+     * @return  a non-null reference to the current environment properties for 
+     *          this context, which should not be modified
+     * @throws NamingException if an error occurs.
+     */
+    public Hashtable getEnvironment() throws NamingException;
+
+    /**
+     * Returns the complete name as a string for this context in the 
+     * namespace. For example, in a namespace accessed using a file system 
+     * service provider on a computer running the Windows operating system, 
+     * <code>getNameInNamespace()</code> will return a string comprising the 
+     * current working disk drive such as "F:\". The returned name is never 
+     * null and should not be used in any naming operations.
+     * 
+     * @return  the complete name as a string for this context in the 
+     *          namespace
+     * @throws NamingException if an error occurs.
+     * @throws OperationNotSupportedException in cases of naming systems 
+     *          where a full name has no meaning.
+     */
+    public String getNameInNamespace() throws NamingException;
+
+    /**
+     * Returns a parser object for the named context. When using a federation
+     * of naming systems in which each has its own rules for parsing names for
+     * its namespace, each naming system will have a different parser. The 
+     * parser for a given context can parse a name composed of several 
+     * components into atomic components according to the rules for the naming 
+     * system associated with the specified context.
+     * 
+     * @param n a <code>Name</code>
+     * @return  a parser object for the named context
+     * @throws NamingException if an error occurs.
+     */
+    public NameParser getNameParser(Name n) throws NamingException;
+
+    /**
+     * Returns a parser object for the named context. When using a federation
+     * of naming systems in which each has its own rules for parsing names for
+     * its namespace, each naming system will have a different parser. The 
+     * parser for a given context can parse a name composed of several 
+     * components into atomic components according to the rules for the naming 
+     * system associated with the specified context.
+     * 
+     * @param s a name in string
+     * @return  a parser object for the named context
+     * @throws NamingException if an error occurs.
+     */
+    public NameParser getNameParser(String s) throws NamingException;
+
+    /**
+     * Returns an enumeration of the bindings of the context for the specified
+     * name excluding any bindings for any subcontexts. If any binding for the
+     * context is changed before closing the enumeration, the state of the
+     * enumeration is undefined. Each element of the enumeration is a
+     * <code>NameClassPair</code> object.
+     * 
+     * @param n a <code>Name</code>
+     * @return  an enumeration of the bindings of the context for the 
+     *          specified name excluding any bindings for any subcontexts
+     * @throws NamingException if an error occurs.
+     */
+    public NamingEnumeration list(Name n) throws NamingException;
+
+    /**
+     * Returns an enumeration of the bindings of the context for the specified
+     * name excluding any bindings for any subcontexts. If any binding for the
+     * context is changed before closing the enumeration, the state of the
+     * enumeration is undefined. Each element of the enumeration is a
+     * <code>NameClassPair</code> object.
+     * 
+     * @param s a name in string
+     * @return  an enumeration of the bindings of the context for the 
+     *          specified name excluding any bindings for any subcontexts
+     * @throws NamingException if an error occurs.
+     */
+    public NamingEnumeration list(String s) throws NamingException;
+
+    /**
+     * Returns an enumeration of the bindings of the context for the specified
+     * name excluding any bindings for any subcontexts. If any binding for the
+     * context is changed before closing the enumeration, the state of the
+     * enumeration is undefined. Each element of the enumeration is a
+     * <code>Binding</code> object. 
+     * 
+     * @param n a <code>Name</code>
+     * @return  an enumeration of the bindings of the context for the specified
+     *          name excluding any bindings for any subcontexts
+     * @throws NamingException if an error occurs.
+     */
+    public NamingEnumeration listBindings(Name n) throws NamingException;
+
+    /**
+     * Returns an enumeration of the bindings of the context for the specified
+     * name excluding any bindings for any subcontexts. If any binding for the
+     * context is changed before closing the enumeration, the state of the
+     * enumeration is undefined. Each element of the enumeration is a
+     * <code>Binding</code> object. 
+     * 
+     * @param s a name in string
+     * @return  an enumeration of the bindings of the context for the specified
+     *          name excluding any bindings for any subcontexts
+     * @throws NamingException if an error occurs.
+     */
+    public NamingEnumeration listBindings(String s) throws NamingException;
+
+    /**
+     * Returns the object bound to the specified name in this context. If the
+     * specified name is empty, a new instance of this context is returned,
+     * complete with its own environment properties. 
+     * 
+     * @param n a <code>Name</code> to lookup
+     * @return  the object bound to the specified name in this context
+     * @throws NamingException if an error occurs.
+     */
+    public Object lookup(Name n) throws NamingException;
+
+    /**
+     * Returns the object bound to the specified name in this context. If the
+     * specified name is empty, a new instance of this context is returned,
+     * complete with its own environment properties.
+     * 
+     * @param s a name to lookup
+     * @return  the object bound to the specified name in this context
+     * @throws NamingException if an error occurs.
+     */
+    public Object lookup(String s) throws NamingException;
+
+    /**
+     * Returns the object bound to the specified name in this context by 
+     * following any links. If the specified name is not a link, then the 
+     * object is returned.
+     * 
+     * @param n a <code>Name</code> to lookup
+     * @return  the object bound to the specified name in this context by 
+     *          following any links
+     * @throws NamingException if an error occurs.
+     */
+    public Object lookupLink(Name n) throws NamingException;
+
+    /**
+     * Returns the object bound to the specified name in this context by 
+     * following any links. If the specified name is not a link, then the 
+     * object is returned.
+     * 
+     * @param s a name in string to lookup
+     * @return  the object bound to the specified name in this context by 
+     *          following any links
+     * @throws NamingException if an error occurs.
+     */
+    public Object lookupLink(String s) throws NamingException;
+
+    /**
+     * Binds the specified name to the specified object, replacing any 
+     * existing binding for the specified name. The specified name may 
+     * not be empty. The specified object may be null.
+     * 
+     * @param n a <code>Name</code> to rebind, may not be null
+     * @param o an object to bind with the name, may be null
+     * @throws NamingException if an error occurs.
+     */
+    public void rebind(Name n, Object o) throws NamingException;
+
+    /**
+     * Binds the specified name to the specified object, replacing any 
+     * existing binding for the specified name. The specified name may 
+     * not be empty. The specified object may be null.
+     * 
+     * @param s a name in string to rebind, may not be null
+     * @param o an object tobind with the name, may be null
+     * @throws NamingException if an error occurs.
+     */
+    public void rebind(String s, Object o) throws NamingException;
+
+    /**
+     * Removes the environment property specified by the non-null parameter 
+     * from the environment of this context. Returns the value that the 
+     * property had before removal, or null if the property did not exist 
+     * in the environment.
+     * 
+     * @param s a property name
+     * @return  the value that the property had before removal, or null if the 
+     *          property did not exist in the environment
+     * @throws NamingException if an error occurs.
+     */
+    public Object removeFromEnvironment(String s) throws NamingException;
+
+    /**
+     * Binds a specified new name to the object, and any attributes, 
+     * previously bound to the specified old name. The old name is removed 
+     * from the bindings for this context.
+     * 
+     * @param nOld  the old name
+     * @param nNew  the new name
+     * @throws NameAlreadyBoundException if the new is already bound
+     * @throws NamingException if an error occurs.
+     */
+    public void rename(Name nOld, Name nNew) throws NamingException;
+
+    /**
+     * Binds a specified new name to the object, and any attributes, 
+     * previously bound to the specified old name. The old name is removed 
+     * from the bindings for this context. Neither the new nor the old name 
+     * may be empty.
+     * 
+     * @param sOld  the old name in string
+     * @param sNew  the new name in string
+     * @throws NameAlreadyBoundException if the new is already bound
+     * @throws NamingException if an error occurs.
+     */
+    public void rename(String sOld, String sNew) throws NamingException;
+
+    /**
+     * Removes the terminal atomic name component of the specified name from 
+     * the bindings in this context, together with any attributes associated 
+     * with the terminal atomic name. Providing that other parts of the 
+     * specified name exist in this context's bindings, the operation succeeds 
+     * whether or not the terminal atomic name exists, otherwise a 
+     * <code>NameNotFoundException</code> is thrown.
+     * Any intermediate contexts remain unchanged.
+     * 
+     * @param n a <code>Name</code> to unbind
+     * @throws NamingException if an error occurs.
+     */
+    public void unbind(Name n) throws NamingException;
+
+    /**
+     * Removes the terminal atomic name component of the specified name from 
+     * the bindings in this context, together with any attributes associated 
+     * with the terminal atomic name. Providing that other parts of the 
+     * specified name exist in this context's bindings, the operation succeeds 
+     * whether or not the terminal atomic name exists, otherwise a 
+     * <code>NameNotFoundException</code> is thrown.
+     * Any intermediate contexts remain unchanged.
+     * 
+     * @param s a name in string to unbind
+     * @throws NamingException if an error occurs.
+     */
+    public void unbind(String s) throws NamingException;
+
+}
+
+

Added: incubator/harmony/enhanced/classlib/trunk/modules/jndi/src/main/java/javax/naming/ContextNotEmptyException.java
URL: http://svn.apache.org/viewcvs/incubator/harmony/enhanced/classlib/trunk/modules/jndi/src/main/java/javax/naming/ContextNotEmptyException.java?rev=386087&view=auto
==============================================================================
--- incubator/harmony/enhanced/classlib/trunk/modules/jndi/src/main/java/javax/naming/ContextNotEmptyException.java (added)
+++ incubator/harmony/enhanced/classlib/trunk/modules/jndi/src/main/java/javax/naming/ContextNotEmptyException.java Wed Mar 15 06:55:38 2006
@@ -0,0 +1,55 @@
+/* Copyright 2004 The Apache Software Foundation or its licensors, as applicable
+ * 
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ * 
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ * 
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+
+package javax.naming;
+
+/**
+ * This is the <code>NamingException</code> used when trying to destroy a
+ * context which is not empty.
+ * <p>
+ * Multithreaded access to an instance is only safe when client code locks the
+ * object first.</p>
+ * 
+ */
+public class ContextNotEmptyException extends NamingException {
+
+    /*
+     * This constant is used during deserialization to check the J2SE version
+     * which created the serialized object.
+     */
+	static final long serialVersionUID = 1090963683348219877L; // J2SE 1.4.2
+
+    /**
+     * Constructs a <code>ContextNotEmptyException</code> instance 
+     * with all data initialized to null.
+     */
+    public ContextNotEmptyException() {
+        super();
+    }
+
+    /**
+     * Constructs a <code>ContextNotEmptyException</code> instance
+     * with the specified message.
+     * 
+     * @param s The detail message for the exception. It may be null.
+     */
+    public ContextNotEmptyException(String s) {
+        super(s);
+    }
+
+}
+
+