private void doIssuanceProtocol(
      IssuerAbcEngine issuerEngine,
      UserAbcEngine userEngine,
      IssuancePolicy ip,
      List<Attribute> issuerAtts)
      throws Exception {

    // Initialize ABC4Trust Issuance Protocol Issuer side
    // Returns an IssuancePolicy from CryptoEngineIssuer to be passed to CryptoEngineUser
    // initialization
    IssuanceMessageAndBoolean issuerIm = issuerEngine.initIssuanceProtocol(ip, issuerAtts);
    assertFalse(issuerIm.isLastMessage());

    // Initialize ABC4Trust Issuance Protocol Prover side
    // FIXME: userEngine indirectly calls CryptoEngineUser.createIssuanceToken() with the
    // IssuancePolicy from the Issuer and returns an IssuanceToken
    // contained in the IssuanceMessage. This IssuanceToken is simply NOT used for now in the next
    // step of the UProve Credential Issuance protocol.
    // However, this seems to be the only proper way for now to initialise CryptoEngineUser to a
    // working state, despite the createIssuanceToken() step being
    // an optional step for the advanced Issuance setting not supported by UProve for now.
    IssuMsgOrCredDesc userIm = userEngine.issuanceProtocolStep(issuerIm.getIssuanceMessage());

    // Execute the UProve issuance protocol:

    // Prover side asks issuer for first message
    issuerIm = issuerEngine.issuanceProtocolStep(userIm.im);
    assertFalse(issuerIm.isLastMessage());

    // Prover side generates second message based on the first message
    userIm = userEngine.issuanceProtocolStep(issuerIm.getIssuanceMessage());

    // Prover side asks issuer for third message based on the second message
    assertNotNull(userIm.im);
    issuerIm = issuerEngine.issuanceProtocolStep(userIm.im);
    assertNotNull(issuerIm.getIssuanceMessage());

    // Prover side generates UProve Tokens based on the third message
    userIm = userEngine.issuanceProtocolStep(issuerIm.getIssuanceMessage());
    boolean userLastMessage = (userIm.cd != null);
    assertTrue(issuerIm.isLastMessage() == userLastMessage);

    assertNull(userIm.im);
    assertNotNull(userIm.cd);

    // CredentialDescription actualCredDesc = userIm.cd;
    // ObjectFactory of = new ObjectFactory();
    // String actualCredentialDesc =
    // XmlUtils.toNormalizedXML(of.createCredentialDescription(actualCredDesc));

    // System.out.println(actualCredentialDesc);
  }
  @Test()
  public void test() throws Exception {
    UProveUtils uproveUtils = new UProveUtils();
    Injector issuerInjector =
        Guice.createInjector(
            IntegrationModuleFactory.newModule(
                new Random(1231), uproveUtils.getIssuerServicePort()));
    Injector userInjector =
        Guice.createInjector(
            IntegrationModuleFactory.newModule(new Random(1231), uproveUtils.getUserServicePort()));
    Injector verifierInjector =
        Guice.createInjector(
            IntegrationModuleFactory.newModule(
                new Random(1231), uproveUtils.getVerifierServicePort()));

    // Step 1. Load the credit card specification into the keystore.
    CredentialSpecification creditCardSpec =
        (CredentialSpecification)
            XmlUtils.getObjectFromXML(
                this.getClass()
                    .getResourceAsStream(
                        "/eu/abc4trust/sampleXml/uprove/credentialSpecificationCreditcardVisa.xml"),
                true);

    KeyManager keyManager = issuerInjector.getInstance(KeyManager.class);
    keyManager.storeCredentialSpecification(creditCardSpec.getSpecificationUID(), creditCardSpec);

    KeyManager userKeyManager = userInjector.getInstance(KeyManager.class);
    userKeyManager.storeCredentialSpecification(
        creditCardSpec.getSpecificationUID(), creditCardSpec);

    // Step 2. Load the issuance policy and attributes.
    IssuancePolicy ip =
        (IssuancePolicy)
            XmlUtils.getObjectFromXML(
                this.getClass()
                    .getResourceAsStream(
                        "/eu/abc4trust/sampleXml/uprove/issuancePolicyCreditcardVisa.xml"),
                true);

    // Populate CreditCard attribute values..
    List<Attribute> issuerAtts = new ArrayList<Attribute>();
    this.populateAttributes(issuerAtts);

    // Step 3. Init the issuer
    IssuerAbcEngine issuerEngine = issuerInjector.getInstance(IssuerAbcEngine.class);

    ReloadTokensInMemoryCommunicationStrategy reloadTokens =
        (ReloadTokensInMemoryCommunicationStrategy)
            userInjector.getInstance(ReloadTokensCommunicationStrategy.class);
    reloadTokens.setIssuerAbcEngine(issuerEngine);
    reloadTokens.setIssuancePolicy(ip);

    int idemixKeyLength = 2048;
    int uproveKeylength = 2048;
    URI cryptographicMechanism = CryptoUriUtil.getUproveMechanism();
    SystemParameters sysParam =
        SystemParametersUtil.generatePilotSystemParameters_WithIdemixSpecificKeySize(
            idemixKeyLength, uproveKeylength);

    userKeyManager.storeSystemParameters(sysParam);
    keyManager.storeSystemParameters(sysParam);

    URI uid = ip.getCredentialTemplate().getIssuerParametersUID();

    URI hash = CryptoUriUtil.getHashSha256();
    URI revocationId = new URI("issuer-cpr-rev-id");

    IssuerParameters issuerParameters =
        issuerEngine.setupIssuerParameters(
            creditCardSpec, sysParam, uid, hash, cryptographicMechanism, revocationId, null);

    // Store received issuer parameters in all keymanagers...
    keyManager.storeIssuerParameters(issuerParameters.getParametersUID(), issuerParameters);
    userKeyManager.storeIssuerParameters(issuerParameters.getParametersUID(), issuerParameters);

    KeyManager verifierKeyManager = verifierInjector.getInstance(KeyManager.class);
    verifierKeyManager.storeIssuerParameters(issuerParameters.getParametersUID(), issuerParameters);
    verifierKeyManager.storeSystemParameters(sysParam);

    // Step 4. Issue a credit card credential.
    UserAbcEngine userEngine = userInjector.getInstance(UserAbcEngine.class);

    this.doIssuanceProtocol(issuerEngine, userEngine, ip, issuerAtts);

    // Step 5. Generate a PresentationToken using a simple HotelBooking Policy with creditcard only
    // credential

    PresentationPolicyAlternatives presentationPolicyAlternatives =
        (PresentationPolicyAlternatives)
            XmlUtils.getObjectFromXML(
                this.getClass()
                    .getResourceAsStream(
                        "/eu/abc4trust/sampleXml/uprove/presentationPolicySimpleHotelBookingCreditCardOnly.xml"),
                true);

    PresentationToken presentationToken =
        userEngine.createPresentationToken(presentationPolicyAlternatives);

    // FIXME: Using createPresentationToken again with the same presentationPolicyAlternatives
    // causes a crash in MockIdentitySelection

    // PresentationToken presentationToken1 =
    // userEngine.createPresentationToken(presentationPolicyAlternatives);

    PresentationPolicyAlternatives presentationPolicyAlternatives2 =
        (PresentationPolicyAlternatives)
            XmlUtils.getObjectFromXML(
                this.getClass()
                    .getResourceAsStream(
                        "/eu/abc4trust/sampleXml/uprove/presentationPolicySimpleHotelBookingCreditCardOnlyNoPseudonym.xml"),
                true);

    PresentationToken presentationToken2 =
        userEngine.createPresentationToken(presentationPolicyAlternatives2);

    // We have run out of UProveTokens and must renew credential
    if (presentationToken2 == null) {
      this.doIssuanceProtocol(issuerEngine, userEngine, ip, issuerAtts);
      presentationToken2 = userEngine.createPresentationToken(presentationPolicyAlternatives2);
    }

    // Step 6. Verify the generated PresentationToken

    // Init the Issuer engine
    VerifierAbcEngine verifierEngine = verifierInjector.getInstance(VerifierAbcEngine.class);
    boolean verifyOK = true;
    try {
      PresentationTokenDescription verifyResult =
          verifierEngine.verifyTokenAgainstPolicy(
              presentationPolicyAlternatives, presentationToken, false);
      assertNotNull(verifyResult);
    } catch (TokenVerificationException ex) {
      verifyOK = false;
      System.out.println("Token Verify FAILED!!");
    }
    assertTrue(verifyOK);

    try {
      PresentationTokenDescription verifyResult2 =
          verifierEngine.verifyTokenAgainstPolicy(
              presentationPolicyAlternatives2, presentationToken2, false);
      assertNotNull(verifyResult2);
    } catch (TokenVerificationException ex) {
      verifyOK = false;
      System.out.println("Token Verify FAILED!!");
    }
    assertTrue(verifyOK);

    //        // try to shut down UProve Services...
    //        int exitCode = userInjector.getInstance(UProveBindingManager.class).stop();
    //        assertEquals("U-Prove exe must have exit code 0", 0, exitCode);
    //        exitCode = issuerInjector.getInstance(UProveBindingManager.class).stop();
    //        assertEquals("U-Prove exe must have exit code 0", 0, exitCode);
    //        exitCode = verifierInjector.getInstance(UProveBindingManager.class).stop();
    //        assertEquals("U-Prove exe must have exit code 0", 0, exitCode);

  }