@Test
 public void testBasic() {
   for (final EUICoreJSPathProvider e : EUICoreJSPathProvider.values()) {
     IReadableResource aRes = new ClassPathResource(e.getJSItemPath(true));
     assertTrue(aRes.getPath(), aRes.exists());
     aRes = new ClassPathResource(e.getJSItemPath(false));
     assertTrue(aRes.getPath(), aRes.exists());
   }
 }
  /**
   * This is the main sending routine. It performs the following steps:
   *
   * <ol>
   *   <li>Verify that all required parameters are present and valid - {@link #verifyContent()}
   *   <li>The business document is read as XML. In case of an error, an exception is thrown.
   *   <li>The Standard Business Document (SBD) is created, all PEPPOL required fields are set and
   *       the business document is embedded.
   *   <li>The SBD is serialized and send via AS2
   *   <li>The AS2 response incl. the MDN is returned for further evaluation.
   * </ol>
   *
   * @return The AS2 response returned by the AS2 sender. This is never <code>null</code>.
   * @throws AS2ClientBuilderException In case the the business document is invalid XML or in case
   *     {@link #verifyContent()} throws an exception because of invalid or incomplete settings.
   */
  @Nonnull
  public AS2ClientResponse sendSynchronous() throws AS2ClientBuilderException {
    // Perform SMP client lookup
    performSMPClientLookup();

    // Set derivable values
    setDefaultDerivedValues();

    // Verify the whole data set
    verifyContent();

    // Build message

    // 1. read business document
    Element aXML = null;
    if (m_aBusinessDocumentRes != null) {
      try {
        final Document aXMLDocument = DOMReader.readXMLDOM(m_aBusinessDocumentRes);
        if (aXMLDocument == null)
          throw new AS2ClientBuilderException(
              "Failed to read business document '" + m_aBusinessDocumentRes.getPath() + "' as XML");
        aXML = aXMLDocument.getDocumentElement();
      } catch (final SAXException ex) {
        throw new AS2ClientBuilderException(
            "Failed to read business document '" + m_aBusinessDocumentRes.getPath() + "' as XML",
            ex);
      }
    } else {
      aXML = m_aBusinessDocumentElement;
    }
    if (aXML == null) throw new AS2ClientBuilderException("No XML business content present!");

    // 2. validate the business document
    if (m_aValidationKey != null) validateOutgoingBusinessDocument(aXML);

    // 3. build SBD data
    final PeppolSBDHDocument aDD = PeppolSBDHDocument.create(aXML);
    aDD.setSenderWithDefaultScheme(m_aPeppolSenderID.getValue());
    aDD.setReceiver(m_aPeppolReceiverID.getScheme(), m_aPeppolReceiverID.getValue());
    aDD.setDocumentType(m_aPeppolDocumentTypeID.getScheme(), m_aPeppolDocumentTypeID.getValue());
    aDD.setProcess(m_aPeppolProcessID.getScheme(), m_aPeppolProcessID.getValue());

    // 4. build SBD
    final StandardBusinessDocument aSBD =
        new PeppolSBDHDocumentWriter().createStandardBusinessDocument(aDD);
    final NonBlockingByteArrayOutputStream aBAOS = new NonBlockingByteArrayOutputStream();
    if (new SBDMarshaller().write(aSBD, new StreamResult(aBAOS)).isFailure())
      throw new AS2ClientBuilderException("Failed to serialize SBD!");
    aBAOS.close();

    // 5. send message
    // Start building the AS2 client settings
    final AS2ClientSettings aAS2ClientSettings = new AS2ClientSettings();
    // Key store
    aAS2ClientSettings.setKeyStore(m_aKeyStoreFile, m_sKeyStorePassword);
    aAS2ClientSettings.setSaveKeyStoreChangesToFile(m_bSaveKeyStoreChangesToFile);

    // Fixed sender
    aAS2ClientSettings.setSenderData(m_sSenderAS2ID, m_sSenderAS2Email, m_sSenderAS2KeyAlias);

    // Dynamic receiver
    aAS2ClientSettings.setReceiverData(m_sReceiverAS2ID, m_sReceiverAS2KeyAlias, m_sReceiverAS2Url);
    aAS2ClientSettings.setReceiverCertificate(m_aReceiverCert);

    // AS2 stuff - no need to change anything in this block
    aAS2ClientSettings.setPartnershipName(
        aAS2ClientSettings.getSenderAS2ID() + "-" + aAS2ClientSettings.getReceiverAS2ID());
    aAS2ClientSettings.setMDNOptions(
        new DispositionOptions()
            .setMICAlg(m_eSigningAlgo)
            .setMICAlgImportance(DispositionOptions.IMPORTANCE_REQUIRED)
            .setProtocol(DispositionOptions.PROTOCOL_PKCS7_SIGNATURE)
            .setProtocolImportance(DispositionOptions.IMPORTANCE_REQUIRED));
    aAS2ClientSettings.setEncryptAndSign(null, m_eSigningAlgo);
    aAS2ClientSettings.setMessageIDFormat(m_sMessageIDFormat);

    final AS2ClientRequest aRequest = new AS2ClientRequest(m_sAS2Subject);
    // Using a String is better when having a
    // com.sun.xml.ws.encoding.XmlDataContentHandler installed!
    aRequest.setData(aBAOS.getAsString(CCharset.CHARSET_UTF_8_OBJ), CCharset.CHARSET_UTF_8_OBJ);

    final AS2Client aAS2Client = m_aAS2ClientFactory.create();
    final AS2ClientResponse aResponse = aAS2Client.sendSynchronous(aAS2ClientSettings, aRequest);
    return aResponse;
  }
  /**
   * Verify the content of all contained fields so that all know issues are captured before sending.
   * This method is automatically called before the message is send (see {@link
   * #sendSynchronous()}). All verification warnings and errors are handled via the message handler.
   *
   * @throws AS2ClientBuilderException In case the message handler throws an exception in case of an
   *     error.
   * @see #setMessageHandler(IAS2ClientBuilderMessageHandler)
   */
  public void verifyContent() throws AS2ClientBuilderException {
    if (m_aKeyStoreFile == null) m_aMessageHandler.error("No AS2 key store is defined");
    else {
      if (!m_aKeyStoreFile.exists())
        m_aMessageHandler.error(
            "The provided AS2 key store '"
                + m_aKeyStoreFile.getAbsolutePath()
                + "' does not exist.");
      else if (!m_aKeyStoreFile.isFile())
        m_aMessageHandler.error(
            "The provided AS2 key store '"
                + m_aKeyStoreFile.getAbsolutePath()
                + "' is not a file but potentially a directory.");
      else if (!m_aKeyStoreFile.canWrite())
        m_aMessageHandler.error(
            "The provided AS2 key store '"
                + m_aKeyStoreFile.getAbsolutePath()
                + "' is not writable. As it is dynamically modified, it must be writable.");
    }
    if (m_sKeyStorePassword == null)
      m_aMessageHandler.error(
          "No key store password provided. If you need an empty password, please provide an empty String!");

    if (StringHelper.hasNoText(m_sAS2Subject))
      m_aMessageHandler.error("The AS2 message subject is missing");

    if (StringHelper.hasNoText(m_sSenderAS2ID))
      m_aMessageHandler.error("The AS2 sender ID is missing");
    else if (!m_sSenderAS2ID.startsWith(APP_PREFIX))
      m_aMessageHandler.warn(
          "The AS2 sender ID '"
              + m_sSenderAS2ID
              + "' should start with '"
              + APP_PREFIX
              + "' as required by the PEPPOL specification");

    if (StringHelper.hasNoText(m_sSenderAS2Email))
      m_aMessageHandler.error("The AS2 sender email address is missing");
    else if (!EmailAddressHelper.isValid(m_sSenderAS2Email))
      m_aMessageHandler.warn(
          "The AS2 sender email address '"
              + m_sSenderAS2Email
              + "' seems to be an invalid email address.");

    if (StringHelper.hasNoText(m_sSenderAS2KeyAlias))
      m_aMessageHandler.error("The AS2 sender key alias is missing");
    else if (!m_sSenderAS2KeyAlias.startsWith(APP_PREFIX))
      m_aMessageHandler.warn(
          "The AS2 sender key alias '"
              + m_sSenderAS2KeyAlias
              + "' should start with '"
              + APP_PREFIX
              + "' for the use with the dynamic AS2 partnerships");
    else if (m_sSenderAS2ID != null && !m_sSenderAS2ID.equals(m_sSenderAS2KeyAlias))
      m_aMessageHandler.warn(
          "The AS2 sender key alias ('"
              + m_sSenderAS2KeyAlias
              + "') should match the AS2 sender ID ('"
              + m_sSenderAS2ID
              + "')");

    if (StringHelper.hasNoText(m_sReceiverAS2ID))
      m_aMessageHandler.error("The AS2 receiver ID is missing");
    else if (!m_sReceiverAS2ID.startsWith(APP_PREFIX))
      m_aMessageHandler.warn(
          "The AS2 receiver ID '"
              + m_sReceiverAS2ID
              + "' should start with '"
              + APP_PREFIX
              + "' as required by the PEPPOL specification");

    if (StringHelper.hasNoText(m_sReceiverAS2KeyAlias))
      m_aMessageHandler.error("The AS2 receiver key alias is missing");
    else if (!m_sReceiverAS2KeyAlias.startsWith(APP_PREFIX))
      m_aMessageHandler.warn(
          "The AS2 receiver key alias '"
              + m_sReceiverAS2KeyAlias
              + "' should start with '"
              + APP_PREFIX
              + "' for the use with the dynamic AS2 partnerships");
    else if (m_sReceiverAS2ID != null && !m_sReceiverAS2ID.equals(m_sReceiverAS2KeyAlias))
      m_aMessageHandler.warn(
          "The AS2 receiver key alias ('"
              + m_sReceiverAS2KeyAlias
              + "') should match the AS2 receiver ID ('"
              + m_sReceiverAS2ID
              + "')");

    if (StringHelper.hasNoText(m_sReceiverAS2Url))
      m_aMessageHandler.error("The AS2 receiver URL (AS2 endpoint URL) is missing");
    else if (URLHelper.getAsURL(m_sReceiverAS2Url) == null)
      m_aMessageHandler.warn(
          "The provided AS2 receiver URL '" + m_sReceiverAS2Url + "' seems to be an invalid URL");

    if (m_aReceiverCert == null)
      m_aMessageHandler.error(
          "The receiver X.509 certificate is missing. Usually this is extracted from the SMP response");

    if (m_eSigningAlgo == null)
      m_aMessageHandler.error("The signing algorithm for the AS2 message is missing");

    if (StringHelper.hasNoText(m_sMessageIDFormat))
      m_aMessageHandler.error("The AS2 message ID format is missing.");

    if (m_aBusinessDocumentRes == null && m_aBusinessDocumentElement == null)
      m_aMessageHandler.error("The XML business document to be send is missing.");
    else if (m_aBusinessDocumentRes != null && !m_aBusinessDocumentRes.exists())
      m_aMessageHandler.error(
          "The XML business document to be send '"
              + m_aBusinessDocumentRes.getPath()
              + "' does not exist.");

    if (m_aPeppolSenderID == null)
      m_aMessageHandler.error("The PEPPOL sender participant ID is missing");
    else if (!IdentifierHelper.hasDefaultParticipantIdentifierScheme(m_aPeppolSenderID))
      m_aMessageHandler.warn(
          "The PEPPOL sender participant ID '"
              + IdentifierHelper.getIdentifierURIEncoded(m_aPeppolSenderID)
              + "' is using a non-standard scheme!");

    if (m_aPeppolReceiverID == null)
      m_aMessageHandler.error("The PEPPOL receiver participant ID is missing");
    else if (!IdentifierHelper.hasDefaultParticipantIdentifierScheme(m_aPeppolReceiverID))
      m_aMessageHandler.warn(
          "The PEPPOL receiver participant ID '"
              + IdentifierHelper.getIdentifierURIEncoded(m_aPeppolReceiverID)
              + "' is using a non-standard scheme!");

    if (m_aPeppolDocumentTypeID == null)
      m_aMessageHandler.error("The PEPPOL document type ID is missing");
    else if (!IdentifierHelper.hasDefaultDocumentTypeIdentifierScheme(m_aPeppolDocumentTypeID))
      m_aMessageHandler.warn(
          "The PEPPOL document type ID '"
              + IdentifierHelper.getIdentifierURIEncoded(m_aPeppolDocumentTypeID)
              + "' is using a non-standard scheme!");

    if (m_aPeppolProcessID == null) m_aMessageHandler.error("The PEPPOL process ID is missing");
    else if (!IdentifierHelper.hasDefaultProcessIdentifierScheme(m_aPeppolProcessID))
      m_aMessageHandler.warn(
          "The PEPPOL process ID '"
              + IdentifierHelper.getIdentifierURIEncoded(m_aPeppolProcessID)
              + "' is using a non-standard scheme!");

    if (m_aValidationKey == null)
      m_aMessageHandler.warn(
          "The validation key determining the business document validation is missing. Therefore the outgoing business document is NOT validated!");

    // Ensure that if a non-throwing message handler is installed, that the
    // sending is not performed!
    if (m_aMessageHandler.getErrorCount() > 0)
      throw new AS2ClientBuilderException(
          "Not all required fields are present so the PEPPOL AS2 client call can NOT be performed. See the message handler for details!");
  }