public static Signature finalizeXadesXL_TM(SignedDoc sdoc, Signature sig)
     throws DigiDocException {
   if (m_logger.isDebugEnabled())
     m_logger.debug("Finalize XAdES-TM: " + sig.getId() + " profile: " + sig.getProfile());
   NotaryFactory notFac = ConfigManager.instance().getNotaryFactory();
   X509Certificate cert = sig.getKeyInfo().getSignersCertificate();
   boolean bUseLocal = ConfigManager.instance().getBooleanProperty("DIGIDOC_USE_LOCAL_TSL", false);
   TrustServiceFactory tslFac = ConfigManager.instance().getTslFactory();
   String ocspUrl = tslFac.findOcspUrlForCert(cert, 0, bUseLocal);
   if (ocspUrl == null)
     ocspUrl = ConfigManager.instance().getProperty("DIGIDOC_OCSP_RESPONDER_URL");
   X509Certificate caCert = tslFac.findCaForCert(cert, bUseLocal, null);
   if (m_logger.isDebugEnabled())
     m_logger.debug(
         "Get confirmation for cert: "
             + ((cert != null)
                 ? ConvertUtils.getCommonName(cert.getSubjectDN().getName())
                 : "NULL")
             + " CA: "
             + ((caCert != null)
                 ? ConvertUtils.getCommonName(caCert.getSubjectDN().getName())
                 : "NULL")
             + " URL: "
             + ((ocspUrl != null) ? ocspUrl : "NONE"));
   System.out.println("Get conf: " + sig.getId());
   Notary not = notFac.getConfirmation(sig, cert, caCert, null, ocspUrl);
   if (m_logger.isDebugEnabled()) m_logger.debug("Resp-id: " + not.getResponderId());
   String sRespId = ConvertUtils.getCommonName(not.getResponderId());
   // if(sRespId != null && sRespId.startsWith("byName: ")) sRespId = sRespId.substring("byName:
   // ".length());
   // if(sRespId != null && sRespId.startsWith("byKey: ")) sRespId = sRespId.substring("byKey:
   // ".length());
   X509Certificate rcert = notFac.getNotaryCert(sRespId, not.getCertNr());
   if (m_logger.isDebugEnabled())
     m_logger.debug(
         "Find responder cert by: "
             + sRespId
             + " and nr: "
             + not.getCertNr()
             + " found: "
             + ((rcert != null) ? "OK" : "NO")
             + " format: "
             + sdoc.getFormat());
   // if the request was successful then
   // create new data memebers
   if (sdoc.getFormat().equals(SignedDoc.FORMAT_BDOC) && (rcert != null)) {
     X509Certificate rcacert = tslFac.findCaForCert(rcert, bUseLocal, null);
     if (m_logger.isDebugEnabled())
       m_logger.debug(
           "Register responders CA: "
               + ((rcacert != null) ? rcacert.getSubjectDN().getName() : "NULL"));
     String caId =
         not.getId() + "-" + ConvertUtils.getCommonName(rcacert.getSubjectDN().getName());
     registerCert(rcacert, CertID.CERTID_TYPE_RESPONDER_CA, caId, sig);
   }
   // add notary to list
   // sig.getUnsignedProperties().addNotary(not);
   // add ocsp ref for this notary
   OcspRef orf =
       new OcspRef(
           "#" + not.getId(),
           not.getResponderId(),
           not.getProducedAt(),
           (sdoc.getFormat().equals(SignedDoc.FORMAT_BDOC)
               ? SignedDoc.SHA256_DIGEST_ALGORITHM_1
               : SignedDoc.SHA1_DIGEST_ALGORITHM),
           SignedDoc.digestOfType(
               not.getOcspResponseData(),
               (sdoc.getFormat().equals(SignedDoc.FORMAT_BDOC)
                   ? SignedDoc.SHA256_DIGEST_TYPE
                   : SignedDoc.SHA1_DIGEST_TYPE)));
   sig.getUnsignedProperties().getCompleteRevocationRefs().addOcspRef(orf);
   // mark status
   sig.setProfile(SignedDoc.BDOC_PROFILE_TM);
   // change profile
   if (sdoc.getFormat().equals(SignedDoc.FORMAT_BDOC) && sig.getPath() != null) {
     if (m_logger.isDebugEnabled()) m_logger.debug("Find signature: " + sig.getPath());
     ManifestFileEntry mfe = sdoc.findManifestEntryByPath(sig.getPath());
     if (mfe != null) {
       mfe.setMediaType(
           SignedDoc.MIME_SIGNATURE_BDOC_ + sdoc.getVersion() + "/" + sig.getProfile());
       if (m_logger.isDebugEnabled())
         m_logger.debug("Change signature: " + sig.getPath() + " type: " + mfe.getMediaType());
     }
   }
   // TODO: update certs and refs
   return sig;
 }
  /**
   * Adds a new uncomplete signature to signed doc
   *
   * @param sdoc SignedDoc object
   * @param profile new signature profile. Use NULL for default
   * @param cert signers certificate
   * @param claimedRoles signers claimed roles
   * @param adr signers address
   * @param sId new signature id, Use NULL for default value
   * @param sSigMethod signature method uri - ddoc: SignedDoc.RSA_SHA1_SIGNATURE_METHOD, bdoc:
   *     depends on card type. Use null for default value
   * @param sDigType digest type (all other hashes but SignedInfo). Use null for default type
   * @return new Signature object
   */
  public static Signature prepareXadesBES(
      SignedDoc sdoc,
      String profile,
      X509Certificate cert,
      String[] claimedRoles,
      SignatureProductionPlace adr,
      String sId,
      String sSigMethod,
      String sDigType)
      throws DigiDocException {
    if (m_logger.isDebugEnabled())
      m_logger.debug(
          "Prepare signature in sdoc: "
              + sdoc.getFormat()
              + "/"
              + sdoc.getVersion()
              + "/"
              + sdoc.getProfile()
              + " profile: "
              + profile
              + " signer: "
              + ((cert != null)
                  ? SignedDoc.getCommonName(cert.getSubjectDN().getName())
                  : "unknown")
              + " id "
              + sId);
    boolean bWeakSig = false;
    for (int i = 0; i < sdoc.countSignatures(); i++) {
      Signature sig = sdoc.getSignature(i);
      if (sig.getAltDigestMatch()) bWeakSig = true;
    }
    if (bWeakSig) {
      m_logger.error(
          "One or more signatures has wrong DataFile hash even if alternative hash matches!");
      throw new DigiDocException(
          DigiDocException.ERR_VERIFY,
          "One or more signatures has wrong DataFile hash even if alternative hash matches!",
          null);
    }
    // count roles
    if (claimedRoles != null && claimedRoles.length > 1) {
      m_logger.error("Currently supports no more than 1 ClaimedRole");
      throw new DigiDocException(
          DigiDocException.ERR_UNSUPPORTED, "Currently supports no more than 1 ClaimedRole", null);
    }
    // cannot proceed if cert has not been read
    if (cert == null) {
      m_logger.error("Signers certificate missing during signature preparation!");
      throw new DigiDocException(
          DigiDocException.ERR_SIGNERS_CERT,
          "Signers certificate missing during signature preparation!",
          null);
    }
    boolean bCheckNonRepu = ConfigManager.instance().getBooleanProperty("KEY_USAGE_CHECK", true);
    if (bCheckNonRepu && !ConfigManager.isSignatureKey(cert)) {
      if (m_logger.isDebugEnabled())
        m_logger.debug("Signers cert does not have non-repudiation bit set!");
      throw new DigiDocException(
          DigiDocException.ERR_SIGNERS_CERT_NONREPUD,
          "Signers cert does not have non-repudiation bit set!",
          null);
    }
    Signature sig = new Signature(sdoc);
    sig.setId(sId != null ? sId : sdoc.getNewSignatureId());
    if (profile != null) { // use new profile for this signature
      sig.setProfile(profile);
      if (sdoc.getProfile() == null || sdoc.getProfile().equals(SignedDoc.BDOC_PROFILE_BES))
        sdoc.setProfile(profile); // change also container to new profile
    } else // use default profile
    sig.setProfile(sdoc.getProfile());

    // create SignedInfo block
    SignedInfo si =
        new SignedInfo(
            sig,
            ((sSigMethod != null) ? sSigMethod : SignedDoc.RSA_SHA1_SIGNATURE_METHOD),
            SignedDoc.CANONICALIZATION_METHOD_20010315);
    if (sdoc.getFormat().equals(SignedDoc.FORMAT_BDOC)
        && sdoc.getVersion().equals(SignedDoc.BDOC_VERSION_2_1)) {
      si.setCanonicalizationMethod(SignedDoc.CANONICALIZATION_METHOD_1_1);
      sdoc.setDefaultNsPref(SignedDoc.FORMAT_BDOC);
    }
    if (m_logger.isDebugEnabled())
      m_logger.debug(
          "Signer: "
              + cert.getSubjectDN().getName()
              + " EC key: "
              + isEcPubKey(cert)
              + " pre-2011: "
              + isPre2011IdCard(cert)
              + " digi-id: "
              + isDigiIdCard(cert)
              + " 2011: "
              + is2011Card(cert));
    if (sSigMethod == null) { // default values
      if (sdoc.getFormat().equals(SignedDoc.FORMAT_BDOC)) {
        if (isPre2011IdCard(cert)) {
          if (m_logger.isDebugEnabled())
            m_logger.debug("Generating rsa-sha224 signature for pre-2011 card");
          si.setSignatureMethod(SignedDoc.RSA_SHA224_SIGNATURE_METHOD);
        } else {
          String dType =
              ConfigManager.instance().getStringProperty("DIGIDOC_DIGEST_TYPE", "SHA-256");
          String sSigMeth = ConfigManager.digType2SigMeth(dType, isEcPubKey(cert));
          if (m_logger.isDebugEnabled())
            m_logger.debug("Generating digest: " + dType + " and signature: " + sSigMeth);
          if (sSigMeth != null) si.setSignatureMethod(sSigMeth);
          else
            throw new DigiDocException(
                DigiDocException.ERR_DIGEST_ALGORITHM, "Invalid digest type: " + dType, null);
        }
      }
    }
    if (sdoc.getFormat().equals(SignedDoc.FORMAT_XADES)
        || sdoc.getFormat().equals(SignedDoc.FORMAT_BDOC)) si.setId(sig.getId() + "-SignedInfo");
    // SignedDataObjectProperties
    SignedDataObjectProperties sdop = new SignedDataObjectProperties();
    // add DataFile references
    for (int i = 0; i < sdoc.countDataFiles(); i++) {
      DataFile df = sdoc.getDataFile(i);
      if (sdoc.getFormat().equals(SignedDoc.FORMAT_BDOC)) {
        if (!df.isDigestsCalculated()) {
          try {
            InputStream is = null;
            if (df.getDfCacheFile() != null) is = df.getBodyAsStream();
            if (is == null) is = sdoc.findDataFileAsStream(df.getFileName());
            if (is == null) is = new java.io.FileInputStream(df.getFileName());
            df.calcHashes(is);
          } catch (java.io.FileNotFoundException ex) {
            throw new DigiDocException(
                DigiDocException.ERR_READ_FILE, "Cannot read file: " + df.getFileName(), null);
          }
        }
      } else {
        if (!df.isDigestsCalculated()) df.calculateFileSizeAndDigest(null);
      }
      if (m_logger.isDebugEnabled()) m_logger.debug("Add ref for df: " + df.getId());
      Reference ref = new Reference(si, df, sDigType);
      if (sdoc.getFormat().equals(SignedDoc.FORMAT_XADES)
          || sdoc.getFormat().equals(SignedDoc.FORMAT_BDOC)) ref.setId(sig.getId() + "-ref-" + i);
      si.addReference(ref);
      if (sdoc.getFormat().equals(SignedDoc.FORMAT_BDOC)
          && sdoc.getVersion().equals(SignedDoc.BDOC_VERSION_2_1)) {
        DataObjectFormat dof = new DataObjectFormat("#" + ref.getId());
        dof.setMimeType(df.getMimeType());
        sdop.addDataObjectFormat(dof);
      }
    }
    // manifest.xml reference - bdoc 2.1-s ei allkirjasta manifest.xml-i
    // create key info
    KeyInfo ki = new KeyInfo(cert);
    if (sdoc.getFormat().equals(SignedDoc.FORMAT_XADES)
        || sdoc.getFormat().equals(SignedDoc.FORMAT_BDOC)) ki.setId(sig.getId() + "-KeyInfo");
    sig.setKeyInfo(ki);
    ki.setSignature(sig);
    registerCert(cert, CertValue.CERTVAL_TYPE_SIGNER, null, sig);
    if (m_logger.isDebugEnabled()) m_logger.debug("Signer cert: " + cert.getSubjectDN().getName());
    boolean bUseLocal = ConfigManager.instance().getBooleanProperty("DIGIDOC_USE_LOCAL_TSL", false);

    if (sdoc.getFormat().equals(SignedDoc.FORMAT_XADES)
        || sdoc.getFormat().equals(SignedDoc.FORMAT_BDOC)) {
      TrustServiceFactory tslFac = ConfigManager.instance().getTslFactory();
      // first lookup in TSL-s
      X509Certificate ca = tslFac.findCaForCert(cert, bUseLocal, null);
      if (ca != null) {
        String caId = sig.getId() + "-" + ConvertUtils.getCommonName(ca.getSubjectDN().getName());
        registerCert(ca, CertValue.CERTVAL_TYPE_CA, caId, sig);
      }
      // TODO: maybe copy local CA certs to signature until the first ca that is in TSL?
    }
    // create signed properties
    SignedProperties sp = new SignedProperties(sig, cert, claimedRoles, adr);
    sig.setSignedProperties(sp);
    // bdoc 2.0 nonce policy
    if (sdoc.getFormat().equals(SignedDoc.FORMAT_BDOC)
        && sdoc.getVersion().equals(SignedDoc.BDOC_VERSION_2_1)
        && (sig.getProfile().equals(SignedDoc.BDOC_PROFILE_TM)
            || sig.getProfile().equals(SignedDoc.BDOC_PROFILE_BES)
            || sig.getProfile().equals(SignedDoc.BDOC_PROFILE_CL)
            || sig.getProfile().equals(SignedDoc.BDOC_PROFILE_TMA))) {
      sp.setSignedDataObjectProperties(sdop);
      Identifier id1 = new Identifier(Identifier.OIDAsURN);
      id1.setUri(BDOC_210_OID);
      ObjectIdentifier oid1 = new ObjectIdentifier(id1);
      SignaturePolicyId spi1 = new SignaturePolicyId(oid1);
      spi1.setDigestAlgorithm(BDOC_210_DIGEST_METHOD);
      spi1.setDigestValue(ConvertUtils.hex2bin(BDOC_210_DIGEST_HEX));
      // System.out.println("Spec hash: " + BDOC_210_DIGEST_HEX + " b64: " +
      // Base64Util.encode(ConvertUtils.hex2bin(BDOC_210_DIGEST_HEX)));
      spi1.addSigPolicyQualifier(new SpUri(BDOC_210_SPURI));
      SignaturePolicyIdentifier spid1 = new SignaturePolicyIdentifier(spi1);
      sp.setSignaturePolicyIdentifier(spid1);
    } else {
      SignaturePolicyIdentifier spid1 = new SignaturePolicyIdentifier(null);
      sp.setSignaturePolicyIdentifier(spid1);
    }
    Reference ref = new Reference(si, sp, sDigType);
    if (sdoc.getFormat().equals(SignedDoc.FORMAT_XADES)
        || sdoc.getFormat().equals(SignedDoc.FORMAT_BDOC)) ref.setId(sig.getId() + "-ref-sp");
    ref.setType(SignedDoc.SIGNEDPROPERTIES_TYPE);
    si.addReference(ref);
    sig.setSignedInfo(si);
    sdoc.addSignature(sig);
    if (m_logger.isDebugEnabled())
      m_logger.debug("Prepared signature: " + sig.getId() + "/" + sig.getProfile());

    return sig;
  }