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

  $Archive: /njcl_v2/src/com/novell/service/file/nw/naming/FSEnvironment.java $
  $Revision: 21 $
  $Modtime: 2/02/00 9:39a $
 
  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.file.nw.naming;

import java.util.Hashtable;
import java.io.Serializable;

import com.novell.utility.naming.Environment;

import com.novell.service.session.Session;
import com.novell.service.session.SessionException;
import com.novell.service.session.SessionEnv;
import com.novell.service.session.SessionAttrs;
import com.novell.service.session.SessionManager;
import com.novell.service.session.SessionManagerFactory;
import com.novell.service.jncpv2.net.NetService;
import com.novell.service.session.xplat.CallsService;

import javax.naming.NamingException;
import javax.naming.AuthenticationException;

/**
 * Defines the environment names of File System specific
 * configuration information.
 *
 * @see com.novell.utility.naming.Environment
 */
public class FSEnvironment 
   extends Environment
   implements Cloneable, Serializable
{
  /**
    * Environment property describing if reference support is enabled.
    *
    * <p>(SUPPORT_REFERENCES = "com.novell.service.file.supportReferences")</p>
   */
   public final static String SUPPORT_REFERENCES =
         "com.novell.service.file.supportReferences";

  /**
    * Environment property containing the current name space.
    *
    * <p>(DEFAULT_NAME_SPACE = "com.novell.service.file.defaultNameSpace")</p>
   */
   public final static String DEFAULT_NAME_SPACE =
         "com.novell.service.file.defaultNameSpace";

  /**
    * Environment property containing the filter currently used to
    * filter the list results.
    *
    * <p>(LIST_FILTER = "com.novell.service.file.listFilter")</p>
   */
   public final static String LIST_FILTER =
         "com.novell.service.file.listFilter";

   /**
    * @deprecated
    * Environment property containing the server name.
    *
    * <p>(SERVER_NAME = "com.novell.service.file.serverName")</p>
    */
   public final static String SERVER_NAME = "com.novell.service.file.serverName";

   /**
    * @deprecated
    * Environment property containing the path.
    *
    * <p>(PATH = "com.novell.service.file.path")</p>
    */
   public final static String PATH = "com.novell.service.file.path";

   private boolean sessionIsNDSHasBeenSet = false;

   private boolean sessionIsNDS;
   private CallsService callsService = null;
   private NetService netService = null;
   private String serverName;
   private String volumeName = null;
   private String nameSpace = null;
   private String fullNodeName;
   private String fullUrlName;

   private boolean supportReferences;  // default set in updateEnv...()
   private String listFilter;          // default set in updateEnv...()

/* *************************************************************************
   Constructors
***************************************************************************/

   /** @internal
    *
    */
   public FSEnvironment(FSEnvironment environment)
      throws NamingException
   {
      super (environment);

      this.sessionIsNDSHasBeenSet = environment.sessionIsNDSHasBeenSet();
      this.sessionIsNDS = environment.sessionIsNDS();
      this.callsService = environment.getCallsService();
      this.netService = environment.getNetService();
      this.serverName = environment.getServerName();
      this.volumeName = environment.getVolumeName();
      this.nameSpace = environment.getNameSpace();

      this.supportReferences = environment.getSupportReferences();
      this.listFilter = environment.getListFilter();
   }

   /** @internal
    *
    */
   public FSEnvironment(Hashtable environment, String serverName)
      throws NamingException
   {
      super (environment);

      this.serverName = serverName;

      updateEnvironment(environment);
   }

   /** @internal
    *
    */
   public FSEnvironment(Environment environment, String serverName)
      throws NamingException
   {
      super (environment);

      this.serverName = serverName;

      updateEnvironment(environment.getEnvironment(false));
   }

   /** @internal
    *
    */
   public Object clone()
   {
      FSEnvironment environment = (FSEnvironment) super.clone();

      environment.sessionIsNDSHasBeenSet = sessionIsNDSHasBeenSet;
      environment.sessionIsNDS = sessionIsNDS;
      environment.callsService = callsService;
      environment.netService = netService;
      environment.serverName = serverName;
      environment.volumeName = volumeName;
      environment.nameSpace = nameSpace;
      environment.supportReferences = supportReferences;

      return environment;
   }

  /** @internal
   *
   * Adds a property name and property value to the environment
   * properties.
   *
   * @param propName The name of the property to add to the environment.
   * @param propVal  The property value to add to the environment.
   *
   * @return An Object containing the property name and value.
   *
   * @exception NamingException 
   */
   public Object addToEnvironment (
         String propName,
         Object propVal)
      throws NamingException
   {
      Object obj = super.addToEnvironment(propName, propVal);

      updateEnvironment(environment);

      return (obj);
   }

  /** @internal
   *
   * Removes a property name from the environment
   * properties.
   *
   * @param propName The name of the property to remove from the environment.
   *
   * @return An Object containing the property name removed. 
   *
   * @exception NamingException 
   */
   public Object removeFromEnvironment (
         String propName)
      throws NamingException
   {
      Object obj = super.removeFromEnvironment(propName);

      updateEnvironment(environment);

      return (obj);
   }

/* *************************************************************************
   Accessors
***************************************************************************/

   /** @internal
    *
    */
   public Session getSession()
      throws NamingException
   {
      try
      {
         if (session == null)
         {
            Object obj = environment.get(Environment.SESSION_OBJECT);

            if (obj != null)
            {
               Session s = (Session) obj;
               SessionAttrs attrs = s.getAttributes(new String[] {
                     Session.DOMAIN_NAME_ATTR_ID,
                     Session.SESSION_TYPE_ATTR_ID });

               if (attrs.getValue(Session.DOMAIN_NAME_ATTR_ID).
                     equals(serverName.toUpperCase()) &&
                     attrs.getValue(Session.SESSION_TYPE_ATTR_ID).
                     equals("SERVER"))
               {
                  session = s;

                  return (session);
               }

            }

            SessionManager sm = (SessionManager)environment.get(
               com.novell.utility.naming.Environment.SESSION_MANAGER_OBJECT);
            if(sm == null)
            {
               SessionEnv env = new SessionEnv();
               env.put(SessionEnv.INITIAL_SESSION_FACTORY,
                  "com.novell.service.session.nds.NDSInitialSessionFactory:" +
                  "com.novell.service.session.bindery.BinderyInitialSessionFactory");
               sm = SessionManagerFactory.getSessionManager(env);
               environment.put(com.novell.utility.naming.Environment.SESSION_MANAGER_OBJECT, sm);
            }

            session = sm.getSessionTop(serverName);
            environment.put(Environment.SESSION_OBJECT, session);
         }
         return session;
      }
      catch (SessionException e)
      {
         NamingException ne = new AuthenticationException ();

         ne.setRootCause (e);
         throw (ne);
      }
   }

   /** @internal
    *
    */
   public boolean sessionIsNDS()
      throws NamingException
   {
      if (sessionIsNDSHasBeenSet)
         return sessionIsNDS;

      if (session == null)
         getSession();

      try
      {
         String provider = null;
         SessionAttrs attr = session.getAttributes(
                                 new String[]{session.PROVIDER_NAME_ATTR_ID});
         provider = (String) attr.getValue(session.PROVIDER_NAME_ATTR_ID);

         sessionIsNDS = false;
         if (provider.equals("NDS"))
            sessionIsNDS = true;

         sessionIsNDSHasBeenSet = true;
         return sessionIsNDS;
      }
      catch (SessionException e)
      {
         NamingException ne = new AuthenticationException ();

         ne.setRootCause (e);
         throw (ne);
      }
   }

   /** @internal
    *
    */
   public CallsService getCallsService()
      throws NamingException
   {
      if (callsService != null)
         return callsService;

      callsService = (CallsService) getService(CallsService.KEY);
      return callsService;
   }

   /** @internal
    *
    */
   public NetService getNetService()
      throws NamingException
   {
      if (!sessionIsNDS())
         return null;


      if (netService != null)
         return netService;

      netService = (NetService) getService(NetService.KEY);
      return netService;
   }

   /** @internal
    *
    */
   public String getServerName()
   {
      return serverName;
   }

   /** @internal
    *
    */
   public String getVolumeName()
   {
      return volumeName;
   }

   /** @internal
    *
    */
   public String getNameSpace()
   {
      return nameSpace;
   }

   /** @internal
    *
    */
   public String getFullNodeName()
   {
      return fullNodeName;
   }

   /** @internal
    *
    */
   public String getFullUrlName()
   {
      return fullUrlName;
   }

   /** @internal
    *
    */
   public String getDefaultNameSpace()
   {
      Object obj = environment.get(DEFAULT_NAME_SPACE);

      if (obj instanceof String)
         return ((String) obj);
      else
         return (null);
   }

   /** @internal
    *
    */
   public boolean getSupportReferences()
   {
      return (supportReferences);
   }

   /** @internal
    *
    */
   public String getListFilter()
   {
      return (listFilter);
   }

   /** @internal
    *
    */
   FSEnvironment setNSandVolume(String nameSpace, String volumeName)
   {
      /*
         FileSystemInitialDirContext is the only class that should ever
         call this method, this DirContext might do a first lookup with 
         sys+dos, and then do a subsequent lookup with sys+long in which
         case we need to clone the environment
      */

      // has never been set before, don't need to clone it
      if (this.nameSpace == null)
      {
         this.nameSpace = nameSpace;
         this.volumeName = volumeName;
         return this;
      }

      // if it is the same as a previous lookup, don't need to clone it
      if (this.nameSpace.equals(nameSpace) && 
          this.volumeName.equals(volumeName))
      {
         return this;      
      }

      // else we need to clone and set
      FSEnvironment env = (FSEnvironment)clone();
      env.nameSpace = nameSpace;
      env.volumeName = volumeName;
      return env;
   }

   /** @internal
    *
    */
   void setFullNames(String fullNodeName, String fullUrlName)
   {
      this.fullNodeName = fullNodeName;
      this.fullUrlName = fullUrlName;
   }

   private boolean sessionIsNDSHasBeenSet()
   {
      return sessionIsNDSHasBeenSet;
   }

   private void updateEnvironment(Hashtable env)
   {
      Object param;

      param = env.get(SUPPORT_REFERENCES);
      if (param instanceof String)
      {
         if ("true".equalsIgnoreCase((String) param))
            supportReferences = true;
         else
            supportReferences = false;
      }
      else
         supportReferences = true;  // default true

      param = env.get(LIST_FILTER);
      if (param instanceof String)
         listFilter = (String) param;
      else
         listFilter = "*";          // default '*'
   }
}   
