使用java 动态代理去掉代码中的bad smell。

在FSI系统中当一个calculator开始进行计算的时候需要把他的status变成busy,而当计算结束(成功或抛出异常)需要把这个calculator的status变成idle。下面是这个FSI系统对这个calculator的实现。

package com.fsillc.remote.server;

import java.net.InetAddress;
import java.net.UnknownHostException;
import java.rmi.RemoteException;
import java.rmi.server.UnicastRemoteObject;
import java.util.GregorianCalendar;

import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.apache.log4j.Category;

import com.fsillc.calculatordata.EspCMOCallOptionSpecStruct;
import com.fsillc.calculatordata.EspIROptionDescStruct;
import com.fsillc.calculatordata.EspIRTreeParamsStruct;
import com.fsillc.calculatordata.EspMBSCalcInputStruct;
import com.fsillc.calculatordata.EspMBSIOPOStripStruct;
import com.fsillc.calculatordata.EspMBSValuationStruct;
import com.fsillc.calculatordata.EspMarketVolatilityDataStruct;
import com.fsillc.calculatordata.EspSetOfCurvePointsStruct;
import com.fsillc.calculatordata.EspTreeSizeSpecStruct;
import com.fsillc.calculatordata.FixedIncomeSecurityDescription;
import com.fsillc.calculatordata.HowToFitPrepayMultiplersAndInitialGuess;
import com.fsillc.calculatordata.MBSCalculatorException;
import com.fsillc.calculatordata.MBSDollarRollStruct;
import com.fsillc.calculatordata.OptionaInputToCFGenerator;
import com.fsillc.calculatordata.OptionalModelManipulationData;
import com.fsillc.calculatordata.YieldCurveException;
import com.fsillc.constants.CFSIBondYieldType;
import com.fsillc.constants.CFSICouponFrequencyType;
import com.fsillc.constants.CFSIDataSource;
import com.fsillc.constants.CFSIDerivativeType;
import com.fsillc.constants.CFSIDiscounting;
import com.fsillc.constants.CFSIIndexType;
import com.fsillc.constants.CFSIMBSTypes;
import com.fsillc.constants.CFSIMortgageRateType;
import com.fsillc.constants.CFSIPrepaySpeedUnit;
import com.fsillc.dataclasses.CFSICashFlowMatrix;
import com.fsillc.dataclasses.CFSIDynamicMeasuresCashFlowMatrixManager;
import com.fsillc.dataclasses.CFSIPartialDurationCashFlowMatrixManager;
import com.fsillc.dataclasses.CFSITotalReturnCashFlowMatrixManager;
import com.fsillc.exceptions.InvalidDataPathException;
import com.fsillc.exceptions.SecurityNotFoundException;
import com.fsillc.interfaces.IFSIBondResults;
import com.fsillc.interfaces.IFSICMOCallOptionSpec;
import com.fsillc.interfaces.IFSICalculationOptions;
import com.fsillc.interfaces.IFSICorpBond;
import com.fsillc.interfaces.IFSIDerivatives;
import com.fsillc.interfaces.IFSIEuroDollarFuture;
import com.fsillc.interfaces.IFSIFixedIncomeSecurityDescription;
import com.fsillc.interfaces.IFSIFutureOption;
import com.fsillc.interfaces.IFSIInterestRateTreeParams;
import com.fsillc.interfaces.IFSIMBSDollarRoll;
import com.fsillc.interfaces.IFSIMBSPrepaymentHistory;
import com.fsillc.interfaces.IFSIMBSResults;
import com.fsillc.interfaces.IFSIMarketVolatility;
import com.fsillc.interfaces.IFSIMortgageBackedSecurity;
import com.fsillc.interfaces.IFSIMortgageCollateralDescription;
import com.fsillc.interfaces.IFSIObjectManager;
import com.fsillc.interfaces.IFSIOptionalModelManipulationData;
import com.fsillc.interfaces.IFSIPrepayLoanLevelDescription;
import com.fsillc.interfaces.IFSIPrepayModelMatrix;
import com.fsillc.interfaces.IFSISecurity;
import com.fsillc.interfaces.IFSISecurityDataSource;
import com.fsillc.interfaces.IFSISynthetic;
import com.fsillc.interfaces.IFSISysConfigParameters;
import com.fsillc.interfaces.IFSITotalReturnInput;
import com.fsillc.interfaces.IFSITotalReturnResults;
import com.fsillc.interfaces.IFSITreeSizeSpec;
import com.fsillc.interfaces.IFSIYieldCurves;
import com.fsillc.natif.release5.BondCalculator;
import com.fsillc.natif.release5.DerivativeCalculator;
import com.fsillc.natif.release5.GetMarketData;
import com.fsillc.natif.release5.MBSCalculator;
import com.fsillc.natif.release5.NewMBSCalculator;
import com.fsillc.natif.release5.SecurityCalculator;
import com.fsillc.natif.release5.MBSCalculator.NoDLLException;
import com.fsillc.remote.interfaces.Calculator;
import com.fsillc.remote.interfaces.FSIHeartBeat;
import com.fsillc.remote.interfaces.FSINamingContext;
import com.fsillc.remote.util.CalcStatus;
import com.fsillc.remote.util.JNDIHelper;
import com.fsillc.securities.CFSICorpBond;
import com.fsillc.securities.SecurityUtils;
import com.fsillc.securities.MBS.CFSIMortgageBackedSecurity;
import com.fsillc.utils.FSISingleton;

public class CalculatorImplementation extends UnicastRemoteObject implements Calculator
{

 //
 // Member variables
 //

 private static final long serialVersionUID = 3978706181671630387L;

 // Logger
 private static Category m_oLogger = Category.getInstance(CalculatorImplementation.class);

 MBSCalculator mbsCalculator;
 NewMBSCalculator newMBSCalculator;
 BondCalculator bondCalculator;
 DerivativeCalculator derivativeCalculator;
 SecurityCalculator securityCalculator;

 private final String calcName;
 private String strHostName;
 GetMarketData getMarketData;
 long timeOfLastFunctionCall;
 private FSIHeartBeat m_fsiGUIHeartBeat;
 private FSIHeartBeat m_fsiManagerHeartBeat;
 private final int calcType;

 static public final long defaultExpirationTimeInMilliSeconds = 7200000; // 80 minutes
 String strScenarioInitializationId;

 // Bigegg -- Added this field to represent if the calculator running on a linux
 private boolean isWindows = true;

  // This id is used to distinguish two calculators with the same name
  private final long id;

 /**
  * Constructor.
  *
  * @param calcName  name of this Calculator
  * @param calcType  type of this Calculator
  * @throws RemoteException
  * @throws MBSCalculator.NoDLLException
  * @throws MBSCalculatorException
  */
 public CalculatorImplementation (String calcName, int calcType)
  throws RemoteException, MBSCalculator.NoDLLException, MBSCalculatorException
 {
   id = System.currentTimeMillis();

  this.calcName = calcName;
  this.calcType = calcType;

  isWindows = isWindowsPlatform();

  init();
 }

 //
 // Calculator implementation
 //

 public long getFreeMemory ()
  throws RemoteException
 {
  updateStatusToJNDI(CalcStatus.CALC_STATUS_BUSY, "getFreeMemory", "");
  Runtime oRuntime = Runtime.getRuntime();
  long lFreeMemory = oRuntime.freeMemory();
  updateStatusToJNDI(CalcStatus.CALC_STATUS_IDLE, "", "");
  return lFreeMemory;
 }

 public long getTotalMemory ()
  throws RemoteException
 {
  updateStatusToJNDI(CalcStatus.CALC_STATUS_BUSY, "getTotalMemory", "");
  Runtime oRuntime = Runtime.getRuntime();
  long lTotalMemory = oRuntime.totalMemory();
  updateStatusToJNDI(CalcStatus.CALC_STATUS_IDLE, "", "");
  return lTotalMemory;
 }

 public String getName ()
  throws RemoteException
 {
  // Bigegg - We dont bother this unnecessary call to JNDI server
  // We only need to adjust the last call timestamp
  // updateStatusToJNDI(CalcStatus.CALC_STATUS_BUSY, "getName", "");
  // updateStatusToJNDI(CalcStatus.CALC_STATUS_IDLE, "", "");
  m_oLogger.debug("in Calculator.getName()");
  setTimeOfLastFunctionCall();
  return calcName;
 }

  public long getId() throws RemoteException {
    return id;
  }

 public void gc ()
  throws RemoteException
 {
  updateStatusToJNDI(CalcStatus.CALC_STATUS_BUSY, "gc", "");

  try
  {
   Runtime oRuntime = Runtime.getRuntime();
   oRuntime.gc();
  }
  finally
  {
   updateStatusToJNDI(CalcStatus.CALC_STATUS_IDLE, "", "");
  }
 }

 public void setScenarioInitializationId (String strId)
  throws RemoteException
 {
  updateStatusToJNDI(CalcStatus.CALC_STATUS_BUSY, "setScenarioInitializationId", "");
  strScenarioInitializationId = strId;
  updateStatusToJNDI(CalcStatus.CALC_STATUS_IDLE, "", "");
 }

 public String getScenarioInitializationId ()
  throws RemoteException
 {
  // Bigegg - We dont bother this unnecessary call to JNDI server.
  // We only need to adjust the last call timestamp
  // updateStatusToJNDI(CalcStatus.CALC_STATUS_BUSY, "getScenarioInitializationId", "");
  // updateStatusToJNDI(CalcStatus.CALC_STATUS_IDLE, "", "");
  m_oLogger.debug("in Calculator.getScenarioInitializationId()");
  setTimeOfLastFunctionCall();
  return strScenarioInitializationId;
 }

 public int copyIfAliveAndAvailable (int i, FSIHeartBeat guiHeartBeat)
  throws RemoteException
 {
  updateStatusToJNDI(CalcStatus.CALC_STATUS_BUSY, "copyIfAliveAndAvailable", "");

  int ret = i - 1;
  try
  {
   String requestingGUI = guiHeartBeat.getHostname();
   String lockingGUI = getGUIHeartBeat().getHostname();
   m_oLogger.info("Requesting GUI is " + requestingGUI + ", locking GUI is " + lockingGUI);
   if (requestingGUI.equalsIgnoreCase(lockingGUI))
   {
    ret = i;
   }
  }
  finally
  {
   updateStatusToJNDI(CalcStatus.CALC_STATUS_IDLE, "", "");
  }

  return ret;
 }

 public String getHostName ()
  throws RemoteException
 {
  // Bigegg - We dont bother this unnecessary call to JNDI server
  // We only need to adjust the last call timestamp
  // updateStatusToJNDI(CalcStatus.CALC_STATUS_BUSY, "getHostName", "");
  // updateStatusToJNDI(CalcStatus.CALC_STATUS_IDLE, "", "");
  m_oLogger.debug("in Calculator.getHostName()");
  setTimeOfLastFunctionCall();
  return strHostName;
 }

 /**
  * This method is synchronized.
  */
 public synchronized boolean setUnavailable (FSIHeartBeat hb)
  throws RemoteException
 {
  String hostname = getHostFromHeartBeat(hb);
  m_oLogger.info("in setUnavailable(" + hostname + ")");
  if (hostname == "")
  {
   m_oLogger.warn("Wrong GUI heart beat, we will not lock this Calculator");
  }

  if (getGUIHeartBeat() == null)
  {
   // We can lock this Calculator
   m_oLogger.debug("[" + calcName + "]This calculator will be locked by " + hostname);
   setGUIHeartBeat(hb);
   // We always call this method in JNDI server, and the server will update the status
   // accordingly. So we dont need to call it here to save some network roundtrip.
   // updateStatusToJNDI(CalcStatus.CALC_STATUS_IDLE, "", "");
   return true;
  }
  else
  {
   // Calculator already locked
   m_oLogger.warn("[" + calcName + "]Failed to lock the Calculator for " + hostname);
   return false;
  }
 }

 /**
  * This method is synchronized.
  */
 public synchronized boolean setAvailable (FSIHeartBeat guiHeartBeat)
  throws RemoteException
 {
  String hostname = getHostFromHeartBeat(guiHeartBeat);
  m_oLogger.info("in setAvailable(" + hostname + ")");
  if (hostname == "")
  {
   m_oLogger.warn("Wrong GUI heart beat, we will not unlock this Calculator");
  }
  String lockingGUI = getHostFromHeartBeat(getGUIHeartBeat());

  if (hostname.equalsIgnoreCase(lockingGUI))
  {
   // The locking GUI calling this method
   m_oLogger.debug("[" + calcName + "]The locking GUI is " + lockingGUI +
           ", we are going to release this Calculator");
   setGUIHeartBeat(null); // Real unlock happens here
   updateStatusToJNDI(CalcStatus.CALC_STATUS_IDLE, "", "");
   return true;
  }
  else
  {
   // The calling GUI is not the owning GUI
   m_oLogger.warn("[" + calcName + "]The locking GUI is " + lockingGUI +
           ", has no rights to release this Calculator");
   return false;
  }
 }

 public boolean isAboutToExpire ()
  throws RemoteException
 {
  m_oLogger.debug("in Calculator.isAboutToExpire()");
  long timeSinceLastFunctionCall = System.currentTimeMillis() - timeOfLastFunctionCall;
  // if 5 minutes before calculator is to expire and become available once again.
  if (timeSinceLastFunctionCall > defaultExpirationTimeInMilliSeconds - 300000)
  {
   return true;
  }
  return false;
 }

 public void refreshAllPrepayParameters ()
  throws RemoteException
 {
  updateStatusToJNDI(CalcStatus.CALC_STATUS_BUSY, "RefreshAllPrepayParameters", "");

  try
  {
   MBSCalculator.RefreshAllPrepayParameters();
  }
  finally
  {
   updateStatusToJNDI(CalcStatus.CALC_STATUS_IDLE, "", "");
  }
 }

 public int obtainTreeId (EspSetOfCurvePointsStruct ycDiscStruct,
              EspTreeSizeSpecStruct treeSpec,
              EspMarketVolatilityDataStruct mvdsp,
              EspIRTreeParamsStruct irpp)
  throws RemoteException, MBSCalculatorException
 {

  updateStatusToJNDI(CalcStatus.CALC_STATUS_BUSY, "obtainTreeId", "");

  int retVal = 0;
  try
  {
   retVal = mbsCalculator.obtainTreeId(ycDiscStruct, treeSpec, mvdsp, irpp);
  }
  catch (MBSCalculator.NoDLLException e)
  {
   System.out.println("No Calculator!");
  }
  finally
  {
   updateStatusToJNDI(CalcStatus.CALC_STATUS_IDLE, "", "");
  }

  return retVal;
 }

 public int obtainTreeId (IFSIYieldCurves fsiYieldCurve,
              IFSITreeSizeSpec fsiTreeSizeSpec,
              IFSIMarketVolatility fsiVolatility,
              IFSIInterestRateTreeParams fsiIRTreeParams,
              IFSISysConfigParameters fsiSysConfig)
  throws RemoteException
 {

  updateStatusToJNDI(CalcStatus.CALC_STATUS_BUSY, "obtainTreeId", "");

  int ret = 0;
  try
  {
   ret = bondCalculator.obtainTreeId(fsiYieldCurve, fsiTreeSizeSpec, fsiVolatility,
                    fsiIRTreeParams, fsiSysConfig);
  }
  finally
  {
   updateStatusToJNDI(CalcStatus.CALC_STATUS_IDLE, "", "");
  }

  return ret;
 }

 public int obtainTreeId (IFSIYieldCurves fsiYieldCurve,
              IFSIYieldCurves fsiHorizonYC,
              IFSITreeSizeSpec fsiTreeSizeSpec,
              IFSIMarketVolatility fsiVolatility,
              IFSIMarketVolatility fsiHorizonVol,
              IFSIInterestRateTreeParams fsiIRTreeParams,
              IFSISysConfigParameters fsiSysConfig)
  throws RemoteException
 {

  updateStatusToJNDI(CalcStatus.CALC_STATUS_BUSY, "obtainTreeId", "");

  int ret = 0;
  try
  {
   ret = bondCalculator.obtainTreeId(fsiYieldCurve, fsiHorizonYC, fsiTreeSizeSpec,
                    fsiVolatility, fsiHorizonVol, fsiIRTreeParams, fsiSysConfig);
  }
  finally
  {
   updateStatusToJNDI(CalcStatus.CALC_STATUS_IDLE, "", "");
  }

  return ret;
 }

 public void resetPaths (IFSIPrepayModelMatrix fsiPrepayMatrix, IFSISecurityDataSource fsiSource)
  throws Exception
 {

  updateStatusToJNDI(CalcStatus.CALC_STATUS_BUSY, "resetPaths", "");

  try
  {
   String sPrepayModelPath = "";
   String sCMOPath = "";

   if (isWindows)
   {
    sPrepayModelPath = fsiPrepayMatrix.getPrepayModelParameterPath();
    sCMOPath = fsiSource.getPath() + ' ' + fsiSource.getPath2();
   }
   else
   {
    sPrepayModelPath = fsiPrepayMatrix.getPrepayModelParameterPathUnix();
    sCMOPath = fsiSource.getPathUnix() + ' ' + fsiSource.getPathUnix2();
   }

   internalResetPaths(sPrepayModelPath, sCMOPath);
  }
  finally
  {
   updateStatusToJNDI(CalcStatus.CALC_STATUS_IDLE, "", "");
  }
 }

 public void resetPaths (String prepayModelPath, String cmoDataVendorPath)
  throws Exception
 {

  updateStatusToJNDI(CalcStatus.CALC_STATUS_BUSY, "resetPaths", "");

  try
  {
   internalResetPaths(prepayModelPath, cmoDataVendorPath);
  }
  finally
  {
   updateStatusToJNDI(CalcStatus.CALC_STATUS_IDLE, "", "");
  }
 }

 public EspMBSValuationStruct[] calcStaticMeasuresVector (String whatToCalculate,
  int optionFlag,
  int mbsType,
  EspMBSCalcInputStruct calcInputStruct,
  OptionalModelManipulationData optionalModelData,
  OptionaInputToCFGenerator optionaInputToCFGenerator,
  EspCMOCallOptionSpecStruct espCMOCallOptionSpecStruct, EspMBSValuationStruct[] givenValues)
  throws MBSCalculatorException
 {

  updateStatusToJNDI(CalcStatus.CALC_STATUS_BUSY, "calcStaticMeasuresVector", "");

  EspMBSValuationStruct[] retVal = null;
  try
  {
   retVal = mbsCalculator.calcStaticMeasures_Vector(whatToCalculate, optionFlag,
    mbsType, calcInputStruct, optionalModelData, optionaInputToCFGenerator,
    espCMOCallOptionSpecStruct, givenValues);
  }
  catch (MBSCalculator.NoDLLException e)
  {
   m_oLogger.error("No DLL", e);
  }
  catch (Exception ex)
  {
   m_oLogger.error("Error when calculating static measure", ex);
  }
  finally
  {
   updateStatusToJNDI(CalcStatus.CALC_STATUS_IDLE, "", "");
  }

  return retVal;
 } // end calcStaticMeasuresVector

 public EspMBSValuationStruct calcDynamicMeasures (int random_seed,
  int number_of_sampling_paths,
  double yield_curve_shift_in_bps,
  int mbsType,
  EspMBSCalcInputStruct calcInputStruct,
  CFSIDiscounting useCMTAsDiscountRateFlag,
  int mortgageRateModelFlag,
  OptionalModelManipulationData optionalModelData,
  OptionaInputToCFGenerator optionaInputToCFGenerator,
  EspCMOCallOptionSpecStruct espCMOCallOptionSpecStruct,
  String whatToCalculate,
  EspMBSValuationStruct givenValues)
  throws MBSCalculatorException
 {

  updateStatusToJNDI(CalcStatus.CALC_STATUS_BUSY, "calcDynamicMeasures", "");

  EspMBSValuationStruct retVal = null;
  try
  {
   retVal = mbsCalculator.calcDynamicMeasures(random_seed, number_of_sampling_paths,
                         yield_curve_shift_in_bps, mbsType, calcInputStruct,
                         useCMTAsDiscountRateFlag, mortgageRateModelFlag,
                         optionalModelData, optionaInputToCFGenerator,
                         espCMOCallOptionSpecStruct, whatToCalculate,
                         givenValues);
  }
  catch (MBSCalculator.NoDLLException e)
  {
   m_oLogger.error("No Calculator", e);
  }
  catch (Exception ex)
  {
   m_oLogger.error("Error when calculating dynamic measures", ex);
  }
  finally
  {
   updateStatusToJNDI(CalcStatus.CALC_STATUS_IDLE, "", "");
  }

  return retVal;
 }

 public EspMBSValuationStruct[] calcDynamicMeasuresVector (int random_seed,
  int number_of_sampling_paths,
  double yield_curve_shift_in_bps,
  int mbsType,
  EspMBSCalcInputStruct calcInputStruct,
  CFSIDiscounting useCMTAsDiscountRateFlag,
  int mortgageRateModelFlag,
  OptionalModelManipulationData optionalModelData,
  OptionaInputToCFGenerator optionaInputToCFGenerator,
  EspCMOCallOptionSpecStruct espCMOCallOptionSpecStruct,
  String whatToCalculate,
  EspMBSValuationStruct[] givenValues)
  throws MBSCalculatorException
 {

  updateStatusToJNDI(CalcStatus.CALC_STATUS_BUSY, "calcDynamicMeasuresVector", "");

  EspMBSValuationStruct[] retVal = null;
  try
  {
   retVal = mbsCalculator.calcDynamicMeasures_Vector(random_seed, number_of_sampling_paths,
    yield_curve_shift_in_bps, mbsType, calcInputStruct, useCMTAsDiscountRateFlag,
    mortgageRateModelFlag, optionalModelData, optionaInputToCFGenerator,
    espCMOCallOptionSpecStruct, whatToCalculate, givenValues);
  }
  catch (MBSCalculator.NoDLLException e)
  {
   m_oLogger.debug("No Calculator", e);
  }
  catch (Exception ex)
  {
   m_oLogger.debug("Error when calculating dynamic measures vector", ex);
  }
  finally
  {
   updateStatusToJNDI(CalcStatus.CALC_STATUS_IDLE, "", "");
  }

  return retVal;
 }

 public EspMBSCalcInputStruct retrieveCMOPoolInfo (int isCusipInput,
  String cusip,
  String dealName,
  String trancheName,
  long settleDate,
  int wamBuckets,
  int wacBuckets)
  throws MBSCalculatorException
 {

  updateStatusToJNDI(CalcStatus.CALC_STATUS_BUSY, "retrieveCMOPoolInfo", "");

  EspMBSCalcInputStruct returnStruct = null;
  try
  {
   returnStruct = mbsCalculator.retrieveCMOPoolInfo(isCusipInput,
    cusip, dealName, trancheName, settleDate,
    wamBuckets, wacBuckets);
   //For collateral override:
   if (returnStruct != null &&
     returnStruct.mbs_collat_desc_struct != null)
   {
    returnStruct.mbs_collat_desc_struct.collatAgencyName =
     returnStruct.mbs_collat_desc_struct.agencyName;
   }
  }
  catch (MBSCalculator.NoDLLException e)
  {
   m_oLogger.error("No Calculator", e);
  }
  catch (Exception ex)
  {
   m_oLogger.debug("Error when retrieving CMO pool info", ex);
  }
  finally
  {
   updateStatusToJNDI(CalcStatus.CALC_STATUS_IDLE, "", "");
  }

  return returnStruct;
 }

 public EspMBSIOPOStripStruct fitPrepayMultiplierForIOPOStrip (
  int randomSeed,
  CFSIDiscounting useCMTAsDiscRateFlag,
  int mortRateModelFlag,
  int numberOfSamplingPaths,
  int mbsType,
  EspMBSIOPOStripStruct stripStruct,
  MBSDollarRollStruct dollarRollStruct)
  throws MBSCalculatorException
 {

  updateStatusToJNDI(CalcStatus.CALC_STATUS_BUSY, "fitPrepayMultiplierForIOPOStrip", "");

  EspMBSIOPOStripStruct returnStruct = null;
  try
  {
   returnStruct = mbsCalculator.fitPrepayMultiplierForIOPOStrip(
    randomSeed, useCMTAsDiscRateFlag, mortRateModelFlag,
    numberOfSamplingPaths, mbsType, stripStruct,
    dollarRollStruct);
  }
  catch (MBSCalculator.NoDLLException e)
  {
   m_oLogger.error("No Calculator", e);
  }
  catch (Exception ex)
  {
   m_oLogger.error("Error when fitting prepay multiplier", ex);
  }
  finally
  {
   updateStatusToJNDI(CalcStatus.CALC_STATUS_IDLE, "", "");
  }

  return returnStruct;
 }

 public FixedIncomeSecurityDescription getCMOBondInfo (long settleDate,
  String cusip,
  String dealName,
  String trancheName)
  throws MBSCalculatorException
 {

  updateStatusToJNDI(CalcStatus.CALC_STATUS_BUSY, "getCMOBondInfo", "");

  FixedIncomeSecurityDescription returnStruct = null;
  try
  {
   returnStruct = mbsCalculator.getCMOBondInfo(settleDate, cusip,
                         dealName, trancheName);
  }
  catch (MBSCalculator.NoDLLException e)
  {
   m_oLogger.error("No Calculator", e);
  }
  catch (Exception ex)
  {
   m_oLogger.error("Error when getting CMO bond info", ex);
  }
  finally
  {
   updateStatusToJNDI(CalcStatus.CALC_STATUS_IDLE, "", "");
  }

  return returnStruct;
 }

 public EspIROptionDescStruct[] calcIROptionPrice (
  EspIROptionDescStruct[] securities,
  int blackFlag,
  int setStrikePriceAtMoneyFlag)
  throws MBSCalculatorException
 {

  updateStatusToJNDI(CalcStatus.CALC_STATUS_BUSY, "calcIROptionPrice", "");

  EspIROptionDescStruct[] returnStructs = null;
  try
  {
   returnStructs = mbsCalculator.calcIROptionPrice(securities,
    blackFlag, setStrikePriceAtMoneyFlag);
  }
  catch (MBSCalculator.NoDLLException e)
  {
   m_oLogger.error("No Calculator", e);
  }
  catch (Exception ex)
  {
   m_oLogger.error("Error when calculating IR option price", ex);
  }
  finally
  {
   updateStatusToJNDI(CalcStatus.CALC_STATUS_IDLE, "", "");
  }

  return returnStructs;
 }

 public EspIROptionDescStruct[] fitTermStructureVolatility (
  EspIROptionDescStruct[] securities,
  int blackFlag,
  int setStrikePriceAtMoneyFlag,
  int fitOnlyOverallFactorFlag,
  int autoChooseStartingVolatCurvesFlag,
  int fitMeanReversionCurveFlag,
  int restrictFittingProcessFlag)
  throws MBSCalculatorException
 {

  updateStatusToJNDI(CalcStatus.CALC_STATUS_BUSY, "fitTermStructureVolatility", "");

  EspIROptionDescStruct[] returnValue = null;
  try
  {
   returnValue = mbsCalculator.fitTermStructureVolatility(securities,
    blackFlag, setStrikePriceAtMoneyFlag, fitOnlyOverallFactorFlag,
    autoChooseStartingVolatCurvesFlag, fitMeanReversionCurveFlag,
    restrictFittingProcessFlag);
  }
  catch (MBSCalculator.NoDLLException e)
  {
   m_oLogger.error("No Calculator", e);
  }
  catch (Exception ex)
  {
   m_oLogger.error("Error when fitting volatility structure", ex);
  }
  finally
  {
   updateStatusToJNDI(CalcStatus.CALC_STATUS_IDLE, "", "");
  }

  return returnValue;
 }

 public EspMarketVolatilityDataStruct getCurrentEspMarketVolatilityDataStruct (
  int treeId)
  throws MBSCalculatorException
 {

  updateStatusToJNDI(CalcStatus.CALC_STATUS_BUSY, "getCurrentEspMarketVolatilityDataStruct", "");

  EspMarketVolatilityDataStruct returnStruct = null;
  try
  {
   returnStruct = mbsCalculator.getCurrentEspMarketVolatilityDataStruct(treeId);
  }
  catch (MBSCalculator.NoDLLException e)
  {
   m_oLogger.error("No Calculator", e);
  }
  catch (Exception ex)
  {
   m_oLogger.error("Error when getting current ESP market volatility", ex);
  }
  finally
  {
   updateStatusToJNDI(CalcStatus.CALC_STATUS_IDLE, "", "");
  }

  return returnStruct;
 }

 public double[] calcVolatilityCorrelation (double[] timesInYear)
  throws MBSCalculatorException
 {

  updateStatusToJNDI(CalcStatus.CALC_STATUS_BUSY, "calcVolatilityCorrelation", "");

  double[] returnArray = null;
  try
  {
   returnArray = mbsCalculator.calcVolatilityCorrelation(timesInYear);
  }
  catch (MBSCalculator.NoDLLException e)
  {
   m_oLogger.error("No Calculator", e);
  }
  catch (Exception ex)
  {
   m_oLogger.error("Error when calculating volatility correlation", ex);
  }
  finally
  {
   updateStatusToJNDI(CalcStatus.CALC_STATUS_IDLE, "", "");
  }

  return returnArray;
 }

 public EspSetOfCurvePointsStruct getYieldCurveFrom (
  long _date,
  String vendor,
  String user,
  String password)
  throws RemoteException, YieldCurveException, GetMarketData.NoDLLException
 {

  updateStatusToJNDI(CalcStatus.CALC_STATUS_BUSY, "getYieldCurveFrom", "");

  EspSetOfCurvePointsStruct returnObj = null;
  try
  {
   returnObj = getMarketData.getYieldCurveFrom(_date, vendor, user, password);
  }
  catch (GetMarketData.NoDLLException e)
  {
   m_oLogger.error("No Calculator", e);
  }
  finally
  {
   updateStatusToJNDI(CalcStatus.CALC_STATUS_IDLE, "", "");
  }

  return returnObj;
 }

 public EspIROptionDescStruct[] getIROption (String[] arrTickers,
                       int[] arrBondTypes,
                       long _date,
                       String vendor,
                       String user,
                       String password)
  throws RemoteException, YieldCurveException
 {

  updateStatusToJNDI(CalcStatus.CALC_STATUS_BUSY, "getIROption", "");

  EspIROptionDescStruct[] returnObjs = null;
  try
  {
   returnObjs = getMarketData.getIROption(arrTickers, arrBondTypes,
                       _date, vendor, user, password);
  }
  catch (GetMarketData.NoDLLException e)
  {
   m_oLogger.error("No Calculator", e);
  }
  finally
  {
   updateStatusToJNDI(CalcStatus.CALC_STATUS_IDLE, "", "");
  }

  return returnObjs;
 }

 public IFSIMortgageBackedSecurity loadMBSFromBloomberg (
  String sSecurityName,
  IFSIMortgageBackedSecurity fsiMBS,
  IFSIFixedIncomeSecurityDescription fsiDescription)
  throws RemoteException, MBSCalculatorException
 {

  updateStatusToJNDI(CalcStatus.CALC_STATUS_BUSY, "loadMBSFromBloomberg", sSecurityName);

  IFSIMortgageBackedSecurity returnObjs = null;
  try
  {
   returnObjs = getMarketData.loadMBSFromBloomberg(sSecurityName, fsiMBS, fsiDescription);
  }
  catch (GetMarketData.NoDLLException e)
  {
   m_oLogger.error("No Calculator", e);
  }
  finally
  {
   updateStatusToJNDI(CalcStatus.CALC_STATUS_IDLE, "", "");
  }

  return returnObjs;
 }

 public IFSIMortgageBackedSecurity loadMBSFromCacheOrBloomberg (
  String sSecurityName)
  throws RemoteException, MBSCalculatorException
 {

  updateStatusToJNDI(CalcStatus.CALC_STATUS_BUSY, "loadMBSFromCacheOrBloomberg", sSecurityName);

  IFSIMortgageBackedSecurity fsiMBS = null;
  try
  {
   IFSIObjectManager om = new CFSIMortgageBackedSecurity(
    FSISingleton.getFSISession());
   ((CFSIMortgageBackedSecurity) om).openFromBloomberg(
    sSecurityName, this);
   fsiMBS = (IFSIMortgageBackedSecurity) om.getManagedObject();

   if (fsiMBS == null)
   {
    throw new RemoteException("Security not found.");
   }
  }
  finally
  {
   updateStatusToJNDI(CalcStatus.CALC_STATUS_IDLE, "", "");
  }

  return fsiMBS;
 }

 public Object[] fitPrepayMultipliersToMBSList (int nRandomSeed,
                         int nuNmberOfSamplingPath,
                         CFSIDiscounting fsiUseCMTAsDiscountRate,
                         CFSIMortgageRateType fsiMortgageRateModel,
                         IFSIMortgageBackedSecurity[] arrMBSList,
                         IFSIMBSResults[] arrMBSValuation,
                         double[] arrTargetOAS,
                         HowToFitPrepayMultiplersAndInitialGuess
                         espFittingParams, int nWhatToCalculate)
  throws RemoteException, MBSCalculatorException
 {

  updateStatusToJNDI(CalcStatus.CALC_STATUS_BUSY, "fitPrepayMultipliersToMBSList", "");

  Object[] arrReturn = null;

  try
  {
   if (arrMBSList.length > 0 &&
     CFSIDataSource.INTEX.equals(arrMBSList[0].getDataSource()))
   {
    checkCMOPaths(arrMBSList[0].getCMOProviderDataDirectoryPath());
   }

   arrReturn = newMBSCalculator.fitPrepayMultipliersToMBSList(
    nRandomSeed, nuNmberOfSamplingPath, fsiUseCMTAsDiscountRate,
    fsiMortgageRateModel, arrMBSList, arrMBSValuation,
    arrTargetOAS, espFittingParams, nWhatToCalculate);
  }
  finally
  {
   updateStatusToJNDI(CalcStatus.CALC_STATUS_IDLE, "", "");
  }

  return arrReturn;
 }

 public IFSIMBSPrepaymentHistory loadPrepaymentHistory (
  IFSISecurityDataSource fsiSource,
  IFSIMBSPrepaymentHistory history)
  throws RemoteException
 {

  updateStatusToJNDI(CalcStatus.CALC_STATUS_BUSY, "loadPrepaymentHistory", "");

  IFSIMBSPrepaymentHistory ret = null;
  try
  {
   String sCMOPath;
   if (isWindows)
   {
    sCMOPath = fsiSource.getPath() + ' ' + fsiSource.getPath2();
   }
   else
   {
    sCMOPath = fsiSource.getPathUnix() + ' ' + fsiSource.getPathUnix2();
   }

   ret = loadPrepaymentHistory(sCMOPath, history);
  }
  finally
  {
   updateStatusToJNDI(CalcStatus.CALC_STATUS_IDLE, "", "");
  }

  return ret;
 }

 public IFSIMBSPrepaymentHistory loadPrepaymentHistory (String dataPath,
  IFSIMBSPrepaymentHistory history)
  throws RemoteException
 {

  updateStatusToJNDI(CalcStatus.CALC_STATUS_BUSY, "loadPrepaymentHistory", "");

  IFSIMBSPrepaymentHistory ret = null;
  try
  {
   ret = newMBSCalculator.loadPrepaymentHistory(dataPath, history);
  }
  finally
  {
   updateStatusToJNDI(CalcStatus.CALC_STATUS_IDLE, "", "");
  }

  return ret;
 }

 public IFSIMBSPrepaymentHistory loadPrepaymentHistoryFromBloomberg (
  IFSIMBSPrepaymentHistory history)
  throws RemoteException
 {

  updateStatusToJNDI(CalcStatus.CALC_STATUS_BUSY, "loadPrepaymentHistoryFromBloomberg", "");

  IFSIMBSPrepaymentHistory ret = null;
  try
  {
   ret = newMBSCalculator.loadPrepaymentHistoryFromBloomberg(history);
  }
  finally
  {
   updateStatusToJNDI(CalcStatus.CALC_STATUS_IDLE, "", "");
  }

  return ret;
 }

 public IFSIMortgageBackedSecurity loadMBS (boolean isCusipInput,
                       String cusip,
                       String dealName,
                       String trancheName,
                       IFSIMortgageBackedSecurity fsiMBS,
                       IFSIFixedIncomeSecurityDescription fsiDescription,
                       GregorianCalendar gcSettleDate,
                       int wamBuckets,
                       int wacBuckets)
  throws RemoteException, SecurityNotFoundException, InvalidDataPathException
 {

  updateStatusToJNDI(CalcStatus.CALC_STATUS_BUSY, "loadMBS", cusip);

  IFSIMortgageBackedSecurity ret = null;
  try
  {
   // Bigegg -- Reset the path according to the running OS
   resetPaths(fsiMBS);
   checkCMOPaths(fsiMBS.getCMOProviderDataDirectoryPath());

   fsiMBS.setARM(true);
   ret = newMBSCalculator.loadMBS(isCusipInput, cusip, dealName,
                   trancheName, fsiMBS,
                   fsiDescription, gcSettleDate, wamBuckets, wacBuckets);
  }
  finally
  {
   updateStatusToJNDI(CalcStatus.CALC_STATUS_IDLE, "", "");
  }

  return ret;
 }

 public IFSIMBSResults[] calculateDynamicMeasures (
  int nRandomSeed,
  int nSamplingPaths,
  double dYieldCurveShiftInBps,
  IFSIMortgageBackedSecurity fsiCalcInputStruct,
  CFSIDiscounting fsiUseCMTAsDiscountRate,
  CFSIMortgageRateType fsiMortgageRateModel,
  IFSIOptionalModelManipulationData fsiOptionalModelData,
  IFSICMOCallOptionSpec fsiCMOCallOptionSpec,
  long lInputOptions,
  long lOutputOptions,
  IFSIMBSResults arrValues[])
  throws RemoteException, MBSCalculatorException
 {

  updateStatusToJNDI(CalcStatus.CALC_STATUS_BUSY,
            "calculateDynamicMeasures", fsiCalcInputStruct.getCusip());

  IFSIMBSResults[] ret = null;
  try
  {
   // Bigegg -- Reset the path according to the running OS
   resetPaths(fsiCalcInputStruct);

   if (fsiCalcInputStruct.getType() == CFSIMBSTypes.FRM_CMO)
   {
    checkCMOPaths(fsiCalcInputStruct.getCMOProviderDataDirectoryPath());
   }
   if (fsiOptionalModelData.getForcedPrepayMethod().equals(
    CFSIPrepaySpeedUnit.CALC_USE_ESPIEL_MODEL))
   {
    checkPrepayModelPath(fsiCalcInputStruct.getParamsDir());
   }

   ret = newMBSCalculator.calculateDynamicMeasures(nRandomSeed,
    nSamplingPaths, dYieldCurveShiftInBps, fsiCalcInputStruct,
    fsiUseCMTAsDiscountRate, fsiMortgageRateModel, fsiOptionalModelData,
    fsiCMOCallOptionSpec, lInputOptions, lOutputOptions,
    arrValues);
  }
  finally
  {
   updateStatusToJNDI(CalcStatus.CALC_STATUS_IDLE, "", "");
  }

  return ret;
 }

 public IFSITotalReturnResults calculateTotalReturn (int nRandomSeed,
  int nSamplingPaths,
  double dYieldCurveShiftInBps,
  IFSIMortgageBackedSecurity fsiCalcInputStruct,
  IFSITotalReturnInput fsiInput,
  CFSIDiscounting fsiUseCMTAsDiscountRate,
  IFSIOptionalModelManipulationData fsiOptionalModelData,
  IFSICMOCallOptionSpec fsiSpec,
  CFSIMortgageRateType fsiMortgageRateModel,
  IFSITotalReturnResults fsiResults,
  long lOutputOptions)
  throws RemoteException, MBSCalculatorException
 {

  updateStatusToJNDI(CalcStatus.CALC_STATUS_BUSY,
            "calculateMBSTotalReturn", fsiCalcInputStruct.getCusip());

  IFSITotalReturnResults ret;
  try
  {
   resetPaths(fsiCalcInputStruct);
   try
   {
    if (fsiCalcInputStruct.getDataSource().equals(
     CFSIDataSource.INTEX))
    {
     checkCMOPaths(fsiCalcInputStruct.getCMOProviderDataDirectoryPath());
    }
   }
   catch (Exception e)
   {
    // ignored
   }

   ret = newMBSCalculator.calculateTotalReturn(nRandomSeed,
                         nSamplingPaths, dYieldCurveShiftInBps,
                         fsiCalcInputStruct,
                         fsiInput, fsiUseCMTAsDiscountRate,
                         fsiOptionalModelData,
                         fsiSpec, fsiMortgageRateModel, fsiResults,
                         lOutputOptions);
  }
  finally
  {
   updateStatusToJNDI(CalcStatus.CALC_STATUS_IDLE, "", "");
  }

  return ret;
 }

 public double[] calculatePartialDuration (int nRandomSeed,
                      int nSamplingPaths,
                      IFSIMortgageBackedSecurity fsiMBS,
                      CFSIDiscounting fsiUseCMTAsDiscountRate,
                      CFSIMortgageRateType fsiMortgageRateModel,
                      IFSIOptionalModelManipulationData fsiOptionalModelData,
                      IFSICMOCallOptionSpec fsiSpec,
                      double dOAS,
                      double[] arrShocks)
  throws RemoteException, MBSCalculatorException
 {

  updateStatusToJNDI(CalcStatus.CALC_STATUS_BUSY,
            "calculateMBSPartialDuration", fsiMBS.getCusip());

  double[] ret = null;
  try
  {
   resetPaths(fsiMBS);
   try
   {
    if (fsiMBS.getDataSource().equals(CFSIDataSource.INTEX))
    {
     checkCMOPaths(fsiMBS.getCMOProviderDataDirectoryPath());
    }
   }
   catch (Exception e)
   {
    // ignored
   }

   ret = newMBSCalculator.calculatePartialDuration(nRandomSeed,
    nSamplingPaths, fsiMBS, fsiUseCMTAsDiscountRate,
    fsiMortgageRateModel, fsiOptionalModelData, fsiSpec,
    dOAS, arrShocks);
  }
  finally
  {
   updateStatusToJNDI(CalcStatus.CALC_STATUS_IDLE, "", "");
  }

  return ret;
 }

 public double[] calculatePartialDurations (
  GregorianCalendar gcSettlementDate,
  IFSICorpBond fsiBond,
  double dOAS,
  double[] arrShockPoints,
  CFSIDiscounting fsiTreasuryFlag,
  int nNeedToFitYCCurve)
  throws RemoteException, MBSCalculatorException
 {

  updateStatusToJNDI(CalcStatus.CALC_STATUS_BUSY,
            "calculateCorpBondPartialDurations", fsiBond.getCusip());

  double[] ret = null;
  try
  {
   ret = bondCalculator.calculatePartialDruations(gcSettlementDate,
                        fsiBond, dOAS, arrShockPoints,
                        fsiTreasuryFlag, nNeedToFitYCCurve);
  }
  finally
  {
   updateStatusToJNDI(CalcStatus.CALC_STATUS_IDLE, "", "");
  }

  return ret;
 }

 public IFSICorpBond loadBondIndicatives (String sDataPath,
                      String sCusip,
                      GregorianCalendar gcSettlementDate,
                      IFSICorpBond fsiCorpBond,
                      IFSIFixedIncomeSecurityDescription fsiDescription)
  throws RemoteException, SecurityNotFoundException, InvalidDataPathException
 {

  updateStatusToJNDI(CalcStatus.CALC_STATUS_BUSY, "loadBondIndicatives", sCusip);

  IFSICorpBond ret = null;
  try
  {
   checkIDCPath(sDataPath);
   m_oLogger.info("loadBondIndicatives with sDataPath = " + sDataPath + " sCusip = " + sCusip +
           " settlement date = " + gcSettlementDate.getTime());

   ret = bondCalculator.loadBondIndicatives(sDataPath, sCusip,
                        gcSettlementDate, fsiCorpBond, fsiDescription);
  }
  finally
  {
   updateStatusToJNDI(CalcStatus.CALC_STATUS_IDLE, "", "");
  }

  return ret;
 }

 public IFSICorpBond loadBondIndicativesFromCacheOrBloomberg (
  String sCusip,
  GregorianCalendar gcSettlementDate)
  throws RemoteException, SecurityNotFoundException, InvalidDataPathException
 {

  updateStatusToJNDI(CalcStatus.CALC_STATUS_BUSY, "loadBondIndicativesFromCacheOrBloomberg",
            sCusip);

  IFSICorpBond fsiCorpBond = null;
  try
  {
   IFSIObjectManager om = new CFSICorpBond(
    FSISingleton.getFSISession());
   ((CFSICorpBond) om).openFromBloomberg(sCusip,
                      gcSettlementDate, this);
   om = SecurityUtils.transformCorpBond(om);
   fsiCorpBond = (IFSICorpBond) om.getManagedObject();
  }
  finally
  {
   updateStatusToJNDI(CalcStatus.CALC_STATUS_IDLE, "", "");
  }

  return fsiCorpBond;
 }

 public IFSICorpBond loadBondIndicativesFromBloomberg (
  String sCusip,
  GregorianCalendar gcSettlementDate,
  IFSICorpBond fsiCorpBond,
  IFSIFixedIncomeSecurityDescription fsiDescription)
  throws RemoteException, SecurityNotFoundException
 {

  updateStatusToJNDI(CalcStatus.CALC_STATUS_BUSY, "loadBondIndicativesFromBloomberg", sCusip);

  IFSICorpBond ret = null;
  try
  {
   ret = bondCalculator.loadBondIndicativesFromBloomberg(sCusip,
    gcSettlementDate, fsiCorpBond, fsiDescription);
  }
  finally
  {
   updateStatusToJNDI(CalcStatus.CALC_STATUS_IDLE, "", "");
  }

  return ret;
 }

 public IFSICorpBond loadBABondIndicatives (String sDataPath,
                       String sCusip,
                       GregorianCalendar gcSettlementDate,
                       IFSICorpBond fsiBond)
  throws RemoteException
 {

  updateStatusToJNDI(CalcStatus.CALC_STATUS_BUSY, "loadBABondIndicatives", sCusip);

  IFSICorpBond ret = null;
  try
  {
   checkIDCPath(sDataPath);
   ret = bondCalculator.loadBABondIndicatives(sDataPath, sCusip,
                         gcSettlementDate, fsiBond);
  }
  finally
  {
   updateStatusToJNDI(CalcStatus.CALC_STATUS_IDLE, "", "");
  }

  return ret;
 }

 public IFSICorpBond checkValidity (GregorianCalendar gcSettlementDate,
                   IFSICorpBond fsiCorpBond)
  throws RemoteException
 {

  updateStatusToJNDI(CalcStatus.CALC_STATUS_BUSY, "checkValidity", fsiCorpBond.getCusip());

  IFSICorpBond ret = null;
  try
  {
   ret = bondCalculator.CheckValidity(gcSettlementDate, fsiCorpBond);
  }
  finally
  {
   updateStatusToJNDI(CalcStatus.CALC_STATUS_IDLE, "", "");
  }

  return ret;
 }

 public IFSIYieldCurves getTreasuryCurvePoint (IFSIYieldCurves fsiCurves)
  throws RemoteException
 {

  updateStatusToJNDI(CalcStatus.CALC_STATUS_BUSY, "getTreasuryCurvePoint", "");

  IFSIYieldCurves ret = null;
  try
  {
   ret = bondCalculator.getTreasuryCurvePoint(fsiCurves);
  }
  finally
  {
   updateStatusToJNDI(CalcStatus.CALC_STATUS_IDLE, "", "");
  }

  return ret;
 }

 public IFSIBondResults calculateDynamicMeasuresFromPrice (
  GregorianCalendar gcSettlementDate,
  IFSICorpBond pEspBond,
  IFSICalculationOptions calculationOption,
  IFSIBondResults pResults,
  int need_fit_yc_flag,
  CFSIDiscounting is_Treasury_flag)
 {

  updateStatusToJNDI(CalcStatus.CALC_STATUS_BUSY, "CalculateDynamicMeasuresFromPrice", "");

  IFSIBondResults ret = null;
  try
  {
   ret = bondCalculator.CalculateDynamicMeasuresFromPrice(
    gcSettlementDate, pEspBond, calculationOption,
    pResults, need_fit_yc_flag, is_Treasury_flag);
  }
  finally
  {
   updateStatusToJNDI(CalcStatus.CALC_STATUS_IDLE, "", "");
  }

  return ret;
 }

 public IFSIBondResults priceFromYield (GregorianCalendar gcSettlementDate,
                     CFSIBondYieldType fsiYieldType, IFSICorpBond oneBondptr,
                     IFSIBondResults calc_results)
 {

  updateStatusToJNDI(CalcStatus.CALC_STATUS_BUSY, "priceFromYield", "");

  IFSIBondResults ret = null;
  try
  {
   ret = bondCalculator.PriceFromYield(gcSettlementDate,
                     fsiYieldType, oneBondptr, calc_results);
  }
  finally
  {
   updateStatusToJNDI(CalcStatus.CALC_STATUS_IDLE, "", "");
  }

  return ret;
 }

 public IFSIBondResults priceFromSpreadToWAL (
  GregorianCalendar gcSettlementDate,
  CFSIDiscounting is_Treasury_flag,
  double dSpreadToWAL,
  IFSICorpBond oneBondptr, IFSIBondResults pResults)
 {

  updateStatusToJNDI(CalcStatus.CALC_STATUS_BUSY, "priceFromSpreadToWAL", "");

  IFSIBondResults ret = null;
  try
  {
   ret = bondCalculator.PriceFromSpreadToWAL(gcSettlementDate,
                        is_Treasury_flag, dSpreadToWAL, oneBondptr,
                        pResults);
  }
  finally
  {
   updateStatusToJNDI(CalcStatus.CALC_STATUS_IDLE, "", "");
  }

  return ret;
 }

 public IFSIBondResults priceFromOAS (GregorianCalendar gcSettlementDate,
                    IFSICorpBond pEspBond,
                    IFSIBondResults pResults,
                    int need_fit_yc_flag,
                    CFSIDiscounting is_Treasury_flag)
 {

  updateStatusToJNDI(CalcStatus.CALC_STATUS_BUSY, "priceFromOAS", "");

  IFSIBondResults ret = null;
  try
  {
   ret = bondCalculator.PriceFromOAS(gcSettlementDate, pEspBond,
                    pResults, need_fit_yc_flag, is_Treasury_flag);
  }
  finally
  {
   updateStatusToJNDI(CalcStatus.CALC_STATUS_IDLE, "", "");
  }

  return ret;
 }

 public IFSIBondResults priceFromZVOAS (GregorianCalendar gcSettlementDate,
                     IFSICorpBond EspBond,
                     IFSIBondResults Results,
                     CFSIDiscounting is_Treasury_flag)
 {

  updateStatusToJNDI(CalcStatus.CALC_STATUS_BUSY, "priceFromZVOAS", "");

  IFSIBondResults ret = null;
  try
  {
   ret = bondCalculator.PriceFromZVOAS(gcSettlementDate, EspBond,
                     Results, is_Treasury_flag);
  }
  finally
  {
   updateStatusToJNDI(CalcStatus.CALC_STATUS_IDLE, "", "");
  }

  return ret;
 }

 public IFSITotalReturnResults calculateTotalReturn (
  GregorianCalendar gcSettlementDate,
  IFSICorpBond pEspBond,
  IFSITotalReturnInput fsiInput,
  IFSITotalReturnResults pResults,
  CFSIDiscounting is_Treasury_flag,
  long lOutputOptions)
  throws RemoteException
 {

  updateStatusToJNDI(CalcStatus.CALC_STATUS_BUSY, "calculateTotalReturn", "");

  IFSITotalReturnResults fsiReturned = null;
  try
  {
   fsiReturned = bondCalculator.CalculateTotalReturn(
    gcSettlementDate, pEspBond, fsiInput, pResults,
    is_Treasury_flag, lOutputOptions);
  }
  finally
  {
   updateStatusToJNDI(CalcStatus.CALC_STATUS_IDLE, "", "");
  }

  return fsiReturned;
 }

 public IFSIBondResults calculate (IFSIDerivatives fsiDerivatives,
                  boolean bBlack,
                  boolean bStrikePriceAtMoney,
                  long lInputOptions,
                  long lOutputOptions,
                  CFSIDiscounting fsiDisountingMethod,
                  IFSIBondResults fsiResults)
  throws RemoteException, MBSCalculatorException
 {

  updateStatusToJNDI(CalcStatus.CALC_STATUS_BUSY, "calculate", "");

  IFSIBondResults fsiReturned = null;
  try
  {
   fsiReturned = newMBSCalculator.calculate(fsiDerivatives, bBlack,
                        bStrikePriceAtMoney, lInputOptions,
                        lOutputOptions, fsiDisountingMethod, fsiResults);
  }
  finally
  {
   updateStatusToJNDI(CalcStatus.CALC_STATUS_IDLE, "", "");
  }

  return fsiReturned;
 }

 public IFSITotalReturnResults calculateTotalReturn (
  IFSIDerivatives fsiDerivatives,
  IFSITotalReturnInput fsiInput,
  boolean bBlack,
  boolean bStrikePriceAtMoney,
  CFSIDiscounting fsiDiscounting,
  IFSITotalReturnResults fsiResults,
  long lOutputOptions)
  throws RemoteException, MBSCalculatorException
 {

  updateStatusToJNDI(CalcStatus.CALC_STATUS_BUSY, "calculateTotalReturn", "");

  IFSITotalReturnResults fsiReturned = null;
  try
  {
   fsiReturned = newMBSCalculator.calculateTotalReturn(
    fsiDerivatives, fsiInput, bBlack, bStrikePriceAtMoney,
    fsiDiscounting, fsiResults, lOutputOptions);
  }
  finally
  {
   updateStatusToJNDI(CalcStatus.CALC_STATUS_IDLE, "", "");
  }

  return fsiReturned;
 }

 public double[] calculatePartialDruations (
  GregorianCalendar gcSettlementDate,
  IFSIDerivatives fsiDerivatives,
  double dOAS,
  double[] arrShockPoints,
  CFSIDiscounting fsiTreasuryFlag,
  int nNeedToFitYCCurve)
  throws RemoteException, MBSCalculatorException
 {

  updateStatusToJNDI(CalcStatus.CALC_STATUS_BUSY, "calculatePartialDruations", "");

  double[] arrPDs = null;
  try
  {
   arrPDs = newMBSCalculator.calculatePartialDruations(
    gcSettlementDate, fsiDerivatives, dOAS,
    arrShockPoints, fsiTreasuryFlag, nNeedToFitYCCurve);
  }
  finally
  {
   updateStatusToJNDI(CalcStatus.CALC_STATUS_IDLE, "", "");
  }

  return arrPDs;
 }

 public Object[] getForwardRate (CFSIIndexType[] arrIndex,
                 double dTimeSpan,
                 CFSICouponFrequencyType fsiFrequency,
                 CFSIMortgageRateType fsiMortgageRateType,
                 String sParametersPath)
  throws RemoteException, MBSCalculatorException
 {

  updateStatusToJNDI(CalcStatus.CALC_STATUS_BUSY, "getForwardRate", "");

  Object[] arrRates = null;
  try
  {
   arrRates = newMBSCalculator.getForwardRate(arrIndex, dTimeSpan,
                         fsiFrequency, fsiMortgageRateType, sParametersPath);
  }
  finally
  {
   updateStatusToJNDI(CalcStatus.CALC_STATUS_IDLE, "", "");
  }

  return arrRates;
 }

 public Object[] getSampledRates (int nRandonSeed,
                  int nNumberOfPath,
                  GregorianCalendar gcSettleDate,
                  CFSIIndexType[] arrIndex,
                  int nTimeSpan,
                  boolean bTreasury)
  throws RemoteException, MBSCalculatorException
 {

  updateStatusToJNDI(CalcStatus.CALC_STATUS_BUSY, "getSampledRates", "");

  Object[] arrRates = null;
  try
  {
   arrRates = newMBSCalculator.getSampledRates(nRandonSeed,
                         nNumberOfPath, gcSettleDate, arrIndex,
                         nTimeSpan, bTreasury);
  }
  finally
  {
   updateStatusToJNDI(CalcStatus.CALC_STATUS_IDLE, "", "");
  }

  return arrRates;
 }

 public Object[] getIRPCorrelation (CFSIIndexType fsiIndex1,
                   CFSIIndexType fsiIndex2,
                   double dTimeSpan,
                   CFSICouponFrequencyType fsiFrequency)
  throws RemoteException, MBSCalculatorException
 {

  updateStatusToJNDI(CalcStatus.CALC_STATUS_BUSY, "getIRPCorrelation", "");

  Object[] arrCorrelation = null;
  try
  {
   arrCorrelation = newMBSCalculator.getIRPCorrelation(fsiIndex1,
    fsiIndex2, dTimeSpan, fsiFrequency);
  }
  finally
  {
   updateStatusToJNDI(CalcStatus.CALC_STATUS_IDLE, "", "");
  }

  return arrCorrelation;
 }

 public Object[] getBlack (CFSIDerivativeType fsiType,
              CFSIIndexType fsiIndex,
              double dTimeSpan,
              CFSICouponFrequencyType fsiFrequency)
  throws RemoteException, MBSCalculatorException
 {

  updateStatusToJNDI(CalcStatus.CALC_STATUS_BUSY, "getBlack", "");

  Object[] arrBlack = null;
  try
  {
   arrBlack = newMBSCalculator.getBlack(fsiType, fsiIndex,
                      dTimeSpan, fsiFrequency);
  }
  finally
  {
   updateStatusToJNDI(CalcStatus.CALC_STATUS_IDLE, "", "");
  }

  return arrBlack;
 }

 public Object[] getPrepaySpeed (GregorianCalendar gcSettleDate,
                 GregorianCalendar gcMRateDate,
                 IFSIMortgageCollateralDescription fsiDescription,
                 IFSIPrepayModelMatrix fsiMatrix,
                 double[] arrCommitRate30,
                 double[] arrCommitRate15,
                 double[] arrCommitRate07,
                 double[] arrCommitRate05,
                 CFSIPrepaySpeedUnit fsiUnit,
                 CFSIMortgageRateType fsiType,
                 IFSIMBSPrepaymentHistory fsiActualHistory)
  throws RemoteException
 {

  updateStatusToJNDI(CalcStatus.CALC_STATUS_BUSY, "getPrepaySpeed", "");

  Object[] arrSpeeds = null;
  try
  {
   String sPrepModelPath = "";
   if (isWindows)
   {
    sPrepModelPath = fsiMatrix.getPrepayModelParameterPath();
   }
   else
   {
    sPrepModelPath = fsiMatrix.getPrepayModelParameterPathUnix();
   }

   arrSpeeds = getPrepaySpeed(gcSettleDate, gcMRateDate,
                 fsiDescription, sPrepModelPath, arrCommitRate30,
                 arrCommitRate15, arrCommitRate07, arrCommitRate05, fsiUnit,
                 fsiType, fsiActualHistory);
  }
  finally
  {
   updateStatusToJNDI(CalcStatus.CALC_STATUS_IDLE, "", "");
  }

  return arrSpeeds;
 }

 public Object[] getPrepaySpeed (GregorianCalendar gcSettleDate,
                 GregorianCalendar gcMRateDate,
                 IFSIMortgageCollateralDescription fsiDescription,
                 String sPrepayModelPath,
                 double[] arrCommitRate30,
                 double[] arrCommitRate15,
                 double[] arrCommitRate07,
                 double[] arrCommitRate05,
                 CFSIPrepaySpeedUnit fsiUnit,
                 CFSIMortgageRateType fsiType,
                 IFSIMBSPrepaymentHistory fsiActualHistory)
  throws RemoteException
 {

  updateStatusToJNDI(CalcStatus.CALC_STATUS_BUSY, "getPrepaySpeed", "");

  Object[] arrSpeeds = null;
  try
  {
   arrSpeeds = newMBSCalculator.getPrepaySpeed(gcSettleDate,
                         gcMRateDate, fsiDescription, sPrepayModelPath,
                         arrCommitRate30, arrCommitRate15, arrCommitRate07,
                         arrCommitRate05, fsiUnit, fsiType,
                         fsiActualHistory);
  }
  finally
  {
   updateStatusToJNDI(CalcStatus.CALC_STATUS_IDLE, "", "");
  }

  return arrSpeeds;
 }

 public IFSIPrepayModelMatrix getPrepayModelMatrixRemote (
  IFSIPrepayModelMatrix fsiMatrix)
  throws RemoteException
 {

  updateStatusToJNDI(CalcStatus.CALC_STATUS_BUSY, "getPrepayModelMatrixRemote", "");

  IFSIPrepayModelMatrix fsiResult = null;
  try
  {
   String sWinPath = fsiMatrix.getPrepayModelParameterPath();
   String sUnixPath = fsiMatrix.getPrepayModelParameterPathUnix();
   if (!isWindows && null != sUnixPath)
   {
    m_oLogger.debug("Unix platform. Path = " + sUnixPath);
    fsiMatrix.setPrepayModelParameterPath(sUnixPath);
   }
   else
   {
    m_oLogger.debug("Win32 platform. Path = " + sWinPath);
   }

   fsiResult = newMBSCalculator.getPrepayModelMatrix(fsiMatrix);
   fsiResult.setPrepayModelParameterPath(sWinPath);
   fsiResult.setPrepayModelParameterPathUnix(sUnixPath);
  }
  finally
  {
   updateStatusToJNDI(CalcStatus.CALC_STATUS_IDLE, "", "");
  }

  return fsiResult;
 }

 public IFSIEuroDollarFuture loadEuroDollarFutureFromBloomberg (
  IFSIEuroDollarFuture fsiFuture)
  throws RemoteException
 {

  updateStatusToJNDI(CalcStatus.CALC_STATUS_BUSY, "loadEuroDollarFutureFromBloomberg", "");

  IFSIEuroDollarFuture fsiReturned = null;
  try
  {
   fsiReturned = derivativeCalculator.loadEuroDollarFutureFromBloomberg(fsiFuture);
  }
  finally
  {
   updateStatusToJNDI(CalcStatus.CALC_STATUS_IDLE, "", "");
  }

  return fsiReturned;
 }

 public IFSIMBSResults calculate (GregorianCalendar gcSettleDate,
                  long lInputOption,
                  long lOutputOption,
                  IFSIFutureOption fsiOption,
                  IFSIMBSResults fsiResults,
                  CFSIDiscounting fsiDiscounting)
  throws RemoteException, MBSCalculatorException
 {

  updateStatusToJNDI(CalcStatus.CALC_STATUS_BUSY, "calculate", "");

  IFSIMBSResults fsiReturned = null;
  try
  {
   fsiReturned = this.derivativeCalculator.calculate(gcSettleDate,
    lInputOption, lOutputOption, fsiOption,
    fsiResults, fsiDiscounting);
  }
  finally
  {
   updateStatusToJNDI(CalcStatus.CALC_STATUS_IDLE, "", "");
  }

  return fsiReturned;
 }

 public double[] calcPartialDurations (GregorianCalendar gcSettleDate,
                    IFSISecurity fsiSecurity,
                    double dOAS,
                    double[] arrShocks,
                    CFSIDiscounting fsiDiscounting)
  throws RemoteException, MBSCalculatorException
 {

  updateStatusToJNDI(CalcStatus.CALC_STATUS_BUSY, "calcPartialDurations", "");

  double[] arrPDs = null;
  try
  {
   arrPDs = this.derivativeCalculator.calcPartialDurations(
    gcSettleDate, fsiSecurity, dOAS,
    arrShocks, fsiDiscounting);
  }
  finally
  {
   updateStatusToJNDI(CalcStatus.CALC_STATUS_IDLE, "", "");
  }

  return arrPDs;
 }

 public IFSITotalReturnResults calculateTotalReturn (
  GregorianCalendar gcSettleDate,
  IFSISecurity fsiSecurity,
  IFSITotalReturnInput fsiInput,
  IFSITotalReturnResults fsiResults,
  long lOutputOptions,
  IFSIBondResults fsiExtraResults,
  CFSIDiscounting fsiDiscounting)
  throws RemoteException, MBSCalculatorException
 {

  updateStatusToJNDI(CalcStatus.CALC_STATUS_BUSY, "calculateTotalReturn", "");

  IFSITotalReturnResults fsiReturned = null;
  try
  {
   fsiReturned = derivativeCalculator.calculateTotalReturn(
    gcSettleDate, fsiSecurity, fsiInput, fsiResults,
    lOutputOptions, fsiExtraResults, fsiDiscounting);
  }
  finally
  {
   updateStatusToJNDI(CalcStatus.CALC_STATUS_IDLE, "", "");
  }

  return fsiReturned;
 }

 public double getEuroDollarFuturePrice (String sCusip)
  throws RemoteException
 {

  updateStatusToJNDI(CalcStatus.CALC_STATUS_BUSY, "getEuroDollarFuturePrice", sCusip);

  double dPrice = 0.0D;
  try
  {
   dPrice = derivativeCalculator.getEuroDollarFuturePrice(sCusip);
  }
  finally
  {
   updateStatusToJNDI(CalcStatus.CALC_STATUS_IDLE, "", "");
  }

  return dPrice;
 }

 public double getEuroDollarFutureYield (String sCusip)
  throws RemoteException
 {

  updateStatusToJNDI(CalcStatus.CALC_STATUS_BUSY, "getEuroDollarFutureYield", sCusip);

  double dYield = 0.0D;
  try
  {
   dYield = derivativeCalculator.getEuroDollarFutureYield(sCusip);
  }
  finally
  {
   updateStatusToJNDI(CalcStatus.CALC_STATUS_IDLE, "", "");
  }

  return dYield;
 }

 /**
  * for full instructions on how to use this, see NewMBSCalculator.
  */
 public CFSICashFlowMatrix getMBSCashFlows (int iRandomSeed,
                       int iNumberOfSamplingPaths,
                       double dYieldCurveShiftInBps,
                       IFSIMortgageBackedSecurity fsiMBS,
                       IFSIOptionalModelManipulationData
                       fsiOptionalModelManipulationData,
                       CFSIMortgageRateType iMortgageRateModel,
                       CFSIDiscounting iYieldCurveToUseForDiscounting,
                       GregorianCalendar gcYieldCurveDate,
                       GregorianCalendar gcSettleDate,
                       IFSISynthetic fsiSynthetic, // if no modifiers are desired, pass in null.
                       IFSICMOCallOptionSpec fsiCallOptionSpec,
                       long lCashFlowType, // as defined in CFSICashFlowType. Can only represent one type.
                       int iPartialDurationYCShockIndex, // ignored if the cash flow type does not denote partial duration. This
                       // is not an index among all the yield curve points, but only among the shocked points. Thus, if there are
                       // two shocked points, then a value of 1 refers to the second shocked point, not necessarily the two-month maturity.
                       boolean bCalculateDollarRoll,
                       IFSITotalReturnInput fsiTotalReturnInput, // ignored if the cash flow type is not one of the total return
                       // types (set to null in this case).
                       long lCalculationOutputOptionsForTotalReturnOnly)
  throws RemoteException
 {

  updateStatusToJNDI(CalcStatus.CALC_STATUS_BUSY, "getMBSCashFlows", "");

  CFSICashFlowMatrix fsiMatrix = null;
  try
  {
   fsiMatrix = newMBSCalculator.getMBSCashFlows(
    iRandomSeed, iNumberOfSamplingPaths, dYieldCurveShiftInBps,
    fsiMBS, fsiOptionalModelManipulationData, iMortgageRateModel,
    iYieldCurveToUseForDiscounting,
    gcYieldCurveDate, gcSettleDate, fsiSynthetic, fsiCallOptionSpec, lCashFlowType,
    iPartialDurationYCShockIndex, bCalculateDollarRoll, fsiTotalReturnInput,
    lCalculationOutputOptionsForTotalReturnOnly);
  }
  finally
  {
   updateStatusToJNDI(CalcStatus.CALC_STATUS_IDLE, "", "");
  }

  return fsiMatrix;
 }

 public long getNecessaryCashFlowTypesForCalculations (
  long lInputOptions, // as defined in IFSICalculationOptions
  long lOutputOptions) // as defined in IFSICalculationOptions
  throws RemoteException
 {

  updateStatusToJNDI(CalcStatus.CALC_STATUS_BUSY, "getNecessaryCashFlowTypesForCalculations", "");

  long lType;
  try
  {
   lType = SecurityCalculator.getNecessaryCashFlowTypesForCalculations(
    lInputOptions, lOutputOptions);
  }
  finally
  {
   updateStatusToJNDI(CalcStatus.CALC_STATUS_IDLE, "", "");
  }

  return lType;
 }

 // see com.fsillc.natif.release5.SecurityCalculator.java for documentation.
 public IFSIMBSResults[] calculateDynamicMeasuresGivenCashFlows (
  long lInputOptions,
  long lOutputOptions,
  CFSIDynamicMeasuresCashFlowMatrixManager[] arrManagers,
  IFSIMBSDollarRoll fsiMBSDollarRoll,
  IFSIMBSResults[] arrMBSResults)
  throws RemoteException
 {

  // the function signature here is different than the native method. This is to accomodate a weird bug
  // in RMI where modifications to an object sent from the client are lost when the function returns. Thus,
  // we actually return the MBSResults array in addition to modifying it.

  updateStatusToJNDI(CalcStatus.CALC_STATUS_BUSY, "calculateDynamicMeasuresGivenCashFlows", "");

  try
  {
   SecurityCalculator.calculateDynamicMeasuresGivenCashFlows(
    lInputOptions, lOutputOptions, arrManagers,
    fsiMBSDollarRoll, arrMBSResults);
  }
  finally
  {
   updateStatusToJNDI(CalcStatus.CALC_STATUS_IDLE, "", "");
  }

  return arrMBSResults;
 }

 // This must be called before getting partial duration cash flows. The values in the maturities array
 // should be in months.
 public void applyPartialDurationYCShocksToIRTree (
  double[] arrYCMaturitiesToShock,
  double dShockMagnitude)
  throws RemoteException
 {

  updateStatusToJNDI(CalcStatus.CALC_STATUS_BUSY, "applyPartialDurationYCShocksToIRTree", "");

  try
  {
   if (arrYCMaturitiesToShock.length < 2)
   {
    throw new RuntimeException(
     "The yield curve must have at least two shocks for partial duration calculation.");
   }
   SecurityCalculator.applyPartialDurationYCShocksToIRTree(
    arrYCMaturitiesToShock, dShockMagnitude);
  }
  finally
  {
   updateStatusToJNDI(CalcStatus.CALC_STATUS_IDLE, "", "");
  }
 }

 // see com.fsillc.natif.release5.SecurityCalculator.java for documentation.
 public double[] calculatePartialDurationGivenCashFlows (
  double dPrice,
  double dOAS,
  CFSIPartialDurationCashFlowMatrixManager[] arrManagers)
  throws RemoteException
 {

  updateStatusToJNDI(CalcStatus.CALC_STATUS_BUSY, "calculatePartialDurationGivenCashFlows", "");

  double[] arrPD = null;
  try
  {
   arrPD = SecurityCalculator.calculatePartialDurationGivenCashFlows(
    dPrice, dOAS, arrManagers);
  }
  finally
  {
   updateStatusToJNDI(CalcStatus.CALC_STATUS_IDLE, "", "");
  }

  return arrPD;
 }

 public double calculateAverageLifeEquivPrepaymentSpeed (
  double[] prepaySpeedsInSMM,
  int nMonths,
  double dWAC,
  int nOrigTerm,
  int nAge,
  int iWAM,
  CFSIPrepaySpeedUnit nOutputAvgPrepaySpeedTypeFlag)
  throws RemoteException
 {

  updateStatusToJNDI(CalcStatus.CALC_STATUS_BUSY, "calculateAverageLifeEquivPrepaymentSpeed", "");

  double dSpeed = 0.0D;
  try
  {
   dSpeed = newMBSCalculator.calculateAverageLifeEquivPrepaymentSpeed(
    prepaySpeedsInSMM, nMonths, dWAC, nOrigTerm, nAge,
    iWAM, nOutputAvgPrepaySpeedTypeFlag.intValue());
  }
  finally
  {
   updateStatusToJNDI(CalcStatus.CALC_STATUS_IDLE, "", "");
  }

  return dSpeed;
 }

 public IFSITotalReturnResults calculateTotalReturnGivenCashFlows (
  IFSITotalReturnInput fsiTotalReturnInput,
  IFSITotalReturnResults fsiTotalReturnResults,
  long lOutputOptions,
  CFSITotalReturnCashFlowMatrixManager[] arrManagers)
  throws RemoteException
 {

  updateStatusToJNDI(CalcStatus.CALC_STATUS_BUSY, "calculateTotalReturnGivenCashFlows", "");

  try
  {
   SecurityCalculator.calculateTotalReturnGivenCashFlows(
    fsiTotalReturnInput, fsiTotalReturnResults,
    lOutputOptions, arrManagers);
  }
  finally
  {
   updateStatusToJNDI(CalcStatus.CALC_STATUS_IDLE, "", "");
  }

  return fsiTotalReturnResults;
 }

 public IFSIPrepayLoanLevelDescription retrieveDefaultLoanLevelParameters (
  IFSIPrepayLoanLevelDescription fsiLevel,
  String strPrepayModelPath,
  String strAgency,
  int nOrigTerm,
  int nIf0IsFixedIf1IsArm)
  throws RemoteException
 {

  updateStatusToJNDI(CalcStatus.CALC_STATUS_BUSY, "retrieveDefaultLoanLevelParameters", strAgency);

  IFSIPrepayLoanLevelDescription fsiDes = null;
  try
  {
   fsiDes = newMBSCalculator.retrieveDefaultLoanLevelParameters(
    fsiLevel, strPrepayModelPath,
    strAgency, nOrigTerm, nIf0IsFixedIf1IsArm);
  }
  finally
  {
   updateStatusToJNDI(CalcStatus.CALC_STATUS_IDLE, "", "");
  }

  return fsiDes;
 }

 public double[] smmToCpr (double[] arrSMMs)
  throws RemoteException
 {
  updateStatusToJNDI(CalcStatus.CALC_STATUS_BUSY, "smmToCpr", "");

  double[] arrCPRs = null;
  try
  {
   arrCPRs = newMBSCalculator.smmToCpr(arrSMMs);
  }
  finally
  {
   updateStatusToJNDI(CalcStatus.CALC_STATUS_IDLE, "", "");
  }

  return arrCPRs;
 }

 public long getTTRCashFlowTypes (IFSITotalReturnInput fsiInput,
                  long lFlagsAtHorizon)
  throws RemoteException
 {

  updateStatusToJNDI(CalcStatus.CALC_STATUS_BUSY, "getTTRCashFlowTypes", "");

  long lTypes = 0L;
  try
  {
   lTypes = newMBSCalculator.getTTRCashFlowTypes(fsiInput,
    lFlagsAtHorizon);
  }
  finally
  {
   updateStatusToJNDI(CalcStatus.CALC_STATUS_IDLE, "", "");
  }

  return lTypes;
 }

  public boolean detectManagerHeartBeat() throws RemoteException {
    // Bigegg - This method will be called inside the JNDI server's cleanup
    // thread. It tries to detect the manager heart beat and returns true
    // if succeeds.
    m_oLogger.debug("in Calculator.detectManagerHeartBeat()");

    // We will give it three tries.
    for (int i = 0; i < 3; i++) {
      try {
        if (getManagerHeartBeat().healthDetect())
          return true;
      }
      catch (Exception e) {
        m_oLogger.debug("Couldn't detect the manager heart beat, will retry", e);
      }

      // Sleep for 500 mili-seconds
      try {
        Thread.sleep(500);
      }
      catch (InterruptedException e) {
        // ignored
      }
    }

    m_oLogger.warn("Manager seems dead, this Calculator will be destroyed soon");
    return false;
  }

 public void updateAvailability ()
  throws RemoteException
 {
  // Bigegg - This method is only called inside the JNDI server, so we don't
  // call the update JNDI status here.
  m_oLogger.debug("in Calculator.updateAvailability()");

  // Shane - If the GUI crashes, all the calculator it uses will not be set to
  // be available. When the GUI retrieves a calculator, it sends a "heart beat"
  // to the calculator which is cached in m_fsiFSIHeartBeat.

  // When setAvailable() is called, m_fsiFSIHeartBeat is set to null.
  // If the GUI crasehs, when the cleanup pool thread invokes this method,
  // all the calculators will have their availability status updated correctly.

  // Bigegg on 2005/06/11
  // This method will only called by FSINamingServer cleanup thread
  if (isLocked())
  {
   m_oLogger.debug("The Calculator is locked by GUI, going to detect the GUI's availability");
   // We will detect the locking GUI still there
   // We will give it more than one chances
   for (int i = 0; i < 3; i++)
   {
    try
    {
     if (getGUIHeartBeat().healthDetect())
     {
      m_oLogger.debug("GUI's heart beat is responding");
      return;
     }
    }
    catch (Exception ex)
    {
     // ignored
     m_oLogger.warn("GUI failed to respond");
    }

    try
    {
     Thread.sleep(3000);
    }
    catch (InterruptedException e)
    {
     // ignored
    }
   }

   m_oLogger.debug("GUI heart beat doesn't respond, going to remove the lock on this Calculator");
   setGUIHeartBeat(null);
  }
 }

 public FSIHeartBeat getManagerHeartBeat ()
  throws RemoteException
 {
  return m_fsiManagerHeartBeat;
 }

 public void setManagerHeartBeat (FSIHeartBeat fsiHeartBeat)
  throws RemoteException
 {
  m_fsiManagerHeartBeat = fsiHeartBeat;
 }

 public void shutdown ()
  throws RemoteException
 {
  System.exit( -1);
 }

 public void fakeCallForTest (long mills)
  throws RemoteException
 {
  updateStatusToJNDI(CalcStatus.CALC_STATUS_BUSY, "fakeCallForTest", "");

  try
  {
   Thread.sleep(mills);
  }
  catch (InterruptedException ex)
  {
   // ignored
  }

  updateStatusToJNDI(CalcStatus.CALC_STATUS_IDLE, "", "");
 }

 public boolean isLocked ()
 {
  return getGUIHeartBeat() != null;
 }

 public String getLockedBy ()
 {
  return getHostFromHeartBeat(getGUIHeartBeat());
 }

 //
 // Private or protected helper methods
 //

 private void setGUIHeartBeat (FSIHeartBeat hb)
 {
  this.m_fsiGUIHeartBeat = hb;
 }

 private FSIHeartBeat getGUIHeartBeat ()
 {
  return m_fsiGUIHeartBeat;
 }

 /**
  * Use the system property "os.name" to judge if the underlying
  * platform is Windows or Unix
  */
 private boolean isWindowsPlatform ()
 {
  String osName = System.getProperty("os.name");
  m_oLogger.info("Constructing CalculatorImplementation for " + osName);
  if (osName.indexOf("Windows") > -1)
  {
   return true;
  }
  else
  {
   return false;
  }
 }

 /**
  * Update the status of this Calculator to the JNDI server. This method also
  * update the time of function calling, so we may possibly implementation
  * a mechanism to detect those long running methods or those lost
  * Calculators.
  *
  * @param status
  * @param methodName
  * @param cusip
  */
 protected void updateStatusToJNDI (int status, String methodName, String cusip)
 {

  if (status == CalcStatus.CALC_STATUS_BUSY)
  {
   m_oLogger.debug("in Calculator." + methodName + "()");
  }
  else
  {
   m_oLogger.debug("About to return from the above method");
  }

  setTimeOfLastFunctionCall();

  try
  {
   // Bigegg on 2005/6/8
   // Now we just update the calc status to JNDI server
   String lockedBy = getHostFromHeartBeat(getGUIHeartBeat());
   m_oLogger.debug("updating Calc status to JNDI server: Calc Name=" + calcName +
           ", status=" + status + ", Method=" + methodName + ", lockedBy = " + lockedBy);

   boolean isLocked = isLocked();
   long lastUpdateTime = System.currentTimeMillis();

   CalcStatus calcStatus = new CalcStatus(CalcStatus.NODE_TYPE_CALC,
                       calcName, status, methodName, cusip, lastUpdateTime,
                       isLocked, lockedBy, calcType);
   FSINamingContext context = JNDIHelper.getFSIContext();
   context.updateCalculatorStatus(calcName, this, calcStatus);
  }
  catch (Exception ex)
  {
   m_oLogger.warn("Error update this calculator status to the JNDI server", ex);
  }
 }

 // Should be called at the beginning of every calculation function call.
 // timeOfLastFunctionCall is used to determine if a calculator is no longer
 // unavailable because it has expired.
 private void setTimeOfLastFunctionCall ()
 {
  timeOfLastFunctionCall = System.currentTimeMillis();
 }

 protected void init ()
  throws RemoteException, MBSCalculator.NoDLLException, MBSCalculatorException
 {

  // Bigegg - Initialize intenal calculators. These calculator implementation
  // needs two path parameter in their constructors. This could probably also
  // deprecated, but it involves some native methods. I will confirm with Shane
  // to remove them from the constructors.
  mbsCalculator = new MBSCalculator("", "");
  newMBSCalculator = new NewMBSCalculator("", "");
  bondCalculator = new BondCalculator("mbsc");
  derivativeCalculator = new DerivativeCalculator();

  try
  {
   getMarketData = new GetMarketData();
  }
  catch (Exception e)
  {
   getMarketData = null;
  }

  strScenarioInitializationId = "";
  try
  {
   strHostName = InetAddress.getLocalHost().getHostName().toLowerCase();
  }
  catch (UnknownHostException e)
  {
   strHostName = "";
  }
 }

 private String getHostFromHeartBeat (FSIHeartBeat hb)
 {
  if (hb == null)
  {
   return "";
  }
  try
  {
   return hb.getHostname();
  }
  catch (Exception ex)
  {
   m_oLogger.warn("Wrong heart beat", ex);
   return "";
  }
 }

 /**
  * @param prepayModelPath
  * @param cmoDataVendorPath
  * @throws RemoteException
  * @throws NoDLLException
  * @throws MBSCalculatorException
  */
 private void internalResetPaths (String prepayModelPath, String cmoDataVendorPath)
  throws RemoteException, NoDLLException, MBSCalculatorException
 {
  checkCMOPaths(cmoDataVendorPath);
  checkPrepayModelPath(prepayModelPath);
  mbsCalculator.resetPaths(prepayModelPath, cmoDataVendorPath);
 }

 private void checkCMOPaths (String sCMOPaths)
  throws RemoteException
 {
  String[] sPath = CalculatorUtils.extractCMOPaths(sCMOPaths);
  String sCDIPath = sPath[0];
  String sCDUPath = sPath[1];

  m_oLogger.debug("Checking paths: " + sCDIPath + " and " + sCDUPath);
  checkCMOPaths(sCDIPath, sCDUPath);
 }

 private void checkCMOPaths (String sCDIPath, String sCDUPath)
  throws RemoteException
 {

  String sErrorMessage = "";
  boolean blnCDIPathValid = true;
  boolean blnCDUPathValid = true;

  if (sCDIPath.trim().length() > 0)
  {
   blnCDIPathValid = isPathValid(sCDIPath);
  }
  if (sCDUPath.trim().length() > 0)
  {
   blnCDUPathValid = isPathValid(sCDUPath);
  }
  if (!blnCDIPathValid && !blnCDUPathValid)
  {
   sErrorMessage = "Invalid CDI and CDU paths: '" + sCDIPath + "' and '" + sCDUPath + "'";
  }
  else if (!blnCDIPathValid)
  {
   sErrorMessage = "The path '" + sCDIPath + "' is not valid.";
  }
  else if (!blnCDUPathValid)
  {
   sErrorMessage = "The path '" + sCDUPath + "' is not valid.";
  }
  if (sErrorMessage.length() > 0)
  {
   throw new RemoteException(sErrorMessage);
  }
 }

 private void resetPaths (IFSIMortgageBackedSecurity fsiMBS)
 {
  IFSISecurityDataSource dataSource = fsiMBS.getSecurityDataSource();
  IFSIPrepayModelMatrix fsiMatrix = fsiMBS.getPrepayModelMatrix();

  // Shane - Reset the prepay model path here also
  m_oLogger.debug("The data source of this MBS is " + dataSource);
  if (isWindows)
  {
   if (fsiMBS.getType().equals(CFSIMBSTypes.FRM_CMO) && null != dataSource)
   {
    fsiMBS.setCMOProviderDataDirectoryPath(
     dataSource.getPath() + " " + dataSource.getPath2());
   }

   if (null != fsiMatrix)
   {
    fsiMBS.setParamsDir(fsiMatrix.getPrepayModelParameterPath());
   }
   m_oLogger.debug("Windows Platform, using " + fsiMBS.getCMOProviderDataDirectoryPath() +
           "/n and " + fsiMBS.getParamsDir() + " for " + fsiMBS.getCusip());
  }
  else
  {
   if (null != dataSource)
   {
    fsiMBS.setCMOProviderDataDirectoryPath(
     dataSource.getPathUnix() + " " + dataSource.getPathUnix2());
   }

   if (null != fsiMatrix)
   {
    fsiMBS.setParamsDir(fsiMatrix.getPrepayModelParameterPathUnix());
   }
   m_oLogger.debug("Unix Platform, using " + fsiMBS.getCMOProviderDataDirectoryPath() +
           "/n and " + fsiMBS.getParamsDir() + " for " + fsiMBS.getCusip());

  }
 }

 private void checkPrepayModelPath (String sPrepayModelPathToUse)
  throws RemoteException
 {
  boolean blnPrepayModelPathValid = isPathValid(sPrepayModelPathToUse);

  if (!blnPrepayModelPathValid ||
    sPrepayModelPathToUse.trim().length() == 0)
  {
   String sErrorMessage = "Prepay Model Path '" + sPrepayModelPathToUse + "' is not valid.";
   throw new RemoteException(sErrorMessage);
  }
 }

 private void checkIDCPath (String sIDCPath)
  throws RemoteException
 {
  String sErrorMessage = "";
  if (sIDCPath.trim().length() == 0)
  {
   sErrorMessage = "IDC Path is not specified.";
  }
  else if (!isPathValid(sIDCPath))
  {
   sErrorMessage = "IDC Path '" + sIDCPath + "' is not valid.";
  }
  if (sErrorMessage.length() > 0)
  {
   throw new RemoteException(sErrorMessage);
  }
 }

 private boolean isPathValid (String sPath)
 {
  return!CalculatorUtils.pathInvalid(sPath);
 }

}

在每个计算业务方法开始都有updateStatusToJNDI(CalcStatus.CALC_STATUS_BUSY, "setScenarioInitializationId", "");和结尾都有  updateStatusToJNDI(CalcStatus.CALC_STATUS_IDLE, "", "");

这样的代码。而且这个类中的计算业务方法非常多,我不清楚作者copy paste这些updateStatusToJNDI是否感觉到累。而且我们应该把业务方法和这些updateStatusToJNDI方法的关注点分离(aop的概念)。我决定把这个类进行refactor。

而且我觉得使用java的动态代理进行refactor比较好,不用引入其他第三方包。

下面是我的最终结果。Calculator是计算类的接口。

/*
 * Created on 2005-7-5
 */
package com.fsillc.remote.server;

import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method;
import java.lang.reflect.Proxy;

import com.fsillc.remote.interfaces.Calculator;
import com.fsillc.remote.util.CalcStatus;

/**
 *   This class is use for update the calculator's status.
 *  
 *  
 *   @author deng.yin(邓胤)
 */

public class CalculatorProxy implements InvocationHandler {

    private Object calculator;
   
    private CalculatorProxy(Object calculator){
        this.calculator = calculator;
    }
   
    private static Calculator getProxyInstance(Object calculator){
       
       return  (Calculator) Proxy.newProxyInstance(calculator.getClass().getClassLoader(),calculator.getClass().getInterfaces(),new CalculatorProxy(calculator));
    }
   
    public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
        Object returnObject = null;
        CalculatorImplementation calc = (CalculatorImplementation) calculator;
        try{
            // before calculation, change the calculator's status to busy
            calc.updateStatusToJNDI(CalcStatus.CALC_STATUS_BUSY,method.getName(),"");
            returnObject = method.invoke(calculator,args);
        }finally{
            //whenever the calculation successfully, change the calculator's status to idle
            calc.updateStatusToJNDI(CalcStatus.CALC_STATUS_IDLE, "", "");
        }
       
        return returnObject;
    }

   
}

 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值