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

  $Archive: /njcl_v2rmi/src/com/novell/service/ncpext/NCPExtensionDirContext.java $
  $Revision: 15 $
  $Modtime: 1/05/01 3:59p $
 
  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 com.sun.jndi.toolkit.ctx.*;

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

import com.novell.service.jncp.*;
import com.novell.service.jncpv2r.cal.CalJNI;

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


/**
 * Represents an NCPExtension loaded on a NetWare server.
 * An NCPExtensionDirContext implements the NCPExtension interface
 * and has one attribute, NCPExtensionInfo, with a single value that
 * is an instance of NCPExtensionInfoImpl with attribute ID equal to
 * the static string value in NCPExtensionStrings.NCPEXTENSION_ATTRIBUTE_ID.
 *
 * @see NCPExtension
 * @see NCPExtensionInfo
 * @see NCPExtensionInfoImpl
 */
public class NCPExtensionDirContext
   extends ComponentDirContext
   implements NCPExtension, Referenceable
{
   private NameParser parser;
   private Hashtable environment;
   private Session session;
   private CallsService service;
   private String serverName;
   private NCPExtensionInfoImpl attr;
   private String extensionName;

   /**
    * @internal
    *
    * Constructs object using the NCPExtensionStrings.NCPEXT_NAME Property
    */
   protected NCPExtensionDirContext(
         Hashtable h)
      throws SessionException, java.rmi.RemoteException
   {
      environment = h;
      session = (Session)h.get(com.novell.utility.naming.Environment.SESSION_OBJECT);
      serverName = session.getDomainName();
      extensionName =
         (String)environment.get(NCPExtensionStrings.NCPEXT_NAME);

      attr = new NCPExtensionInfoImpl(extensionName);
      service = (CallsService) session.getService(
         CallsService.KEY);
      service.getNCPExtensionInfoByName(attr);
   }


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

   /** @internal
    *
    */
   public String getNameInNamespace ()
      throws NamingException
   {
      return (extensionName);
   }

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

      cont.setError(this, name);  // No bindings
      throw cont.fillInException(new NameNotFoundException());
   }

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

  /**
   * @internal
   *
   */
   protected NamingEnumeration c_list(
         Name name,
         Continuation cont)
      throws NamingException
   {
      if(name.isEmpty())
      {
         cont.setSuccess();
         return new NamingEnumerator();
      }
      return (NamingEnumeration)resolveNext(name, cont);
   }

  /**
   * @internal
   *
   */
   protected NamingEnumeration c_listBindings(
         Name name,
         Continuation cont)
      throws NamingException
   {
      if(name.isEmpty())
      {
         cont.setSuccess();
         return new NamingEnumerator();
      }
      return (NamingEnumeration)resolveNext(name, cont);
   }

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

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

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

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

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

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

  /**
   * @internal
   *
   * Retrieves the name parser for this name space.
   */
   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);
   }

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

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

  /**
   * @internal
   *
   */
	public Hashtable getEnvironment() throws NamingException
	{
	   return (Hashtable)environment.clone();
	}

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

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

  /**
   * @internal
   *
   */
   protected Attributes c_getAttributes(
         Name name,
         String[] attrIds,
         Continuation cont)
      throws NamingException
   {
      if(name.isEmpty())
      {
         Attributes attrSet = new NAttributes(true);
         if(attrIds == null)
            attrSet.put(attr.buildAttribute());
         else
         {
            for(int i = 0; i < attrIds.length; i++)
            {
               if(attrIds[i].equalsIgnoreCase(attr.getID()))
               {
                  attrSet.put(attr.buildAttribute());
               }
            }
         }
         cont.setSuccess();
         return attrSet;
      }
      else
      {
         return (Attributes)resolveNext(name, cont);
      }
   }

  /**
   * @internal
   *
   */
   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);
      }
   }

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

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

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

  /**
   * @internal
   *
   */
   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);
      }
   }

  /**
   * @internal
   *
   */
   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);
      }
   }

  /**
   * @internal
   *
   */
   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);
      }
   }

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

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

  /**
   * @internal
   *    
   * Construct a Reference from yourself.
   * uses Environment.SERVICE_HOST and NCPExtensionStrings.NCPEXT_NAME from environment
   */
   public Reference getReference()
   {
      try
      {
         return new ReferenceFactoryImpl().createReference(environment);
      }
      catch(NamingException e)
      {
         return null;
      }
   }

   // Implementation for methods in NCPExtension interface

  /**
   * Sends a request to an NCP Extension. Request data for the NCP
   * Extension must be packed into the request byte array. Any return
   * data will be contained in the return byte array.
   *
   * @param request        The byte array containing request data.
	* @param maxReplyLength The maximum number of bytes the user wants
   *                       returned.
   *
   * @return    A byte array containing reply data.
   *
   * @exception NSIException Standard NJCL exception for working on top
   *                         of Xplat libraries.
   */
   public byte[] send(
         byte[] request,
         int maxReplyLength)
      throws NSIException
   {
      try
      {
         if((maxReplyLength > 0xFFFF) || (maxReplyLength < 0))
            throw new IllegalArgumentException();
         short maxLen = (short)maxReplyLength;
         Object[] replyHolder = new Object[1];
         service.ncpExtensionRequest(attr.getExtensionID(), request,
            maxLen, replyHolder);
         return (byte[])replyHolder[0];
      }
      catch(Exception e)
      {
         throw NSIExceptionBuilder.build(e);
      }
   }

  /**
   * @internal
   *
   */
   public Properties setEnvironment(Properties p)
   {
      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());
   }

} /* NCPExtensionDirContext */


