/* **************************************************************************

  $Archive: /njcl_v2/src/com/novell/service/ncpext/NCPExtensionInitialDirContext.java $
  $Revision: 14 $
  $Modtime: 1/28/00 11:49a $

  Copyright (c) 1998 Novell, Inc.  All Rights Reserved.

  THIS WORK IS  SUBJECT  TO  U.S.  AND  INTERNATIONAL  COPYRIGHT  LAWS  AND
  TREATIES.   NO  PART  OF  THIS  WORK MAY BE  USED,  PRACTICED,  PERFORMED
  COPIED, DISTRIBUTED, REVISED, MODIFIED, TRANSLATED,  ABRIDGED, CONDENSED,
  EXPANDED,  COLLECTED,  COMPILED,  LINKED,  RECAST, TRANSFORMED OR ADAPTED
  WITHOUT THE PRIOR WRITTEN CONSENT OF NOVELL, INC. ANY USE OR EXPLOITATION
  OF THIS WORK WITHOUT AUTHORIZATION COULD SUBJECT THE PERPETRATOR TO
  CRIMINAL AND CIVIL LIABILITY.

****************************************************************************/

package com.novell.service.ncpext;


import java.util.*;

import javax.naming.*;
import javax.naming.directory.*;
import javax.naming.spi.*;

import com.sun.jndi.toolkit.ctx.*;

import com.novell.service.jncp.*;

import com.novell.service.session.*;
import com.novell.service.session.xplat.*;

import com.novell.utility.naming.*;
//import com.novell.utility.naming.directory.Environment;


/** @internal
* Root of NCPExtension Name Space.
* <p> Has bindings to all NCPExtensions on server
*/
public class NCPExtensionInitialDirContext
extends ComponentDirContext
   implements Referenceable
{
   private FlatNameParser parser;
   private Hashtable environment;
   private Session session;
   private String serverName;

   /**
    * Properties contain the server name
    */
   protected NCPExtensionInitialDirContext(
         Hashtable h)
      throws SessionException, java.rmi.RemoteException
   {
      environment = h;
      session = (Session)h.get(Environment.SESSION_OBJECT);
      serverName = session.getDomainName();
   }


   // ******************** Context Interface ********************

   /** @internal
    *
    */
   public String getNameInNamespace ()
      throws NamingException
   {
      return ("[Root]");
   }

   protected Object c_lookup(
         Name name,
         Continuation cont)
      throws NamingException
   {
      if(name.isEmpty())
      {
         cont.setSuccess();
         return this;
      }

      try
      {
         environment.put(NCPExtensionStrings.NCPEXT_NAME, name.toString());
         Object obj = NamingManager.getObjectInstance(
            new ReferenceFactoryImpl().createReference(environment),
            null,
            null,
            environment); //ObjectFactory will make clone() of environment
         if(obj==null)
            throw new NameNotFoundException();
         cont.setSuccess();
         return obj;
      }
      catch(Exception e)
      {
         cont.setError(this, name);
         NameNotFoundException ex = new NameNotFoundException();
         ex.setRootCause(e);
         throw cont.fillInException(ex);
      }
   }

   protected Object c_lookupLink(
         Name name,
         Continuation cont)
   	throws NamingException
	{
      return c_lookup(name, cont);
   }

   protected NamingEnumeration c_list(
         Name name,
         Continuation cont)
      throws NamingException
   {
      if(name.isEmpty())
      {
         cont.setSuccess();
         return new NCPExtensionInitialNameClassEnumerator(session);
      }
      return (NamingEnumeration)resolveNext(name, cont);
   }

   protected NamingEnumeration c_listBindings(
         Name name,
         Continuation cont)
      throws NamingException
   {
      if(name.isEmpty())
      {
         cont.setSuccess();
         return new NCPExtensionInitialBindingEnumerator(session, environment);
      }
      return (NamingEnumeration)resolveNext(name, cont);
   }

   protected void c_bind(
         Name name,
         Object obj,
         Continuation cont)
      throws NamingException
   {
      notSupported(name, cont);
   }

   protected void c_rebind(
         Name name,
         Object obj,
         Continuation cont)
      throws NamingException
   {
      notSupported(name, cont);
   }

   protected void c_unbind(
         Name name,
         Continuation cont)
      throws NamingException
   {
      notSupported(name, cont);
   }

   protected void c_rename(
         Name oldName,
         Name newName,
         Continuation cont)
      throws NamingException
   {
      notSupported(oldName, cont);
   }

   protected void c_destroySubcontext(
         Name name,
         Continuation cont)
      throws NamingException
   {
      notSupported(name, cont);
   }

   protected Context c_createSubcontext(
         Name name,
         Continuation cont)
      throws NamingException
   {
      return (Context)notSupported(name, cont);
   }

   /**
   * Retrieves FlatNameParser
   */
   protected NameParser c_getNameParser(
         Name name,
         Continuation cont)
      throws NamingException
   {
      if(name.isEmpty())
      {
         if(null == parser)
            parser = new FlatNameParser("ncpext+" + serverName);
         return parser;
      }
      return (NameParser)resolveNext(name, cont);
   }

	public Object addToEnvironment(
   	   String name,
   	   Object value)
   	throws NamingException
	{
      return environment.put(name, value);
	}

	public Object removeFromEnvironment(
   	   String name)
   	throws NamingException
	{
      return environment.remove(name);
	}

	public Hashtable getEnvironment() throws NamingException
	{
	   return (Hashtable)environment.clone();
	}

   public void close() throws NamingException
   {
      //no action necessary
   }

   /***************************************************************
   * Dir methods
   ***************************************************************/
   protected DirContext c_createSubcontext(
         Name name,
         Attributes attrs,
         Continuation cont)
      throws NamingException
   {
      return (DirContext)notSupported(name, cont);
   }

   protected Attributes c_getAttributes(
         Name name,
         String[] attrIds,
         Continuation cont)
      throws NamingException
   {
      if(name.isEmpty())
      {
         return new BasicAttributes(); //No Attributes
      }
      else
      {
         return (Attributes)resolveNext(name, cont);
      }
   }

   protected void c_modifyAttributes(
         Name name,
         int mod_op,
         Attributes attrs,
         Continuation cont)
      throws NamingException
   {
      if(name.isEmpty())
      {
         notSupported(name, cont);
      }
      else
      {
         resolveNext(name, cont);
      }
   }

   protected void c_modifyAttributes(
         Name name,
         ModificationItem[] mods,
         Continuation cont)
      throws NamingException
   {
      if(name.isEmpty())
      {
         notSupported(name, cont);
      }
      else
      {
         resolveNext(name, cont);
      }
   }

   protected void c_bind(
         Name name,
         Object obj,
         Attributes attrs,
         Continuation cont)
      throws NamingException
   {
      notSupported(name, cont);
   }

   protected void c_rebind(
         Name name,
         Object obj,
         Attributes attrs,
         Continuation cont)
      throws NamingException
   {
      notSupported(name, cont);
   }

   protected NamingEnumeration c_search(
         Name name,
         Attributes matchingAttributes,
         String[] attributesToReturn,
         Continuation cont)
      throws NamingException
   {
      if(name.isEmpty())
      {
         return (NamingEnumeration)notSupported(name, cont);
      }
      else
      {
         return (NamingEnumeration)resolveNext(name, cont);
      }
   }

   protected NamingEnumeration c_search(
         Name name,
         String filterExpr,
         Object[] filterArgs,
         SearchControls cons,
         Continuation cont)
      throws NamingException
   {
      if(name.isEmpty())
      {
         return (NamingEnumeration)notSupported(name, cont);
      }
      else
      {
         return (NamingEnumeration)resolveNext(name, cont);
      }
   }

   protected NamingEnumeration c_search(
         Name name,
         String filter,
         SearchControls cons,
         Continuation cont)
      throws NamingException
   {
      if(name.isEmpty())
      {
         return (NamingEnumeration)notSupported(name, cont);
      }
      else
      {
         return (NamingEnumeration)resolveNext(name, cont);
      }
   }

   protected DirContext c_getSchema(
         Name name,
         Continuation cont)
      throws NamingException
   {
      if(name.isEmpty())
      {
         return (DirContext)notSupported(name, cont);
      }
      else
      {
         return (DirContext)resolveNext(name, cont);
      }
   }

   protected DirContext c_getSchemaClassDefinition(
         Name name,
         Continuation cont)
      throws NamingException
   {
      if(name.isEmpty())
      {
         return (DirContext)notSupported(name, cont);
      }
      else
      {
         return (DirContext)resolveNext(name, cont);
      }
   }

   /**
    * Construct a Reference from yourself
    * <p> Uses Environment.SERVICE_HOST from environment
    */
   public Reference getReference()
   {
      try
      {
         //if NCPExtensionStrings.NCPEXT_NAME exists, wrong reference will be created.
         environment.remove(NCPExtensionStrings.NCPEXT_NAME);
         return new ReferenceFactoryImpl().createReference(environment);
      }
      catch(NamingException e)
      {
         return null;
      }
   }

	/**
   * Common code for resoving a non-empty name
   */
	private Object resolveNext(
	      Name n,
	      Continuation c)
	   throws NamingException
	{
      Object obj = c_lookup(n, c);
      if (obj != null)
         c.setContinue(obj, n, this);
      return null;
   }

   /**
   * Common code for setting up and throwing OperationNotSupported Exception
   */
   private Object notSupported(
         Name n,
         Continuation c)
      throws NamingException
   {
      c.setError(this, n);
      throw c.fillInException(new OperationNotSupportedException());
   }
};

/**
 ********************************************************************
 *  Enumerates the NCPExtensions on this server.
 */
class NCPExtensionInitialBindingEnumerator implements NamingEnumeration
{
   private NCPExtensionNamesEnumerator extensions;
   private Hashtable env;

   /**
    * Uses NCPExtensionNamesEnumerator class to Enumerate
    */
   public NCPExtensionInitialBindingEnumerator(
         Session session,
         Hashtable h)
   {
      extensions = new NCPExtensionNamesEnumerator(session);
      env = h;
   }

   public boolean hasMoreElements()
   {
      return extensions.hasMoreElements();
   }

   public boolean hasMore()
   {
      return hasMoreElements();
   }

   public Object nextElement()
   {
      try
      {
         return next();
      }
      catch(NamingException e)
      {
         throw new NoSuchElementException(e.getMessage());
      }
   }

   public Object next()
      throws NamingException
   {
      try
      {
         String extName = (String)extensions.nextElement();
         env.put(NCPExtensionStrings.NCPEXT_NAME, extName);
         Object extObj = NamingManager.getObjectInstance(
            new ReferenceFactoryImpl().createReference(env),
            null,
            null,
            env); //ObjectFactory will make clone() of environment
         if(extObj==null)
            throw new NamingException();
         return new Binding(extName, extObj);
      }
      catch(Exception e)
      {
         NamingException ex = new NamingException();
         ex.setRootCause(e);
         throw ex;
      }
   }

   /**
    *
    */
   public void close() throws NamingException
   {
      //no action necessary
   }
}


/**
 ********************************************************************
 *  Enumerates the NCPExtensions on this server.
 */
class NCPExtensionInitialNameClassEnumerator implements NamingEnumeration
{
   private NCPExtensionNamesEnumerator extensions;

   /**
    * Uses NCPExtensionNamesEnumerator class to Enumerate
    */
   public NCPExtensionInitialNameClassEnumerator(
         Session session
   )
   {
      extensions = new NCPExtensionNamesEnumerator(session);
   }

   public boolean hasMoreElements()
   {
      return extensions.hasMoreElements();
   }

   public boolean hasMore()
   {
      return hasMoreElements();
   }

   public Object nextElement()
   {
      try
      {
         return next();
      }
      catch(NamingException e)
      {
         throw new NoSuchElementException(e.getMessage());
      }
   }

   public Object next()
      throws NamingException
   {
      return new NameClassPair(
         (String)extensions.nextElement(),
         NCPExtensionStrings.EXTENSION_CLASS);
   }

   /**
    *
    */
   public void close() throws NamingException
   {
      //no action necessary
   }

}


/**
 ********************************************************************
 * Enumerates extension names using native call NWScanNCPExtensions
 */
class NCPExtensionNamesEnumerator implements Enumeration
{
   private CallsService service;
   private NCPExtensionInfoImpl oldInfo;
   private boolean more;

   public NCPExtensionNamesEnumerator(
         Session session)
   {
      try
      {
         service = (CallsService)session.getService(
            CallsService.KEY);
         oldInfo = new NCPExtensionInfoImpl(-1);
         more = true;
         scanObject();
      }
      catch(Exception e)
      {
         more = false;
         throw NSIExceptionBuilder.build(e);
      }
   }

   public boolean hasMoreElements
   (
   )
   {
      return more;
   }

   public Object nextElement
   (
   )
   {
      if(!more)
         throw new NoSuchElementException();
      String name = oldInfo.getExtensionName();
      scanObject();
      return name;
   }

   private void scanObject()
   {
      try
      {
         service.scanNCPExtensions(oldInfo);
      }
      catch(NSIException ne)
      {
         more=false; //Expecting an exception when no more elements
      }
      catch(Exception e)
      {
         more=false;
         throw NSIExceptionBuilder.build(e);
      }
   }
}
