package examples.cluster.ejb.account;

import java.io.Serializable;
import java.rmi.RemoteException;
import javax.ejb.*;

import weblogic.common.*;

/**
 * AccountBean is an EntityBean. This EJBean illustrates:
 * <ul>
 * <li> Container-managed JDBC persistence and transactions; 
 *      the code in this file never directly accesses the data storage.
 * <li> Application-defined exceptions.
 * </ul>
 *
 * @author Copyright (c) 1999-2000 by BEA Systems, Inc. All Rights Reserved.
 */
public class AccountBean implements EntityBean {
  final static boolean VERBOSE = true;
  final static int     SLEEP    = 3000; //time to sleep to give an 
                                        //opportunity to test failover

  // -----------------------------------------------------------------
  // private variables
  private EntityContext ctx;
  private transient String        serverName;

  // -----------------------------------------------------------------
  // public container managed variables
  public            String        accountId; // also the primary Key
  public            double        balance;
     
  // -----------------------------------------------------------------
  // EntityBean implementation
  
  /**
   * Returns the Primary Key identifying this EJBean.
   * 
   * @return                  String Identification
   */
  private String id() {
    return "" + System.identityHashCode(this) + ", PK = " + 
      (String) ((ctx == null) ? "nullctx" 
                 : ((ctx.getPrimaryKey() == null ?
                   "null" : ctx.getPrimaryKey().toString())));
  }

  /**
   * This method is required by the EJB Specification,
   * but is not used by this example.
   */
  public void ejbActivate() {
    if (VERBOSE)
      System.out.println("AccountBean.ejbActivate (" + id() + ")");
  }

  /**
   * This method is required by the EJB Specification,
   * but is not used by this example.
   */
  public void ejbPassivate() {
    if (VERBOSE)
      System.out.println("AccountBean.ejbPassivate (" + id() + ")");
  }

  /**
   * Sets the EntityContext and the server name for the EJBean.
   * 
   * @param ctx               EntityContext 
   */
  public void setEntityContext(EntityContext ctx) {
    if (VERBOSE)
      System.out.println("AccountBean.setEntityContext (" + id() + ")");
    this.ctx = ctx;
    this.serverName = getServerName();
  }

  /**
   * Unsets the EntityContext for the EJBean.
   * 
   */
  public void unsetEntityContext() {
    if (VERBOSE)
      System.out.println("AccountBean.unsetEntityContext (" + id() + ")");
    this.ctx = null;
  }

  /**
   * This method is required by the EJB Specification,
   * but is not used by this example.
   * 
   */
  public void ejbLoad() {
    if (VERBOSE)
      System.out.println("AccountBean.ejbLoad (" + id() +  ")");
  }

  /**
   * This method is required by the EJB Specification,
   * but is not used by this example.
   * 
   */
  public void ejbStore() {
    if (VERBOSE) {
      System.out.println("AccountBean.ejbStore (" + id() + "): failover test point");
      try {
        Thread.sleep(SLEEP);
      } catch (InterruptedException ie) {
      // do nothing
      }
    }
  }

  /**
   * This method is required by the EJB Specification,
   * but is not used by this example.
   * 
   * @exception               javax.ejb.RemoveException
   *                          if the EJBean does not allow removing the EJBean
   */
  public void ejbRemove() throws RemoveException {
    if (VERBOSE)
      System.out.println("AccountBean.ejbRemove (" + id() + ")");
  }

  /**
   * This method corresponds to the create method in the home interface
   * "AccountHome.java". 
   * The parameter sets of the two methods are identical.  When the client calls
   * <code>AccountHome.create()</code>, the container (which in WebLogic EJB is
   * also the home) allocates an instance of this EJBean and
   * calls <code>AccountBean.ejbCreate()</code>.
   * <p>
   * For container-managed persistence, <code>ejbCreate()</code> returns 
   * a void, unlike the case of bean-managed
   * persistence, where it returns a primary key.
   *
   * @param accountId         String Account ID
   * @param initialBalance    double Initial Balance
   * @exception               javax.ejb.CreateException
   *                          if there is a problem creating the bean
   */
  public AccountPK ejbCreate(String accountId, double initialBalance)
    throws CreateException
  {
    if (VERBOSE) 
      System.out.println("AccountBean.ejbCreate( id = " + System.identityHashCode(this) + ", PK = " +
                         accountId + ", " + "initial balance = $ '" + initialBalance + ")");

    this.accountId  = accountId;
    this.balance    = initialBalance;
    return null;
  }

  /**
   * This method is required by the EJB Specification,
   * but is not used by this example.
   *
   * @param accountId         String Account ID
   * @param initialBalance    double Initial Balance 
   */
  public void ejbPostCreate(String accountId, double initialBalance) {
    if (VERBOSE)
      System.out.println("AccountBean.ejbPostCreate (" + id() + ")");
  }

  // Application defined methods

  /**
   * Returns current balance.
   *
   * @return                  AccountResult 
   */
  public AccountResult balance() {
    if (VERBOSE) 
      System.out.println("AccountBean.balance (" + id() + ")");
    return new AccountResult(serverName, balance);
  }

  /**
   * Adds amount to balance.
   *
   * @param amount            double Amount
   * @return                  AccountResult 
   */
  public AccountResult deposit(double amount) {
    if (VERBOSE) 
      System.out.println("AccountBean.deposit ($" + amount + 
                         " into '" + accountId + "', " + id() + ")");
    balance += amount;
    return new AccountResult(serverName, balance);
  }

  /**
   * Subtracts amount from balance.
   *
   * @param amount            double Amount
   * @return                  AccountResult 
   * @exception               AccountException
   *                          if Amount &gt; Balance
   */
  public AccountResult withdraw(double amount)
       throws AccountException
  {
    if (VERBOSE) 
      System.out.println("AccountBean.withdraw ($" + amount + " from '" + accountId + 
                         "', " + id() + ")");
    if (amount > balance) {
      throw new AccountException("Request to withdraw $" + amount +
                                 " more than balance " + balance +
                                 " in account " + accountId);
    }
    balance -= amount;
    return new AccountResult(serverName, balance);
  }


  /**
   * Determines the weblogic.system.name of the server
   * the bean is instantiated on.
   *
   * @return                  String Server name (server that invocation ocurred on)
   */
  private String getServerName() {
    String toReturn = null;
    try {
      toReturn = T3Services.getT3Services().config().getProperty("weblogic.system.name");
      if (toReturn == null) {
        return "";
      } else {
        return toReturn;
      }
    }
    catch (T3Exception t3E) {
      return "";
    }
  }

}

