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

  $Archive: /njcl_v2/src/com/novell/service/nds/naming/net/NetReplicaInfoEnumerator.java $
  $Revision: 4 $
  $Modtime: 1/28/00 12:42p $
 
  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.nds.naming.net;


import java.util.*;

import javax.naming.*;

import com.novell.service.jncp.*;
import com.novell.service.nds.NdsTimestamp;
import com.novell.java.lang.IntegerBuffer;

import com.novell.service.session.SessionException;
import com.novell.service.jncpv2.net.*;


/** @internal
 *
 */
public class NetReplicaInfoEnumerator implements Enumeration {

   private String serverName;
   private StringBuffer serverRead;
   private NetService service;

   private NetIterationHandle iterationHandle;
   private IntegerBuffer partCount;
   private NetBuffer partInfo;

   private boolean moreInfo;
   private boolean extInfo;

   /**
    * Constructs a NetReplicaInfoEnumerator.
    *
    * @param ndsContext     NDS context handle.
    * @param serverDN       NDS distinguished name in partial dot form.
    *
    * @exception NSIException
    */
   protected NetReplicaInfoEnumerator (
                       NetService service,
                       String serverDN)
       throws NSIException
   {
       /* save info needed later */
      this.service = service;
      this.serverName = serverDN;

      /* setup and initialize necessary working environment */
      this.iterationHandle = new NetIterationHandle(
                 service, NetJNI.DSV_READ);
      this.partInfo = new NetBuffer(service);

      this.partCount = new IntegerBuffer(0);
      this.moreInfo = true;

      /* setup branch info. We need this one here because */
      /* the SDKs prior to v13 do not support extended    */
      /* partition information such as PartitionBusy...   */
      IntegerBuffer   majorVersion = new IntegerBuffer(0);
      IntegerBuffer   minorVersion = new IntegerBuffer(0);
      IntegerBuffer   revisionLevel = new IntegerBuffer(0);
      IntegerBuffer   betaLevel = new IntegerBuffer(0);

      try
      {
         service.getNWNetVersion (
                     majorVersion,
                     minorVersion,
                     revisionLevel,
                     betaLevel);
      }
      catch (SessionException e)
      {
         NSIException ne = new NSIException ();

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

      this.extInfo = majorVersion.intValue() >= 5 &&
                     minorVersion.intValue() >= 2;
   }

   /** @internal
    * Read partition info from NDS server
    */
   private void getPartInfo()
       throws NSIException
   {
      /* if there is no more things to retrieve, do nothing */
      if (!this.moreInfo)
          return;

      /* read some info at a time */
      try
      {
         if (this.extInfo) {
            int dspFlags = NetJNI.DSP_REPLICA_STATE |
                           NetJNI.DSP_MODIFICATION_TIMESTAMP |
                           NetJNI.DSP_PARTITION_DN |
                           NetJNI.DSP_REPLICA_TYPE |
                           NetJNI.DSP_PARTITION_BUSY;

            service.listPartitionsExtInfo (
                                   this.iterationHandle, this.serverName,
                                   dspFlags, this.partInfo.getHandle());
         }
         else
            service.listPartitions(
                              this.iterationHandle, this.serverName,
                              this.partInfo.getHandle());

         serverRead = new StringBuffer();

         /* this one should be called all the time to retrieve */
         /* how many pieces of info we have got from this NDS */
         service.getServerName(
                           this.partInfo.getHandle(),
                           serverRead, this.partCount);

         /* set up iteration info for next time */
         this.moreInfo = this.iterationHandle.moreIterations();
      }
      catch (SessionException e)
      {
         NSIException ne = new NSIException ();

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

   }

    /**
    * Tests if this enumeration contains more elements.
    */
   public boolean hasMoreElements()
   {
      /* if no more elements left in the cache, try get some */
      try {
         if (this.partCount.intValue() == 0)
            this.getPartInfo();
      }
      catch (NSIException e) {
         this.partCount.setValue(0);
      }

      return this.partCount.intValue() != 0;
   }

   /**
    * Returns the next element of this enumeration.
    */
   public Object nextElement ()
      throws NoSuchElementException
   {
      /* if no more elements left in the cache, try get some */
      try {
         if (this.partCount.intValue() == 0)
            this.getPartInfo();
      }
      catch (NSIException e) {
         throw new NoSuchElementException(e.getMessage());
      }

      /* if nothing to enumerate, throw exception */
      if (this.partCount.intValue() == 0)
          throw new NoSuchElementException();

      /* read repicaType, replicaState, partitionName,    */
      /* partitionBusy, modificationTimestamp.            */
      IntegerBuffer replicaType = null;
      IntegerBuffer replicaState = null;
      StringBuffer partitionName = null;
      IntegerBuffer partitionBusy = null;
      NdsTimestamp modificationTime = null;

      int result;

      try
      {

         /* branch on different versions of Client 32 SDKs */
         if (extInfo) {
            IntegerBuffer   infoPtr = new IntegerBuffer(0);
            IntegerBuffer   infoPtrEnd = new IntegerBuffer(0);

            /* read extended info */
            service.getPartitionExtInfoPtr(
                                                 this.partInfo.getHandle(),
                                                   infoPtr, infoPtrEnd);

            NetPartitionExtInfo partExt = new NetPartitionExtInfo();

            /* partition name */
            service.getPartitionExtInfo(
                                        infoPtr.intValue(),
                                        infoPtrEnd.intValue(),
                                        NetJNI.DSP_PARTITION_DN,
                                        null, partExt);

// bberg - which one ?
//            partitionName = (String)partExt.get();
            partitionName = new StringBuffer((String)partExt.getValue());

            /* replica type */
            service.getPartitionExtInfo(
                                        infoPtr.intValue(),
                                        infoPtrEnd.intValue(),
                                        NetJNI.DSP_REPLICA_TYPE,
                                        null, partExt);

            replicaType = (IntegerBuffer)partExt.getValue();

            /* replica state */
            service.getPartitionExtInfo(
                                        infoPtr.intValue(),
                                        infoPtrEnd.intValue(),
                                        NetJNI.DSP_REPLICA_STATE,
                                        null, partExt);

            replicaState = (IntegerBuffer)partExt.getValue();

            /* partition busy */
            service.getPartitionExtInfo(
                                        infoPtr.intValue(),
                                        infoPtrEnd.intValue(),
                                        NetJNI.DSP_PARTITION_BUSY,
                                        null, partExt);

            partitionBusy = (IntegerBuffer)partExt.getValue();

            service.getPartitionExtInfo(
                                        infoPtr.intValue(),
                                        infoPtrEnd.intValue(),
                                        NetJNI.DSP_MODIFICATION_TIMESTAMP,
                                        null, partExt);

            modificationTime = (NdsTimestamp) partExt.getValue();

         }
         else
         {
            replicaType = new IntegerBuffer(0);
            partitionName = new StringBuffer();

            /* read standard info */
            service.getPartitionInfo(
                                            this.partInfo.getHandle(),
                                            partitionName,
                                            replicaType);

            replicaState = new IntegerBuffer((replicaType.intValue() & 0xFFFF0000) >> 16) ;
            replicaType.setValue(replicaType.intValue() & 0x0000FFFF);
            partitionBusy = new IntegerBuffer(0);
            modificationTime = new NdsTimestamp(0, 0, 0);
         }

         /* decrease the counter */
         this.partCount.setValue(this.partCount.intValue() - 1);

         /* return the object to clients */
         return new NetReplicaInfo(this.serverName,
                            this.serverRead.toString (),
                            replicaType.intValue(),
                            replicaState.intValue(),
                            partitionName.toString(),
                            partitionBusy.intValue() != 0,
                            modificationTime);
      }
      catch (NSIException e)
      {
         throw (new NoSuchElementException (e.getMessage ()));
      }
      catch (SessionException e)
      {
         throw (new NoSuchElementException (e.getMessage ()));
      }

   } /* nextElement () */

} /* NetReplicaInfoEnumerator */

