@Test
  public void testSignPDF() throws Exception {
    SignatureServiceImpl ssi = (SignatureServiceImpl) signatureService;

    // first user signs
    Blob origBlob = Blobs.createBlob(origPdfFile);
    assertEquals(UNSIGNED, ssi.getSigningStatus(origBlob, user));
    Blob signedBlob =
        signatureService.signPDF(origBlob, null, user, USER_KEY_PASSWORD, "test reason");
    assertNotNull(signedBlob);
    assertEquals(SIGNED_CURRENT, ssi.getSigningStatus(signedBlob, user));
    assertEquals(SIGNED_OTHER, ssi.getSigningStatus(signedBlob, user2));

    // try for the same user to sign the certificate again
    Blob signedBlobTwice = null;
    try {
      signedBlobTwice =
          signatureService.signPDF(signedBlob, null, user, USER_KEY_PASSWORD, "test reason");
      fail("Should raise AlreadySignedException");
    } catch (AlreadySignedException e) {
      // ok
    }

    // try for the second user to sign the certificate
    signedBlobTwice =
        signatureService.signPDF(signedBlob, null, user2, USER_KEY_PASSWORD, "test reason");
    assertNotNull(signedBlobTwice);
    assertEquals(SIGNED_CURRENT, ssi.getSigningStatus(signedBlobTwice, user));
    assertEquals(SIGNED_CURRENT, ssi.getSigningStatus(signedBlobTwice, user2));

    // test presence of multiple signatures
    List<String> names = getSignatureNames(signedBlobTwice);
    assertEquals(2, names.size());
    assertEquals(Arrays.asList("Signature2", "Signature1"), names);
  }
  @Test
  public void testSignPDFDocumentArchive() throws Exception {
    Blob pdfBlob = Blobs.createBlob(origPdfFile, "application/pdf", null, "foo.pdf");
    DocumentModel doc = session.createDocumentModel("File");
    doc.setPropertyValue("file:content", (Serializable) pdfBlob);

    Blob signedBlob =
        signatureService.signDocument(
            doc,
            user,
            USER_KEY_PASSWORD,
            "test",
            false,
            SigningDisposition.ARCHIVE,
            "foo archive.pdf");

    assertEquals("foo.pdf", signedBlob.getFilename());
    assertEquals(Arrays.asList("Signature1"), getSignatureNames(signedBlob));
    assertEquals(signedBlob, doc.getPropertyValue("file:content"));
    @SuppressWarnings("unchecked")
    List<Map<String, Serializable>> files =
        (List<Map<String, Serializable>>) doc.getPropertyValue("files:files");
    assertEquals(1, files.size());
    Blob archivedBlob = (Blob) files.get(0).get("file");
    assertEquals("application/pdf", archivedBlob.getMimeType());
    assertEquals("foo archive.pdf", archivedBlob.getFilename());
    assertEquals("foo archive.pdf", files.get(0).get("filename"));
  }
  @Test
  public void testResignDocument() throws Exception {
    Blob pdfBlob = Blobs.createBlob(signedPdfFile, "application/pdf", null, "foo.pdf");
    assertEquals(Arrays.asList("Signature1"), getSignatureNames(pdfBlob));

    DocumentModel doc = session.createDocumentModel("File");
    doc.setPropertyValue("file:content", (Serializable) pdfBlob);

    Blob signedBlob =
        signatureService.signDocument(
            doc, user, USER_KEY_PASSWORD, "test", false, SigningDisposition.REPLACE, null);

    assertEquals("foo.pdf", signedBlob.getFilename());
    assertEquals(Arrays.asList("Signature2", "Signature1"), getSignatureNames(signedBlob));
  }
  @Test
  public void testSignDocumentReplace() throws Exception {
    Blob txtBlob = Blobs.createBlob(helloTxtFile, "text/plain", null, "foo.txt");
    DocumentModel doc = session.createDocumentModel("File");
    doc.setPropertyValue("file:content", (Serializable) txtBlob);

    Blob signedBlob =
        signatureService.signDocument(
            doc, user, USER_KEY_PASSWORD, "test", false, SigningDisposition.REPLACE, null);

    assertEquals("foo.pdf", signedBlob.getFilename());
    assertEquals(Arrays.asList("Signature1"), getSignatureNames(signedBlob));
    assertEquals(signedBlob, doc.getPropertyValue("file:content"));
    assertEquals(Collections.emptyList(), doc.getPropertyValue("files:files"));
  }
  @Test
  public void testGetCertificates() throws Exception {
    SignatureServiceImpl ssi = (SignatureServiceImpl) signatureService;

    // sign the original PDF file
    Blob signedBlob =
        signatureService.signPDF(
            Blobs.createBlob(origPdfFile), null, user, USER_KEY_PASSWORD, "test reason");
    assertNotNull(signedBlob);
    // verify there are certificates in the signed file
    List<X509Certificate> certificates = ssi.getCertificates(signedBlob);
    assertTrue(
        "There has to be at least 1 certificate in a signed document", certificates.size() > 0);
    assertTrue(certificates.get(0).getSubjectDN().toString().contains("CN=Homer Simpson"));
  }
 @OperationMethod
 public Blob run(DocumentModel doc) throws OperationException {
   if (!(ctx.getPrincipal() instanceof NuxeoPrincipal)
       || !((NuxeoPrincipal) ctx.getPrincipal()).isAdministrator()) {
     throw new OperationException("Not allowed. You must be administrator to use this operation");
   }
   DocumentModel user = userManager.getUserModel(username);
   Blob originalBlob = doc.getAdapter(BlobHolder.class).getBlob();
   boolean originalIsPdf = MIME_TYPE_PDF.equals(originalBlob.getMimeType());
   // decide if we want PDF/A
   boolean pdfa = SignatureHelper.getPDFA();
   // decide disposition
   SigningDisposition disposition = SignatureHelper.getDisposition(originalIsPdf);
   // decide archive filename
   String filename = originalBlob.getFilename();
   String archiveFilename = SignatureHelper.getArchiveFilename(filename);
   return signatureService.signDocument(
       doc, user, password, reason, pdfa, disposition, archiveFilename);
 }
  @Test
  public void testSignDocumentAttach() throws Exception {
    Blob txtBlob = Blobs.createBlob(helloTxtFile, "text/plain", null, "foo.txt");
    DocumentModel doc = session.createDocumentModel("File");
    doc.setPropertyValue("file:content", (Serializable) txtBlob);

    Blob signedBlob =
        signatureService.signDocument(
            doc, user, USER_KEY_PASSWORD, "test", false, SigningDisposition.ATTACH, null);

    assertEquals("foo.pdf", signedBlob.getFilename());
    assertEquals(Arrays.asList("Signature1"), getSignatureNames(signedBlob));
    assertEquals(txtBlob, doc.getPropertyValue("file:content"));
    @SuppressWarnings("unchecked")
    List<Map<String, Serializable>> files =
        (List<Map<String, Serializable>>) doc.getPropertyValue("files:files");
    assertEquals(1, files.size());
    assertEquals(signedBlob, files.get(0).get("file"));
  }
  @Test
  public void testGetSigningStatus() throws Exception {
    Serializable pdfBlob = (Serializable) Blobs.createBlob(origPdfFile, "application/pdf");
    Serializable signedBlob = (Serializable) Blobs.createBlob(signedPdfFile, "application/pdf");
    Blob otherBlob = Blobs.createBlob("foo", "application/octet-stream");
    DocumentModel doc = session.createDocumentModel("File");
    StatusWithBlob swb;

    swb = signatureService.getSigningStatus(doc, null);
    assertEquals(UNSIGNABLE, swb.status);
    assertNull(swb.path);
    assertNull(swb.blob);

    // unsigned PDF in main file
    doc.setPropertyValue("file:content", pdfBlob);
    swb = signatureService.getSigningStatus(doc, null);
    assertEquals(UNSIGNED, swb.status);
    assertEquals("file:content", swb.path);
    assertEquals(pdfBlob, swb.blob);

    // signed PDF in main file
    doc.setPropertyValue("file:content", signedBlob);
    swb = signatureService.getSigningStatus(doc, null);
    assertEquals(SIGNED_OTHER, swb.status);
    assertEquals("file:content", swb.path);
    assertEquals(signedBlob, swb.blob);

    // not PDF in main file
    doc.setPropertyValue("file:content", (Serializable) otherBlob);
    swb = signatureService.getSigningStatus(doc, null);
    assertEquals(UNSIGNED, swb.status);
    assertEquals("file:content", swb.path);
    assertEquals(otherBlob, swb.blob);

    // no files attached
    doc.setPropertyValue("file:content", null);
    doc.setPropertyValue("files:files", null);
    swb = signatureService.getSigningStatus(doc, null);
    assertEquals(UNSIGNABLE, swb.status);
    assertNull(swb.path);
    assertNull(swb.blob);
    doc.setPropertyValue("files:files", (Serializable) Collections.emptyList());
    swb = signatureService.getSigningStatus(doc, null);
    assertEquals(UNSIGNABLE, swb.status);
    assertNull(swb.path);
    assertNull(swb.blob);

    // unsigned PDF attached
    List<Map<String, Serializable>> fileList = new ArrayList<Map<String, Serializable>>();
    fileList.add(Collections.singletonMap("file", pdfBlob));
    doc.setPropertyValue("files:files", (Serializable) fileList);
    swb = signatureService.getSigningStatus(doc, null);
    assertEquals(UNSIGNABLE, swb.status);
    assertNull(swb.path);
    assertNull(swb.blob);

    // signed PDF attached second
    fileList.clear();
    fileList.add(Collections.singletonMap("file", pdfBlob));
    fileList.add(Collections.singletonMap("file", signedBlob));
    doc.setPropertyValue("files:files", (Serializable) fileList);
    swb = signatureService.getSigningStatus(doc, null);
    assertEquals(SIGNED_OTHER, swb.status);
    assertEquals("files:files/1/file", swb.path);
    assertEquals(signedBlob, swb.blob);

    // and PDF as main file
    doc.setPropertyValue("file:content", pdfBlob);
    swb = signatureService.getSigningStatus(doc, null);
    assertEquals(SIGNED_OTHER, swb.status);
    assertEquals("files:files/1/file", swb.path);
    assertEquals(signedBlob, swb.blob);
  }