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/05/30 13:25:01 UTC

svn commit: r410240 [1/4] - in /incubator/harmony/enhanced/classlib/trunk/modules/jndi: make/ make/common/ src/main/java/org/apache/harmony/jndi/provider/ src/main/java/org/apache/harmony/jndi/provider/dns/ src/main/java/org/apache/harmony/util/ src/ma...

Author: tellison
Date: Tue May 30 04:24:59 2006
New Revision: 410240

URL: http://svn.apache.org/viewvc?rev=410240&view=rev
Log:
Initial commit of HARMONY-256 (Contribution of DNS service provider for JNDI classlibrary code)


Added:
    incubator/harmony/enhanced/classlib/trunk/modules/jndi/src/main/java/org/apache/harmony/jndi/provider/
    incubator/harmony/enhanced/classlib/trunk/modules/jndi/src/main/java/org/apache/harmony/jndi/provider/dns/
    incubator/harmony/enhanced/classlib/trunk/modules/jndi/src/main/java/org/apache/harmony/jndi/provider/dns/BasicNamingEnumerator.java   (with props)
    incubator/harmony/enhanced/classlib/trunk/modules/jndi/src/main/java/org/apache/harmony/jndi/provider/dns/DNSContext.java   (with props)
    incubator/harmony/enhanced/classlib/trunk/modules/jndi/src/main/java/org/apache/harmony/jndi/provider/dns/DNSContextFactory.java   (with props)
    incubator/harmony/enhanced/classlib/trunk/modules/jndi/src/main/java/org/apache/harmony/jndi/provider/dns/DNSName.java   (with props)
    incubator/harmony/enhanced/classlib/trunk/modules/jndi/src/main/java/org/apache/harmony/jndi/provider/dns/DNSNameParser.java   (with props)
    incubator/harmony/enhanced/classlib/trunk/modules/jndi/src/main/java/org/apache/harmony/jndi/provider/dns/DNSPseudoURL.java   (with props)
    incubator/harmony/enhanced/classlib/trunk/modules/jndi/src/main/java/org/apache/harmony/jndi/provider/dns/DomainProtocolException.java   (with props)
    incubator/harmony/enhanced/classlib/trunk/modules/jndi/src/main/java/org/apache/harmony/jndi/provider/dns/Message.java   (with props)
    incubator/harmony/enhanced/classlib/trunk/modules/jndi/src/main/java/org/apache/harmony/jndi/provider/dns/ProviderConstants.java   (with props)
    incubator/harmony/enhanced/classlib/trunk/modules/jndi/src/main/java/org/apache/harmony/jndi/provider/dns/ProviderMgr.java   (with props)
    incubator/harmony/enhanced/classlib/trunk/modules/jndi/src/main/java/org/apache/harmony/jndi/provider/dns/QuestionRecord.java   (with props)
    incubator/harmony/enhanced/classlib/trunk/modules/jndi/src/main/java/org/apache/harmony/jndi/provider/dns/Resolver.java   (with props)
    incubator/harmony/enhanced/classlib/trunk/modules/jndi/src/main/java/org/apache/harmony/jndi/provider/dns/ResolverCache.java   (with props)
    incubator/harmony/enhanced/classlib/trunk/modules/jndi/src/main/java/org/apache/harmony/jndi/provider/dns/ResourceRecord.java   (with props)
    incubator/harmony/enhanced/classlib/trunk/modules/jndi/src/main/java/org/apache/harmony/jndi/provider/dns/SList.java   (with props)
    incubator/harmony/enhanced/classlib/trunk/modules/jndi/src/main/java/org/apache/harmony/jndi/provider/dns/TransportMgr.java   (with props)
    incubator/harmony/enhanced/classlib/trunk/modules/jndi/src/main/java/org/apache/harmony/jndi/provider/dns/dnsURLContext.java   (with props)
    incubator/harmony/enhanced/classlib/trunk/modules/jndi/src/main/java/org/apache/harmony/jndi/provider/dns/dnsURLContextFactory.java   (with props)
    incubator/harmony/enhanced/classlib/trunk/modules/jndi/src/main/java/org/apache/harmony/util/
    incubator/harmony/enhanced/classlib/trunk/modules/jndi/src/main/java/org/apache/harmony/util/logging/
    incubator/harmony/enhanced/classlib/trunk/modules/jndi/src/main/java/org/apache/harmony/util/logging/LogConst.java   (with props)
    incubator/harmony/enhanced/classlib/trunk/modules/jndi/src/test/java/org/apache/harmony/jndi/provider/
    incubator/harmony/enhanced/classlib/trunk/modules/jndi/src/test/java/org/apache/harmony/jndi/provider/dns/
    incubator/harmony/enhanced/classlib/trunk/modules/jndi/src/test/java/org/apache/harmony/jndi/provider/dns/DNSContextTest.java   (with props)
    incubator/harmony/enhanced/classlib/trunk/modules/jndi/src/test/java/org/apache/harmony/jndi/provider/dns/DNSNameParserTest.java   (with props)
    incubator/harmony/enhanced/classlib/trunk/modules/jndi/src/test/java/org/apache/harmony/jndi/provider/dns/DNSPseudoURLTest.java   (with props)
    incubator/harmony/enhanced/classlib/trunk/modules/jndi/src/test/java/org/apache/harmony/jndi/provider/dns/NSLookup.java   (with props)
    incubator/harmony/enhanced/classlib/trunk/modules/jndi/src/test/java/org/apache/harmony/jndi/provider/dns/ResourceRecordTest.java   (with props)
    incubator/harmony/enhanced/classlib/trunk/modules/jndi/src/test/java/org/apache/harmony/jndi/provider/dns/TestMgr.java   (with props)
Modified:
    incubator/harmony/enhanced/classlib/trunk/modules/jndi/make/common/build.xml
    incubator/harmony/enhanced/classlib/trunk/modules/jndi/make/patternset.txt

Modified: incubator/harmony/enhanced/classlib/trunk/modules/jndi/make/common/build.xml
URL: http://svn.apache.org/viewvc/incubator/harmony/enhanced/classlib/trunk/modules/jndi/make/common/build.xml?rev=410240&r1=410239&r2=410240&view=diff
==============================================================================
--- incubator/harmony/enhanced/classlib/trunk/modules/jndi/make/common/build.xml (original)
+++ incubator/harmony/enhanced/classlib/trunk/modules/jndi/make/common/build.xml Tue May 30 04:24:59 2006
@@ -101,7 +101,8 @@
 
                 <fileset dir="${hy.jndi.src.test.java}">
                     <include name="**/*Test.java"/>
-                	
+                        <exclude name="org/apache/harmony/jndi/provider/dns/DNSContextTest.java" />                	
+
                 	<!--  These tests run in a separate jvm below -->
                 	<exclude name="org/apache/harmony/jndi/tests/javax/naming/spi/NamingManagerBuilderTest.java" />
                     <exclude name="org/apache/harmony/jndi/tests/javax/naming/spi/NamingManagerTest.java" />

Modified: incubator/harmony/enhanced/classlib/trunk/modules/jndi/make/patternset.txt
URL: http://svn.apache.org/viewvc/incubator/harmony/enhanced/classlib/trunk/modules/jndi/make/patternset.txt?rev=410240&r1=410239&r2=410240&view=diff
==============================================================================
--- incubator/harmony/enhanced/classlib/trunk/modules/jndi/make/patternset.txt (original)
+++ incubator/harmony/enhanced/classlib/trunk/modules/jndi/make/patternset.txt Tue May 30 04:24:59 2006
@@ -18,4 +18,5 @@
 javax/naming/ldap/*
 javax/naming/spi/*
 
-org/apache/harmony/jndi/internal/*
\ No newline at end of file
+org/apache/harmony/jndi/**
+org/apache/harmony/util/logging/LogConst.*

Added: incubator/harmony/enhanced/classlib/trunk/modules/jndi/src/main/java/org/apache/harmony/jndi/provider/dns/BasicNamingEnumerator.java
URL: http://svn.apache.org/viewvc/incubator/harmony/enhanced/classlib/trunk/modules/jndi/src/main/java/org/apache/harmony/jndi/provider/dns/BasicNamingEnumerator.java?rev=410240&view=auto
==============================================================================
--- incubator/harmony/enhanced/classlib/trunk/modules/jndi/src/main/java/org/apache/harmony/jndi/provider/dns/BasicNamingEnumerator.java (added)
+++ incubator/harmony/enhanced/classlib/trunk/modules/jndi/src/main/java/org/apache/harmony/jndi/provider/dns/BasicNamingEnumerator.java Tue May 30 04:24:59 2006
@@ -0,0 +1,83 @@
+/*
+ * Copyright 2005-2006 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.
+ */
+
+/**
+ * @author Alexei Y. Zakharov
+ * @version $Revision: 1.1.2.4 $
+ */
+package org.apache.harmony.jndi.provider.dns;
+
+import javax.naming.NamingEnumeration;
+import javax.naming.NamingException;
+import java.util.Enumeration;
+
+/**
+ * Trivial implementation of <code>NamingEnumeration</code> interface.
+ * @author Alexei Zakharov
+ * @version $Revision: 1.1.2.4 $
+ */
+public class BasicNamingEnumerator implements NamingEnumeration {
+    
+    private Enumeration enum1 = null;
+    
+    /**
+     * Constructs new enumerator from existing <code>Enumeration</code>.
+     * @param enum1 enumeration 
+     */
+    public BasicNamingEnumerator(Enumeration newEnum) {
+        this.enum1 = newEnum;
+    }
+
+    /**
+     * @return next element of enumeration
+     * @see javax.naming.NamingEnumeration#next()
+     */
+    public Object next() {
+        return enum1.nextElement();
+    }
+
+    /**
+     * @return <code>true</code> if the enumeration has more elements
+     * @see javax.naming.NamingEnumeration#hasMore()
+     */
+    public boolean hasMore() {
+        return enum1.hasMoreElements();
+    }
+
+    /**
+     * Do nothing in current implementation.
+     * @see javax.naming.NamingEnumeration#close()
+     */
+    public void close() throws NamingException {}
+
+    /**
+     * @return next element of enumeration
+     * @see java.util.Enumeration#nextElement()
+     */
+    public Object nextElement() {
+        return enum1.nextElement();
+    }
+
+    /**
+     * @return <code>true</code> if the enumeration has more elements
+     * @see java.util.Enumeration#hasMoreElements()
+     */
+    public boolean hasMoreElements() {
+        return enum1.hasMoreElements();
+    }
+
+}

Propchange: incubator/harmony/enhanced/classlib/trunk/modules/jndi/src/main/java/org/apache/harmony/jndi/provider/dns/BasicNamingEnumerator.java
------------------------------------------------------------------------------
    svn:eol-style = native

Added: incubator/harmony/enhanced/classlib/trunk/modules/jndi/src/main/java/org/apache/harmony/jndi/provider/dns/DNSContext.java
URL: http://svn.apache.org/viewvc/incubator/harmony/enhanced/classlib/trunk/modules/jndi/src/main/java/org/apache/harmony/jndi/provider/dns/DNSContext.java?rev=410240&view=auto
==============================================================================
--- incubator/harmony/enhanced/classlib/trunk/modules/jndi/src/main/java/org/apache/harmony/jndi/provider/dns/DNSContext.java (added)
+++ incubator/harmony/enhanced/classlib/trunk/modules/jndi/src/main/java/org/apache/harmony/jndi/provider/dns/DNSContext.java Tue May 30 04:24:59 2006
@@ -0,0 +1,1943 @@
+/*
+ * Copyright 2005-2006 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.
+ */
+
+/**
+ * @author Alexei Y. Zakharov
+ * @version $Revision: 1.1.2.5 $
+ */
+package org.apache.harmony.jndi.provider.dns;
+
+import java.util.Enumeration;
+import java.util.HashSet;
+import java.util.Hashtable;
+import java.util.Iterator;
+import java.util.StringTokenizer;
+
+import javax.naming.Binding;
+import javax.naming.CannotProceedException;
+import javax.naming.CompositeName;
+import javax.naming.ConfigurationException;
+import javax.naming.Context;
+import javax.naming.InvalidNameException;
+import javax.naming.Name;
+import javax.naming.NameClassPair;
+import javax.naming.NameParser;
+import javax.naming.NamingEnumeration;
+import javax.naming.NamingException;
+import javax.naming.NoPermissionException;
+import javax.naming.NotContextException;
+import javax.naming.OperationNotSupportedException;
+import javax.naming.RefAddr;
+import javax.naming.Reference;
+import javax.naming.directory.Attribute;
+import javax.naming.directory.Attributes;
+import javax.naming.directory.BasicAttribute;
+import javax.naming.directory.BasicAttributes;
+import javax.naming.directory.DirContext;
+import javax.naming.directory.InvalidAttributeIdentifierException;
+import javax.naming.directory.ModificationItem;
+import javax.naming.directory.SearchControls;
+import javax.naming.spi.DirectoryManager;
+import javax.naming.spi.NamingManager;
+
+/**
+ * This class represents DNS context. This is the main class and the main entry
+ * point to DNS service provider for JNDI.
+ *
+ * @author Alexei Zakharov
+ * @version $Revision: 1.1.2.5 $
+ * @see dnsURLContext
+ * @see DNSName
+ * @see DNSNameParser
+ */
+public class DNSContext implements DirContext, Cloneable {
+
+    // some environment property names
+    public static final String LOOKUP_ATTR =
+            "org.apache.harmony.jndi.provider.dns.lookup.attr";
+    public static final String RECURSION =
+            "org.apache.harmony.jndi.provider.dns.recursion";
+    public static final String TIMEOUT_INITIAL =
+            "org.apache.harmony.jndi.provider.dns.timeout.initial";
+    public static final String TIMEOUT_RETRIES =
+            "org.apache.harmony.jndi.provider.dns.timeout.retries";
+    public static final String THREADS_MAX =
+            "org.apache.harmony.jndi.provider.dns.threads.max";
+
+    // used in internal methods
+    private static int NAME_CLASS_SWT = 1;
+    private static int BINDING_SWT = 2;
+    
+    private DNSNameParser nameParser = null;
+    private Hashtable environment = null;
+    private Resolver resolver = null;
+
+    private DNSName contextName = null;
+
+    // default values for properties that has been read from the environment
+    private boolean authoritative = ProviderConstants.DEFAULT_AUTHORITATIVE;
+    private int lookupAttrType = ProviderConstants.DEFAULT_LOOKUP_ATTR_TYPE;
+    private int lookupAttrClass = ProviderConstants.DEFAULT_LOOKUP_ATTR_CLASS;
+    private boolean recursion = ProviderConstants.DEFAULT_RECURSION;
+    private int timeoutInitial = ProviderConstants.DEFAULT_INITIAL_TIMEOUT;
+    private int timeoutRetries = ProviderConstants.DEFAULT_TIMEOUT_RETRIES;
+    private int maxThreads = ProviderConstants.DEFAULT_MAX_THREADS;
+
+    // <--- start of constructor section
+    
+    /**
+     * A DNS context constructor. Should not be accessed directly.
+     * @param env the hash table with environment variables. The context
+     * will make a clone of given hash table.
+     * @throws InvalidNameException something wrong with domain names given in
+     * <code>java.naming.provider.url</code> property
+     * @throws ConfigurationException if some error occured during parsing of
+     * configuration parameters
+     * @throws NamingException if some parse error occured
+     * @throws NullPointerException if the environment is null
+     *  
+     */
+    DNSContext(Hashtable env) throws NamingException
+    {
+        nameParser = new DNSNameParser();
+        if (env == null) {
+           throw new NullPointerException("environment is null");
+        }
+        this.environment = (Hashtable) env.clone();
+        parseBoolProp(Context.AUTHORITATIVE);
+        parseLookupProp();
+        if (environment.containsKey(RECURSION)) {
+            parseBoolProp(RECURSION);
+        }
+        if (environment.containsKey(TIMEOUT_INITIAL)) {
+            parseIntProp(TIMEOUT_INITIAL);
+        }
+        if (environment.containsKey(TIMEOUT_RETRIES)) {
+            parseIntProp(TIMEOUT_RETRIES);
+        }
+        parseIntProp(THREADS_MAX);
+        resolver = new Resolver(timeoutInitial, timeoutRetries, maxThreads,
+                authoritative, recursion);
+        parseProviderUrlProp();
+    }
+
+    /**
+     * Parses integer environment property and fills appropriate internal
+     * variable if necessary.
+     * @param paramName name of parameter
+     * @throws NumberFormatException if error encountered while parsing
+     */
+    private void parseIntProp(String paramName)
+            throws NumberFormatException
+    {
+        Object tmp = environment.get(paramName);
+
+        if (tmp != null && tmp instanceof String) {
+            try {
+                int n = Integer.parseInt((String) tmp);
+
+                if (paramName.equals(TIMEOUT_RETRIES)) {
+                    timeoutRetries = n;
+                } else if (paramName.equals(TIMEOUT_INITIAL)) {
+                    timeoutInitial = n;
+                } else if (paramName.equals(THREADS_MAX)) {
+                    maxThreads = n;
+                } 
+            } catch (NumberFormatException e) {
+                throw e;
+            }
+        }
+    }
+
+    /**
+     * Parses boolean environment property and fills appropriate internal
+     * variable if necessary.
+     * @param paramName name of parameter
+     */
+    private void parseBoolProp(String paramName)
+    {
+        Object tmp = environment.get(paramName);
+        boolean val = false;
+
+        if (tmp != null) {
+            if (tmp instanceof String && tmp.equals("true")) {
+                val = true;
+            }
+            if (paramName.equals(Context.AUTHORITATIVE)) {
+                authoritative = val;
+            } else if (paramName.equals(DNSContext.RECURSION)) {
+                recursion = val;
+            }
+        }
+    }
+
+    /**
+     * Parses "lookup attribute" environment property and fills appropriate
+     * internal variable.
+     * @throws ConfigurationException if some DNS type or DNS class is unknown
+     */
+    private void parseLookupProp() throws ConfigurationException {
+        Object tmp;
+
+        if (environment.containsKey(LOOKUP_ATTR)) {
+            int k;
+            String recClassName;
+            String recTypeName;
+            String lookupAttr;
+
+            tmp = environment.get(LOOKUP_ATTR);
+            if (tmp instanceof String) {
+                lookupAttr = (String) tmp;
+                k = lookupAttr.indexOf(" ");
+                if (k > -1) {
+                    recClassName = lookupAttr.substring(0, k);
+
+                    lookupAttrClass = ProviderMgr.getRecordClassNumber(
+                            recClassName);
+                    if (lookupAttrClass == -1) {
+                        throw new ConfigurationException("DNS class " +
+                                recClassName + " is not supported");
+                    }
+                    recTypeName = lookupAttr.substring(k).trim();
+                }
+                else {
+                    lookupAttrClass =
+                            ProviderConstants.DEFAULT_LOOKUP_ATTR_CLASS;
+                    recTypeName = lookupAttr.trim();
+                }
+                lookupAttrType = ProviderMgr.getRecordTypeNumber(recTypeName);
+                if (lookupAttrType == -1) {
+                    throw new ConfigurationException("DNS type " +
+                            recTypeName + " is not supported");
+                }
+            }
+        }
+    }
+
+    /**
+     * Parses "provider URL" environment property and fills appropriate
+     * internal variable.
+     * @throws NamingException if such exception encountered while parsing
+     */
+    private void parseProviderUrlProp() throws NamingException {
+        Object tmp;
+        
+        if (environment.containsKey(Context.PROVIDER_URL)) {
+            tmp = environment.get(Context.PROVIDER_URL);
+            if (tmp instanceof String) {
+                StringTokenizer st = new StringTokenizer((String) tmp, " ");
+                
+                while (st.hasMoreTokens()) {
+                    String token = st.nextToken();
+                    DNSPseudoURL dnsURL;
+
+                    try {
+                        dnsURL = new DNSPseudoURL(token);
+                        if (dnsURL.isHostIpGiven()) {
+                            resolver.addInitialServer(null, dnsURL.getHost(),
+                                    dnsURL.getPort(), dnsURL.getDomain());
+                        }
+                        else {
+                            resolver.addInitialServer(dnsURL.getHost(), null, 
+                                    dnsURL.getPort(), dnsURL.getDomain());
+                        }
+                        if (contextName == null) {
+                            contextName = (DNSName)
+                                    nameParser.parse(dnsURL.getDomain());
+                        }
+                        else {
+                            DNSName name2 = (DNSName)
+                                    nameParser.parse(dnsURL.getDomain());
+
+                            if (name2.compareTo(contextName) != 0) {
+                                throw new ConfigurationException(
+                                        "conflicting domains: " +
+                                        contextName + " and " +
+                                        name2);
+                            }
+                        }
+                    } catch (IllegalArgumentException e) {
+                        throw new ConfigurationException(
+                                "Unable to parse DNS URL " +
+                                token + ". " + e.getMessage());
+                    }
+                }
+            }
+        } else {
+            contextName = ProviderConstants.ROOT_ZONE_NAME_OBJ;
+        }
+    }
+
+    
+    /**
+     * Constructs new DNS context with given name. This
+     * constructor will read all private properties from its ancestor context.
+     * The environment will not be parsed.
+     * @param ancestorCtx an ancestor context to read all internal properties from
+     * @param name name of newly created context in the ancestor context
+     */
+    DNSContext(DNSContext ancestorCtx, DNSName name) {
+        this.contextName = (DNSName) name.clone();
+        this.nameParser = ancestorCtx.nameParser;
+        this.environment = (Hashtable) ancestorCtx.environment.clone();
+        this.resolver = ancestorCtx.resolver;
+        this.authoritative = ancestorCtx.authoritative;
+        this.lookupAttrType = ancestorCtx.lookupAttrType;
+        this.lookupAttrClass = ancestorCtx.lookupAttrClass;
+        this.recursion = ancestorCtx.recursion;
+        this.timeoutInitial = ancestorCtx.timeoutInitial;
+        this.timeoutRetries = ancestorCtx.timeoutRetries;
+        this.maxThreads = ancestorCtx.maxThreads;
+    }
+    
+    // <----- end of constructor section
+
+    /**
+     * Obtains all attributes associated with given name.
+     * @param name domain name or composite name in string form
+     * @return collection of found attributes
+     * @throws NamingException or its subtype if such has been encountered
+     * @see DNSContext#getAttributes(Name, String[]) for more details 
+     * @see javax.naming.directory.DirContext#getAttributes(java.lang.String)
+     */
+    public Attributes getAttributes(String name) throws NamingException {
+        return getAttributes(convertNameFromStringForm(name), null);
+    }
+
+    /** 
+     * This method is not supported by the DNS provider.
+     * @see javax.naming.directory.DirContext#modifyAttributes(java.lang.String, int, javax.naming.directory.Attributes)
+     */
+    public void modifyAttributes(String arg0, int arg1, Attributes arg2)
+            throws NamingException
+    {
+        Object obj = lookup(arg0);
+        
+        if (obj instanceof DNSContext) {
+            throw new OperationNotSupportedException();
+        } else if (obj instanceof DirContext) {
+            ((DirContext) obj).modifyAttributes("", arg1, arg2);
+        } else {
+            throw new NotContextException("found object is not a DirContext"); 
+        }
+    }
+
+    /**
+     * Determines all attributes associated with given name.
+     * 
+     * @param name the name to look for; should be an instance of either
+     * <code>DNSName</code> class or <code>CompositeName</code> class
+     * @return collection of found attributes
+     * @throws NamingException or its subtype if such has been encountered
+     * @see DNSContext#getAttributes(Name, String[]) for more details 
+     * @see javax.naming.directory.DirContext#getAttributes(javax.naming.Name)
+     */
+    public Attributes getAttributes(Name name) throws NamingException {
+        return getAttributes(name, null);
+    }
+
+    /** 
+     * This method is not supported by the DNS provider.
+     * @see javax.naming.directory.DirContext#modifyAttributes(javax.naming.Name, int, javax.naming.directory.Attributes)
+     */
+    public void modifyAttributes(Name arg0, int arg1, Attributes arg2)
+            throws NamingException
+    {
+        Object obj = lookup(arg0);
+        
+        if (obj instanceof DNSContext) {
+            throw new OperationNotSupportedException();
+        } else if (obj instanceof DirContext) {
+            ((DirContext) obj).modifyAttributes("", arg1, arg2);
+        } else {
+            throw new NotContextException("found object is not a DirContext"); 
+        }
+    }
+
+    /** 
+     * This method is not supported by the DNS provider.
+     * @see javax.naming.directory.DirContext#getSchema(java.lang.String)
+     */
+    public DirContext getSchema(String arg0) throws NamingException {
+        Object obj = lookup(arg0);
+        
+        if (obj instanceof DNSContext) {
+            throw new OperationNotSupportedException();
+        } else if (obj instanceof DirContext) {
+            return ((DirContext) obj).getSchema("");
+        } else {
+            throw new NotContextException("found object is not a DirContext"); 
+        }
+    }
+
+    /** 
+     * This method is not supported.
+     * @see javax.naming.directory.DirContext#getSchemaClassDefinition(java.lang.String)
+     */
+    public DirContext getSchemaClassDefinition(String arg0)
+            throws NamingException
+    {
+        Object obj = lookup(arg0);
+        
+        if (obj instanceof DNSContext) {
+            throw new OperationNotSupportedException();
+        } else if (obj instanceof DirContext) {
+            return ((DirContext) obj).getSchemaClassDefinition("");
+        } else {
+            throw new NotContextException("found object is not a DirContext"); 
+        }
+    }
+
+    /** 
+     * This method is not supported.
+     * @see javax.naming.directory.DirContext#getSchema(javax.naming.Name)
+     */
+    public DirContext getSchema(Name arg0) throws NamingException {
+        Object obj = lookup(arg0);
+        
+        if (obj instanceof DNSContext) {
+            throw new OperationNotSupportedException();
+        } else if (obj instanceof DirContext) {
+            return ((DirContext) obj).getSchema("");
+        } else {
+            throw new NotContextException("found object is not a DirContext"); 
+        }
+    }
+
+    /** 
+     * This method is not supported.
+     * @see javax.naming.directory.DirContext#getSchemaClassDefinition(javax.naming.Name)
+     */
+    public DirContext getSchemaClassDefinition(Name arg0)
+            throws NamingException
+    {
+        Object obj = lookup(arg0);
+        
+        if (obj instanceof DNSContext) {
+            throw new OperationNotSupportedException();
+        } else if (obj instanceof DirContext) {
+            return ((DirContext) obj).getSchemaClassDefinition("");
+        } else {
+            throw new NotContextException("found object is not a DirContext"); 
+        }
+    }
+
+    /** 
+     * This method is not supported.
+     * @see javax.naming.directory.DirContext#modifyAttributes(java.lang.String, javax.naming.directory.ModificationItem[])
+     */
+    public void modifyAttributes(String arg0, ModificationItem[] arg1)
+            throws NamingException
+    {
+        Object obj = lookup(arg0);
+        
+        if (obj instanceof DNSContext) {
+            throw new OperationNotSupportedException();
+        } else if (obj instanceof DirContext) {
+            ((DirContext) obj).modifyAttributes("", arg1);
+        } else {
+            throw new NotContextException("found object is not a DirContext"); 
+        }
+    }
+
+    /** 
+     * This method is not supported.
+     * @see javax.naming.directory.DirContext#modifyAttributes(javax.naming.Name, javax.naming.directory.ModificationItem[])
+     */
+    public void modifyAttributes(Name arg0, ModificationItem[] arg1)
+            throws NamingException {
+        Object obj = lookup(arg0);
+        
+        if (obj instanceof DNSContext) {
+            throw new OperationNotSupportedException();
+        } else if (obj instanceof DirContext) {
+            ((DirContext) obj).modifyAttributes("", arg1);
+        } else {
+            throw new NotContextException("found object is not a DirContext"); 
+        }
+    }
+
+    /** 
+     * This method is not supported.
+     * @see javax.naming.directory.DirContext#search(java.lang.String, javax.naming.directory.Attributes)
+     */
+    public NamingEnumeration search(String arg0, Attributes arg1)
+            throws NamingException
+    {
+        Object obj = lookup(arg0);
+        
+        if (obj instanceof DNSContext) {
+            throw new OperationNotSupportedException();
+        } else if (obj instanceof DirContext) {
+            return ((DirContext) obj).search("", arg1);
+        } else {
+            throw new NotContextException("found object is not a DirContext"); 
+        }
+    }
+
+    /** 
+     * This method is not supported.
+     * @see javax.naming.directory.DirContext#search(javax.naming.Name, javax.naming.directory.Attributes)
+     */
+    public NamingEnumeration search(Name arg0, Attributes arg1)
+            throws NamingException
+    {
+        Object obj = lookup(arg0);
+        
+        if (obj instanceof DNSContext) {
+            throw new OperationNotSupportedException();
+        } else if (obj instanceof DirContext) {
+            return ((DirContext) obj).search("", arg1);
+        } else {
+            throw new NotContextException("found object is not a DirContext"); 
+        }
+    }
+
+    /** 
+     * This method is not supported.
+     * @see javax.naming.directory.DirContext#bind(java.lang.String, java.lang.Object, javax.naming.directory.Attributes)
+     */
+    public void bind(String arg0, Object arg1, Attributes arg2)
+            throws NamingException
+    {
+        bind(convertNameFromStringForm(arg0), arg1, arg2);
+    }
+
+    /** 
+     * This method is not supported.
+     * @see javax.naming.directory.DirContext#rebind(java.lang.String, java.lang.Object, javax.naming.directory.Attributes)
+     */
+    public void rebind(String arg0, Object arg1, Attributes arg2)
+            throws NamingException
+    {
+        rebind(convertNameFromStringForm(arg0), arg1, arg2);
+    }
+
+    /** 
+     * This method is not supported.
+     * @see javax.naming.directory.DirContext#bind(javax.naming.Name, java.lang.Object, javax.naming.directory.Attributes)
+     */
+    public void bind(Name arg0, Object arg1, Attributes arg2)
+            throws NamingException
+    {
+        ContextNamePair pair;
+        
+        try {
+            pair = getTargetNamespaceContextNamePair(arg0);
+        } catch (IllegalArgumentException e) {
+            throw new OperationNotSupportedException();
+        }
+        if (pair.context instanceof DirContext) {
+            ((DirContext) pair.context).bind(pair.name, arg1, arg2);
+        } else {
+            throw new NotContextException("found object is not a DirContext"); 
+        }
+    }
+
+    /** 
+     * This method is not supported.
+     * @see javax.naming.directory.DirContext#rebind(javax.naming.Name, java.lang.Object, javax.naming.directory.Attributes)
+     */
+    public void rebind(Name arg0, Object arg1, Attributes arg2)
+            throws NamingException
+    {
+        ContextNamePair pair;
+        
+        try {
+            pair = getTargetNamespaceContextNamePair(arg0);
+        } catch (IllegalArgumentException e) {
+            throw new OperationNotSupportedException();
+        }
+        if (pair.context instanceof DirContext) {
+            ((DirContext) pair.context).rebind(pair.name, arg1, arg2);
+        } else {
+            throw new NotContextException("found object is not a DirContext"); 
+        }
+    }
+
+    /**
+     * Retrieves attributes associated with given name.
+     * @param name name to look for; should be either domain name or composite
+     * name in string form
+     * @param attrNames array of attribute names that should be retrieved
+     * @return collection of found attributes
+     * @throws NamingException or its subtypes if such have been encountered 
+     * @see #getAttributes(Name) for details 
+     * @see javax.naming.directory.DirContext#getAttributes(java.lang.String,
+     *  java.lang.String[])
+     */
+    public Attributes getAttributes(String name, String[] attrNames)
+            throws NamingException {
+        return getAttributes(convertNameFromStringForm(name), attrNames);
+    }
+
+    /**
+     * Obtains attributes associated with the given name. Each members of
+     * <code>attrNames</code> array should be the correct name of DNS resource
+     * record type (possibly prefixed with correct DNS resource record class)
+     * as specified in RFC 1035. If class name is given then it should be
+     * separated with space from the type name. If class name is missed then
+     * IN class is used by default.   
+     *  
+     * @param name the name to look for; should have either <code>DNSName</code>
+     * type or <code>CompositeName</code> type 
+     * @param attrNames the array with names of attributes to look for; if
+     *  null then all attributes will be retrieved; if
+     * empty then none of attributes will be retrieved
+     * @throws InvalidNameException if <code>name</code> is neither the instance
+     * of <code>DNSName</code> nor <code>CompositeName</code> class or the first
+     * component of composite name is not a domain name 
+     * @throws InvalidAttributeIdentifierException if the name of DNS type or
+     * DNS class given in <code>attrNames</code> array is invalid
+     * @throws NameNotFoundException if authoritative server for desired
+     * zone was contacted but given name has not been found in that zone
+     * @throws ServiceUnavailableException if no authoritative server for
+     * desired name was found or all servers are dead or malfunction   
+     * @throws NoPermissionException if no appropriate permissions on using
+     * network resources were granted
+     * @throws NullPointerException if <code>name</code> is null
+     * @throws NamingException if some other type of problem has been
+     * encountered
+     * @see javax.naming.directory.DirContext#getAttributes(javax.naming.Name,
+     *  java.lang.String[])
+     * @see RFC 1035
+     */
+    public Attributes getAttributes(Name name, String[] attrNames)
+            throws NamingException
+    {
+        int[] types;
+        int[] classes;
+        DNSName nameToLookFor = null;
+        DNSName altName = null;
+        CompositeName remainingName = null;
+        Attributes attrs = null;
+
+        // analyze given name object
+        if (name == null) {
+            throw new NullPointerException("The name is null");
+        }
+        else if (name.size() == 0) {
+            // attributes of the current context are requested
+            nameToLookFor = (DNSName) contextName.clone();
+        }
+        else if (name instanceof CompositeName) {
+            // treat the first component of the given composite name as
+            // a domain name and the rest as a Next Naming System name
+            String tmp = name.get(0);
+            // check if it is really a domain name
+            altName = (DNSName) nameParser.parse(tmp);
+            //if (!altName.isAbsolute()) {
+            nameToLookFor = (DNSName) composeName(altName, contextName);
+            //} else {
+            //    nameToLookFor = (DNSName) altName.clone();
+            //}
+            if (name.size() > 1) {
+                remainingName = (CompositeName) name.getSuffix(1);
+            }
+        }
+        else if (name instanceof DNSName) {
+            //if (!((DNSName) name).isAbsolute()) {
+            nameToLookFor = (DNSName) composeName(name, contextName);
+            //} else {
+            //    nameToLookFor = (DNSName) name.clone();
+            //}
+        }
+        else {
+            throw new InvalidNameException("Only instances of CompositeName " +
+                    "class or DNSName class are acceptable");
+        }
+
+        // we should have correct nameToLookFor at this point
+        if (remainingName != null) {
+            CannotProceedException cpe = constructCannotProceedException(
+                    altName, remainingName);
+            DirContext nnsContext =
+                    DirectoryManager.getContinuationDirContext(cpe);
+
+            attrs = nnsContext.getAttributes(remainingName, attrNames);
+        } else {
+            DNSContext resolvedCtx = new DNSContext(this, nameToLookFor);
+                
+            // analyze given attrNames object
+            if (attrNames == null) {
+                // this means that all attributes should be obtained
+                types = new int[1];
+                classes = new int[1];
+                types[0] = ProviderConstants.ANY_QTYPE;
+                classes[0] = ProviderConstants.ANY_QCLASS;
+            }
+            else {
+                HashSet classesSet = new HashSet();
+                HashSet typesSet = new HashSet();
+                Iterator iter;
+                int j;
+
+                for (int i = 0; i < attrNames.length; i++) {
+                    int k = attrNames[i].indexOf(' ');
+                    String typeStr = null;
+                    int classInt;
+                    int typesInt;
+    
+                    if (k > 0) {
+                        String classStr = attrNames[i].substring(0, k);
+
+                        classInt =
+                                ProviderMgr.getRecordClassNumber(classStr); 
+                        if (classInt == -1) {
+                            throw new InvalidAttributeIdentifierException(
+                                    "Unknown record class: " + classStr);
+                        }
+                        classesSet.add(new Integer(classInt));
+                        typeStr = attrNames[i].substring(k, attrNames[i].length())
+                                .trim();
+                    } 
+                    else {
+                        classesSet.add(new Integer(
+                                ProviderConstants.IN_CLASS));
+                        typeStr = attrNames[i].trim();
+                    }
+                    typesInt = ProviderMgr.getRecordTypeNumber(typeStr);
+                    if (typesInt == -1) {
+                        throw new InvalidAttributeIdentifierException(
+                                "Unknown record type: " + typeStr);
+                    }
+                    typesSet.add(new Integer(typesInt));
+                }
+                // filling classes array
+                classes = new int[classesSet.size()];
+                iter = classesSet.iterator();
+                j = 0;
+                while (iter.hasNext()) {
+                    Integer n = (Integer) iter.next();
+
+                    classes[j++] = n.intValue();
+                }
+                // filling types array
+                types = new int[typesSet.size()];
+                iter = typesSet.iterator();
+                j = 0;
+                while (iter.hasNext()) {
+                    Integer n = (Integer) iter.next();
+
+                    types[j++] = n.intValue();
+                }
+            }
+            
+            // we should have correct nameToLookFor, classes and types at this point
+            // let's look for attributes
+            try {
+                Enumeration records = resolver.lookup(nameToLookFor.toString(),
+                        types, classes);
+
+                attrs = createAttributesFromRecords(records);
+            } catch (SecurityException e) {
+                NoPermissionException e2 = new NoPermissionException();
+
+                e2.setRootCause(e);
+                throw e2;
+            } catch (NamingException e) {
+                throw e;
+            } catch (Exception e) {
+                NamingException ne = new NamingException();
+
+                ne.setRootCause(e);
+                throw ne;
+            }
+        }
+        return attrs;
+    }
+
+    /** 
+     * This method is not supported.
+     * @see javax.naming.directory.DirContext#createSubcontext(java.lang.String, javax.naming.directory.Attributes)
+     */
+    public DirContext createSubcontext(String arg0, Attributes arg1)
+            throws NamingException
+    {
+        return createSubcontext(convertNameFromStringForm(arg0), arg1);
+    }
+
+    /** 
+     * This method is not supported.
+     * @see javax.naming.directory.DirContext#createSubcontext(javax.naming.Name, javax.naming.directory.Attributes)
+     */
+    public DirContext createSubcontext(Name arg0, Attributes arg1)
+            throws NamingException
+    {
+        ContextNamePair pair;
+        
+        try {
+            pair = getTargetNamespaceContextNamePair(arg0);
+        } catch (IllegalArgumentException e) {
+            throw new OperationNotSupportedException();
+        }
+        if (pair.context instanceof DirContext) {
+            return ((DirContext) pair.context).createSubcontext(pair.name, arg1);
+        } else {
+            throw new NotContextException("found object is not a DirContext"); 
+        }
+    }
+
+    /** 
+     * This method is not supported.
+     * @see javax.naming.directory.DirContext#search(java.lang.String, javax.naming.directory.Attributes, java.lang.String[])
+     */
+    public NamingEnumeration search(String arg0, Attributes arg1, String[] arg2)
+            throws NamingException
+    {
+        Object obj = lookup(arg0);
+        
+        if (obj instanceof DNSContext) {
+            throw new OperationNotSupportedException();
+        } else if (obj instanceof DirContext) {
+            return ((DirContext) obj).search("", arg1, arg2);
+        } else {
+            throw new NotContextException("found object is not a DirContext"); 
+        }
+    }
+
+    /** 
+     * This method is not supported.
+     * @see javax.naming.directory.DirContext#search(javax.naming.Name, javax.naming.directory.Attributes, java.lang.String[])
+     */
+    public NamingEnumeration search(Name arg0, Attributes arg1, String[] arg2)
+            throws NamingException
+    {
+        Object obj = lookup(arg0);
+        
+        if (obj instanceof DNSContext) {
+            throw new OperationNotSupportedException();
+        } else if (obj instanceof DirContext) {
+            return ((DirContext) obj).search("", arg1, arg2);
+        } else {
+            throw new NotContextException("found object is not a DirContext"); 
+        }
+    }
+
+    /** 
+     * This method is not supported.
+     * @see javax.naming.directory.DirContext#search(java.lang.String, java.lang.String, javax.naming.directory.SearchControls)
+     */
+    public NamingEnumeration search(String arg0, String arg1,
+            SearchControls arg2) throws NamingException
+    {
+        Object obj = lookup(arg0);
+        
+        if (obj instanceof DNSContext) {
+            throw new OperationNotSupportedException();
+        } else if (obj instanceof DirContext) {
+            return ((DirContext) obj).search("", arg1, arg2);
+        } else {
+            throw new NotContextException("found object is not a DirContext"); 
+        }
+    }
+
+    /** 
+     * This method is not supported.
+     * @see javax.naming.directory.DirContext#search(javax.naming.Name, java.lang.String, javax.naming.directory.SearchControls)
+     */
+    public NamingEnumeration search(Name arg0, String arg1, SearchControls arg2)
+            throws NamingException
+    {
+        Object obj = lookup(arg0);
+        
+        if (obj instanceof DNSContext) {
+            throw new OperationNotSupportedException();
+        } else if (obj instanceof DirContext) {
+            return ((DirContext) obj).search("", arg1, arg2);
+        } else {
+            throw new NotContextException("found object is not a DirContext"); 
+        }
+    }
+
+    /** 
+     * This method is not supported.
+     * @see javax.naming.directory.DirContext#search(java.lang.String, java.lang.String, java.lang.Object[], javax.naming.directory.SearchControls)
+     */
+    public NamingEnumeration search(String arg0, String arg1, Object[] arg2,
+            SearchControls arg3) throws NamingException
+    {
+        Object obj = lookup(arg0);
+        
+        if (obj instanceof DNSContext) {
+            throw new OperationNotSupportedException();
+        } else if (obj instanceof DirContext) {
+            return ((DirContext) obj).search("", arg1, arg2, arg3);
+        } else {
+            throw new NotContextException("found object is not a DirContext"); 
+        }
+    }
+
+    /** 
+     * This method is not supported.
+     * @see javax.naming.directory.DirContext#search(javax.naming.Name, java.lang.String, java.lang.Object[], javax.naming.directory.SearchControls)
+     */
+    public NamingEnumeration search(Name arg0, String arg1, Object[] arg2,
+            SearchControls arg3) throws NamingException
+    {
+        Object obj = lookup(arg0);
+        
+        if (obj instanceof DNSContext) {
+            throw new OperationNotSupportedException();
+        } else if (obj instanceof DirContext) {
+            return ((DirContext) obj).search("", arg1, arg2, arg3);
+        } else {
+            throw new NotContextException("found object is not a DirContext"); 
+        }
+    }
+
+    /**
+     * Frees all resources obtained by the current context.
+     * @see javax.naming.Context#close()
+     */
+    public void close() throws NamingException {
+        // do nothing right now
+    }
+
+    /**
+     * @return fully qualified DNS name of the current context
+     * @see javax.naming.Context#getNameInNamespace()
+     */
+    public String getNameInNamespace() {
+        return contextName.toString();
+    }
+
+    /** 
+     * This method is not supported.
+     * @see javax.naming.Context#destroySubcontext(java.lang.String)
+     */
+    public void destroySubcontext(String arg0) throws NamingException {
+        destroySubcontext(convertNameFromStringForm(arg0));
+    }
+
+    /** 
+     * This method is not supported.
+     * @see javax.naming.Context#unbind(java.lang.String)
+     */
+    public void unbind(String arg0) throws NamingException {
+        unbind(convertNameFromStringForm(arg0));
+    }
+
+    /**
+     * Returns a clone of the environment associated with this context.
+     * @return a hash table with the context's environment
+     * @see javax.naming.Context#getEnvironment()
+     */
+    public Hashtable getEnvironment() throws NamingException {
+        return (Hashtable) environment.clone();
+    }
+
+    /** 
+     * This method is not supported.
+     * @see javax.naming.Context#destroySubcontext(javax.naming.Name)
+     */
+    public void destroySubcontext(Name arg0) throws NamingException {
+        ContextNamePair pair;
+        
+        try {
+            pair = getTargetNamespaceContextNamePair(arg0);
+        } catch (IllegalArgumentException e) {
+            throw new OperationNotSupportedException();
+        }
+        if (pair.context instanceof Context) {
+            ((Context) pair.context).destroySubcontext(pair.name);
+        } else {
+            throw new NotContextException("found object is not a Context"); 
+        }
+    }
+
+    /** 
+     * This method is not supported.
+     * @see javax.naming.Context#unbind(javax.naming.Name)
+     */
+    public void unbind(Name arg0) throws NamingException {
+        ContextNamePair pair;
+        
+        try {
+            pair = getTargetNamespaceContextNamePair(arg0);
+        } catch (IllegalArgumentException e) {
+            throw new OperationNotSupportedException();
+        }
+        if (pair.context instanceof Context) {
+            ((Context) pair.context).unbind(pair.name);
+        } else {
+            throw new NotContextException("found object is not a Context"); 
+        }
+    }
+
+    /**
+     * Performs the lookup operation for given name.
+     * The method will try to construct a composite name from given argument
+     * value. If it is succeed and resulting composite name has the size more than
+     * one then the <code>lookup(Name)</code>  version of <code>lookup</code>
+     *  method will be
+     * called with constructed composite name as an argument. If the size of 
+     * constructed composite name equals to one then the value of given argument
+     * will be treated as a string form of a domain name and an attempt
+     * to create an instance of <code>DNSName</code> class will be made. 
+     * The <code>lookup(Name)</code> will be called after this.
+     *     
+     * @param name the name to look for
+     * @return an object associated with given name
+     * @throws InvalidNameException if given argument is a string
+     *  representation of neither a composite name nor a domain name; or the
+     *  first component of the composite name is not a domain name. 
+     * @throws NamingException if some other type of
+     * <code>NamingException</code> was encountered
+     * @throws NullPointerException if the name is null
+     * @see #lookup(Name)
+     * @see javax.naming.Context#lookup(java.lang.String)
+     */
+    public Object lookup(String name) throws NamingException {
+        return lookup(convertNameFromStringForm(name));
+    }
+
+    /**
+     * @param nameStr string representation of a name
+     * @return an instance of <code>CompositeName</code> or
+     *  <code>DNSName</code> class
+     * @throws InvalidNameException if <code>nameStr</code> is neither a string
+     * representation of <code>CompositeName</code> class nor an instance of
+     * <code>DNSName</code> class.
+     */
+    private Name convertNameFromStringForm(String nameStr)
+            throws InvalidNameException
+    {
+        Name nameObj = null;
+        
+        if (nameStr == null) {
+            throw new NullPointerException("The name is null");
+        }
+        nameObj = new CompositeName(nameStr);
+        if (nameObj.size() == 1) {
+            nameObj = nameParser.parse(nameStr);
+        }
+        else if (nameObj.size() == 0) {
+            nameObj = new DNSName();
+        }
+        return nameObj;
+    }
+    
+    /**
+     * Looks for a object associated with the given name. This methods just
+     * forwards the request to <code>#lookup(String)</code> method and do
+     * nothing more.
+     * @param name name to look for
+     * @return found object
+     * @throws NamingException if encountered
+     * @see #lookup(String) for details
+     * @see javax.naming.Context#lookupLink(javax.naming.Name)
+     */
+
+    public Object lookupLink(String name) throws NamingException {
+        return lookup(name);
+    }
+
+    /**
+     * Removes the property with given name from the contex's environment.
+     * @param name the name of the property to remove
+     * @see javax.naming.Context#removeFromEnvironment(java.lang.String)
+     */
+    public Object removeFromEnvironment(String name) {
+        return environment.remove(name);
+    }
+
+    /** 
+     * This method is not supported.
+     * @see javax.naming.Context#bind(java.lang.String, java.lang.Object)
+     */
+    public void bind(String arg0, Object arg1) throws NamingException {
+        bind(convertNameFromStringForm(arg0), arg1);
+    }
+
+    /** 
+     * This method is not supported.
+     * @see javax.naming.Context#rebind(java.lang.String, java.lang.Object)
+     */
+    public void rebind(String arg0, Object arg1) throws NamingException {
+        rebind(convertNameFromStringForm(arg0), arg1);
+    }
+
+    /**
+     * Performs the lookup operation for the given name in the current context.
+     * @param name this method looks for object associated with given name 
+     * @return found object
+     * @throws InvalidNameException if the argument is not a valid type, e.g. 
+     * <code>CompositeName</code> or <code>DNSName</code>;
+     * or the first component of given composite name is not a domain name 
+     * @throws NameNotFoundException if authoritative server for desired
+     * zone was contacted but given name has not been found in that zone
+     * @throws ServiceUnavailableException if no authoritative server for
+     * desired name was found or all servers are dead or malfunction   
+     * @throws NoPermissionException if no appropriate permissions on using
+     * network resources were granted
+     * @throws NullPointerException if <code>name</code> is null
+     * @throws NamingException if some other type of
+     * <code>NamingException</code> was encountered
+     * @see javax.naming.Context#lookup(javax.naming.Name)
+     */
+    public Object lookup(Name name) throws NamingException {
+        int[] types = new int[1];
+        int[] classes = new int[1];
+        DNSName nameToLookFor = null;
+        DNSName altName = null;
+        CompositeName remainingName = null;
+        Object result = null;
+
+        // analyze given name object
+        if (name == null) {
+            throw new NullPointerException("The name is null");
+        }
+        else if (name.size() == 0) {
+            // attributes of the current context are requested
+            nameToLookFor = (DNSName) contextName.clone();
+        }
+        else if (name instanceof CompositeName) {
+            // treat the first component of the given composite name as
+            // a domain name and the rest as a Next Naming System name
+            String tmp = name.get(0);
+            // check if it is really a domain name
+            altName = (DNSName) nameParser.parse(tmp);
+            //if (!altName.isAbsolute()) {
+            nameToLookFor = (DNSName) composeName(altName, contextName);
+            //} else {
+            //    nameToLookFor = (DNSName) altName.clone();
+            //}
+            if (name.size() > 1) {
+                remainingName = (CompositeName) name.getSuffix(1);
+            }
+        }
+        else if (name instanceof DNSName) {
+            //if (!((DNSName) name).isAbsolute()) {
+            nameToLookFor = (DNSName) composeName(name, contextName);
+            //} else {
+            //    nameToLookFor = (DNSName) name.clone();
+            //}
+        }
+        else {
+            throw new InvalidNameException("Only instances of CompositeName " +
+                    "class or DNSName class are acceptable");
+        }
+        // we should have correct nameToLookFor at this point
+        types[0] = lookupAttrType;
+        classes[0] = lookupAttrClass;
+        if (remainingName != null) {
+            CannotProceedException cpe = constructCannotProceedException(
+                    altName, remainingName);
+            Context nnsContext = DirectoryManager.getContinuationContext(cpe);
+
+            result = nnsContext.lookup(remainingName);
+        } else {
+            try {
+                DNSContext resolvedCtx = new DNSContext(this, nameToLookFor);
+                Enumeration records = resolver.lookup(nameToLookFor.toString(),
+                        types, classes);
+                Attributes attrs = createAttributesFromRecords(records);
+
+                result = DirectoryManager.getObjectInstance(
+                        resolvedCtx, name, this, environment, attrs);
+            } catch (SecurityException e) {
+                NoPermissionException e2 =
+                        new NoPermissionException(e.getMessage());
+
+                e2.setRootCause(e);
+                throw e2;
+            } catch (NamingException e) {
+                throw e;
+            } catch (Exception e) {
+                NamingException ne = new NamingException(e.getMessage());
+                
+                ne.setRootCause(e);
+                throw ne;
+            }
+        }
+        return result;
+    }
+
+    /**
+     * Constructs <code>CannotProcessException</code> object and fills it
+     * with necessary information. Values of some instance variables of the
+     * current context are used.
+     * 
+     * @param name the portion of name that belongs to DNS namespace
+     * @param remainingName the remainder of the name that belongs to NNS
+     *  namespace
+     * @return newly constructed exception object
+     * @throws NamingException if <code>NamingException</code> was encountered
+     * somewhere
+     */
+    private CannotProceedException constructCannotProceedException(
+            DNSName name, CompositeName remainingName)
+            throws NamingException
+    {
+        DNSName nameToLookFor = (DNSName) composeName(name, contextName);
+        final DNSContext resolvedCtx = new DNSContext(this, nameToLookFor);
+        // namespace border violation, need to ask NNS
+        RefAddr refAddr = new RefAddr("nns") {
+            private static final long serialVersionUID = 8654740210501193418L;
+            
+            DNSContext context = (DNSContext) resolvedCtx.clone();
+            
+            public Object getContent() {
+                return context;
+            }
+        };
+        Reference ref = new Reference(
+                this.getClass().getName(), refAddr);
+        CannotProceedException cpe = null;
+        CompositeName resolvedName = null;
+
+        if (environment.containsKey(NamingManager.CPE)) {
+            cpe = (CannotProceedException)
+                    environment.get(NamingManager.CPE);
+            resolvedName = (CompositeName) cpe.getResolvedName();
+            // remove the last component if it is ""
+            // (the sign of the next naming system)
+            if (resolvedName != null &&
+                    resolvedName.get(resolvedName.size() - 1)
+                            .equals(""))
+            {
+                resolvedName.remove(resolvedName.size() - 1);
+            }
+        }                
+        else {
+            cpe = new CannotProceedException();
+        }
+        cpe.setEnvironment((Hashtable) environment.clone());
+        cpe.setAltName(name);
+        cpe.setAltNameCtx((DNSContext) this.clone());
+        cpe.setRemainingName(remainingName);
+        if (resolvedName == null) {
+            resolvedName = new CompositeName();
+        }
+        resolvedName.add(nameToLookFor.toString());
+        // the sign of the next naming system
+        resolvedName.add("");
+        cpe.setResolvedName(resolvedName);
+        cpe.setResolvedObj(ref);
+        return cpe;
+    }
+    
+    /**
+     * Creates an <code>Attributes</code> object from the given enumeration
+     * of resource records.
+     * @param recs enumeration of resource records received from the resolver
+     * @return corresponding instance of <code>Attributes</code>
+     */
+    private static Attributes createAttributesFromRecords(Enumeration recs) {
+        Attributes attrs = new BasicAttributes(true);
+        
+        while (recs.hasMoreElements()) {
+            ResourceRecord curRec = (ResourceRecord) recs.nextElement();
+            String clssTypeStr = null;
+            Attribute oldAttr = null;
+            
+            if (curRec.getRRClass() == ProviderConstants.IN_CLASS) {
+                clssTypeStr = ProviderConstants.rrTypeNames[curRec.getRRType()];
+            }
+            else {
+                clssTypeStr =
+                        ProviderConstants.rrClassNames[curRec.getRRClass()] +
+                        " " + 
+                        ProviderConstants.rrTypeNames[curRec.getRRType()];
+            }
+            oldAttr = attrs.get(clssTypeStr);
+            if (oldAttr != null) {
+                oldAttr.add(oldAttr.size(), curRec.getRData());
+            } else {
+                BasicAttribute attr = new BasicAttribute(clssTypeStr,
+                        curRec.getRData(), false);
+
+                attrs.put(attr);             
+            }
+        }
+        return attrs;
+    }
+    
+    /**
+     * Looks for a object associated with the given name. This methods just
+     * forwards the request to <code>#lookup(Name)</code> method and do nothing
+     * more.
+     * @param name name to look for
+     * @return found object
+     * @throws NamingException if encountered
+     * @see #lookup(Name) for details
+     * @see javax.naming.Context#lookupLink(javax.naming.Name)
+     */
+    public Object lookupLink(Name name) throws NamingException {
+        return lookup(name);
+    }
+    
+    /** 
+     * This method is not supported.
+     * @see javax.naming.Context#bind(javax.naming.Name, java.lang.Object)
+     */
+    public void bind(Name arg0, Object arg1) throws NamingException {
+        ContextNamePair pair;
+        
+        try {
+            pair = getTargetNamespaceContextNamePair(arg0);
+        } catch (IllegalArgumentException e) {
+            throw new OperationNotSupportedException();
+        }
+        if (pair.context instanceof Context) {
+            ((Context) pair.context).bind(pair.name, arg1);
+        } else {
+            throw new NotContextException("found object is not a Context"); 
+        }
+    }
+
+    /** 
+     * This method is not supported.
+     * @see javax.naming.Context#rebind(javax.naming.Name, java.lang.Object)
+     */
+    public void rebind(Name arg0, Object arg1) throws NamingException {
+        ContextNamePair pair;
+        
+        try {
+            pair = getTargetNamespaceContextNamePair(arg0);
+        } catch (IllegalArgumentException e) {
+            throw new OperationNotSupportedException();
+        }
+        if (pair.context instanceof Context) {
+            ((Context) pair.context).rebind(pair.name, arg1);
+        } else {
+            throw new NotContextException("found object is not a Context"); 
+        }
+    }
+
+    /** 
+     * This method is not supported.
+     * @see javax.naming.Context#rename(java.lang.String, java.lang.String)
+     */
+    public void rename(String arg0, String arg1) throws NamingException {
+        rename(convertNameFromStringForm(arg0),
+               convertNameFromStringForm(arg1));
+    }
+
+    /** 
+     * This method is not supported.
+     * @see javax.naming.Context#createSubcontext(java.lang.String)
+     */
+    public Context createSubcontext(String arg0) throws NamingException {
+        return createSubcontext(convertNameFromStringForm(arg0));
+    }
+
+    /** 
+     * This method is not supported.
+     * @see javax.naming.Context#createSubcontext(javax.naming.Name)
+     */
+    public Context createSubcontext(Name arg0) throws NamingException {
+        ContextNamePair pair;
+        
+        try {
+            pair = getTargetNamespaceContextNamePair(arg0);
+        } catch (IllegalArgumentException e) {
+            throw new OperationNotSupportedException();
+        }
+        if (pair.context instanceof Context) {
+            return ((Context) pair.context).createSubcontext(pair.name);
+        } else {
+            throw new NotContextException("found object is not a Context"); 
+        }
+    }
+
+    /** 
+     * This method is not supported.
+     * @see javax.naming.Context#rename(javax.naming.Name, javax.naming.Name)
+     */
+    public void rename(Name arg0, Name arg1) throws NamingException {
+        ContextNamePair pair1;
+        ContextNamePair pair2;
+        
+        try {
+            pair1 = getTargetNamespaceContextNamePair(arg0);
+            pair2 = getTargetNamespaceContextNamePair(arg1);
+        } catch (IllegalArgumentException e) {
+            throw new OperationNotSupportedException();
+        }
+        if (pair1.context instanceof Context &&
+            pair1.context.getClass().getName().equals(
+                    pair2.context.getClass().getName()) &&
+            ((Context) pair1.context).getNameInNamespace().equals(
+                    ((Context) pair2.context).getNameInNamespace()))
+        {
+            ((Context) pair1.context).rename(pair1.name, pair2.name);
+        } else {
+            throw new NotContextException("found object is not a Context or " +
+                    "target contexts are not equal"); 
+        }
+    }
+
+    /**
+     * Returns the name parser for given name.
+     * @param name a name in the string form to return a name parser for
+     * @return the name parser found
+     * @throws NotContextException if found object is not a context 
+     * @throws NamingException if such exception was encountered during lookup 
+     * @see DNSContext#getNameParser(Name) for details 
+     * @see javax.naming.Context#getNameParser(java.lang.String)
+     */
+    public NameParser getNameParser(String name) throws NamingException {
+        Object obj;
+
+        if (name == null) {
+            throw new NullPointerException("name is null");
+        }
+        obj = lookup(name);
+        if (obj instanceof DNSContext) {
+            return nameParser;
+        }
+        else if (obj instanceof Context) {
+            return ((Context) obj).getNameParser("");
+        }
+        throw new NotContextException("Found object is not a context");
+    }
+
+    /**
+     * Tries to look for the context associated with the given name and returns
+     * the appropriate name parser. For <code>DNSContext</code> this method
+     * will return an instance of <code>DNSNameParser</code> class.
+     * @param a name to return a name parser for
+     * @return a name parser for the naming system the found context is
+     * associated with 
+     * @throws NotContextException if found object is not a context so we
+     * cannot obtain a name parser from it
+     * @throws NamingException if such exception was encountered during lookup
+     * @see javax.naming.Context#getNameParser(javax.naming.Name)
+     */
+    public NameParser getNameParser(Name name) throws NamingException {
+        Object obj;
+
+        if (name == null) {
+            throw new NullPointerException("name is null");
+        }
+        obj = lookup(name);
+        if (obj instanceof DNSContext) {
+            return nameParser;
+        }
+        else if (obj instanceof Context) {
+            return ((Context) obj).getNameParser("");
+        }
+        throw new NotContextException("Found object is not a context");
+    }
+
+    /**
+     * Lists all names along with corresponding class names contained by given
+     * context.
+     * @param name context name to list
+     * @return enumeration of <code>NameClassPair</code> objects 
+     * @throws NamingException if an error was encountered
+     * @see javax.naming.Context#list(javax.naming.Name)
+     */
+    public NamingEnumeration list(String name) throws NamingException {
+        return list_common(convertNameFromStringForm(name), NAME_CLASS_SWT);
+    }
+
+    /**
+     * Lists all names along with corresponding objects contained by given
+     * context.
+     * @param name context name to list
+     * @return enumeration of <code>Binding</code> objects 
+     * @throws NamingException if an error was encountered
+     * @see javax.naming.Context#listBindings(java.lang.String)
+     */
+    public NamingEnumeration listBindings(String name) throws NamingException {
+        return list_common(convertNameFromStringForm(name), BINDING_SWT);
+    }
+
+    /**
+     * Lists all names along with corresponding class names contained by given
+     * context.
+     * @param name context name to list
+     * @return enumeration of <code>NameClassPair</code> objects 
+     * @throws NoPermissionException if the resolver is not allowed to use a
+     *  network subsystem
+     * @throws NameNotFoundException if authoritative server(s) was not found
+     * @throws ServiceUnavailableException if none of found servers permits zone
+     * transfers   
+     * @throws DomainProtocolException if some DNS specific error has occured
+     * @throws NamingException if other type of error has occured 
+     * @see javax.naming.Context#list(javax.naming.Name)
+     */
+    public NamingEnumeration list(Name name) throws NamingException {
+        return list_common(name, NAME_CLASS_SWT);
+    }
+
+    
+    /**
+     * Lists all names along with corresponding class names contained by given
+     * context.
+     * @param name context name to list
+     * @param contentSwt method will return enumeration of
+     *  <code>NameClassPair</code> objects if this switch is set to
+     *  <code>1<code>; enumeration of <code>Binding</code> if the switch is set
+     * to <code>2</code>
+     * @return enumeration of <code>NameClassPair</code> or
+     *  <code>Binding</code> objects 
+     * @throws NamingException
+     * 
+     * TODO better resolve situation then the zone just has been transferred and
+     * then ANY_QTYPE request is performed; we could take the result from
+     * resolver's cache since we are sure the cache is up to date and contains
+     * absolutely all records from target zone
+     */
+    private NamingEnumeration list_common(Name name, int contentSwt)
+            throws NamingException
+    {
+        DNSName nameToList = null;
+        DNSName altName = null;
+        CompositeName remainingName = null;
+        NamingEnumeration result = null;
+
+        if (contentSwt != 1 && contentSwt != 2) {
+            throw new IllegalArgumentException(
+                    "contentSwt should be equal to 1 or 2");
+        }
+        if (name == null) {
+            throw new NullPointerException("name is null");
+        }
+        // analyze given name object
+        else if (name.size() == 0) {
+            // attributes of the current context are requested
+            nameToList = (DNSName) contextName.clone();
+        }
+        else if (name instanceof CompositeName) {
+            // treat the first component of the given composite name as
+            // a domain name and the rest as a Next Naming System name
+            String tmp = name.get(0);
+            // check if it is really a domain name
+            altName = (DNSName) nameParser.parse(tmp);
+            //if (!altName.isAbsolute()) {
+            nameToList = (DNSName) composeName(altName, contextName);
+            //} else {
+            //    nameToList = (DNSName) altName.clone();
+            //}
+            if (name.size() > 1) {
+                remainingName = (CompositeName) name.getSuffix(1);
+            }
+        }
+        else if (name instanceof DNSName) {
+            //if (!((DNSName) name).isAbsolute()) {
+            nameToList = (DNSName) composeName(name, contextName);
+            //} else {
+            //    nameToList = (DNSName) name.clone();
+            //}
+        }
+        else {
+            throw new InvalidNameException("Only instances of CompositeName " +
+                    "class or DNSName class are acceptable");
+        }
+        // we should have correct nameToLookFor at this point
+        if (remainingName != null) {
+            CannotProceedException cpe = constructCannotProceedException(
+                    altName, remainingName);
+            Context nnsContext = DirectoryManager.getContinuationContext(cpe);
+
+            result = nnsContext.list(remainingName);
+        } else {
+            // do the job
+            try {
+                Enumeration resEnum = resolver.list(nameToList.toString());
+                Hashtable entries = new Hashtable();
+                DNSContext targetCtx = new DNSContext(this, nameToList); 
+                
+                // collecting direct children
+                while (resEnum.hasMoreElements()) {
+                    ResourceRecord rr = (ResourceRecord) resEnum.nextElement();
+                    // fullName is an full name of current record
+                    Name curName = nameParser.parse(rr.getName());
+
+                    // if contains direct child of current context
+                    if (curName.startsWith(nameToList) &&
+                            curName.size() > nameToList.size())
+                    {
+                        // extract relative name of direct child 
+                        String elNameStr = curName.get(nameToList.size());
+
+                        // if we don't have such child yet 
+                        if (!entries.containsKey(elNameStr)) {
+                            Object elObj;
+                            Object objToPut = null;
+                            // absolute name of direct child
+                            DNSName elNameAbs = null;
+                            // relative name of direct child
+                            DNSName elNameRel = null;
+                            // context that represents direct child
+                            DNSContext elCtx;
+
+                            elNameRel = new DNSName();
+                            elNameRel.add(elNameStr);
+                            elNameAbs = (DNSName) nameToList.clone();
+                            elNameAbs.add(elNameStr);
+                            elCtx = new DNSContext(this, (DNSName) elNameAbs);
+                            elObj = DirectoryManager.getObjectInstance(elCtx,
+                                    elNameRel, targetCtx, environment, null);
+                            switch (contentSwt) {
+                            case 1:
+                                // NameClassPair
+                                objToPut = new NameClassPair(elNameStr,
+                                        elObj.getClass().getName(), true);
+                                break;
+                            case 2:
+                                // Binding
+                                objToPut = new Binding(elNameStr, elObj, true);
+                                break;
+                            }
+                            entries.put(elNameStr, objToPut);
+                        }
+                    }
+                }
+                result = new BasicNamingEnumerator(entries.elements());
+            } catch (SecurityException e) {
+                throw e;
+            } catch (NamingException e) {
+                throw e;
+            } catch (Exception e) {
+                NamingException e2 = new NamingException(e.getMessage());
+                
+                e2.setRootCause(e);
+                throw e2;
+            }
+            
+        }
+        return result;
+    }
+
+    /**
+     * Lists all names along with corresponding objects contained by given
+     * context.
+     * @param name context name to list
+     * @return enumeration of <code>Binding</code> objects 
+     * @throws NamingException if an error was encountered
+     * @see javax.naming.Context#listBindings(javax.naming.Name)
+     */
+    public NamingEnumeration listBindings(Name name) throws NamingException {
+        return list_common(name, BINDING_SWT);
+    }
+
+    /**
+     * Add a new property to the environment.
+     * @param propName a name for the new property
+     * @param propValue a value of the new property
+     * @return an old value of this property; <code>null</code> if not found
+     * @throws NullPointerException if <code>propName</code> or
+     * <code>propValue</code> is null.
+     * @throws NamingException if such was encountered
+     * @see javax.naming.Context#addToEnvironment(java.lang.String, java.lang.Object)
+     */
+    public Object addToEnvironment(String propName, Object propValue)
+         throws NamingException
+    {
+        Object oldVal = environment.put(propName, propValue);
+
+        if (propName.equals(Context.AUTHORITATIVE)) {
+            parseBoolProp(Context.AUTHORITATIVE);
+            resolver.setAuthoritativeAnswerDesired(authoritative);
+        } else if (propName.equals(RECURSION)) {
+            parseBoolProp(RECURSION);
+            resolver.setRecursionDesired(recursion);
+        } else if (propName.equals(TIMEOUT_INITIAL)) {
+            parseIntProp(TIMEOUT_INITIAL);
+            resolver.setInitialTimeout(timeoutInitial);
+        } else if (propName.equals(TIMEOUT_RETRIES)) {
+            parseIntProp(TIMEOUT_RETRIES);
+            resolver.setTimeoutRetries(timeoutRetries);
+        } else if (propName.equals(THREADS_MAX)) {
+            parseIntProp(THREADS_MAX);
+            resolver.setThreadNumberLimit(maxThreads);
+        } else if (propName.equals(LOOKUP_ATTR)) {
+            parseLookupProp();
+        } else if (propName.equals(Context.PROVIDER_URL)) {
+            parseProviderUrlProp();
+        }
+        return oldVal;
+    }
+
+    /**
+     * Appends one name to another. The method initially tries to construct
+     * composite names from given strings. If it succeeds and resulting composite
+     * names have length more than 1 then the method
+     *  <code>composeName(Name, Name)</code> will be called
+     * with constructed composite names as arguments. If one of constructed
+     * composite names (or both) have the length less or equal to 1 then
+     * it will be treated as a string representation of DNS name. The
+     * <code>DNSNameParser.parse</code> method will be called with given string
+     * as an argument. If no exception is thrown then the
+     *  <code>composeName(Name, Name)</code> will be called with the parsed
+     * <code>DNSName</code> as an argument.
+     * @param name a name relative to the current context 
+     * @param prefix the name of the current context in one of its ancestors
+     * @return a composition of <code>prefix</code> and <code>name</code>
+     * @throws NamingException 
+     * @throws NullPointerException if the value of any argument is null 
+     * @see DNSContext#composeName(Name, Name)
+     * @see javax.naming.Context#composeName(java.lang.String, java.lang.String)
+     */
+    public String composeName(String name, String prefix)
+            throws NamingException
+    {
+        Name name1 = null;
+        Name name2 = null;
+        
+        if (name == null || prefix == null) {
+            throw new NullPointerException("Given name of prefix is null");
+        }
+        if (name.length() == 0) {
+            return prefix;
+        }
+        if (prefix.length() == 0) {
+            return name;
+        }
+        try {
+            name1 = new CompositeName(name);
+            name2 = new CompositeName(prefix);
+        }
+        catch (InvalidNameException e) {}
+        if (name1 == null || name1.size() <= 1) {
+            name1 = nameParser.parse(name);
+        }
+        if (name2 == null || name2.size() <= 1) {
+            name2 = nameParser.parse(prefix);
+        }
+        return composeName(name1, name2).toString();
+    }
+
+    /**
+     * Adds <code>name</code> to the end of <code>prefix</code>.
+     * Following cases are checked:
+     * <ol>
+     * <li><code>suffix</code> is a composite name, <code>name</code> is
+     *  compound one</li>
+     * <li><code>suffix</code> is a compound name, <code>name</code> is
+     *  composite one</li>
+     * <li>Both <code>suffix</code> and <code>name</code> are compound names</li>
+     * <li>Both <code>suffix</code> and <code>name</code> are composite names</li>
+     * </ol>
+     * If one of names is a composite name then the result will be also a
+     * composite name. If we are composing compound name and composite name then
+     * the compound name will be converted to the string form and appended
+     * as a member to the resulting composite name.  
+     * @param name a name relative to the current context 
+     * @param prefix the name of the current context in one of its ancestors
+     * @return a composition of <code>prefix</code> and <code>name</code>
+     * @throws NamingException if the compound name is not an instance of
+     * <code>DNSName</code> class or we are trying to append an absolute DNS
+     * name to the non-root prefix.
+     * @throws NullPointerException if <code>name</code> or <code>prefix</code>
+     * is null 
+     * @see javax.naming.Context#composeName(javax.naming.Name, javax.naming.Name)
+     */
+    public Name composeName(Name name, Name prefix) throws NamingException {
+        Name result = null;
+
+        if (name == null || prefix == null) {
+            throw new NullPointerException("The name or prefix given is null");
+        }
+        if (name.size() == 0) {
+            return prefix;
+        }
+        if (prefix.size() == 0) {
+            return name;
+        }
+        if (name instanceof CompositeName && prefix instanceof CompositeName) {
+            // probably we need to glue together the last element of the prefix 
+            // and the first element of the name
+            String comp1 = name.get(0);
+            String comp2 = prefix.get(prefix.size() - 1);
+
+            result = new CompositeName();
+            if (prefix.size() > 1) {
+                result.addAll(prefix.getPrefix(prefix.size() - 1));
+            }
+            try {
+                result.add(concatenateDNSNames(comp1, comp2));
+            } catch (InvalidNameException e) {
+                // comp1 or comp2 is not a valid DNS name
+                // components should be strongly separated
+                result.add(comp2);
+                result.add(comp1);
+            }
+            if (name.size() > 1) {
+                result.addAll(name.getSuffix(1));
+            }
+        }
+        else if (prefix instanceof CompositeName && name instanceof DNSName) {
+            // probably we need to glue together the last element of the prefix 
+            // and the name
+            String comp1 = name.toString();
+            String comp2 = prefix.get(prefix.size() - 1);
+
+            result = new CompositeName();
+            if (prefix.size() > 1) {
+                result.addAll(prefix.getPrefix(prefix.size() - 1));
+            }
+            try {
+                result.add(concatenateDNSNames(comp1, comp2));
+            } catch (InvalidNameException e) {
+                // comp2 is not a valid DNS name
+                // components should be strongly separated
+                result.add(comp2);
+                result.add(comp1);
+            }
+        }
+        else if (prefix instanceof DNSName && name instanceof CompositeName) {
+            // probably we need to glue together the prefix and
+            // the first element of the name
+            String comp1 = name.get(0);
+            String comp2 = prefix.toString();
+
+            result = new CompositeName();
+            try {
+                result.add(concatenateDNSNames(comp1, comp2));
+            } catch (InvalidNameException e) {
+                // comp2 is not a valid DNS name
+                // components should be strongly separated
+                result.add(comp2);
+                result.add(comp1);
+            }
+            if (name.size() > 1) {
+                result.addAll(name.getSuffix(1));
+            }
+        }
+        else if (prefix instanceof DNSName && name instanceof DNSName) {
+            DNSName rootZone = ProviderConstants.ROOT_ZONE_NAME_OBJ;
+            boolean prefixIsRoot = (prefix.compareTo(rootZone) == 0); 
+            boolean nameIsRoot = (name.compareTo(rootZone) == 0);
+            boolean nameStartsFromRoot =
+                name.get(0).equals(""); 
+
+            if (nameStartsFromRoot) {
+                throw new NamingException("Can't append an absolute " +
+                        "DNS name");
+            }
+            if (prefixIsRoot && nameIsRoot) {
+                result = (DNSName) rootZone.clone();
+            }
+            else if (!prefixIsRoot && nameIsRoot) {
+                throw new NamingException("Root domain should " +
+                        "be the rightmost one");
+            }
+            else {
+                result = new DNSName();
+                result.addAll(prefix);
+                result.addAll(name);
+            }
+        }
+        else {
+            throw new NamingException("Only instances of DNSName class " +
+                    "or CompositeName class are acceptable");
+        }
+        return result;
+    }
+
+    /**
+     * Concatenate two DNS name components into one DNS name
+     * @param comp1
+     * @param comp2
+     * @return concatenation of <code>comp1</code> and <code>comp2</code>
+     * @throws InvalidNameException if either <code>comp1</code> or
+     * <code>comp2</code> cannot be parsed
+     * @throws NamingException if DNS name syntax is violated during
+     *  composition of a new name from given components    
+     */
+    private String concatenateDNSNames(String comp1, String comp2)
+            throws NamingException
+    {
+        boolean comp1IsRoot = comp1.equals(".");
+        boolean comp2IsRoot = comp2.equals(".");
+        String composition = null;
+
+        nameParser.parse(comp1);
+        nameParser.parse(comp2);
+        if (comp1.endsWith(".")) {
+            throw new NamingException("Can't append an absolute DNS name");
+        }
+        if (comp1IsRoot && comp2IsRoot) {
+            composition = ".";
+        }
+        else if (!comp1IsRoot && comp2IsRoot) {
+            composition = comp1 + ".";
+        }
+        else if (comp1IsRoot && !comp2IsRoot) {
+            throw new NamingException("Root domain should " +
+                    "be the rightmost one");
+        }
+        else {
+            composition = comp1 + "."  + comp2;
+        }
+        return composition;
+    }
+
+    /**
+     * Constructs the clone of this DNS context.
+     * @see Object#clone()
+     */
+    public Object clone() {
+        return new DNSContext(this, contextName);
+    }
+    
+    /**
+     * Checks if the given object is equal to the current context. It will
+     * return <code>true</code> if and only if the specified object is an 
+     * instance of <code>DNSContext</code> class and has the same domain name.
+     * @param obj an object to compare with
+     * @return <code>true</code> if given object is equal to this one;
+     *  <code>false</code> otherwise
+     */
+    public boolean equals(Object obj) {
+        if (obj != null && obj instanceof DNSContext &&
+                contextName.equals(((DNSContext) obj).contextName)) {
+            return true;
+        }
+        return false;
+    }
+    
+    /**
+     * @param name composite name to process 
+     * @return root context of the namespace to that the target object belongs
+     *   and the name relative to this root context 
+     */
+    private ContextNamePair getTargetNamespaceContextNamePair(Name cmpName)
+            throws NamingException
+    {
+        CompositeName nameToLookFor;
+        String remainingName;
+        Object obj;
+        
+        if (cmpName == null || !(cmpName instanceof CompositeName) ||
+                cmpName.size() < 2)
+        {
+            throw new IllegalArgumentException();
+        }
+        remainingName = cmpName.get(cmpName.size() - 1);
+        nameToLookFor = (CompositeName) cmpName.getPrefix(cmpName.size() - 1);
+        nameToLookFor.add("");
+        obj = lookup(nameToLookFor);
+        return new ContextNamePair(obj, remainingName);
+    }
+    
+    static class ContextNamePair {
+        ContextNamePair(Object context, String name) {
+            this.context = context;
+            this.name = name;
+        }
+        
+        Object context;
+        String name;
+    }
+}

Propchange: incubator/harmony/enhanced/classlib/trunk/modules/jndi/src/main/java/org/apache/harmony/jndi/provider/dns/DNSContext.java
------------------------------------------------------------------------------
    svn:eol-style = native