/***************************************************************************
 Copyright (c) 1999 Novell, Inc. All Rights Reserved.

 THIS WORK IS SUBJECT TO U.S. AND INTERNATIONAL COPYRIGHT LAWS AND TREATIES.
 USE AND REDISTRIBUTION OF THIS WORK IS SUBJECT TO THE LICENSE AGREEMENT
 ACCOMPANYING THE SOFTWARE DEVELOPMENT KIT (SDK) THAT CONTAINS THIS WORK.
 PURSUANT TO THE SDK LICENSE AGREEMENT, NOVELL HEREBY GRANTS TO DEVELOPER A
 ROYALTY-FREE, NON-EXCLUSIVE LICENSE TO INCLUDE NOVELL'S SAMPLE CODE IN ITS
 PRODUCT. NOVELL GRANTS DEVELOPER WORLDWIDE DISTRIBUTION RIGHTS TO MARKET,
 DISTRIBUTE, OR SELL NOVELL'S SAMPLE CODE AS A COMPONENT OF DEVELOPER'S
 PRODUCTS. NOVELL SHALL HAVE NO OBLIGATIONS TO DEVELOPER OR DEVELOPER'S
 CUSTOMERS WITH RESPECT TO THIS CODE.
****************************************************************************/
import java.util.*;
import javax.naming.*;
import javax.naming.directory.*;
import com.novell.service.session.*;
import com.novell.java.security.*;
import com.novell.service.server.*;
import com.novell.java.lang.*;
import com.novell.service.security.*;

/**
* Demonstrates the capability of multiple separate Sessions to the same domain. 
* This example shows how to create and authenticate multiple session to the same
* server and then use these separate session in JNDI operations.
*
* NOTE: Multi User capability is only available when run on a NetWare server.
* This sample will not work on a client machine.
*/
public class MultiUserSessionTest
{
   public static void main(String args[])
   {
      if(args.length != 4)
      {
         System.out.print("Usage: Java MultiUserSessionTest ServerName UserName ");
         System.out.println("Password Vol/Dir/File");
         System.out.println("Example: java SessionTest serv1 admin passw sys/java");
         System.exit(0);
      }

      try
      {
         String serverName = args[0];
         String userName = args[1];
         String password = args[2];

         //prepend "FileSystem" binding name to federate into File name space
         String fileName = "FileSystem/" + args[3];

         SessionManager sm1 = SessionManagerFactory.getPrivate(new SessionEnv());
         SessionManager sm2 = SessionManagerFactory.getPrivate(new SessionEnv());

         Session s1 = sm1.getSession(serverName);
         Session s2 = sm2.getSession(serverName);

         Identity ident = s1.createIdentity(userName);
         if(ident instanceof PasswordIdentityFactory)
         {
            //Dont use GUI to obtain password
            ident = (Identity)
               ((PasswordIdentityFactory)ident).getPasswordIdentityInstance();
            ((PasswordIdentity)ident).setPassword(new Password(password));
         }
         Authenticator.login(ident);

         DirContext ctx1 = getServerDirContext(sm1, serverName);
         DirContext ctx2 = getServerDirContext(sm2, serverName);

         //Should succeed. We have authenticated this session.
         ctx1 = (DirContext)ctx1.lookup(fileName);

         try
         {
            ctx2 = (DirContext)ctx2.lookup(fileName);
            throw new Exception("lookup(" + fileName +
               ") should have thrown an exception");
         }
         catch(NamingException e)
         {
            //Should fail - no rights
         }

         System.out.println("Successful");
      }
      catch(Exception e)
      {
         dumpException(e);
      }
   }

   /**
   * Shows how to use a SessionManger in creating a DirContext.
   */
   public static ServerDirContext getServerDirContext(SessionManager sm, String serverName) throws Exception
   {
      Hashtable hash = new Hashtable();
      hash.put(Context.INITIAL_CONTEXT_FACTORY, "com.novell.service.server.ServerInitialContextFactory");
      hash.put(Context.PROVIDER_URL, serverName);

      //This is the key piece - provide the SessionManager you want this provider to use.
      hash.put(com.novell.utility.naming.Environment.SESSION_MANAGER_OBJECT, sm);

      DirContext ctx1 = new InitialDirContext(hash);
      ServerDirContext ctx2 = (ServerDirContext)ctx1.lookup("");  //eliminate middle man - (InitialContext)
      return ctx2;
   }

   /**
    * This function recurses through exceptions with root causes printing the stack trace
    * and messages of each.
    */
   synchronized static public void dumpException(Throwable e)
   {
      System.out.flush();
      System.err.flush();
      System.out.println("Dumping Exception...");
      while(e != null)
      {
         e.printStackTrace();
         if (e instanceof HasRootCauses)
         {
            System.out.println("\nRoot causes...");
            Enumeration enum = ((HasRootCauses)e).getRootCauses();
            while (enum.hasMoreElements())
            {
               dumpException((Throwable)enum.nextElement());
            }
         }
         if (e instanceof HasRootCause)
            e = ((HasRootCause)e).getRootCause();
         else if (e instanceof NamingException)
            e = ((NamingException)e).getRootCause();
         else if(e instanceof java.rmi.RemoteException)
            e = ((java.rmi.RemoteException)e).detail;
         else
            e = null;
         if(e != null)
            System.out.println("Root cause...");
      }
      System.err.flush();
      System.out.flush();
   }
}
