/////////////////////////////////////////////////////////////////////////
//
// © University of Southampton IT Innovation Centre, 2004
//
// Copyright in this library belongs to the IT Innovation Centre of
// 2 Venture Road, Chilworth Science Park, Southampton, SO16 7NP, UK.
//
// This software may not be used, sold, licensed, transferred, copied
// or reproduced in whole or in part in any manner or form or in or
// on any media by any person other than in accordance with the terms
// of the Licence Agreement supplied with the software, or otherwise
// without the prior written consent of the copyright owners.
//
// This software is distributed WITHOUT ANY WARRANTY, without even the
// implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
// PURPOSE, except where stated in the Licence Agreement supplied with
// the software.
//
//      Created by:             Stuart E. Middleton
//      Created date:           2004/04/30
//      Created for project:    GEMSS
//
/////////////////////////////////////////////////////////////////////////
//
//      Dependencies: None
//
/////////////////////////////////////////////////////////////////////////
//
//      Last commit info:       $Author: $
//                              $Date: $
//                              $Revision: $
//
/////////////////////////////////////////////////////////////////////////

package uk.ac.soton.itinnovation.gemss.proxies;

import java.lang.*;
import java.util.*;
import java.io.*;
import java.net.*;
import java.util.logging.Level;
import java.util.logging.Logger;

import uk.ac.soton.itinnovation.gemss.proxies.*;
import uk.ac.soton.itinnovation.gemss.transportmessaging.*;
import uk.ac.soton.itinnovation.gemss.transportmessaging.servicedescription.*;
import uk.ac.soton.itinnovation.gemss.transportmessaging.servicedescription.interfacetypes.*;
import uk.ac.soton.itinnovation.gemss.transportmessaging.servicedescription.policytypes.*;
import uk.ac.soton.itinnovation.gemss.transportmessaging.servicedescription.endpointtypes.*;
import uk.ac.soton.itinnovation.gemss.transportmessaging.payload.typedescriptions.*;
import uk.ac.soton.itinnovation.gemss.transportmessaging.proxies.gemss.*;
import uk.ac.soton.itinnovation.gemss.state.*;
import uk.ac.soton.itinnovation.gemss.xmlobject.XMLObject;
import uk.ac.soton.itinnovation.gemss.transportmessaging.payload.*;

import eu.gemss.GridException;
import eu.gemss.GEMSS;
import eu.gemss.components.*;
import eu.gemss.components.proxies.*;
import eu.gemss.components.transport.*;
import eu.gemss.components.transport.payload.*;

import javax.wsdl.xml.*;
import javax.wsdl.factory.*;
import javax.wsdl.*;
import org.jdom.output.*;
import org.jdom.input.*;
import javax.xml.transform.dom.*;
import javax.xml.parsers.*;
import org.w3c.dom.*;

/*
* GEMSSProxy class implementation. Ths class provides the GEMSSProxy interface, and has a
* WebServiceInvoker attribute which will actually make all web service invocations.
*/
public class GEMSSProxyImp implements Terminable, Serializable, GEMSSProxy {

      // member variables
      private State mstate;
      private WebServiceInvoker mWSInvoker;
      private int mHandleCounter;

      // test
      // TODO remove this and replace with account call to get ID
      private String mstrNegID = null;
      // end test

      // app service special status return strings (if not app XML data)
      private final static String mstaticFinishedStatusValue = "FINISHED";
      private final static String mstaticFailedStatusValue = "FAILED";
      private final static String mstaticKilledStatusValue = "KILLED";

      // private object labels
      // job handling
      private final static String mstaticWSDLURI = "WSDLURI";
      private final static String mstaticServiceName = "ServiceName";
      private final static String mstaticEndPointPortName = "EndPointPortType";
      private final static String mstaticServicePortType = "ServicePortType";
      private final static String mstaticBinding = "Binding";

      private final static String mstaticOpGetJobCID = "GetJobCIDOp";
      private final static String mstaticOpUploadData = "UploadAttachmentOp";
      private final static String mstaticOpStart = "StartOp";
      private final static String mstaticOpKill = "KillOp";
      private final static String mstaticOpGetStatus = "GetStatusOp";
      private final static String mstaticOpDownload = "DownloadAttachmentOp";
      private final static String mstaticOpAcknowledgeResults = "AcknowledgeResultsOp";

      // args to all the operations (job handling and negotiation)
      private final static String mstaticArgConversationID = "CIdArg";
      private final static String mstaticArgFilenameParam = "DownloadFilename";
      private final static String mstaticArgInputDataFileTag = "InputFileTag";
      private final static String mstaticArgOutputDataFileTag = "DownloadFileTag";
      private final static String mstaticArgAuctionMessage = "AuctionMessageTag";

      // negotiation
      private final static String mstaticOpGetNegCID = "GetNegCIDOp";
      private final static String mstaticOpGetWSLA = "GetWSLAOp";
      private final static String mstaticOpUploadRequestDesc = "UploadRequestDescAttachmentOp";
      private final static String mstaticOpAuctionInform = "AuctionInformOp";
      private final static String mstaticOpAuctionCFP = "AuctionCFPOp";
      private final static String mstaticOpAuctionPropose = "AuctionProposeOp";
      private final static String mstaticOpAuctionAcceptProposal = "AuctionAcceptProposalOp";
      private final static String mstaticOpAuctionRejectProposal = "AuctionRejectProposalOp";
      private final static String mstaticOpAuctionRequest = "AuctionRequestOp";

      // security policy
      private final static String mstaticUsePolicyFile = "UseSecurityPolicyFile";
      public final static boolean mbstaticUsePolicyFileDefault = true; // if false NoPolicy used

      // conversation ID's
      private final static String mstaticJobConvID = "JobConversationID";
      private final static String mstaticNegConvID = "NegConversationID";
      private final static String mstaticAccountConvID = "AccountConversationID";

      // logger variable etc
      private Logger mlogger = Logger.getLogger("uk.ac.soton.itinnovation.gemss.proxies.gemssproxyimp");
      private final static String mstaticWSInvokerName = "eu.gemss.components.proxies.WebServiceInvoker";
      private static final int mstaticInvocationStatusCheckDelay = 100; // 1/10 of a second to let RPC get it together


      /**
       * constructor
       */
      public GEMSSProxyImp()
      {
            super();

            // The GEMSSProxyProvider will create a new instance of the
            // proxy component each time it is asked to. This proxy init() method will be called by the
            // GEMSSProxyProvider to initialize. However, we should do the alloc of objects
            // in the constructor.
            mstate = new State();
            mHandleCounter = 1;
            mWSInvoker = null;

            // all done
            return;
      }

      /**
       * destructor
       */
      public void finalize() throws Throwable
      {
            // all done
            return;
      }

      /**
       * Signal to kill on-going threads but do not wait for them to finish. If state is required to be saved
       * then the serialization functions should have been called prior to this method.
       */
      synchronized public void terminate()
      {
            try
            {
                  // Nothing to do since all proxy methods are blocking
                  return;
            }
            catch ( Exception ex )
            {
                  mlogger.log( Level.SEVERE,"Exception during terminate",ex);
                  return;
            }
      }

      /**
       * Initiate the GEMSSProxy. An end point is provided so the proxy can be attached to a
       * single service end point. The functions provided by the GEMSSProxy are simple wrappers
       * to the application service WSDL defined functions.
       * @param strConfigFile Config file containing the service proxy details such as bindings and operation names
       */
      public void init( String strConfigFile ) throws Exception
      {
            Properties props;
            ComponentManager compMan;
            Boolean bUsePolicyFile;
            String strValue;

            try
            {
                  // check param
                  if( strConfigFile == null ) throw new IOException("null filename");

                  // read the configuration options from the config file
                  props = new Properties();
                  props.load( new FileInputStream( strConfigFile ) );

                  // read parameters. Note the static config file tags are re-used for state tags to save
                  // defining a whole new set of tags
                  mstate.addObject( mstaticWSDLURI,props.getProperty( mstaticWSDLURI ) );
                  mstate.addObject( mstaticServiceName,props.getProperty( mstaticServiceName ) );
                  mstate.addObject( mstaticEndPointPortName,props.getProperty( mstaticEndPointPortName ) );
                  mstate.addObject( mstaticServicePortType,props.getProperty( mstaticServicePortType ) );
                  mstate.addObject( mstaticBinding,props.getProperty( mstaticBinding ) );

                  // add job handling operation names
                  mstate.addObject( mstaticOpUploadData,props.getProperty( mstaticOpUploadData ) );
                  mstate.addObject( mstaticOpStart,props.getProperty( mstaticOpStart ) );
                  mstate.addObject( mstaticOpKill,props.getProperty( mstaticOpKill ) );
                  mstate.addObject( mstaticOpGetStatus,props.getProperty( mstaticOpGetStatus ) );
                  mstate.addObject( mstaticOpDownload,props.getProperty( mstaticOpDownload ) );
                  mstate.addObject( mstaticOpAcknowledgeResults,props.getProperty( mstaticOpAcknowledgeResults ) );
                  mstate.addObject( mstaticOpGetJobCID,props.getProperty( mstaticOpGetJobCID ) );

                  // add neg operation names
                  mstate.addObject( mstaticOpGetWSLA,props.getProperty( mstaticOpGetWSLA ) );
                  mstate.addObject( mstaticOpUploadRequestDesc,props.getProperty( mstaticOpUploadRequestDesc ) );
                  mstate.addObject( mstaticOpAuctionInform,props.getProperty( mstaticOpAuctionInform ) );
                  mstate.addObject( mstaticOpAuctionCFP,props.getProperty( mstaticOpAuctionCFP ) );
                  mstate.addObject( mstaticOpAuctionPropose,props.getProperty( mstaticOpAuctionPropose ) );
                  mstate.addObject( mstaticOpAuctionAcceptProposal,props.getProperty( mstaticOpAuctionAcceptProposal ) );
                  mstate.addObject( mstaticOpAuctionRejectProposal,props.getProperty( mstaticOpAuctionRejectProposal ) );
                  mstate.addObject( mstaticOpAuctionRequest,props.getProperty( mstaticOpAuctionRequest ) );
                  mstate.addObject( mstaticOpGetNegCID,props.getProperty( mstaticOpGetNegCID ) );

                  // add argument types
                  mstate.addObject( mstaticArgConversationID,props.getProperty( mstaticArgConversationID ) );
                  mstate.addObject( mstaticArgFilenameParam,props.getProperty( mstaticArgFilenameParam ) );
                  mstate.addObject( mstaticArgInputDataFileTag,props.getProperty( mstaticArgInputDataFileTag ) );
                  mstate.addObject( mstaticArgOutputDataFileTag,props.getProperty( mstaticArgOutputDataFileTag ) );
                  mstate.addObject( mstaticArgAuctionMessage,props.getProperty( mstaticArgAuctionMessage ) );

                  // add policy setting
                  strValue = props.getProperty( mstaticUsePolicyFile );
                  if( strValue == null ) {
                        bUsePolicyFile = new Boolean( mbstaticUsePolicyFileDefault ); // default value
                        mlogger.log( Level.INFO,"Proxy security policy = "+bUsePolicyFile+" (default)");
                  }
                  else {
                        bUsePolicyFile = Boolean.valueOf( strValue );
                        mlogger.log( Level.INFO,"Proxy security policy = "+bUsePolicyFile);
                  }
                  mstate.addObject( mstaticUsePolicyFile,bUsePolicyFile );

                  // get the component manager
                  compMan = GEMSS.getInstance();
                  if( compMan == null ) throw new Exception("null component manager");

                  // make a WebServiceInvoker object
                  mWSInvoker = (WebServiceInvoker) compMan.getInstance( mstaticWSInvokerName );
                  if( mWSInvoker == null ) throw new Exception("null invoker");

                  // all done
                  return;
            }
            catch ( IOException ioex )
            {
                  mlogger.log( Level.SEVERE,"IOException during init",ioex);
                  throw new Exception("init failed loading config file");
            }
            catch ( Exception ex )
            {
                  mlogger.log( Level.SEVERE,"Exception during init",ex);
                  throw new Exception("init failed");
            }
      }

      /**
       * Initiate the GEMSSProxy. An end point is provided so the proxy can be attached to a
       * single service end point. The functions provided by the GEMSSProxy are simple wrappers
       * to the application service WSDL defined functions.
       * @param strWSDLURI WSDL URI for this proxy to bind to
       * @param strServiceName The name of the service
       * @param strEndPointPortName The name of the end point port
       * @param strServicePortType The name of the service port
       * @param strBinding The binding type to be used
       * @param strOpUploadData Name of the upload operation
       * @param strOpStart Name of the start operation
       * @param strOpKill Name of the kill operation
       * @param strOpGetStatus Name of the get status op
       * @param strOpDownload Name of the download op
       * @param strOpAcknowledgeResults Name of the acknowledge results op
       * @param strOpGetWSLA Name of the get WSLA op
       * @param strOpUploadRequestDesc Name of the upload request descriptor file op
       * @param strOpAuctionInform Name of the auction inform op
       * @param strOpAuctionCFP Name of the auction call for proposals op
       * @param strOpAuctionPropose Name of the auctino propose op
       * @param strOpAuctionAcceptProposal Name of the auction accept proposal op
       * @param strOpAuctionRejectProposal Name of the auction reject proposal op
       * @param strOpAuctionRequest Name of the auction request op
       * @param strOpGetJobCID Name of the getJobCID op
       * @param strOpGetNegCID Name of the getNegCID op
       * @param strArgConversationID Name of the conv ID argument type
       * @param strArgFilenameParam Name of the filename argument type
       * @param strArgInputDataFileTag Name of the input file tag argument (for SOAP attachment version of upload/download)
       * @param strArgOutputDataFileTag Name of the output file tag argument (for SOAP attachment version of upload/download)
       * @param strArgAuctionMessage Name of the auction message tag argument
       * @param bUsePolicy use security policy (false = no policy)
       */
      public void init( String strWSDLURI, String strServiceName, String strEndPointPortName, String strServicePortType,
                        String strBinding, String strOpUploadData, String strOpStart, String strOpKill,
                        String strOpGetStatus, String strOpDownload, String strOpAcknowledgeResults,
                        String strOpGetWSLA, String strOpUploadRequestDesc, String strOpAuctionInform, String strOpAuctionCFP,
                        String strOpAuctionPropose, String strOpAuctionAcceptProposal, String strOpAuctionRejectProposal,
                        String strOpAuctionRequest, String strOpGetJobCID, String strOpGetNegCID,
                        String strArgConversationID, String strArgFilenameParam, String strArgInputDataFileTag, String strArgOutputDataFileTag,
                        String strArgAuctionMessage,
                        boolean bUsePolicy ) throws Exception
      {
            ComponentManager compMan;

            try
            {
                  // WSDL stuff
                  mstate.addObject( mstaticWSDLURI,strWSDLURI );
                  mstate.addObject( mstaticServiceName,strServiceName );
                  mstate.addObject( mstaticEndPointPortName,strEndPointPortName );
                  mstate.addObject( mstaticServicePortType,strServicePortType );
                  mstate.addObject( mstaticBinding,strBinding );

                  // add operation names (job handling)
                  mstate.addObject( mstaticOpUploadData,strOpUploadData );
                  mstate.addObject( mstaticOpStart,strOpStart );
                  mstate.addObject( mstaticOpKill,strOpKill );
                  mstate.addObject( mstaticOpGetStatus,strOpGetStatus );
                  mstate.addObject( mstaticOpDownload,strOpDownload );
                  mstate.addObject( mstaticOpGetJobCID,strOpGetJobCID );
                  mstate.addObject( mstaticOpAcknowledgeResults,strOpAcknowledgeResults );

                  // add neg operation names
                  mstate.addObject( mstaticOpGetWSLA,strOpGetWSLA );
                  mstate.addObject( mstaticOpUploadRequestDesc,strOpUploadRequestDesc );
                  mstate.addObject( mstaticOpAuctionInform,strOpAuctionInform );
                  mstate.addObject( mstaticOpAuctionCFP,strOpAuctionCFP );
                  mstate.addObject( mstaticOpAuctionPropose,strOpAuctionPropose );
                  mstate.addObject( mstaticOpAuctionAcceptProposal,strOpAuctionAcceptProposal );
                  mstate.addObject( mstaticOpAuctionRejectProposal,strOpAuctionRejectProposal );
                  mstate.addObject( mstaticOpAuctionRequest,strOpAuctionRequest );
                  mstate.addObject( mstaticOpGetNegCID,strOpGetNegCID );

                  // add argument types
                  mstate.addObject( mstaticArgConversationID,strArgConversationID );
                  mstate.addObject( mstaticArgFilenameParam,strArgFilenameParam );
                  mstate.addObject( mstaticArgInputDataFileTag,strArgInputDataFileTag );
                  mstate.addObject( mstaticArgOutputDataFileTag,strArgOutputDataFileTag );
                  mstate.addObject( mstaticArgAuctionMessage,strArgAuctionMessage );

                  // add policy setting
                  mstate.addObject( mstaticUsePolicyFile, new Boolean( bUsePolicy ) );

                  // get the component manager
                  compMan = GEMSS.getInstance();
                  if( compMan == null ) throw new Exception("null component manager");

                  // make a WebServiceInvoker object
                  mWSInvoker = (WebServiceInvoker) compMan.getInstance( mstaticWSInvokerName );
                  if( mWSInvoker == null ) throw new Exception("null invoker");

                  // all done
                  return;
            }
            catch ( Exception ex )
            {
                  mlogger.log( Level.SEVERE,"Exception during init",ex);
                  throw new Exception("init failed");
            }
      }

      /**
       * Set the account conv ID which this proxy can use. This is normally agreed offline so there will
       * not be a service provider operation to get this.
       * @param strID account conv ID
       */
      public void setAccountConversationID( String strID )
      {
            try {
                  mstate.addObject( mstaticAccountConvID, strID );
            }
            catch( Exception ex ) {
                  mlogger.log( Level.SEVERE,"Failed to set Account CID :" + ex.getMessage(),ex);
                  return;
            }
      }

      /**
       * Set the neg conversation ID. This should only be called if the client knows the conversation ID
       * already. The getNegConvID method should normally be called to invoke the service provider
       * operation appropriate to this task.
       * @param strID account conv ID
       */
      public void setNegConversationID( String strID )
      {
            try {
                  mstate.addObject( mstaticNegConvID, strID );
            }
            catch( Exception ex ) {
                  mlogger.log( Level.SEVERE,"Failed to set neg CID :" + ex.getMessage(),ex);
                  return;
            }
      }

      /**
       * Set the job conversation ID. This should only be called if the client knows the conversation ID
       * already. The getJobConvID method should normally be called to invoke the service provider
       * operation appropriate to this task.
       * @param strID account conv ID
       */
      public void setJobConversationID( String strID )
      {
            try {
                  mstate.addObject( mstaticJobConvID, strID );
            }
            catch( Exception ex ) {
                  mlogger.log( Level.SEVERE,"Failed to set job CID :" + ex.getMessage(),ex);
                  return;
            }
      }

      /**
       * Return the proxy flags. Null is returned on error.
       * @return vector of strings representing the current proxy flags
       */
      synchronized public Vector getProxyFlags()
      {
            try {
                  // return all flags
                  return mstate.getFlags();
            }
            catch( Exception ex ) {
                  mlogger.log( Level.SEVERE,"Failed to get flags :" + ex.getMessage(),ex);
                  return null;
            }
      }

      /**
       * Return the job CID, if there is one. If not null is returned.
       * @return job conversation ID
       */
      public String queryJobConversationID()
      {
            try {
                  return (String) mstate.getObject( mstaticJobConvID );
            }
            catch( Exception ex ) {
                  mlogger.log( Level.SEVERE,"Failed to get Job CID :" + ex.getMessage(),ex);
                  return null;
            }
      }

      /**
       * Return the negotiation CID, if there is one. If not null is returned.
       * @return neg conversation ID
       */
      public String queryNegConversationID()
      {
            try {
                  return (String) mstate.getObject( mstaticNegConvID );
            }
            catch( Exception ex ) {
                  mlogger.log( Level.SEVERE,"Failed to get Neg CID :" + ex.getMessage(),ex);
                  return null;
            }
      }

      /**
       * Return the account CID, if there is one. If not null is returned.
       * @return account conversation ID
       */
      public String queryAccountConversationID()
      {
            try {
                  return (String) mstate.getObject( mstaticAccountConvID );
            }
            catch( Exception ex ) {
                  mlogger.log( Level.SEVERE,"Failed to get Account CID :" + ex.getMessage(),ex);
                  return null;
            }
      }

      /**
      * upload data from the provided file to the Grid server.
      * This method will block.
      * @param inputArchiveFilename Filename of the input data
      */
      synchronized public void uploadData( String inputArchiveFilename ) throws GridException
      {
            String strHandle, strStatus;
            long nFileLength;
            byte[] arrayInputBytes;
            File file;
            FileInputStream streamIn;
            Payload payloadInput, payloadOutput;
            ServiceDescriptionImp serviceDesc;
            WSDL11InterfaceImp wsdlInterface;
            WSDLEndpointImp wsdlEndPoint;
            ServicePolicyImp policyContainer;
            DataItem [] arrayDataItems;
            XMLObject xmlObject;
            String strConvId, strServiceName, strServicePortType, strEndPointPortName, strBinding, strWSDLURI;
            String strOperation;
            HashMap hashMapFilenames;
            Vector vectorFlags;
            boolean bUsePolicy;

            try
            {
                  // ACTION LIST
                  // 1) get state parameters and read WSDL
                  // 2) load input file into memory (this will change for large file transfer code)
                  // 3) make payload input
                  // 4) invoke service operation
                  // 5) wait for completion
                  // 6) check payload result

                  // get parameters from state object
                  strServiceName = (String) mstate.getObject( mstaticServiceName );
                  strServicePortType = (String) mstate.getObject( mstaticServicePortType );
                  strEndPointPortName = (String) mstate.getObject( mstaticEndPointPortName );
                  strBinding = (String) mstate.getObject( mstaticBinding );
                  strWSDLURI = (String) mstate.getObject( mstaticWSDLURI );
                  strOperation = (String) mstate.getObject( mstaticOpUploadData );
                  bUsePolicy = ((Boolean) mstate.getObject( mstaticUsePolicyFile )).booleanValue();

                  // make the endpoint
                  wsdlEndPoint = new WSDLEndpointImp( strWSDLURI,strServiceName,strEndPointPortName );
                  wsdlInterface = new WSDL11InterfaceImp( strWSDLURI,strOperation,strServicePortType,strBinding );

                  // get filename of input data
                  if( inputArchiveFilename == null ) {
                        throw new Exception("Null input filename");
                  }

                  // make input payload (convID)
                  arrayDataItems = new DataItem[2];
                  strConvId = queryJobConversationID();
                  arrayDataItems[0] = new DataItemImpl(
                              (String) mstate.getObject( mstaticArgConversationID ),
                              new XSDTypeDescription( "",XSDTypeDescription.XSD_STRING ),
                              strConvId );
                  arrayDataItems[1] = new DataItemImpl(
                              (String) mstate.getObject( mstaticArgInputDataFileTag ),
                              new XSDTypeDescription( "",XSDTypeDescription.XSD_STRING ),
                              inputArchiveFilename, true ) ;
                  payloadInput = new PayloadImpl( arrayDataItems );

                  // helpful info
                  mlogger.log( Level.INFO,"GEMSSProxy upload parameters = "+strOperation+", "+strServicePortType+", "+strBinding+", "+strConvId);
                  mlogger.log( Level.INFO,"Probe: uploadData\t"+strOperation+"\t"+strConvId+"\t"+inputArchiveFilename );

                  // invoke the uploadData service (blocking)
                  policyContainer = new ServicePolicyImp();
                  if( !bUsePolicy ) {
                        policyContainer.addIncomingPolicy( new BodyX509SigVerifyWSPolicyImp() );
                        policyContainer.addOutgoingPolicy( new BodyX509SigCreateWSPolicyImp() );
                  }
                  else {
                        policyContainer.addIncomingPolicy( new NoPolicyImp() );
                        policyContainer.addOutgoingPolicy( new NoPolicyImp() );
                  }
                  serviceDesc = new ServiceDescriptionImp( wsdlInterface,wsdlEndPoint,policyContainer );
                  strHandle = mWSInvoker.invokeService( serviceDesc,payloadInput,makeUniqueHandle() );

                  // wait until result is ready or the invocation has failed
                  do {
                        // wait a short time
                        try { Thread.sleep( mstaticInvocationStatusCheckDelay ); } catch( InterruptedException ie ) {;}

                        // get status of web service invocation
                        vectorFlags = mWSInvoker.getInvocationFlags( strHandle );
                        if( vectorFlags == null ) throw new Exception("bad invoker handle");
                  } while( !vectorFlags.contains( WebServiceInvoker.mstaticStatusValueFinished ) &&
                           !vectorFlags.contains( WebServiceInvoker.mstaticStatusValueFailed ) );

                  // get the result (should be 0 length void return for upload data) and add it to the state
                  // if the invocation failed this call will either genrate a GridException or return null
                  payloadOutput = mWSInvoker.getInvocationResult( strHandle );
                  if( payloadOutput == null ) {
                        throw new Exception("result payload null");
                  }
                  if( payloadOutput.getDataItems().length != 0 ) {
                        throw new Exception("result payload not zero length");
                  }

                  // helpful info
                  mlogger.log( Level.INFO,"GEMSSProxy upload successful" );

                  // flag that the input data has been uploaded
                  mstate.addFlag( GEMSSJobHandlingProxy.mstaticUploadCompleteFlag );

                  // success
                  return;
            }
            catch( GridException gridex ) {
                  // pass any GridExceptions on so app can handle them
                  throw gridex;
            }
            catch( Exception ex ) {
                  mlogger.log( Level.SEVERE,"Failed to upload data :" + ex.getMessage(),ex);
                  throw new GridException( "GEMSS proxy failed to upload data to the application service, please check client logs for details as the cause was client side","upload failed : "+ex.getMessage() );
            }
      } // end of upload

      /**
       * Start the job.
       * This method will block.
       */
      synchronized public void start() throws GridException
      {
            String strHandle, strStatus;
            long nFileLength;
            byte[] arrayInputBytes;
            File file;
            FileInputStream streamIn;
            Payload payloadInput, payloadOutput;
            ServiceDescriptionImp serviceDesc;
            WSDL11InterfaceImp wsdlInterface;
            WSDLEndpointImp wsdlEndPoint;
            ServicePolicyImp policyContainer;
            DataItem [] arrayDataItems;
            XMLObject xmlObject;
            String strConvId, strServiceName, strServicePortType, strEndPointPortName, strBinding, strWSDLURI;
            String strOperation;
            Vector vectorFlags;
            boolean bUsePolicy;

            try
            {
                  // ACTION LIST
                  // 1) get state parameters and read WSDL
                  // 3) make payload input
                  // 4) invoke service operation
                  // 5) wait for completion
                  // 6) check payload result

                  // get parameters from state object
                  strServiceName = (String) mstate.getObject( mstaticServiceName );
                  strServicePortType = (String) mstate.getObject( mstaticServicePortType );
                  strEndPointPortName = (String) mstate.getObject( mstaticEndPointPortName );
                  strBinding = (String) mstate.getObject( mstaticBinding );
                  strWSDLURI = (String) mstate.getObject( mstaticWSDLURI );
                  strOperation = (String) mstate.getObject( mstaticOpStart );
                  bUsePolicy = ((Boolean) mstate.getObject( mstaticUsePolicyFile )).booleanValue();

                  // make the endpoint
                  wsdlEndPoint = new WSDLEndpointImp( strWSDLURI,strServiceName,strEndPointPortName );
                  wsdlInterface = new WSDL11InterfaceImp( strWSDLURI,strOperation,strServicePortType,strBinding );

                  // make input payload (convID)
                  arrayDataItems = new DataItem[1];
                  strConvId = queryJobConversationID();
                  arrayDataItems[0] = new DataItemImpl(
                              (String) mstate.getObject( mstaticArgConversationID ),
                              new XSDTypeDescription( "",XSDTypeDescription.XSD_STRING ),
                              strConvId );
                  payloadInput = new PayloadImpl( arrayDataItems );

                  // helpful info
                  mlogger.log( Level.INFO,"GEMSSProxy start parameters = "+strOperation+", "+strServicePortType+", "+strBinding+", "+strConvId);
                  mlogger.log( Level.INFO,"Probe: start\t"+strOperation+"\t"+strConvId );

                  // invoke the start service (blocking)
                  policyContainer = new ServicePolicyImp();
                  if( !bUsePolicy ) {
                        policyContainer.addIncomingPolicy( new BodyX509SigVerifyWSPolicyImp() );
                        policyContainer.addOutgoingPolicy( new BodyX509SigCreateWSPolicyImp() );
                  }
                  else {
                        policyContainer.addIncomingPolicy( new NoPolicyImp() );
                        policyContainer.addOutgoingPolicy( new NoPolicyImp() );
                  }
                  serviceDesc = new ServiceDescriptionImp( wsdlInterface,wsdlEndPoint,policyContainer );
                  strHandle = mWSInvoker.invokeService( serviceDesc,payloadInput,makeUniqueHandle() );

                  // wait until result is ready or the invocation has failed
                  do {
                        // wait a short time
                        try { Thread.sleep( mstaticInvocationStatusCheckDelay ); } catch( InterruptedException ie ) {;}

                        // get status of web service invocation
                        vectorFlags = mWSInvoker.getInvocationFlags( strHandle );

                        // paranoia check
                        if( vectorFlags == null ) throw new Exception("bad invoker handle");

                  } while( !vectorFlags.contains( WebServiceInvoker.mstaticStatusValueFinished ) &&
                           !vectorFlags.contains( WebServiceInvoker.mstaticStatusValueFailed ) );

                  // get the result (should be 0 length void return for start) and add it to the state
                  // if the invocation failed this call will either genrate a GridException or return null
                  payloadOutput = mWSInvoker.getInvocationResult( strHandle );
                  if( payloadOutput == null ) {
                        throw new Exception("result payload null");
                  }
                  if( payloadOutput.getDataItems().length != 0 ) {
                        throw new Exception("result payload not zero length");
                  }

                  // helpful info
                  mlogger.log( Level.INFO,"GEMSSProxy start successful" );

                  // flag that the input data has been uploaded
                  mstate.addFlag( GEMSSJobHandlingProxy.mstaticJobStartedFlag );

                  // success
                  return;
            }
            catch( GridException gridex ) {
                  // pass any GridExceptions on so app can handle them
                  throw gridex;
            }
            catch( Exception ex ) {
                  mlogger.log( Level.SEVERE,"Failed to start :" + ex.getMessage(),ex);
                  throw new GridException( "GEMSS proxy failed to start the application service's job, please check client logs for details as the cause was client side","start failed : "+ex.getMessage() );
            }
      } // end of start

      /**
       * kill the job.
       * This method will block.
       */
      synchronized public void kill() throws GridException
      {
            String strHandle, strStatus;
            long nFileLength;
            byte[] arrayInputBytes;
            File file;
            FileInputStream streamIn;
            Payload payloadInput, payloadOutput;
            ServiceDescriptionImp serviceDesc;
            WSDL11InterfaceImp wsdlInterface;
            WSDLEndpointImp wsdlEndPoint;
            ServicePolicyImp policyContainer;
            DataItem [] arrayDataItems;
            XMLObject xmlObject;
            String strConvId, strServiceName, strServicePortType, strEndPointPortName, strBinding, strWSDLURI;
            String strOperation;
            Vector vectorFlags;
            boolean bUsePolicy;

            try
            {
                  // ACTION LIST
                  // 1) get state parameters and read WSDL
                  // 3) make payload input
                  // 4) invoke service operation
                  // 5) wait for completion
                  // 6) check payload result

                  // get parameters from state object
                  strServiceName = (String) mstate.getObject( mstaticServiceName );
                  strServicePortType = (String) mstate.getObject( mstaticServicePortType );
                  strEndPointPortName = (String) mstate.getObject( mstaticEndPointPortName );
                  strBinding = (String) mstate.getObject( mstaticBinding );
                  strWSDLURI = (String) mstate.getObject( mstaticWSDLURI );
                  strOperation = (String) mstate.getObject( mstaticOpKill );
                  bUsePolicy = ((Boolean) mstate.getObject( mstaticUsePolicyFile )).booleanValue();

                  // make the endpoint
                  wsdlEndPoint = new WSDLEndpointImp( strWSDLURI,strServiceName,strEndPointPortName );
                  wsdlInterface = new WSDL11InterfaceImp( strWSDLURI,strOperation,strServicePortType,strBinding );

                  // make input payload (convID)
                  arrayDataItems = new DataItem[1];
                  strConvId = queryJobConversationID();
                  arrayDataItems[0] = new DataItemImpl(
                              (String) mstate.getObject( mstaticArgConversationID ),
                              new XSDTypeDescription( "",XSDTypeDescription.XSD_STRING ),
                              strConvId );
                  payloadInput = new PayloadImpl( arrayDataItems );

                  // helpful info
                  mlogger.log( Level.INFO,"GEMSSProxy kill parameters = "+strOperation+", "+strServicePortType+", "+strBinding+", "+strConvId);
                  mlogger.log( Level.INFO,"Probe: kill\t"+strOperation+"\t"+strConvId );

                  // invoke the kill service (blocking)
                  policyContainer = new ServicePolicyImp();
                  if( !bUsePolicy ) {
                        policyContainer.addIncomingPolicy( new BodyX509SigVerifyWSPolicyImp() );
                        policyContainer.addOutgoingPolicy( new BodyX509SigCreateWSPolicyImp() );
                  }
                  else {
                        policyContainer.addIncomingPolicy( new NoPolicyImp() );
                        policyContainer.addOutgoingPolicy( new NoPolicyImp() );
                  }
                  serviceDesc = new ServiceDescriptionImp( wsdlInterface,wsdlEndPoint,policyContainer );
                  strHandle = mWSInvoker.invokeService( serviceDesc,payloadInput,makeUniqueHandle() );

                  // wait until result is ready or the invocation has failed
                  do {
                        // wait a short time
                        try { Thread.sleep( mstaticInvocationStatusCheckDelay ); } catch( InterruptedException ie ) {;}

                        // get status of web service invocation
                        vectorFlags = mWSInvoker.getInvocationFlags( strHandle );
                        if( vectorFlags == null ) throw new Exception("bad invoker handle");
                  } while( !vectorFlags.contains( WebServiceInvoker.mstaticStatusValueFinished ) &&
                           !vectorFlags.contains( WebServiceInvoker.mstaticStatusValueFailed ) );

                  // get the result (should be 0 length void return for kill) and add it to the state
                  // if the invocation failed this call will either genrate a GridException or return null
                  payloadOutput = mWSInvoker.getInvocationResult( strHandle );
                  if( payloadOutput == null ) {
                        throw new Exception("result payload null");
                  }
                  if( payloadOutput.getDataItems().length != 0 ) {
                        throw new Exception("result payload not zero length");
                  }

                  // helpful info
                  mlogger.log( Level.INFO,"GEMSSProxy kill successful" );

                  // flag that the input data has been uploaded
                  mstate.addFlag( GEMSSJobHandlingProxy.mstaticJobKilledFlag );

                  // success
                  return;
            }
            catch( GridException gridex ) {
                  // pass any GridExceptions on so app can handle them
                  throw gridex;
            }
            catch( Exception ex ) {
                  mlogger.log( Level.SEVERE,"Failed to kill :" + ex.getMessage(),ex);
                  throw new GridException( "GEMSS proxy failed to kill the application service's job, please check client logs for details as the cause was client side","kill failed : "+ex.getMessage() );
            }
      } // end of kill

      /**
       * Get the status of the proxy. The status report is a string returned directly from
       * the application specific monitor status script. The job finished flag
       * will be set if the status returns "FINISHED". The job killed flag
       * will be set if the status returns "KILLED". The job failed flag
       * will be set if the status returns "FAILED"
       * This method will block.
       * @return String containing the status report
       */
      synchronized public String getStatus() throws GridException
      {
            String strHandle, strStatus;
            long nFileLength;
            byte[] arrayInputBytes, arrayOutputBytes;
            File file;
            FileInputStream streamIn;
            Payload payloadInput, payloadOutput;
            ServiceDescriptionImp serviceDesc;
            WSDL11InterfaceImp wsdlInterface;
            WSDLEndpointImp wsdlEndPoint;
            ServicePolicyImp policyContainer;
            DataItem [] arrayDataItems;
            DataItem dataItem;
            String strConvId, strServiceName, strServicePortType, strEndPointPortName, strBinding, strWSDLURI;
            String strOperation;
            Vector vectorFlags;
            boolean bUsePolicy;

            try
            {
                  // ACTION LIST
                  // 1) get state parameters and read WSDL
                  // 3) make payload input
                  // 4) invoke service operation
                  // 5) wait for completion
                  // 6) check payload result
                  // 7) return string

                  // get parameters from state object
                  strServiceName = (String) mstate.getObject( mstaticServiceName );
                  strServicePortType = (String) mstate.getObject( mstaticServicePortType );
                  strEndPointPortName = (String) mstate.getObject( mstaticEndPointPortName );
                  strBinding = (String) mstate.getObject( mstaticBinding );
                  strWSDLURI = (String) mstate.getObject( mstaticWSDLURI );
                  strOperation = (String) mstate.getObject( mstaticOpGetStatus );
                  bUsePolicy = ((Boolean) mstate.getObject( mstaticUsePolicyFile )).booleanValue();

                  // make the endpoint
                  wsdlEndPoint = new WSDLEndpointImp( strWSDLURI,strServiceName,strEndPointPortName );
                  wsdlInterface = new WSDL11InterfaceImp( strWSDLURI,strOperation,strServicePortType,strBinding );

                  // make input payload (convID)
                  arrayDataItems = new DataItem[1];
                  strConvId = queryJobConversationID();
                  arrayDataItems[0] = new DataItemImpl(
                              (String) mstate.getObject( mstaticArgConversationID ),
                              new XSDTypeDescription( "",XSDTypeDescription.XSD_STRING ),
                              strConvId );
                  payloadInput = new PayloadImpl( arrayDataItems );

                  // helpful info
                  mlogger.log( Level.INFO,"GEMSSProxy getStatus parameters = "+strOperation+", "+strServicePortType+", "+strBinding+", "+strConvId);
                  mlogger.log( Level.INFO,"Probe: getStatus\t"+strOperation+"\t"+strConvId );

                  // invoke the getStatus service (blocking)
                  policyContainer = new ServicePolicyImp();
                  if( !bUsePolicy ) {
                        policyContainer.addIncomingPolicy( new BodyX509SigVerifyWSPolicyImp() );
                        policyContainer.addOutgoingPolicy( new BodyX509SigCreateWSPolicyImp() );
                  }
                  else {
                        policyContainer.addIncomingPolicy( new NoPolicyImp() );
                        policyContainer.addOutgoingPolicy( new NoPolicyImp() );
                  }
                  serviceDesc = new ServiceDescriptionImp( wsdlInterface,wsdlEndPoint,policyContainer );
                  strHandle = mWSInvoker.invokeService( serviceDesc,payloadInput,makeUniqueHandle() );

                  // wait until result is ready or the invocation has failed
                  do {
                        // wait a short time
                        try { Thread.sleep( mstaticInvocationStatusCheckDelay ); } catch( InterruptedException ie ) {;}

                        // get status of web service invocation
                        vectorFlags = mWSInvoker.getInvocationFlags( strHandle );

                        // paranoia check
                        if( vectorFlags == null ) throw new Exception("bad invoker handle");

                  } while( !vectorFlags.contains( WebServiceInvoker.mstaticStatusValueFinished ) &&
                           !vectorFlags.contains( WebServiceInvoker.mstaticStatusValueFailed ) );

                  // get the result (should be 1 length data array return for getStatus) and add it to the state
                  // if the invocation failed this call will either genrate a GridException or return null
                  payloadOutput = mWSInvoker.getInvocationResult( strHandle );
                  if( payloadOutput == null ) {
                        throw new Exception("result payload null");
                  }
                  if( payloadOutput.getDataItems().length != 1 ) {
                        throw new Exception("result payload not 1 length");
                  }

                  // get the payload string
                  arrayDataItems = payloadOutput.getDataItems();
                  if( arrayDataItems == null ) throw new Exception("null array of data items");

                  dataItem = arrayDataItems[0];
                  if( dataItem == null ) throw new Exception("null data item");

                  arrayOutputBytes = (byte[]) dataItem.getValue();
                  if( arrayOutputBytes == null ) throw new Exception("null data array");
                  strStatus = new String( arrayOutputBytes );

                  // check for finished flag
                  if( strStatus.equals( mstaticFinishedStatusValue ) ) {
                        // set the job finished flag
                        mstate.addFlag( GEMSSJobHandlingProxy.mstaticJobFinishedFlag );
                  }
                  // check for failed flag
                  else if( strStatus.equals( mstaticFailedStatusValue ) ) {
                        // set the job finished flag
                        mstate.addFlag( GEMSSJobHandlingProxy.mstaticJobFailedFlag );
                  }
                  // check for killed flag
                  else if( strStatus.equals( mstaticKilledStatusValue ) ) {
                        // set the job killed flag
                        mstate.addFlag( GEMSSJobHandlingProxy.mstaticJobKilledFlag );
                  }

                  // helpful info
                  mlogger.log( Level.INFO,"GEMSSProxy getStatus successful" );

                  // success
                  return strStatus;
            }
            catch( GridException gridex ) {
                  // pass any GridExceptions on so app can handle them
                  throw gridex;
            }
            catch( Exception ex ) {
                  mlogger.log( Level.SEVERE,"Failed to getStatus :" + ex.getMessage(),ex);
                  throw new GridException( "GEMSS proxy failed to get the status of the job, please check client logs for details as the cause was client side","getStatus failed : "+ex.getMessage() );
            }
      } // end of getStatus

      /**
       * download the result data for a job. This method can be called many times until
       * the full result download has been performed. Calls to this method with an empty
       * string perameter will do a full result download, and set the final download complete
       * flag.
       * This method will block.
       * @param filename A filename to download. An empty string will download all results.
       * @param outputArchiveFilename The output filename for the downloaded archive.
       */
      public void downloadData( String filename, String outputArchiveFilename ) throws GridException
      {
            String strHandle;
            long nFileLength;
            byte[] arrayInputBytes, arrayOutputBytes;
            File file;
            FileOutputStream streamOut;
            Payload payloadInput, payloadOutput;
            ServiceDescriptionImp serviceDesc;
            WSDL11InterfaceImp wsdlInterface;
            WSDLEndpointImp wsdlEndPoint;
            ServicePolicyImp policyContainer;
            DataItem [] arrayDataItems;
            DataItem dataItem;
            XMLObject xmlObject;
            String strConvId, strServiceName, strServicePortType, strEndPointPortName, strBinding, strWSDLURI;
            String strOperation;
            Vector vectorFlags;
            HashMap hashMapFilenames;
            boolean bUsePolicy;

            try
            {
                  // ACTION LIST
                  // 1) get state parameters and read WSDL
                  // 3) make payload input
                  // 4) invoke service operation
                  // 5) wait for completion
                  // 6) check payload result
                  // 7) save archive to the filename specified

                  // get parameters from state object
                  strServiceName = (String) mstate.getObject( mstaticServiceName );
                  strServicePortType = (String) mstate.getObject( mstaticServicePortType );
                  strEndPointPortName = (String) mstate.getObject( mstaticEndPointPortName );
                  strBinding = (String) mstate.getObject( mstaticBinding );
                  strWSDLURI = (String) mstate.getObject( mstaticWSDLURI );
                  strOperation = (String) mstate.getObject( mstaticOpDownload );
                  bUsePolicy = ((Boolean) mstate.getObject( mstaticUsePolicyFile )).booleanValue();

                  // make the endpoint
                  wsdlEndPoint = new WSDLEndpointImp( strWSDLURI,strServiceName,strEndPointPortName );
                  wsdlInterface = new WSDL11InterfaceImp( strWSDLURI,strOperation,strServicePortType,strBinding );

                  // make input payload (convID,filename) - filename might be "" for all files
                  arrayDataItems = new DataItem[2];
                  strConvId = queryJobConversationID();
                  arrayDataItems[0] = new DataItemImpl(
                              (String) mstate.getObject( mstaticArgConversationID ),
                              new XSDTypeDescription( "",XSDTypeDescription.XSD_STRING ),
                              strConvId );
                  arrayDataItems[1] = new DataItemImpl(
                              (String) mstate.getObject( mstaticArgFilenameParam ),
                              new XSDTypeDescription( "",XSDTypeDescription.XSD_STRING ),
                              filename );
                  payloadInput = new PayloadImpl( arrayDataItems );

                  // make the filename hash map for output filename
                  hashMapFilenames = new HashMap();
                  hashMapFilenames.put( (String) mstate.getObject( mstaticArgOutputDataFileTag ),outputArchiveFilename );

                  // helpful info
                  mlogger.log( Level.INFO,"GEMSSProxy download parameters = "+strOperation+", "+strServicePortType+", "+strBinding+", "+strConvId);
                  mlogger.log( Level.INFO,"Probe: downloadData\t"+strOperation+"\t"+strConvId+"\t"+filename );

                  // invoke the download service operation (blocking)
                  policyContainer = new ServicePolicyImp();
                  if( !bUsePolicy ) {
                        policyContainer.addIncomingPolicy( new BodyX509SigVerifyWSPolicyImp() );
                        policyContainer.addOutgoingPolicy( new BodyX509SigCreateWSPolicyImp() );
                  }
                  else {
                        policyContainer.addIncomingPolicy( new NoPolicyImp() );
                        policyContainer.addOutgoingPolicy( new NoPolicyImp() );
                  }
                  serviceDesc = new ServiceDescriptionImp( wsdlInterface,wsdlEndPoint,policyContainer );
                  strHandle = mWSInvoker.invokeService( serviceDesc,payloadInput,makeUniqueHandle(),hashMapFilenames );

                  // wait until result is ready or the invocation has failed
                  do {
                        // wait a short time
                        try { Thread.sleep( mstaticInvocationStatusCheckDelay ); } catch( InterruptedException ie ) {;}

                        // get status of web service invocation
                        vectorFlags = mWSInvoker.getInvocationFlags( strHandle );

                        // paranoia check
                        if( vectorFlags == null ) throw new Exception("bad invoker handle");

                  } while( !vectorFlags.contains( WebServiceInvoker.mstaticStatusValueFinished ) &&
                           !vectorFlags.contains( WebServiceInvoker.mstaticStatusValueFailed ) );

                  // get the result (should be 1 length return for download data)
                  // if the invocation failed this call will either genrate a GridException or return null
                  payloadOutput = mWSInvoker.getInvocationResult( strHandle );
                  if( payloadOutput == null ) {
                        throw new Exception("result payload null");
                  }
                  if( payloadOutput.getDataItems().length != 1 ) {
                        throw new Exception("result payload not 1 length");
                  }

                  // set flag if it's the final download
                  if( filename.equals("") ) mstate.addFlag( GEMSSJobHandlingProxy.mstaticFinalDownloadCompleteFlag );

                  // success
                  return;
            }
            catch( GridException gridex ) {
                  // pass any GridExceptions on so app can handle them
                  throw gridex;
            }
            catch( Exception ex ) {
                  mlogger.log( Level.SEVERE,"Failed to download :" + ex.getMessage(),ex);
                  throw new GridException( "GEMSS proxy failed to download "+filename+" from the application service, please check client logs for details as the cause was client side","download of "+filename+" failed : "+ex.getMessage() );
            }
      } // end of download

      /**
       * acknowledge the results are ok. This will trigger the service provider to delete all traces
       * of the jobs input and result data, which is required for legal reasons. The application should
       * not call this function until it has a copy of the result data.
       * This method will block.
       */
      synchronized public void acknowledgeResults() throws GridException
      {
            String strHandle, strStatus;
            long nFileLength;
            byte[] arrayInputBytes, arrayOutputBytes;
            File file;
            FileInputStream streamIn;
            Payload payloadInput, payloadOutput;
            ServiceDescriptionImp serviceDesc;
            WSDL11InterfaceImp wsdlInterface;
            WSDLEndpointImp wsdlEndPoint;
            ServicePolicyImp policyContainer;
            DataItem [] arrayDataItems;
            DataItem dataItem;
            XMLObject xmlObject;
            String strConvId, strServiceName, strServicePortType, strEndPointPortName, strBinding, strWSDLURI;
            String strOperation;
            Vector vectorFlags;
            boolean bUsePolicy;

            try
            {
                  // ACTION LIST
                  // 1) get state parameters and read WSDL
                  // 3) make payload input
                  // 4) invoke service operation
                  // 5) wait for completion
                  // 6) check payload result

                  // get parameters from state object
                  strServiceName = (String) mstate.getObject( mstaticServiceName );
                  strServicePortType = (String) mstate.getObject( mstaticServicePortType );
                  strEndPointPortName = (String) mstate.getObject( mstaticEndPointPortName );
                  strBinding = (String) mstate.getObject( mstaticBinding );
                  strWSDLURI = (String) mstate.getObject( mstaticWSDLURI );
                  strOperation = (String) mstate.getObject( mstaticOpAcknowledgeResults );
                  bUsePolicy = ((Boolean) mstate.getObject( mstaticUsePolicyFile )).booleanValue();

                  // make the endpoint
                  wsdlEndPoint = new WSDLEndpointImp( strWSDLURI,strServiceName,strEndPointPortName );
                  wsdlInterface = new WSDL11InterfaceImp( strWSDLURI,strOperation,strServicePortType,strBinding );

                  // make input payload (convID)
                  arrayDataItems = new DataItem[1];
                  strConvId = queryJobConversationID();
                  arrayDataItems[0] = new DataItemImpl(
                              (String) mstate.getObject( mstaticArgConversationID ),
                              new XSDTypeDescription( "",XSDTypeDescription.XSD_STRING ),
                              strConvId );
                  payloadInput = new PayloadImpl( arrayDataItems );

                  // helpful info
                  mlogger.log( Level.INFO,"GEMSSProxy acknowledgeResults parameters = "+strOperation+", "+strServicePortType+", "+strBinding+", "+strConvId);
                  mlogger.log( Level.INFO,"Probe: acknowledgeResults\t"+strOperation+"\t"+strConvId );

                  // invoke the acknowledgeResults service (blocking)
                  policyContainer = new ServicePolicyImp();
                  if( !bUsePolicy ) {
                        policyContainer.addIncomingPolicy( new BodyX509SigVerifyWSPolicyImp() );
                        policyContainer.addOutgoingPolicy( new BodyX509SigCreateWSPolicyImp() );
                  }
                  else {
                        policyContainer.addIncomingPolicy( new NoPolicyImp() );
                        policyContainer.addOutgoingPolicy( new NoPolicyImp() );
                  }
                  serviceDesc = new ServiceDescriptionImp( wsdlInterface,wsdlEndPoint,policyContainer );
                  strHandle = mWSInvoker.invokeService( serviceDesc,payloadInput,makeUniqueHandle() );

                  // wait until result is ready or the invocation has failed
                  do {
                        // wait a short time
                        try { Thread.sleep( mstaticInvocationStatusCheckDelay ); } catch( InterruptedException ie ) {;}

                        // get status of web service invocation
                        vectorFlags = mWSInvoker.getInvocationFlags( strHandle );

                        // paranoia check
                        if( vectorFlags == null ) throw new Exception("bad invoker handle");

                  } while( !vectorFlags.contains( WebServiceInvoker.mstaticStatusValueFinished ) &&
                           !vectorFlags.contains( WebServiceInvoker.mstaticStatusValueFailed ) );

                  // get the result (should be 0 length data array return for acknowledgeResults)
                  // if the invocation failed this call will either genrate a GridException or return null
                  payloadOutput = mWSInvoker.getInvocationResult( strHandle );
                  if( payloadOutput == null ) {
                        throw new Exception("result payload null");
                  }
                  if( payloadOutput.getDataItems().length != 0 ) {
                        throw new Exception("result payload not 0 length");
                  }

                  // helpful info
                  mlogger.log( Level.INFO,"GEMSSProxy acknowledgeResults successful" );

                  // success
                  return;
            }
            catch( GridException gridex ) {
                  // pass any GridExceptions on so app can handle them
                  throw gridex;
            }
            catch( Exception ex ) {
                  mlogger.log( Level.SEVERE,"Failed to acknowledge results :" + ex.getMessage(),ex);
                  throw new GridException( "GEMSS proxy failed to acknowledge receiving the job's result data, please check client logs for details as the cause was client side","acknowledgeResult failed : "+ex.getMessage() );
            }
      } // end of acknowledgeResults

      /**
       * Returns the job conversation ID spawned by this negotiation conversation after a successful
       * exchange of contracts and a moved to the job handling phase.
       * This method will block.
       * @return job conversation ID value returned by the service
       */
      synchronized public String getJobCID() throws GridException
      {
            String strHandle, strCId;
            long nFileLength;
            byte[] arrayInputBytes, arrayOutputBytes;
            File file;
            FileInputStream streamIn;
            Payload payloadInput, payloadOutput;
            ServiceDescriptionImp serviceDesc;
            WSDL11InterfaceImp wsdlInterface;
            WSDLEndpointImp wsdlEndPoint;
            ServicePolicyImp policyContainer;
            DataItem [] arrayDataItems;
            DataItem dataItem;
            XMLObject xmlObject;
            String strConvId, strServiceName, strServicePortType, strEndPointPortName, strBinding, strWSDLURI;
            String strOperation, strNegID;
            Vector vectorFlags;
            boolean bUsePolicy;

            try
            {
                  // ACTION LIST
                  // 1) get state parameters and read WSDL
                  // 3) make payload input
                  // 4) invoke service operation
                  // 5) wait for completion
                  // 6) check payload result
                  // 7) return ID

                  // get parameters from state object
                  strServiceName = (String) mstate.getObject( mstaticServiceName );
                  strServicePortType = (String) mstate.getObject( mstaticServicePortType );
                  strEndPointPortName = (String) mstate.getObject( mstaticEndPointPortName );
                  strBinding = (String) mstate.getObject( mstaticBinding );
                  strWSDLURI = (String) mstate.getObject( mstaticWSDLURI );
                  strOperation = (String) mstate.getObject( mstaticOpGetJobCID );
                  bUsePolicy = ((Boolean) mstate.getObject( mstaticUsePolicyFile )).booleanValue();

                  // make the endpoint
                  wsdlEndPoint = new WSDLEndpointImp( strWSDLURI,strServiceName,strEndPointPortName );
                  wsdlInterface = new WSDL11InterfaceImp( strWSDLURI,strOperation,strServicePortType,strBinding );

                  // check neg ID
                  strNegID = (String) mstate.getObject( mstaticNegConvID );
                  if( strNegID == null ) {
                        mlogger.log( Level.WARNING, "Trying to obtain a job conv ID before the neg conv ID has been setup" );
                        strNegID = ""; // allow calls to getJobCID with empty string conv id's for now
                        // TODO work out how to handle job's with no neg ID
                  }

                  // make input payload (NegConvID)
                  arrayDataItems = new DataItem[1];
                  arrayDataItems[0] = new DataItemImpl(
                              (String) mstate.getObject( mstaticArgConversationID ),
                              new XSDTypeDescription( "",XSDTypeDescription.XSD_STRING ),
                              strNegID );
                  payloadInput = new PayloadImpl( arrayDataItems );

                  // helpful info
                  mlogger.log( Level.INFO,"GEMSSProxy getJobCID parameters = "+strOperation+", "+strServicePortType+", "+strBinding);
                  mlogger.log( Level.INFO,"Probe: getJobCID\t"+strOperation+"\t"+strNegID );

                  // invoke the getCId service (blocking)
                  policyContainer = new ServicePolicyImp();
                  if( !bUsePolicy ) {
                        policyContainer.addIncomingPolicy( new BodyX509SigVerifyWSPolicyImp() );
                        policyContainer.addOutgoingPolicy( new BodyX509SigCreateWSPolicyImp() );
                  }
                  else {
                        policyContainer.addIncomingPolicy( new NoPolicyImp() );
                        policyContainer.addOutgoingPolicy( new NoPolicyImp() );
                  }
                  serviceDesc = new ServiceDescriptionImp( wsdlInterface,wsdlEndPoint,policyContainer );
                  strHandle = mWSInvoker.invokeService( serviceDesc,payloadInput,makeUniqueHandle() );

                  // wait until result is ready or the invocation has failed
                  do {
                        // wait a short time
                        try { Thread.sleep( mstaticInvocationStatusCheckDelay ); } catch( InterruptedException ie ) {;}

                        // get status of web service invocation
                        vectorFlags = mWSInvoker.getInvocationFlags( strHandle );

                        // paranoia check
                        if( vectorFlags == null ) throw new Exception("bad invoker handle");

                  } while( !vectorFlags.contains( WebServiceInvoker.mstaticStatusValueFinished ) &&
                           !vectorFlags.contains( WebServiceInvoker.mstaticStatusValueFailed ) );

                  // get the result (should be 1 length data array return for getCId) and add it to the state
                  // if the invocation failed this call will either genrate a GridException or return null
                  payloadOutput = mWSInvoker.getInvocationResult( strHandle );
                  if( payloadOutput == null ) {
                        throw new Exception("result payload null");
                  }
                  if( payloadOutput.getDataItems().length != 1 ) {
                        throw new Exception("result payload not 1 length");
                  }

                  // convert the payload data into a string
                  arrayDataItems = payloadOutput.getDataItems();
                  if( arrayDataItems == null ) throw new Exception("null array of data items");

                  dataItem = arrayDataItems[0];
                  if( dataItem == null ) throw new Exception("null data item");

                  strCId = (String) dataItem.getValue();

                  // record the CId so all future operations can use it
                  mstate.addObject( mstaticJobConvID,strCId );
                  mstate.addFlag( mstaticJobPrepFlag );

                  // helpful info
                  mlogger.log( Level.INFO,"GEMSSProxy getJobCID successful, ID = "+strCId );

                  // success
                  return strCId;
            }
            catch( GridException gridex ) {
                  // pass any GridExceptions on so app can handle them
                  throw gridex;
            }
            catch( Exception ex ) {
                  mlogger.log( Level.SEVERE,"Failed to getJobCID :" + ex.getMessage(),ex);
                  throw new GridException( "GEMSS proxy failed to get the job conversation ID from the application service, please check client logs for details as the cause was client side","getCId failed : "+ex.getMessage() );
            }
      } // end of getJobCID

      /**
       * Returns the neg conversation ID spawned from this account conversation.
       * This method will block.
       * @return neg conversation ID value returned by the service
       */
      synchronized public String getNegCID() throws GridException
      {
            String strHandle, strCId;
            long nFileLength;
            byte[] arrayInputBytes, arrayOutputBytes;
            File file;
            FileInputStream streamIn;
            Payload payloadInput, payloadOutput;
            ServiceDescriptionImp serviceDesc;
            WSDL11InterfaceImp wsdlInterface;
            WSDLEndpointImp wsdlEndPoint;
            ServicePolicyImp policyContainer;
            DataItem [] arrayDataItems;
            DataItem dataItem;
            XMLObject xmlObject;
            String strConvId, strServiceName, strServicePortType, strEndPointPortName, strBinding, strWSDLURI;
            String strOperation;
            Vector vectorFlags;
            boolean bUsePolicy;

            try
            {
                  // ACTION LIST
                  // 1) get state parameters and read WSDL
                  // 3) make payload input
                  // 4) invoke service operation
                  // 5) wait for completion
                  // 6) check payload result
                  // 7) return ID

                  // get parameters from state object
                  strServiceName = (String) mstate.getObject( mstaticServiceName );
                  strServicePortType = (String) mstate.getObject( mstaticServicePortType );
                  strEndPointPortName = (String) mstate.getObject( mstaticEndPointPortName );
                  strBinding = (String) mstate.getObject( mstaticBinding );
                  strWSDLURI = (String) mstate.getObject( mstaticWSDLURI );
                  strOperation = (String) mstate.getObject( mstaticOpGetNegCID );
                  bUsePolicy = ((Boolean) mstate.getObject( mstaticUsePolicyFile )).booleanValue();

                  // make the endpoint
                  wsdlEndPoint = new WSDLEndpointImp( strWSDLURI,strServiceName,strEndPointPortName );
                  wsdlInterface = new WSDL11InterfaceImp( strWSDLURI,strOperation,strServicePortType,strBinding );

                  // check neg ID
                  if( mstate.getObject( mstaticAccountConvID ) == null ) throw new Exception("Cannot obtain a neg conv ID before the account conv ID has been setup");

                  // make input payload ()
                  arrayDataItems = new DataItem[1];
                  arrayDataItems[0] = new DataItemImpl(
                              (String) mstate.getObject( mstaticArgConversationID ),
                              new XSDTypeDescription( "",XSDTypeDescription.XSD_STRING ),
                              (String) mstate.getObject( mstaticAccountConvID ) );
                  payloadInput = new PayloadImpl( arrayDataItems );

                  // helpful info
                  mlogger.log( Level.INFO,"GEMSSProxy getNegCID parameters = "+strOperation+", "+strServicePortType+", "+strBinding);
                  mlogger.log( Level.INFO,"Probe: getNegCID\t"+strOperation+"\t"+((String) mstate.getObject( mstaticAccountConvID )) );

                  // invoke the getNegCID service (blocking)
                  policyContainer = new ServicePolicyImp();
                  if( !bUsePolicy ) {
                        policyContainer.addIncomingPolicy( new BodyX509SigVerifyWSPolicyImp() );
                        policyContainer.addOutgoingPolicy( new BodyX509SigCreateWSPolicyImp() );
                  }
                  else {
                        policyContainer.addIncomingPolicy( new NoPolicyImp() );
                        policyContainer.addOutgoingPolicy( new NoPolicyImp() );
                  }
                  serviceDesc = new ServiceDescriptionImp( wsdlInterface,wsdlEndPoint,policyContainer );
                  strHandle = mWSInvoker.invokeService( serviceDesc,payloadInput,makeUniqueHandle() );

                  // wait until result is ready or the invocation has failed
                  do {
                        // wait a short time
                        try { Thread.sleep( mstaticInvocationStatusCheckDelay ); } catch( InterruptedException ie ) {;}

                        // get status of web service invocation
                        vectorFlags = mWSInvoker.getInvocationFlags( strHandle );

                        // paranoia check
                        if( vectorFlags == null ) throw new Exception("bad invoker handle");

                  } while( !vectorFlags.contains( WebServiceInvoker.mstaticStatusValueFinished ) &&
                           !vectorFlags.contains( WebServiceInvoker.mstaticStatusValueFailed ) );

                  // get the result (should be 1 length data array return for getNegCID) and add it to the state
                  // if the invocation failed this call will either genrate a GridException or return null
                  payloadOutput = mWSInvoker.getInvocationResult( strHandle );
                  if( payloadOutput == null ) {
                        throw new Exception("result payload null");
                  }
                  if( payloadOutput.getDataItems().length != 1 ) {
                        throw new Exception("result payload not 1 length");
                  }

                  // convert the payload data into a string
                  arrayDataItems = payloadOutput.getDataItems();
                  if( arrayDataItems == null ) throw new Exception("null array of data items");

                  dataItem = arrayDataItems[0];
                  if( dataItem == null ) throw new Exception("null data item");

                  strCId = (String) dataItem.getValue();

                  // record the CId so all future operations can use it
                  mstate.addObject( mstaticNegConvID,strCId );
                  mstate.addFlag( mstaticNegPrepFlag );

                  // helpful info
                  mlogger.log( Level.INFO,"GEMSSProxy getNegCID successful, ID = "+strCId );

                  // success
                  return strCId;
            }
            catch( GridException gridex ) {
                  // pass any GridExceptions on so app can handle them
                  throw gridex;
            }
            catch( Exception ex ) {
                  mlogger.log( Level.SEVERE,"Failed to getNegCID :" + ex.getMessage(),ex);
                  throw new GridException( "GEMSS proxy failed to get the neg conversation ID from the application service, please check client logs for details as the cause was client side","getNegCID failed : "+ex.getMessage() );
            }
      } // end of getNegCID


      /**
       * get WSLA file for a specific account and service. This WSLA will reference the written agreement between
       * the client and service provider, and the account ref they have. It will also specify the QoS parameters
       * which the service provider will be expecting to be negotiated over.
       * @return string containing the WSLA object for this service
       */
      public String getWSLA() throws GridException
      {
            String strHandle, strStatus;
            long nFileLength;
            byte[] arrayInputBytes, arrayOutputBytes;
            File file;
            FileInputStream streamIn;
            Payload payloadInput, payloadOutput;
            ServiceDescriptionImp serviceDesc;
            WSDL11InterfaceImp wsdlInterface;
            WSDLEndpointImp wsdlEndPoint;
            ServicePolicyImp policyContainer;
            DataItem [] arrayDataItems;
            DataItem dataItem;
            String strConvId, strServiceName, strServicePortType, strEndPointPortName, strBinding, strWSDLURI;
            String strOperation, strWSLA;
            Vector vectorFlags;
            boolean bUsePolicy;

            try
            {
                  // ACTION LIST
                  // 1) get state parameters and read WSDL
                  // 3) make payload input
                  // 4) invoke service operation
                  // 5) wait for completion
                  // 6) check payload result
                  // 7) return string

                  // get parameters from state object
                  strServiceName = (String) mstate.getObject( mstaticServiceName );
                  strServicePortType = (String) mstate.getObject( mstaticServicePortType );
                  strEndPointPortName = (String) mstate.getObject( mstaticEndPointPortName );
                  strBinding = (String) mstate.getObject( mstaticBinding );
                  strWSDLURI = (String) mstate.getObject( mstaticWSDLURI );
                  strOperation = (String) mstate.getObject( mstaticOpGetWSLA );
                  bUsePolicy = ((Boolean) mstate.getObject( mstaticUsePolicyFile )).booleanValue();

                  // make the endpoint
                  wsdlEndPoint = new WSDLEndpointImp( strWSDLURI,strServiceName,strEndPointPortName );
                  wsdlInterface = new WSDL11InterfaceImp( strWSDLURI,strOperation,strServicePortType,strBinding );

                  // make input payload (convID)
                  arrayDataItems = new DataItem[1];
                  strConvId = queryNegConversationID();
                  arrayDataItems[0] = new DataItemImpl(
                              (String) mstate.getObject( mstaticArgConversationID ),
                              new XSDTypeDescription( "",XSDTypeDescription.XSD_STRING ),
                              strConvId );
                  payloadInput = new PayloadImpl( arrayDataItems );

                  // helpful info
                  mlogger.log( Level.INFO,"GEMSSProxy getWSLA parameters = "+strOperation+", "+strServicePortType+", "+strBinding+", "+strConvId+", "+strServiceName);
                  mlogger.log( Level.INFO,"Probe: getWSLA\t"+strOperation+"\t"+strConvId );

                  // invoke the getStatus service (blocking)
                  policyContainer = new ServicePolicyImp();
                  if( !bUsePolicy ) {
                        policyContainer.addIncomingPolicy( new BodyX509SigVerifyWSPolicyImp() );
                        policyContainer.addOutgoingPolicy( new BodyX509SigCreateWSPolicyImp() );
                  }
                  else {
                        policyContainer.addIncomingPolicy( new NoPolicyImp() );
                        policyContainer.addOutgoingPolicy( new NoPolicyImp() );
                  }
                  serviceDesc = new ServiceDescriptionImp( wsdlInterface,wsdlEndPoint,policyContainer );
                  strHandle = mWSInvoker.invokeService( serviceDesc,payloadInput,makeUniqueHandle() );

                  // wait until result is ready or the invocation has failed
                  do {
                        // wait a short time
                        try { Thread.sleep( mstaticInvocationStatusCheckDelay ); } catch( InterruptedException ie ) {;}

                        // get status of web service invocation
                        vectorFlags = mWSInvoker.getInvocationFlags( strHandle );

                        // paranoia check
                        if( vectorFlags == null ) throw new Exception("bad invoker handle");

                  } while( !vectorFlags.contains( WebServiceInvoker.mstaticStatusValueFinished ) &&
                           !vectorFlags.contains( WebServiceInvoker.mstaticStatusValueFailed ) );

                  // get the result (should be 1 length data array return for getWSLA) and add it to the state
                  // if the invocation failed this call will either generate a GridException or return null
                  payloadOutput = mWSInvoker.getInvocationResult( strHandle );
                  if( payloadOutput == null ) {
                        throw new Exception("result payload null");
                  }
                  if( payloadOutput.getDataItems().length != 1 ) {
                        throw new Exception("result payload not 1 length");
                  }

                  // get the payload string
                  arrayDataItems = payloadOutput.getDataItems();
                  if( arrayDataItems == null ) throw new Exception("null array of data items");

                  dataItem = arrayDataItems[0];
                  if( dataItem == null ) throw new Exception("null data item");

                  strWSLA = (String) dataItem.getValue();
                  if( strWSLA == null ) throw new Exception("null WSLA");

                  // helpful info
                  mlogger.log( Level.INFO,"GEMSSProxy getWSLA successful" );

                  // success
                  return strWSLA;

            }
            catch( GridException gridex ) {
                  // pass any GridExceptions on so app can handle them
                  throw gridex;
            }
            catch( Exception ex ) {
                  mlogger.log( Level.SEVERE,"Failed to getWSLA :" + ex.getMessage(),ex);
                  throw new GridException( "GEMSS proxy failed to get a WSLA template, please check client logs for details as the cause was client side","getWSLA failed : "+ex.getMessage() );
            }
      }

      /**
       * Uploads the RequestDesc file. This is needed as a pre-requisit to starting the auction
       * since the service providers must run thier performance models to determine how long
       * the job will take to run.
       * @param strRequestDescFilename filename of the request desc file
       */
      public void uploadRequestDesc( String strRequestDescFilename ) throws GridException
      {
            String strHandle, strStatus;
            long nFileLength;
            byte[] arrayInputBytes;
            File file;
            FileInputStream streamIn;
            Payload payloadInput, payloadOutput;
            ServiceDescriptionImp serviceDesc;
            WSDL11InterfaceImp wsdlInterface;
            WSDLEndpointImp wsdlEndPoint;
            ServicePolicyImp policyContainer;
            DataItem [] arrayDataItems;
            XMLObject xmlObject;
            String strConvId, strServiceName, strServicePortType, strEndPointPortName, strBinding, strWSDLURI;
            String strOperation;
            HashMap hashMapFilenames;
            Vector vectorFlags;
            boolean bUsePolicy;

            try
            {
                  // ACTION LIST
                  // 1) get state parameters and read WSDL
                  // 2) load input file into memory (this will change for large file transfer code)
                  // 3) make payload input
                  // 4) invoke service operation
                  // 5) wait for completion
                  // 6) check payload result

                  // get parameters from state object
                  strServiceName = (String) mstate.getObject( mstaticServiceName );
                  strServicePortType = (String) mstate.getObject( mstaticServicePortType );
                  strEndPointPortName = (String) mstate.getObject( mstaticEndPointPortName );
                  strBinding = (String) mstate.getObject( mstaticBinding );
                  strWSDLURI = (String) mstate.getObject( mstaticWSDLURI );
                  strOperation = (String) mstate.getObject( mstaticOpUploadRequestDesc );
                  bUsePolicy = ((Boolean) mstate.getObject( mstaticUsePolicyFile )).booleanValue();

                  // make the endpoint
                  wsdlEndPoint = new WSDLEndpointImp( strWSDLURI,strServiceName,strEndPointPortName );
                  wsdlInterface = new WSDL11InterfaceImp( strWSDLURI,strOperation,strServicePortType,strBinding );

                  // get filename of input data
                  if( strRequestDescFilename == null ) {
                        throw new Exception("Null request desc filename");
                  }

                  // make input payload (convID, filename)
                  arrayDataItems = new DataItem[2];
                  strConvId = queryNegConversationID();
                  arrayDataItems[0] = new DataItemImpl(
                              (String) mstate.getObject( mstaticArgConversationID ),
                              new XSDTypeDescription( "",XSDTypeDescription.XSD_STRING ),
                              strConvId );
                  arrayDataItems[1] = new DataItemImpl(
                              (String) mstate.getObject( mstaticArgInputDataFileTag ),
                              new XSDTypeDescription( "",XSDTypeDescription.XSD_STRING ),
                              strRequestDescFilename, true ) ;
                  payloadInput = new PayloadImpl( arrayDataItems );

                  // helpful info
                  mlogger.log( Level.INFO,"GEMSSProxy upload request desc parameters = "+strOperation+", "+strServicePortType+", "+strBinding+", "+strConvId);
                  mlogger.log( Level.INFO,"Probe: uploadRequestDesc\t"+strOperation+"\t"+strConvId+"\t"+strRequestDescFilename );

                  // invoke the uploadData service (blocking)
                  policyContainer = new ServicePolicyImp();
                  if( !bUsePolicy ) {
                        policyContainer.addIncomingPolicy( new BodyX509SigVerifyWSPolicyImp() );
                        policyContainer.addOutgoingPolicy( new BodyX509SigCreateWSPolicyImp() );
                  }
                  else {
                        policyContainer.addIncomingPolicy( new NoPolicyImp() );
                        policyContainer.addOutgoingPolicy( new NoPolicyImp() );
                  }
                  serviceDesc = new ServiceDescriptionImp( wsdlInterface,wsdlEndPoint,policyContainer );
                  strHandle = mWSInvoker.invokeService( serviceDesc,payloadInput,makeUniqueHandle() );

                  // wait until result is ready or the invocation has failed
                  do {
                        // wait a short time
                        try { Thread.sleep( mstaticInvocationStatusCheckDelay ); } catch( InterruptedException ie ) {;}

                        // get status of web service invocation
                        vectorFlags = mWSInvoker.getInvocationFlags( strHandle );

                        // paranoia check
                        if( vectorFlags == null ) throw new Exception("bad invoker handle");

                  } while( !vectorFlags.contains( WebServiceInvoker.mstaticStatusValueFinished ) &&
                           !vectorFlags.contains( WebServiceInvoker.mstaticStatusValueFailed ) );

                  // get the result (should be 0 length void return for upload request desc) and add it to the state
                  // if the invocation failed this call will either genrate a GridException or return null
                  payloadOutput = mWSInvoker.getInvocationResult( strHandle );
                  if( payloadOutput == null ) {
                        throw new Exception("result payload null");
                  }
                  if( payloadOutput.getDataItems().length != 0 ) {
                        throw new Exception("result payload not zero length");
                  }

                  // helpful info
                  mlogger.log( Level.INFO,"GEMSSProxy upload request desc successful" );

                  // flag that the input data has been uploaded
                  mstate.addFlag( mstaticUploadRequestDescCompleteFlag );

                  // success
                  return;
            }
            catch( GridException gridex ) {
                  // pass any GridExceptions on so app can handle them
                  throw gridex;
            }
            catch( Exception ex ) {
                  mlogger.log( Level.SEVERE,"Failed to upload request desc :" + ex.getMessage(),ex);
                  throw new GridException( "GEMSS proxy failed to upload the job request desc to the application service, please check client logs for details as the cause was client side","upload failed : "+ex.getMessage() );
            }
      }

      /**
       * Inform function used to inform the service provider about the start of an auction
       * and the end of an auction.
       * @param strMessage FIPA message string containing the inform ACL message
       */
      public void auctionInform( String strMessage ) throws GridException
      {
            String strHandle, strStatus;
            long nFileLength;
            byte[] arrayInputBytes, arrayOutputBytes;
            File file;
            FileInputStream streamIn;
            Payload payloadInput, payloadOutput;
            ServiceDescriptionImp serviceDesc;
            WSDL11InterfaceImp wsdlInterface;
            WSDLEndpointImp wsdlEndPoint;
            ServicePolicyImp policyContainer;
            DataItem [] arrayDataItems;
            DataItem dataItem;
            XMLObject xmlObject;
            String strConvId, strServiceName, strServicePortType, strEndPointPortName, strBinding, strWSDLURI;
            String strOperation;
            Vector vectorFlags;
            boolean bUsePolicy;

            try
            {
                  // ACTION LIST
                  // 1) get state parameters and read WSDL
                  // 3) make payload input
                  // 4) invoke service operation
                  // 5) wait for completion
                  // 6) check payload result

                  // get parameters from state object
                  strServiceName = (String) mstate.getObject( mstaticServiceName );
                  strServicePortType = (String) mstate.getObject( mstaticServicePortType );
                  strEndPointPortName = (String) mstate.getObject( mstaticEndPointPortName );
                  strBinding = (String) mstate.getObject( mstaticBinding );
                  strWSDLURI = (String) mstate.getObject( mstaticWSDLURI );
                  strOperation = (String) mstate.getObject( mstaticOpAuctionInform );
                  bUsePolicy = ((Boolean) mstate.getObject( mstaticUsePolicyFile )).booleanValue();

                  // make the endpoint
                  wsdlEndPoint = new WSDLEndpointImp( strWSDLURI,strServiceName,strEndPointPortName );
                  wsdlInterface = new WSDL11InterfaceImp( strWSDLURI,strOperation,strServicePortType,strBinding );

                  // make input payload (convID, message as base64 bytes)
                  arrayDataItems = new DataItem[2];
                  strConvId = queryNegConversationID();
                  arrayDataItems[0] = new DataItemImpl(
                              (String) mstate.getObject( mstaticArgConversationID ),
                              new XSDTypeDescription( "",XSDTypeDescription.XSD_STRING ),
                              strConvId );
                  arrayDataItems[1] = new DataItemImpl(
                              (String) mstate.getObject( mstaticArgAuctionMessage ),
                              new XSDTypeDescription( "",XSDTypeDescription.XSD_BYTEARRAY ),
                              strMessage.getBytes() );
                  payloadInput = new PayloadImpl( arrayDataItems );

                  // helpful info
                  mlogger.log( Level.INFO,"GEMSSProxy auctionInform parameters = "+strOperation+", "+strServicePortType+", "+strBinding+", "+strConvId);
                  mlogger.log( Level.INFO,"Probe: auctionInform\t"+strOperation+"\t"+strConvId+"\t"+strMessage );

                  // invoke the acknowledgeResults service (blocking)
                  policyContainer = new ServicePolicyImp();
                  if( !bUsePolicy ) {
                        policyContainer.addIncomingPolicy( new BodyX509SigVerifyWSPolicyImp() );
                        policyContainer.addOutgoingPolicy( new BodyX509SigCreateWSPolicyImp() );
                  }
                  else {
                        policyContainer.addIncomingPolicy( new NoPolicyImp() );
                        policyContainer.addOutgoingPolicy( new NoPolicyImp() );
                  }
                  serviceDesc = new ServiceDescriptionImp( wsdlInterface,wsdlEndPoint,policyContainer );
                  strHandle = mWSInvoker.invokeService( serviceDesc,payloadInput,makeUniqueHandle() );

                  // wait until result is ready or the invocation has failed
                  do {
                        // wait a short time
                        try { Thread.sleep( mstaticInvocationStatusCheckDelay ); } catch( InterruptedException ie ) {;}

                        // get status of web service invocation
                        vectorFlags = mWSInvoker.getInvocationFlags( strHandle );

                        // paranoia check
                        if( vectorFlags == null ) throw new Exception("bad invoker handle");

                  } while( !vectorFlags.contains( WebServiceInvoker.mstaticStatusValueFinished ) &&
                           !vectorFlags.contains( WebServiceInvoker.mstaticStatusValueFailed ) );

                  // get the result (should be 0 length data array return for auctionInform)
                  // if the invocation failed this call will either genrate a GridException or return null
                  payloadOutput = mWSInvoker.getInvocationResult( strHandle );
                  if( payloadOutput == null ) {
                        throw new Exception("result payload null");
                  }
                  if( payloadOutput.getDataItems().length != 0 ) {
                        throw new Exception("result payload not 0 length");
                  }

                  // helpful info
                  mlogger.log( Level.INFO,"GEMSSProxy auctionInform successful" );

                  // success
                  return;
            }
            catch( GridException gridex ) {
                  // pass any GridExceptions on so app can handle them
                  throw gridex;
            }
            catch( Exception ex ) {
                  mlogger.log( Level.SEVERE,"Failed to do auctionInform :" + ex.getMessage(),ex);
                  throw new GridException( "GEMSS proxy failed to do an inform as part of the auction, please check client logs for details as the cause was client side","auctionInform failed : "+ex.getMessage() );
            }
      }

      /**
       * Call for proposals function used to request from the the service provider a
       * proposal. Within the CFP is the deadline after which any proposals must be ready.
       * @param strMessage FIPA message string containing the CFP ACL message
       */
      public void auctionCFP( String strMessage ) throws GridException
      {
            String strHandle, strStatus;
            long nFileLength;
            byte[] arrayInputBytes, arrayOutputBytes;
            File file;
            FileInputStream streamIn;
            Payload payloadInput, payloadOutput;
            ServiceDescriptionImp serviceDesc;
            WSDL11InterfaceImp wsdlInterface;
            WSDLEndpointImp wsdlEndPoint;
            ServicePolicyImp policyContainer;
            DataItem [] arrayDataItems;
            DataItem dataItem;
            XMLObject xmlObject;
            String strConvId, strServiceName, strServicePortType, strEndPointPortName, strBinding, strWSDLURI;
            String strOperation;
            Vector vectorFlags;
            boolean bUsePolicy;

            try
            {
                  // ACTION LIST
                  // 1) get state parameters and read WSDL
                  // 3) make payload input
                  // 4) invoke service operation
                  // 5) wait for completion
                  // 6) check payload result

                  // get parameters from state object
                  strServiceName = (String) mstate.getObject( mstaticServiceName );
                  strServicePortType = (String) mstate.getObject( mstaticServicePortType );
                  strEndPointPortName = (String) mstate.getObject( mstaticEndPointPortName );
                  strBinding = (String) mstate.getObject( mstaticBinding );
                  strWSDLURI = (String) mstate.getObject( mstaticWSDLURI );
                  strOperation = (String) mstate.getObject( mstaticOpAuctionCFP );
                  bUsePolicy = ((Boolean) mstate.getObject( mstaticUsePolicyFile )).booleanValue();

                  // make the endpoint
                  wsdlEndPoint = new WSDLEndpointImp( strWSDLURI,strServiceName,strEndPointPortName );
                  wsdlInterface = new WSDL11InterfaceImp( strWSDLURI,strOperation,strServicePortType,strBinding );

                  // make input payload (convID)
                  arrayDataItems = new DataItem[2];
                  strConvId = queryNegConversationID();
                  arrayDataItems[0] = new DataItemImpl(
                              (String) mstate.getObject( mstaticArgConversationID ),
                              new XSDTypeDescription( "",XSDTypeDescription.XSD_STRING ),
                              strConvId );
                  arrayDataItems[1] = new DataItemImpl(
                              (String) mstate.getObject( mstaticArgAuctionMessage ),
                              new XSDTypeDescription( "",XSDTypeDescription.XSD_BYTEARRAY ),
                              strMessage.getBytes() );
                  payloadInput = new PayloadImpl( arrayDataItems );

                  // helpful info
                  mlogger.log( Level.INFO,"GEMSSProxy auctionCFP parameters = "+strOperation+", "+strServicePortType+", "+strBinding+", "+strConvId);
                  mlogger.log( Level.INFO,"Probe: auctionCFP\t"+strOperation+"\t"+strConvId+"\t"+strMessage );

                  // invoke the acknowledgeResults service (blocking)
                  policyContainer = new ServicePolicyImp();
                  if( !bUsePolicy ) {
                        policyContainer.addIncomingPolicy( new BodyX509SigVerifyWSPolicyImp() );
                        policyContainer.addOutgoingPolicy( new BodyX509SigCreateWSPolicyImp() );
                  }
                  else {
                        policyContainer.addIncomingPolicy( new NoPolicyImp() );
                        policyContainer.addOutgoingPolicy( new NoPolicyImp() );
                  }
                  serviceDesc = new ServiceDescriptionImp( wsdlInterface,wsdlEndPoint,policyContainer );
                  strHandle = mWSInvoker.invokeService( serviceDesc,payloadInput,makeUniqueHandle() );

                  // wait until result is ready or the invocation has failed
                  do {
                        // wait a short time
                        try { Thread.sleep( mstaticInvocationStatusCheckDelay ); } catch( InterruptedException ie ) {;}

                        // get status of web service invocation
                        vectorFlags = mWSInvoker.getInvocationFlags( strHandle );

                        // paranoia check
                        if( vectorFlags == null ) throw new Exception("bad invoker handle");

                  } while( !vectorFlags.contains( WebServiceInvoker.mstaticStatusValueFinished ) &&
                           !vectorFlags.contains( WebServiceInvoker.mstaticStatusValueFailed ) );

                  // get the result (should be 0 length data array return for auctionCFP)
                  // if the invocation failed this call will either genrate a GridException or return null
                  payloadOutput = mWSInvoker.getInvocationResult( strHandle );
                  if( payloadOutput == null ) {
                        throw new Exception("result payload null");
                  }
                  if( payloadOutput.getDataItems().length != 0 ) {
                        throw new Exception("result payload not 0 length");
                  }

                  // helpful info
                  mlogger.log( Level.INFO,"GEMSSProxy auctionCFP successful" );

                  // success
                  return;
            }
            catch( GridException gridex ) {
                  // pass any GridExceptions on so app can handle them
                  throw gridex;
            }
            catch( Exception ex ) {
                  mlogger.log( Level.SEVERE,"Failed to do auctionCFP :" + ex.getMessage(),ex);
                  throw new GridException( "GEMSS proxy failed issue a call for proposals as part of the auction, please check client logs for details as the cause was client side","auctionCFP failed : "+ex.getMessage() );
            }
      }

      /**
       * Propose function used to obtain a proposal from the service provider, in response to
       * a previous CFP.
       * @return FIPA message string containing the Propose ACL message
       */
      public String auctionPropose() throws GridException
      {
            String strHandle, strStatus;
            long nFileLength;
            byte[] arrayInputBytes, arrayOutputBytes;
            File file;
            FileInputStream streamIn;
            Payload payloadInput, payloadOutput;
            ServiceDescriptionImp serviceDesc;
            WSDL11InterfaceImp wsdlInterface;
            WSDLEndpointImp wsdlEndPoint;
            ServicePolicyImp policyContainer;
            DataItem [] arrayDataItems;
            DataItem dataItem;
            String strConvId, strServiceName, strServicePortType, strEndPointPortName, strBinding, strWSDLURI;
            String strOperation, strMessageResult;
            Vector vectorFlags;
            boolean bUsePolicy;

            try
            {
                  // ACTION LIST
                  // 1) get state parameters and read WSDL
                  // 3) make payload input
                  // 4) invoke service operation
                  // 5) wait for completion
                  // 6) check payload result
                  // 7) return string

                  // get parameters from state object
                  strServiceName = (String) mstate.getObject( mstaticServiceName );
                  strServicePortType = (String) mstate.getObject( mstaticServicePortType );
                  strEndPointPortName = (String) mstate.getObject( mstaticEndPointPortName );
                  strBinding = (String) mstate.getObject( mstaticBinding );
                  strWSDLURI = (String) mstate.getObject( mstaticWSDLURI );
                  strOperation = (String) mstate.getObject( mstaticOpAuctionPropose );
                  bUsePolicy = ((Boolean) mstate.getObject( mstaticUsePolicyFile )).booleanValue();

                  // make the endpoint
                  wsdlEndPoint = new WSDLEndpointImp( strWSDLURI,strServiceName,strEndPointPortName );
                  wsdlInterface = new WSDL11InterfaceImp( strWSDLURI,strOperation,strServicePortType,strBinding );

                  // make input payload (convID, serviceName)
                  arrayDataItems = new DataItem[1];
                  strConvId = queryNegConversationID();
                  arrayDataItems[0] = new DataItemImpl(
                              (String) mstate.getObject( mstaticArgConversationID ),
                              new XSDTypeDescription( "",XSDTypeDescription.XSD_STRING ),
                              strConvId );
                  payloadInput = new PayloadImpl( arrayDataItems );

                  // helpful info
                  mlogger.log( Level.INFO,"GEMSSProxy auctionPropose parameters = "+strOperation+", "+strServicePortType+", "+strBinding+", "+strConvId+", "+strServiceName);
                  mlogger.log( Level.INFO,"Probe: auctionPropose\t"+strOperation+"\t"+strConvId );

                  // invoke the getStatus service (blocking)
                  policyContainer = new ServicePolicyImp();
                  if( !bUsePolicy ) {
                        policyContainer.addIncomingPolicy( new BodyX509SigVerifyWSPolicyImp() );
                        policyContainer.addOutgoingPolicy( new BodyX509SigCreateWSPolicyImp() );
                  }
                  else {
                        policyContainer.addIncomingPolicy( new NoPolicyImp() );
                        policyContainer.addOutgoingPolicy( new NoPolicyImp() );
                  }
                  serviceDesc = new ServiceDescriptionImp( wsdlInterface,wsdlEndPoint,policyContainer );
                  strHandle = mWSInvoker.invokeService( serviceDesc,payloadInput,makeUniqueHandle() );

                  // wait until result is ready or the invocation has failed
                  do {
                        // wait a short time
                        try { Thread.sleep( mstaticInvocationStatusCheckDelay ); } catch( InterruptedException ie ) {;}

                        // get status of web service invocation
                        vectorFlags = mWSInvoker.getInvocationFlags( strHandle );

                        // paranoia check
                        if( vectorFlags == null ) throw new Exception("bad invoker handle");

                  } while( !vectorFlags.contains( WebServiceInvoker.mstaticStatusValueFinished ) &&
                           !vectorFlags.contains( WebServiceInvoker.mstaticStatusValueFailed ) );

                  // get the result (should be 1 length data array return for auctionPropose) and return it
                  // if the invocation failed this call will either generate a GridException or return null
                  payloadOutput = mWSInvoker.getInvocationResult( strHandle );
                  if( payloadOutput == null ) {
                        throw new Exception("result payload null");
                  }
                  if( payloadOutput.getDataItems().length != 1 ) {
                        throw new Exception("result payload not 1 length");
                  }

                  // get the payload string
                  arrayDataItems = payloadOutput.getDataItems();
                  if( arrayDataItems == null ) throw new Exception("null array of data items");

                  dataItem = arrayDataItems[0];
                  if( dataItem == null ) throw new Exception("null data item");

                  arrayOutputBytes = (byte[]) dataItem.getValue();
                  if( arrayOutputBytes == null ) throw new Exception("null data array");

                  strMessageResult = new String( arrayOutputBytes );

                  // helpful info
                  mlogger.log( Level.INFO,"GEMSSProxy auctionPropose successful" );

                  // success
                  return strMessageResult;
            }
            catch( GridException gridex ) {
                  // pass any GridExceptions on so app can handle them
                  throw gridex;
            }
            catch( Exception ex ) {
                  mlogger.log( Level.SEVERE,"Failed to auctionPropose :" + ex.getMessage(),ex);
                  throw new GridException( "GEMSS proxy failed to get a bid from a service provider, please check client logs for details as the cause was client side","auctionPropose failed : "+ex.getMessage() );
            }
      }

      /**
       * Accepts a proposal. The service provider will next expect to exchange signed contracts using
       * the request method. No commitment is made until contracts are exchanged.
       * @param strMessage FIPA message string containing the AcceptProposal ACL message
       */
      public void auctionAcceptProposal( String strMessage ) throws GridException
      {
            String strHandle, strStatus;
            long nFileLength;
            byte[] arrayInputBytes, arrayOutputBytes;
            File file;
            FileInputStream streamIn;
            Payload payloadInput, payloadOutput;
            ServiceDescriptionImp serviceDesc;
            WSDL11InterfaceImp wsdlInterface;
            WSDLEndpointImp wsdlEndPoint;
            ServicePolicyImp policyContainer;
            DataItem [] arrayDataItems;
            DataItem dataItem;
            XMLObject xmlObject;
            String strConvId, strServiceName, strServicePortType, strEndPointPortName, strBinding, strWSDLURI;
            String strOperation;
            Vector vectorFlags;
            boolean bUsePolicy;

            try
            {
                  // ACTION LIST
                  // 1) get state parameters and read WSDL
                  // 3) make payload input
                  // 4) invoke service operation
                  // 5) wait for completion
                  // 6) check payload result

                  // get parameters from state object
                  strServiceName = (String) mstate.getObject( mstaticServiceName );
                  strServicePortType = (String) mstate.getObject( mstaticServicePortType );
                  strEndPointPortName = (String) mstate.getObject( mstaticEndPointPortName );
                  strBinding = (String) mstate.getObject( mstaticBinding );
                  strWSDLURI = (String) mstate.getObject( mstaticWSDLURI );
                  strOperation = (String) mstate.getObject( mstaticOpAuctionAcceptProposal );
                  bUsePolicy = ((Boolean) mstate.getObject( mstaticUsePolicyFile )).booleanValue();

                  // make the endpoint
                  wsdlEndPoint = new WSDLEndpointImp( strWSDLURI,strServiceName,strEndPointPortName );
                  wsdlInterface = new WSDL11InterfaceImp( strWSDLURI,strOperation,strServicePortType,strBinding );

                  // make input payload (convID)
                  arrayDataItems = new DataItem[2];
                  strConvId = queryNegConversationID();
                  arrayDataItems[0] = new DataItemImpl(
                              (String) mstate.getObject( mstaticArgConversationID ),
                              new XSDTypeDescription( "",XSDTypeDescription.XSD_STRING ),
                              strConvId );
                  arrayDataItems[1] = new DataItemImpl(
                              (String) mstate.getObject( mstaticArgAuctionMessage ),
                              new XSDTypeDescription( "",XSDTypeDescription.XSD_BYTEARRAY ),
                              strMessage.getBytes() );
                  payloadInput = new PayloadImpl( arrayDataItems );

                  // helpful info
                  mlogger.log( Level.INFO,"GEMSSProxy auctionAcceptProposal parameters = "+strOperation+", "+strServicePortType+", "+strBinding+", "+strConvId);
                  mlogger.log( Level.INFO,"Probe: auctionAcceptProposal\t"+strOperation+"\t"+strConvId+"\t"+strMessage );

                  // invoke the service (blocking)
                  policyContainer = new ServicePolicyImp();
                  if( !bUsePolicy ) {
                        policyContainer.addIncomingPolicy( new BodyX509SigVerifyWSPolicyImp() );
                        policyContainer.addOutgoingPolicy( new BodyX509SigCreateWSPolicyImp() );
                  }
                  else {
                        policyContainer.addIncomingPolicy( new NoPolicyImp() );
                        policyContainer.addOutgoingPolicy( new NoPolicyImp() );
                  }
                  serviceDesc = new ServiceDescriptionImp( wsdlInterface,wsdlEndPoint,policyContainer );
                  strHandle = mWSInvoker.invokeService( serviceDesc,payloadInput,makeUniqueHandle() );

                  // wait until result is ready or the invocation has failed
                  do {
                        // wait a short time
                        try { Thread.sleep( mstaticInvocationStatusCheckDelay ); } catch( InterruptedException ie ) {;}

                        // get status of web service invocation
                        vectorFlags = mWSInvoker.getInvocationFlags( strHandle );

                        // paranoia check
                        if( vectorFlags == null ) throw new Exception("bad invoker handle");

                  } while( !vectorFlags.contains( WebServiceInvoker.mstaticStatusValueFinished ) &&
                           !vectorFlags.contains( WebServiceInvoker.mstaticStatusValueFailed ) );

                  // get the result (should be 0 length data array return for auctionAcceptProposal)
                  // if the invocation failed this call will either genrate a GridException or return null
                  payloadOutput = mWSInvoker.getInvocationResult( strHandle );
                  if( payloadOutput == null ) {
                        throw new Exception("result payload null");
                  }
                  if( payloadOutput.getDataItems().length != 0 ) {
                        throw new Exception("result payload not 0 length");
                  }

                  // helpful info
                  mlogger.log( Level.INFO,"GEMSSProxy auctionAcceptProposal successful" );

                  // success
                  return;
            }
            catch( GridException gridex ) {
                  // pass any GridExceptions on so app can handle them
                  throw gridex;
            }
            catch( Exception ex ) {
                  mlogger.log( Level.SEVERE,"Failed to do auctionAcceptProposal :" + ex.getMessage(),ex);
                  throw new GridException( "GEMSS proxy failed to accept proposal as part of the auction, please check client logs for details as the cause was client side","auctionAcceptProposal failed : "+ex.getMessage() );
            }
      }

      /**
       * Rejects a proposal. The service provider can now release any temporary reservations.
       * @param strMessage FIPA message string containing the RejectProposal ACL message
       */
      public void auctionRejectProposal( String strMessage ) throws GridException
      {
            String strHandle, strStatus;
            long nFileLength;
            byte[] arrayInputBytes, arrayOutputBytes;
            File file;
            FileInputStream streamIn;
            Payload payloadInput, payloadOutput;
            ServiceDescriptionImp serviceDesc;
            WSDL11InterfaceImp wsdlInterface;
            WSDLEndpointImp wsdlEndPoint;
            ServicePolicyImp policyContainer;
            DataItem [] arrayDataItems;
            DataItem dataItem;
            XMLObject xmlObject;
            String strConvId, strServiceName, strServicePortType, strEndPointPortName, strBinding, strWSDLURI;
            String strOperation;
            Vector vectorFlags;
            boolean bUsePolicy;

            try
            {
                  // ACTION LIST
                  // 1) get state parameters and read WSDL
                  // 3) make payload input
                  // 4) invoke service operation
                  // 5) wait for completion
                  // 6) check payload result

                  // get parameters from state object
                  strServiceName = (String) mstate.getObject( mstaticServiceName );
                  strServicePortType = (String) mstate.getObject( mstaticServicePortType );
                  strEndPointPortName = (String) mstate.getObject( mstaticEndPointPortName );
                  strBinding = (String) mstate.getObject( mstaticBinding );
                  strWSDLURI = (String) mstate.getObject( mstaticWSDLURI );
                  strOperation = (String) mstate.getObject( mstaticOpAuctionRejectProposal );
                  bUsePolicy = ((Boolean) mstate.getObject( mstaticUsePolicyFile )).booleanValue();

                  // make the endpoint
                  wsdlEndPoint = new WSDLEndpointImp( strWSDLURI,strServiceName,strEndPointPortName );
                  wsdlInterface = new WSDL11InterfaceImp( strWSDLURI,strOperation,strServicePortType,strBinding );

                  // make input payload (convID)
                  arrayDataItems = new DataItem[2];
                  strConvId = queryNegConversationID();
                  arrayDataItems[0] = new DataItemImpl(
                              (String) mstate.getObject( mstaticArgConversationID ),
                              new XSDTypeDescription( "",XSDTypeDescription.XSD_STRING ),
                              strConvId );
                  arrayDataItems[1] = new DataItemImpl(
                              (String) mstate.getObject( mstaticArgAuctionMessage ),
                              new XSDTypeDescription( "",XSDTypeDescription.XSD_BYTEARRAY ),
                              strMessage.getBytes() );
                  payloadInput = new PayloadImpl( arrayDataItems );

                  // helpful info
                  mlogger.log( Level.INFO,"GEMSSProxy auctionRejectProposal parameters = "+strOperation+", "+strServicePortType+", "+strBinding+", "+strConvId);
                  mlogger.log( Level.INFO,"Probe: auctionRejectProposal\t"+strOperation+"\t"+strConvId+"\t"+strMessage );

                  // invoke the service (blocking)
                  policyContainer = new ServicePolicyImp();
                  if( !bUsePolicy ) {
                        policyContainer.addIncomingPolicy( new BodyX509SigVerifyWSPolicyImp() );
                        policyContainer.addOutgoingPolicy( new BodyX509SigCreateWSPolicyImp() );
                  }
                  else {
                        policyContainer.addIncomingPolicy( new NoPolicyImp() );
                        policyContainer.addOutgoingPolicy( new NoPolicyImp() );
                  }
                  serviceDesc = new ServiceDescriptionImp( wsdlInterface,wsdlEndPoint,policyContainer );
                  strHandle = mWSInvoker.invokeService( serviceDesc,payloadInput,makeUniqueHandle() );

                  // wait until result is ready or the invocation has failed
                  do {
                        // wait a short time
                        try { Thread.sleep( mstaticInvocationStatusCheckDelay ); } catch( InterruptedException ie ) {;}

                        // get status of web service invocation
                        vectorFlags = mWSInvoker.getInvocationFlags( strHandle );

                        // paranoia check
                        if( vectorFlags == null ) throw new Exception("bad invoker handle");

                  } while( !vectorFlags.contains( WebServiceInvoker.mstaticStatusValueFinished ) &&
                           !vectorFlags.contains( WebServiceInvoker.mstaticStatusValueFailed ) );

                  // get the result (should be 0 length data array return for auctionRejectProposal)
                  // if the invocation failed this call will either genrate a GridException or return null
                  payloadOutput = mWSInvoker.getInvocationResult( strHandle );
                  if( payloadOutput == null ) {
                        throw new Exception("result payload null");
                  }
                  if( payloadOutput.getDataItems().length != 0 ) {
                        throw new Exception("result payload not 0 length");
                  }

                  // helpful info
                  mlogger.log( Level.INFO,"GEMSSProxy auctionRejectProposal successful" );

                  // success
                  return;
            }
            catch( GridException gridex ) {
                  // pass any GridExceptions on so app can handle them
                  throw gridex;
            }
            catch( Exception ex ) {
                  mlogger.log( Level.SEVERE,"Failed to do auctionRejectProposal :" + ex.getMessage(),ex);
                  throw new GridException( "GEMSS proxy failed to reject proposal as part of the auction, please check client logs for details as the cause was client side","auctionAcceptProposal failed : "+ex.getMessage() );
            }
      }

      /**
       * The client requests a signed contract, providing a signed contract itself. This allows for
       * the exchange of contracts.
       * @param strMessage FIPA message string containing the Request ACL message
       * @return FIPA message string containing the Inform ACL message
       */
      public String auctionRequest( String strMessage ) throws GridException
      {
            String strHandle, strStatus, strMessageResult;
            long nFileLength;
            byte[] arrayInputBytes, arrayOutputBytes;
            File file;
            FileInputStream streamIn;
            Payload payloadInput, payloadOutput;
            ServiceDescriptionImp serviceDesc;
            WSDL11InterfaceImp wsdlInterface;
            WSDLEndpointImp wsdlEndPoint;
            ServicePolicyImp policyContainer;
            DataItem [] arrayDataItems;
            DataItem dataItem;
            XMLObject xmlObject;
            String strConvId, strServiceName, strServicePortType, strEndPointPortName, strBinding, strWSDLURI;
            String strOperation;
            Vector vectorFlags;
            boolean bUsePolicy;

            try
            {
                  // ACTION LIST
                  // 1) get state parameters and read WSDL
                  // 3) make payload input
                  // 4) invoke service operation
                  // 5) wait for completion
                  // 6) check payload result

                  // get parameters from state object
                  strServiceName = (String) mstate.getObject( mstaticServiceName );
                  strServicePortType = (String) mstate.getObject( mstaticServicePortType );
                  strEndPointPortName = (String) mstate.getObject( mstaticEndPointPortName );
                  strBinding = (String) mstate.getObject( mstaticBinding );
                  strWSDLURI = (String) mstate.getObject( mstaticWSDLURI );
                  strOperation = (String) mstate.getObject( mstaticOpAuctionRequest );
                  bUsePolicy = ((Boolean) mstate.getObject( mstaticUsePolicyFile )).booleanValue();

                  // make the endpoint
                  wsdlEndPoint = new WSDLEndpointImp( strWSDLURI,strServiceName,strEndPointPortName );
                  wsdlInterface = new WSDL11InterfaceImp( strWSDLURI,strOperation,strServicePortType,strBinding );

                  // make input payload (convID)
                  arrayDataItems = new DataItem[2];
                  strConvId = queryNegConversationID();
                  arrayDataItems[0] = new DataItemImpl(
                              (String) mstate.getObject( mstaticArgConversationID ),
                              new XSDTypeDescription( "",XSDTypeDescription.XSD_STRING ),
                              strConvId );
                  arrayDataItems[1] = new DataItemImpl(
                              (String) mstate.getObject( mstaticArgAuctionMessage ),
                              new XSDTypeDescription( "",XSDTypeDescription.XSD_BYTEARRAY ),
                              strMessage.getBytes() );
                  payloadInput = new PayloadImpl( arrayDataItems );

                  // helpful info
                  mlogger.log( Level.INFO,"GEMSSProxy auctionRequest parameters = "+strOperation+", "+strServicePortType+", "+strBinding+", "+strConvId);
                  mlogger.log( Level.INFO,"Probe: auctionRequest\t"+strOperation+"\t"+strConvId+"\t"+strMessage );

                  // invoke the service (blocking)
                  policyContainer = new ServicePolicyImp();
                  if( !bUsePolicy ) {
                        policyContainer.addIncomingPolicy( new BodyX509SigVerifyWSPolicyImp() );
                        policyContainer.addOutgoingPolicy( new BodyX509SigCreateWSPolicyImp() );
                  }
                  else {
                        policyContainer.addIncomingPolicy( new NoPolicyImp() );
                        policyContainer.addOutgoingPolicy( new NoPolicyImp() );
                  }
                  serviceDesc = new ServiceDescriptionImp( wsdlInterface,wsdlEndPoint,policyContainer );
                  strHandle = mWSInvoker.invokeService( serviceDesc,payloadInput,makeUniqueHandle() );

                  // wait until result is ready or the invocation has failed
                  do {
                        // wait a short time
                        try { Thread.sleep( mstaticInvocationStatusCheckDelay ); } catch( InterruptedException ie ) {;}

                        // get status of web service invocation
                        vectorFlags = mWSInvoker.getInvocationFlags( strHandle );

                        // paranoia check
                        if( vectorFlags == null ) throw new Exception("bad invoker handle");

                  } while( !vectorFlags.contains( WebServiceInvoker.mstaticStatusValueFinished ) &&
                           !vectorFlags.contains( WebServiceInvoker.mstaticStatusValueFailed ) );

                  // get the result (should be 1 length data array return for auctionRequest)
                  // if the invocation failed this call will either genrate a GridException or return null
                  payloadOutput = mWSInvoker.getInvocationResult( strHandle );
                  if( payloadOutput == null ) {
                        throw new Exception("result payload null");
                  }
                  if( payloadOutput.getDataItems().length != 1 ) {
                        throw new Exception("result payload not 1 length");
                  }

                  // get payload (message in base64binary)
                  arrayDataItems = payloadOutput.getDataItems();
                  if( arrayDataItems == null ) throw new Exception("null array of data items");

                  dataItem = arrayDataItems[0];
                  if( dataItem == null ) throw new Exception("null data item");

                  arrayOutputBytes = (byte[]) dataItem.getValue();
                  if( arrayOutputBytes == null ) throw new Exception("null data array");

                  strMessageResult = new String( arrayOutputBytes );

                  // helpful info
                  mlogger.log( Level.INFO,"GEMSSProxy auctionRequest successful" );

                  // success
                  return strMessageResult;
            }
            catch( GridException gridex ) {
                  // pass any GridExceptions on so app can handle them
                  throw gridex;
            }
            catch( Exception ex ) {
                  mlogger.log( Level.SEVERE,"Failed to do auctionRequest :" + ex.getMessage(),ex);
                  throw new GridException( "GEMSS proxy failed to request contract as part of the auction, please check client logs for details as the cause was client side","auctionRequest failed : "+ex.getMessage() );
            }
      }

      /**
       * Make a unique web service invocation handle name
       * @return Unique handle name based on an incremented counter
       */
      private String makeUniqueHandle()
      {
            String strHandle;

            // simple counter to get unique names
            strHandle = "GEMSSProxyInternalHandle"+mHandleCounter;
            mHandleCounter++;

            // all done
            return strHandle;
      }


      /**
       * Write state and contents to a stream.
       * @param out stream where writes should go
       */
      synchronized private void writeObject(java.io.ObjectOutputStream out) throws IOException
      {
            try
            {
                  // write the negotiation state
                  out.writeObject( mstate );

                  // do NOT write the invoker to file
                  // since we are NOT serializing RPC calls

                  // all done
                  return;
            }
            catch ( Exception ex )
            {
                  mlogger.log( Level.SEVERE,"Exception during writeObject",ex);
                  throw new IOException("Failed to serialize state object");
            }
      } // end of writeObject

      /**
       * read state and contents from a stream.
       * @param in stream where to read from
       */
      synchronized private void readObject(java.io.ObjectInputStream in) throws IOException, ClassNotFoundException
      {
            ComponentManager compMan;

            // init (no constructor)
            mlogger = Logger.getLogger("uk.ac.soton.itinnovation.gemss.proxies.gemssproxyimp");

            try
            {
                  // read state
                  mstate = (State) in.readObject();
                  mHandleCounter = 1;

                  // get a new invoker instance from the component manager
                  // we are NOT going to be re-starting RPC calls
                  compMan = GEMSS.getInstance();
                  mWSInvoker = (WebServiceInvoker) compMan.getInstance( mstaticWSInvokerName );

                  // all done
                  return;
            }
            catch ( Exception ex )
            {
                  mlogger.log( Level.SEVERE,"Exception during readObject",ex);
                  throw new IOException("Failed to serialize state object");
            }
      } // end of readObject
} // end of GEMSSProxyImp