/**
  * Serializes an authentication request into a string.
  *
  * @param request the request to serialize
  * @return the serialized form of the string
  * @throws MarshallingException thrown if the request can not be marshalled and serialized
  */
 protected String serializeRequest(AuthnRequest request) throws MarshallingException {
   Marshaller marshaller = Configuration.getMarshallerFactory().getMarshaller(request);
   Element requestElem = marshaller.marshall(request);
   StringWriter writer = new StringWriter();
   XMLHelper.writeNode(requestElem, writer);
   return writer.toString();
 }
  /**
   * Encodes the SAML 2.0 based request XML object into its corresponding Base64 notation, based on
   * the type of SAML 2.0 binding.
   *
   * @param requestMessage the {@link RequestAbstractType} XML object to be encoded
   * @param binding the SAML 2.0 binding type
   * @return encoded {@link String} corresponding to the request XML object
   * @throws SSOException if an error occurs while encoding SAML2 request
   */
  protected static String encodeRequestMessage(RequestAbstractType requestMessage, String binding)
      throws SSOException {
    Marshaller marshaller = Configuration.getMarshallerFactory().getMarshaller(requestMessage);
    Element authDOM;
    try {
      //  Marshall this element, and its children, and root them in a newly created Document
      authDOM = marshaller.marshall(requestMessage);
    } catch (MarshallingException e) {
      throw new SSOException(
          "Error occurred while encoding SAML2 request, failed to marshall the SAML 2.0. "
              + "Request element XMLObject to its corresponding W3C DOM element",
          e);
    }

    StringWriter writer = new StringWriter();
    //  Writes the node out to the writer using the DOM
    XMLHelper.writeNode(authDOM, writer);

    if (SAMLConstants.SAML2_REDIRECT_BINDING_URI.equals(binding)) {
      //  Compress the message, Base 64 encode and URL encode
      Deflater deflater = new Deflater(Deflater.DEFLATED, true);
      ByteArrayOutputStream byteArrayOutputStream = new ByteArrayOutputStream();
      try (DeflaterOutputStream deflaterOutputStream =
          new DeflaterOutputStream(byteArrayOutputStream, deflater)) {
        deflaterOutputStream.write(writer.toString().getBytes(Charset.forName("UTF-8")));
      } catch (IOException e) {
        throw new SSOException("Error occurred while deflate encoding SAML2 request", e);
      }

      String encodedRequestMessage =
          Base64.encodeBytes(byteArrayOutputStream.toByteArray(), Base64.DONT_BREAK_LINES);
      try {
        return URLEncoder.encode(encodedRequestMessage, "UTF-8").trim();
      } catch (UnsupportedEncodingException e) {
        throw new SSOException("Error occurred while encoding SAML2 request", e);
      }
    } else if (SAMLConstants.SAML2_POST_BINDING_URI.equals(binding)) {
      return Base64.encodeBytes(
          writer.toString().getBytes(Charset.forName("UTF-8")), Base64.DONT_BREAK_LINES);
    } else {
      logger.log(
          Level.FINE,
          "Unsupported SAML2 HTTP Binding. Defaulting to " + SAMLConstants.SAML2_POST_BINDING_URI);
      return Base64.encodeBytes(
          writer.toString().getBytes(Charset.forName("UTF-8")), Base64.DONT_BREAK_LINES);
    }
  }
  private String encodeRequestMessage(RequestAbstractType requestMessage) throws SAMLSSOException {

    Marshaller marshaller = Configuration.getMarshallerFactory().getMarshaller(requestMessage);
    Element authDOM = null;
    try {
      authDOM = marshaller.marshall(requestMessage);

      /* Compress the message */
      Deflater deflater = new Deflater(Deflater.DEFLATED, true);
      ByteArrayOutputStream byteArrayOutputStream = new ByteArrayOutputStream();
      DeflaterOutputStream deflaterOutputStream =
          new DeflaterOutputStream(byteArrayOutputStream, deflater);
      StringWriter rspWrt = new StringWriter();
      XMLHelper.writeNode(authDOM, rspWrt);
      deflaterOutputStream.write(rspWrt.toString().getBytes());
      deflaterOutputStream.close();

      /* Encoding the compressed message */
      String encodedRequestMessage =
          Base64.encodeBytes(byteArrayOutputStream.toByteArray(), Base64.DONT_BREAK_LINES);

      byteArrayOutputStream.write(byteArrayOutputStream.toByteArray());
      byteArrayOutputStream.toString();

      // log saml
      if (log.isDebugEnabled()) {
        log.debug("SAML Request  :  " + rspWrt.toString());
      }

      return URLEncoder.encode(encodedRequestMessage, "UTF-8").trim();

    } catch (MarshallingException e) {
      throw new SAMLSSOException("Error occurred while encoding SAML request", e);
    } catch (UnsupportedEncodingException e) {
      throw new SAMLSSOException("Error occurred while encoding SAML request", e);
    } catch (IOException e) {
      throw new SAMLSSOException("Error occurred while encoding SAML request", e);
    }
  }
  protected String encodeRequestMessage(RequestAbstractType requestMessage, String binding)
      throws SSOAgentException {

    Marshaller marshaller = Configuration.getMarshallerFactory().getMarshaller(requestMessage);
    Element authDOM = null;
    try {
      authDOM = marshaller.marshall(requestMessage);
      StringWriter rspWrt = new StringWriter();
      XMLHelper.writeNode(authDOM, rspWrt);
      if (SAMLConstants.SAML2_REDIRECT_BINDING_URI.equals(binding)) {
        // Compress the message, Base 64 encode and URL encode
        Deflater deflater = new Deflater(Deflater.DEFLATED, true);
        ByteArrayOutputStream byteArrayOutputStream = new ByteArrayOutputStream();
        DeflaterOutputStream deflaterOutputStream =
            new DeflaterOutputStream(byteArrayOutputStream, deflater);
        deflaterOutputStream.write(rspWrt.toString().getBytes(Charset.forName("UTF-8")));
        deflaterOutputStream.close();
        String encodedRequestMessage =
            Base64.encodeBytes(byteArrayOutputStream.toByteArray(), Base64.DONT_BREAK_LINES);
        return URLEncoder.encode(encodedRequestMessage, "UTF-8").trim();
      } else if (SAMLConstants.SAML2_POST_BINDING_URI.equals(binding)) {
        return Base64.encodeBytes(rspWrt.toString().getBytes(), Base64.DONT_BREAK_LINES);
      } else {
        LOGGER.log(
            Level.FINE,
            "Unsupported SAML2 HTTP Binding. Defaulting to "
                + SAMLConstants.SAML2_POST_BINDING_URI);
        return Base64.encodeBytes(rspWrt.toString().getBytes(), Base64.DONT_BREAK_LINES);
      }
    } catch (MarshallingException e) {
      throw new SSOAgentException("Error occurred while encoding SAML2 request", e);
    } catch (UnsupportedEncodingException e) {
      throw new SSOAgentException("Error occurred while encoding SAML2 request", e);
    } catch (IOException e) {
      throw new SSOAgentException("Error occurred while encoding SAML2 request", e);
    }
  }