/**
   * Register a service-operation either as secure or unsecure
   *
   * @param serviceOperationEPR EndpointReference for the target service-operation
   * @param isSecure Must be true if the service-operation is secure and false otherwise
   */
  public void setIsInvocationHelperSecure(EndpointReference serviceOperationEPR, boolean isSecure) {

    WorkflowInvocationHelperClient client = null;
    String EPRStr = null;
    try {
      client = new WorkflowInvocationHelperClient(serviceOperationEPR);
      EPRStr = client.getEPRString();

    } catch (MalformedURIException e) {
      e.printStackTrace();
    } catch (RemoteException e) {
      e.printStackTrace();
    }

    if (isSecure) {

      logger.info("Creating locks");

      // Initializes mutual exclusion key that denotes the availability of the delegated credential
      Lock key = new ReentrantLock();
      Condition credentialAvailability = key.newCondition();
      this.serviceConditionVariable.put(EPRStr, credentialAvailability);
      this.servicelLock.put(EPRStr, key);

      this.printCredentials();

    } else {

      logger.info("Adding service to unsecure list");

      this.unsecureInvocations.add(EPRStr);
    }
    logger.info("Done");
  }
  /* (non-Javadoc)
   * @see org.cagrid.workflow.helper.instance.service.globus.resource.WorkflowInstanceHelperResourceBase#remove()
   */
  public void remove() throws ResourceException {

    logger.info("Destroying InstanceHelper resource");

    super.remove();

    // Destroy each InvocationHelper associated with this resource
    Iterator<EndpointReferenceType> stages_iter = this.stagesEPRs.iterator();
    while (stages_iter.hasNext()) {

      EndpointReferenceType curr_epr = stages_iter.next();
      WorkflowInvocationHelperClient curr_client;
      try {
        curr_client = new WorkflowInvocationHelperClient(curr_epr);

        String stageID = curr_client.getEPRString();
        this.stageStatus.remove(stageID); // Stop monitoring current stage's status changes

        curr_client.destroy(); // Destroy the resource associated with current stage
      } catch (MalformedURIException e) {
        e.printStackTrace();
      } catch (RemoteException e) {
        e.printStackTrace();
      }

      logger.info("Done");
      return;
    }
  }
  /** Register an InvocationHelper in order to monitor its status changes */
  public void registerInvocationHelper(EndpointReferenceType epr, QName name) {

    logger.info("Registering " + name);

    WorkflowInvocationHelperClient invocationHelper;
    try {

      // Request notification from the InvocationHelper
      invocationHelper = new WorkflowInvocationHelperClient(epr);
      invocationHelper.subscribeWithCallback(
          TimestampedStatus.getTypeDesc().getXmlType(), this); // Monitor status changes
      invocationHelper.subscribeWithCallback(
          InstrumentationRecord.getTypeDesc().getXmlType(),
          this); // Monitor instrumentation reports

      // Store reference to the InvocationHelper internally
      String key = invocationHelper.getEPRString();
      this.stageStatus.put(key, new TimestampedStatus(Status.UNCONFIGURED, 0));
      this.EPR2OperationName.put(key, name.toString());
      this.stagesEPRs.add(epr);

    } catch (MalformedURIException e) {
      e.printStackTrace();
    } catch (RemoteException e) {
      e.printStackTrace();
    } catch (ContainerException e) {
      e.printStackTrace();
    }

    logger.info("END");
  }
 public String getStatus(EndpointReferenceType epr) throws WorkflowException {
   try {
     return TavernaWorkflowServiceClient.getStatus(epr).getValue();
   } catch (MalformedURIException e) {
     throw new WorkflowException(e.getMessage(), e);
   } catch (RemoteException e) {
     throw new WorkflowException(e.getMessage(), e);
   }
 }
 public String[] getOutput(EndpointReferenceType epr) throws WorkflowException {
   if (!this.getStatus(epr).equals("Done")) return null;
   try {
     return TavernaWorkflowServiceClient.getOutput(epr).getOutputFile();
   } catch (MalformedURIException e) {
     throw new WorkflowException(e.getMessage(), e);
   } catch (RemoteException e) {
     throw new WorkflowException(e.getMessage(), e);
   }
 }
  @Override
  protected Vector<Step> steps() {
    Vector<Step> steps = new Vector<Step>();
    File tempMMSServiceDir = new File(SERVICE_TEMP_PATH);

    // SETUP
    steps.add(new UnpackContainerStep(getContainer()));
    steps.add(new CopyServiceStep(getMMSDir(), tempMMSServiceDir));

    // CONFIGURE
    // steps.add(new SetDatabasePropertiesStep(tempMMSServiceDir));
    // steps.add(new CreateDatabaseStep(tempMMSServiceDir));

    DeployServiceStep deployStep =
        new DeployServiceStep(
            getContainer(),
            tempMMSServiceDir.getAbsolutePath(),
            Arrays.asList(new String[] {"-Dno.deployment.validation=true"}));
    steps.add(deployStep);
    steps.add(new StartContainerStep(getContainer()));

    EndpointReferenceType epr = null;
    try {
      epr = getContainer().getServiceEPR(MMS_URL_PATH);
    } catch (MalformedURIException e) {
      e.printStackTrace();
      fail("Error constructing client:" + e.getMessage());
    }

    // TEST
    steps.add(new CheckMetadataStep(epr));

    // retrieve failures

    return steps;
  }
  /** Process a received notification */
  public void deliver(List arg0, EndpointReferenceType arg1, Object arg2) {

    org.oasis.wsrf.properties.ResourcePropertyValueChangeNotificationType changeMessage =
        ((org.globus.wsrf.core.notification.ResourcePropertyValueChangeNotificationElementType)
                arg2)
            .getResourcePropertyValueChangeNotification();

    MessageElement actual_property = changeMessage.getNewValue().get_any()[0];
    QName message_qname = actual_property.getQName();
    boolean isTimestampedStatusChange =
        message_qname.equals(TimestampedStatus.getTypeDesc().getXmlType());
    boolean isInstrumentationReport =
        message_qname.equals(InstrumentationRecord.getTypeDesc().getXmlType());
    String stageKey = null;
    try {
      stageKey = new WorkflowInvocationHelperClient(arg1).getEPRString();
    } catch (RemoteException e1) {
      e1.printStackTrace();
    } catch (MalformedURIException e1) {
      e1.printStackTrace();
    }

    logger.debug(
        "[CreateTestWorkflowsStep] Received message of type "
            + message_qname.getLocalPart()
            + " from "
            + stageKey);

    /// Handle status change notifications
    if (isTimestampedStatusChange) {
      TimestampedStatus status = null;
      ;
      try {
        status =
            (TimestampedStatus)
                actual_property.getValueAsType(message_qname, TimestampedStatus.class);
      } catch (Exception e) {
        e.printStackTrace();
      }

      logger.info(
          "Received new status value: "
              + status.getStatus().toString()
              + ':'
              + status.getTimestamp()
              + " from "
              + this.EPR2OperationName.get(stageKey));

      this.isFinishedKey.lock();
      try {

        boolean timestampChanged = false;
        if (this.stageStatus.containsKey(stageKey)) {

          TimestampedStatus curr_status = this.stageStatus.get(stageKey);
          timestampChanged =
              (!curr_status.getStatus().equals(status.getStatus()))
                  && (curr_status.getTimestamp() < status.getTimestamp());

          if (timestampChanged) {

            this.stageStatus.remove(stageKey);
            this.stageStatus.put(stageKey, status);
          }

        } else
          logger.error(
              "[WorkflowInstanceHelperResource] Unrecognized stage notified status change: "
                  + stageKey);

        // Calculate new status value
        if (timestampChanged) {

          // Set new status
          Status new_status = this.calculateStatus();
          TimestampedStatus currTimestampedStatus = this.getTimestampedStatus();
          if (currTimestampedStatus == null) {

            String errMsg =
                "Unable to retrieve current timestamped status from " + this.getEPRString();
            logger.error(errMsg);
            throw new RemoteException(errMsg);
          }

          boolean statusesDiffer = (!new_status.equals(currTimestampedStatus.getStatus()));
          if (statusesDiffer)
            this.localWorkflowInstrumentation.eventEnd(
                currTimestampedStatus.getStatus().toString());

          TimestampedStatus nextStatus = new TimestampedStatus(new_status, ++this.timestamp);

          // Get and store time for the start of the new state
          if (statusesDiffer) {

            this.localWorkflowInstrumentation.eventStart(
                currTimestampedStatus.getStatus().toString());

            // If the local workflow is finished, copy all the collected instrumentation data to a
            // resource property so it is exposed by this resource
            if (nextStatus.getStatus().equals(Status.FINISHED)
                || nextStatus.getStatus().equals(Status.ERROR)) {

              LocalWorkflowInstrumentationRecord localWorkflowInstrumentationRecord =
                  new LocalWorkflowInstrumentationRecord();
              localWorkflowInstrumentationRecord.setIdentifier(this.getEPRString());
              InstrumentationRecord localWorkflowRecord =
                  new InstrumentationRecord(
                      this.localWorkflowInstrumentation.getIdentifier(),
                      this.localWorkflowInstrumentation.retrieveRecordAsArray());
              localWorkflowInstrumentationRecord.setLocalWorkflowRecord(
                  localWorkflowRecord); // Info about local workflow as a whole

              InstrumentationRecord[] stagesRecords =
                  this.stagesInstrumentation.toArray(new InstrumentationRecord[0]);
              localWorkflowInstrumentationRecord.setStagesRecords(
                  stagesRecords); // Info about the InvocationHelpers under this resource
              this.setLocalWorkflowInstrumentationRecord(localWorkflowInstrumentationRecord);
              //							System.out.println("[InstanceHelperResource::deliver] Sending "+
              // stagesRecords.length +" instrumentation reports to Manager"); //DEBUG
            }
          }

          this.setTimestampedStatus(nextStatus);
        }

      } catch (ResourceException e) {
        logger.error(e.getMessage(), e);
        e.printStackTrace();
      } catch (Exception e) {
        logger.error(e.getMessage(), e);
        e.printStackTrace();
      } finally {
        this.isFinishedKey.unlock();
      }
    }

    /// Handle instrumentation reports
    else if (isInstrumentationReport) {

      InstrumentationRecord instrumentation_data = null;
      try {
        instrumentation_data =
            (InstrumentationRecord)
                actual_property.getValueAsType(message_qname, InstrumentationRecord.class);
      } catch (Exception e) {
        e.printStackTrace();
      }

      // Store the received measurements
      this.stagesInstrumentation.add(instrumentation_data);

      // Update the instrumentation data exposed by this resource
      LocalWorkflowInstrumentationRecord localWorkflowInstrumentationRecord =
          new LocalWorkflowInstrumentationRecord();
      localWorkflowInstrumentationRecord.setIdentifier(this.getEPRString());
      InstrumentationRecord localWorkflowRecord =
          new InstrumentationRecord(
              this.localWorkflowInstrumentation.getIdentifier(),
              this.localWorkflowInstrumentation.retrieveRecordAsArray());
      localWorkflowInstrumentationRecord.setLocalWorkflowRecord(
          localWorkflowRecord); // Info about local workflow as a whole

      InstrumentationRecord[] stagesRecords =
          this.stagesInstrumentation.toArray(new InstrumentationRecord[0]);
      localWorkflowInstrumentationRecord.setStagesRecords(
          stagesRecords); // Info about the InvocationHelpers under this resource
      //			try {
      //				this.setLocalWorkflowInstrumentationRecord(localWorkflowInstrumentationRecord);
      //			} catch (ResourceException e) {
      //				logger.error(e.getMessage(), e);
      //				e.printStackTrace();
      //			}

      // Log the instrumentation data
      logger.info(
          "Instrumentation data for InvocationHelper identified by "
              + instrumentation_data.getIdentifier());
      //			System.out.println("[InstanceHelperResource::deliver] "+ stagesRecords.length +" reports
      // stored so far"); //DEBUG
      //			System.out.println("[InstanceHelperResource::deliver] Instrumentation data for
      // InvocationHelper identified by "+ instrumentation_data.getIdentifier()); //DEBUG
      final int numMeasurements = instrumentation_data.getRecords().length;
      for (int i = 0; i < numMeasurements; i++) {

        EventTimePeriod curr_measurement = instrumentation_data.getRecords(i);
        long elapsedTimeInNanos = curr_measurement.getEndTime() - curr_measurement.getStartTime();
        logger.info(
            curr_measurement.getEvent() + ": " + (elapsedTimeInNanos / 1000000) + " miliseconds");
        //				System.out.println(curr_measurement.getEvent()+ ": "+ (elapsedTimeInNanos/1000000) + "
        // miliseconds"); //DEBUG
      }
      logger.info("-------------------------------------------------------");
      //			System.out.println("-------------------------------------------------------"); //DEBUG

    }
  }
  /**
   * Associate an InvocationHelper with a GlobusCredential, removing previous associations if any
   *
   * @param serviceOperationEPR EPR of the InvocationHelper
   * @param proxyEPR the credential to be used by the InvocationHelper
   */
  public void replaceCredential(EndpointReference serviceOperationEPR, EndpointReference proxyEPR) {

    logger.info("BEGIN");

    String serviceOperationEPR_str = null;
    try {
      WorkflowInvocationHelperClient client =
          new WorkflowInvocationHelperClient(serviceOperationEPR);
      serviceOperationEPR_str = client.getEPRString();

    } catch (MalformedURIException e1) {
      e1.printStackTrace();
    } catch (RemoteException e1) {
      e1.printStackTrace();
    }

    // Initializes mutual exclusion key that denotes the availability of the delegated credential
    Lock key;
    Condition credentialAvailability;
    if (this.serviceConditionVariable.containsKey(serviceOperationEPR_str)) {

      key = this.servicelLock.get(serviceOperationEPR_str);
      credentialAvailability = this.serviceConditionVariable.get(serviceOperationEPR_str);
    } else {

      key = new ReentrantLock();
      credentialAvailability = key.newCondition();
      this.servicelLock.put(serviceOperationEPR_str, key);
      this.serviceConditionVariable.put(serviceOperationEPR_str, credentialAvailability);
    }

    key.lock();
    try {

      // Delete old credential (if any) from the associations
      boolean serviceExists = this.servicesCredentials.containsKey(serviceOperationEPR_str);
      if (serviceExists) {

        this.servicesCredentials.remove(serviceOperationEPR_str);
        this.eprCredential.remove(proxyEPR);
      }

      // Retrieve the delegated credential
      GlobusCredential credential = null;

      if (proxyEPR != null) {
        try {

          credential = CredentialHandlingUtil.getDelegatedCredential(proxyEPR);

        } catch (Exception e) {
          System.err.println("Error retrieving delegated credential");
          e.printStackTrace();
        }
      }

      // Add the new credential
      this.servicesCredentials.put(serviceOperationEPR_str, credential);
      this.eprCredential.put(proxyEPR, credential);

      // Signal any waiting threads that the credential is available
      credentialAvailability.signalAll();

    } finally {
      key.unlock();
    }

    logger.info("END");

    return;
  }
  /**
   * Retrieve the GlobusCredential associated with a service-operation. If credential retrieval is
   * pending, caller is blocked until the credential becomes available.
   *
   * @param serviceOperationEPR EPR of the InvocationHelper
   * @return The associated GlobusCredential, or null if no such association does exist
   * @throws RemoteException
   */
  public GlobusCredential getCredential(EndpointReference serviceOperationEPR)
      throws RemoteException {

    this.printCredentials();

    String eprStr = null;
    try {
      WorkflowInvocationHelperClient client =
          new WorkflowInvocationHelperClient(serviceOperationEPR);
      eprStr = client.getEPRString();

    } catch (MalformedURIException e1) {
      e1.printStackTrace();
    } catch (RemoteException e1) {
      e1.printStackTrace();
    }

    GlobusCredential credential = null;
    boolean serviceIsUnsecure = this.unsecureInvocations.contains(eprStr);

    if (serviceIsUnsecure) {
      logger.info(
          "[WorkflowInstanceHelperResource.getCredential] Service is unsecure, returning null credential");
      return null;
    } else {

      logger.info("[WorkflowInstanceHelperResource.getCredential] Service is secure");

      Lock key = this.servicelLock.get(eprStr);
      Condition credentialAvailability = this.serviceConditionVariable.get(eprStr);

      // Mutual exclusive access session: we can only return the credential if it was already
      // retrieved from the
      // Credential Delegation Service
      key.lock();
      try {

        printCredentials();

        // If credential is unavailable, block until it is available
        boolean credentialIsNotSet = (!this.servicesCredentials.containsKey(eprStr));

        if (credentialIsNotSet) {

          boolean explicitlyAwaken = credentialAvailability.await(60, TimeUnit.SECONDS);
          if (!explicitlyAwaken)
            throw new RemoteException(
                "[WorkflowInstanceHelperResource.getCredential] Couldn't retrieve credential. "
                    + "Was it registered into the InstanceHelper? Is the EndpointReference for the credential proxy valid?");
        }
        credential = this.servicesCredentials.get(eprStr);

        logger.info("[getCredential] Retrieved credential: " + credential.getIdentity());

      } catch (InterruptedException e) {
        logger.error("[getCredential] Error retrieving credential");
        e.printStackTrace();
      } finally {
        key.unlock();
      }

      logger.info(
          "Returning credential: " + ((credential != null) ? credential.getIdentity() : null));
      return credential;
    }
  }