
com.helger.as2lib.disposition.DispositionOptions Maven / Gradle / Ivy
Go to download
Show more of this group Show more artifacts with this name
Show all versions of as2-lib Show documentation
Show all versions of as2-lib Show documentation
Open AS2 fork - library part
/**
* The FreeBSD Copyright
* Copyright 1994-2008 The FreeBSD Project. All rights reserved.
* Copyright (C) 2013-2016 Philip Helger philip[at]helger[dot]com
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are
* met:
*
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
*
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
*
* THIS SOFTWARE IS PROVIDED BY THE FREEBSD PROJECT ``AS IS'' AND ANY
* EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
* PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FREEBSD PROJECT OR
* CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
* EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
* PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
* PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
* LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*
* The views and conclusions contained in the software and documentation
* are those of the authors and should not be interpreted as representing
* official policies, either expressed or implied, of the FreeBSD Project.
*/
package com.helger.as2lib.disposition;
import java.util.Locale;
import java.util.NoSuchElementException;
import java.util.StringTokenizer;
import javax.annotation.Nonnegative;
import javax.annotation.Nonnull;
import javax.annotation.Nullable;
import javax.annotation.concurrent.NotThreadSafe;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import com.helger.as2lib.crypto.ECryptoAlgorithmSign;
import com.helger.as2lib.exception.OpenAS2Exception;
import com.helger.commons.annotation.ReturnsMutableCopy;
import com.helger.commons.collection.ext.CommonsArrayList;
import com.helger.commons.collection.ext.ICommonsList;
import com.helger.commons.string.StringHelper;
import com.helger.commons.string.ToStringGenerator;
/**
* Parser and domain object for disposition options. This is usually used in the
* HTTP header "Disposition-Notification-Options".
*
* @author Philip Helger
*/
@NotThreadSafe
public class DispositionOptions
{
/** Protocol attribute */
public static final String SIGNED_RECEIPT_PROTOCOL = "signed-receipt-protocol";
/** MicAlg attribute */
public static final String SIGNED_RECEIPT_MICALG = "signed-receipt-micalg";
public static final String IMPORTANCE_REQUIRED = "required";
public static final String IMPORTANCE_OPTIONAL = "optional";
/** Default protocol value */
public static final String PROTOCOL_PKCS7_SIGNATURE = "pkcs7-signature";
private static final Logger s_aLogger = LoggerFactory.getLogger (DispositionOptions.class);
private String m_sProtocolImportance;
private String m_sProtocol;
private String m_sMICAlgImportance;
private final ICommonsList m_aMICAlgs = new CommonsArrayList<> ();
public DispositionOptions ()
{}
/**
* Check if the passed importance value is a standard one (null
,
* "optional" or "required").
*
* @param sImportance
* The value to be checked.
*/
private static void _checkImportance (@Nullable final String sImportance)
{
if (sImportance != null && !sImportance.equals (IMPORTANCE_REQUIRED) && !sImportance.equals (IMPORTANCE_OPTIONAL))
s_aLogger.warn ("Non-standard importance value '" + sImportance + "' used!");
}
/**
* Set the protocol importance.
*
* @param sProtocolImportance
* The importance to set. May be null
.
* @return this
*/
@Nonnull
public DispositionOptions setProtocolImportance (@Nullable final String sProtocolImportance)
{
_checkImportance (sProtocolImportance);
m_sProtocolImportance = sProtocolImportance;
return this;
}
/**
* @return the protocol importance (null
or "required" or
* "optional"). May be null
.
*/
@Nullable
public String getProtocolImportance ()
{
return m_sProtocolImportance;
}
public boolean isProtocolRequired ()
{
return IMPORTANCE_REQUIRED.equals (m_sProtocolImportance);
}
public boolean isProtocolOptional ()
{
return IMPORTANCE_OPTIONAL.equals (m_sProtocolImportance);
}
/**
* Set the protocol
*
* @param sProtocol
* The protocol name (e.g. "pkcs7-signature"). May be null
* .
* @return this
*/
@Nonnull
public DispositionOptions setProtocol (@Nullable final String sProtocol)
{
m_sProtocol = sProtocol;
return this;
}
/**
* @return The protocol. Currently only "pkcs7-signature" or null
* is supported.
*/
@Nullable
public String getProtocol ()
{
return m_sProtocol;
}
/**
* Set the MIC algorithm importance
*
* @param sMICAlgImportance
* The importance. May be null
.
* @return this
*/
@Nonnull
public DispositionOptions setMICAlgImportance (@Nullable final String sMICAlgImportance)
{
_checkImportance (sMICAlgImportance);
m_sMICAlgImportance = sMICAlgImportance;
return this;
}
/**
* @return the MIC algorithm importance (null
or "required" or
* "optional").
*/
@Nullable
public String getMICAlgImportance ()
{
return m_sMICAlgImportance;
}
public boolean isMICAlgRequired ()
{
return IMPORTANCE_REQUIRED.equals (m_sMICAlgImportance);
}
public boolean isMICAlgOptional ()
{
return IMPORTANCE_OPTIONAL.equals (m_sMICAlgImportance);
}
/**
* Set the MIC algorithm(s) to use. The passed string is parsed as a comma
* separated list. This overwrites all existing MIC algorithms. If any of the
* contained MIC algorithms is not supported by this library, a log message is
* emitted but no Exception is thrown.
*
* @param sMICAlgs
* The MIC algorithm(s). May be null
.
* @return this
*/
@Nonnull
public DispositionOptions setMICAlg (@Nullable final String sMICAlgs)
{
m_aMICAlgs.clear ();
if (StringHelper.hasText (sMICAlgs))
{
final ICommonsList aMICAlgs = StringHelper.getExploded (',', sMICAlgs.trim ());
for (final String sMICAlg : aMICAlgs)
{
// trim and lowercase
final String sRealMICAlg = sMICAlg.trim ().toLowerCase (Locale.US);
final ECryptoAlgorithmSign eMICAlg = ECryptoAlgorithmSign.getFromIDOrNull (sRealMICAlg);
if (eMICAlg == null)
{
// Ignore all unsupported MIC algorithms and continue
s_aLogger.warn ("The passed MIC algorithm '" + sRealMICAlg + "' is unsupported!");
}
else
{
m_aMICAlgs.add (eMICAlg);
}
}
}
return this;
}
/**
* Set the MIC algorithm to use. This overwrites all existing MIC algorithms.
*
* @param aMICAlgs
* The digesting MIC algorithm(s). May be null
.
* @return this
*/
@Nonnull
public DispositionOptions setMICAlg (@Nullable final ECryptoAlgorithmSign... aMICAlgs)
{
m_aMICAlgs.clear ();
if (aMICAlgs != null)
for (final ECryptoAlgorithmSign eMICAlg : aMICAlgs)
if (eMICAlg != null)
m_aMICAlgs.add (eMICAlg);
return this;
}
/**
* Set the MIC algorithm to use. This overwrites all existing MIC algorithms.
*
* @param aMICAlgs
* The digesting MIC algorithm(s). May be null
.
* @return this
*/
@Nonnull
public DispositionOptions setMICAlg (@Nullable final Iterable extends ECryptoAlgorithmSign> aMICAlgs)
{
m_aMICAlgs.clear ();
if (aMICAlgs != null)
for (final ECryptoAlgorithmSign eMICAlg : aMICAlgs)
if (eMICAlg != null)
m_aMICAlgs.add (eMICAlg);
return this;
}
/**
* @return All MIC algorithms contained. Never null
but maybe
* empty.
*/
@Nonnull
@ReturnsMutableCopy
public ICommonsList getAllMICAlgs ()
{
return m_aMICAlgs.getClone ();
}
/**
* @return The first MIC algorithm contained in the list. May be
* null
if no MIC algorithm is set.
*/
@Nullable
public ECryptoAlgorithmSign getFirstMICAlg ()
{
return m_aMICAlgs.getFirst ();
}
/**
* @return The number of contained MIC algorithms. Always ≥ 0.
*/
@Nonnegative
public int getMICAlgCount ()
{
return m_aMICAlgs.size ();
}
/**
* @return true
if at least one MIC algorithm is present,
* false
if none is present.
*/
public boolean hasMICAlg ()
{
return m_aMICAlgs.isNotEmpty ();
}
/**
* @return The MIC algorithm(s) as a comma delimited string. May be
* null
.
*/
@Nullable
public String getMICAlgAsString ()
{
if (m_aMICAlgs.isEmpty ())
return null;
return StringHelper.getImploded (", ", m_aMICAlgs, ECryptoAlgorithmSign::getID);
}
@Nonnull
public String getAsString ()
{
final StringBuilder aSB = new StringBuilder ();
if (StringHelper.hasText (m_sProtocolImportance) && StringHelper.hasText (m_sProtocol))
{
aSB.append (SIGNED_RECEIPT_PROTOCOL)
.append ('=')
.append (m_sProtocolImportance)
.append (", ")
.append (m_sProtocol);
}
if (StringHelper.hasText (m_sMICAlgImportance) && !m_aMICAlgs.isEmpty ())
{
if (aSB.length () > 0)
aSB.append ("; ");
aSB.append (SIGNED_RECEIPT_MICALG)
.append ('=')
.append (m_sMICAlgImportance)
.append (", ")
.append (getMICAlgAsString ());
}
return aSB.toString ();
}
@Override
public String toString ()
{
return new ToStringGenerator (this).append ("ProtocolImportance", m_sProtocolImportance)
.append ("Protocol", m_sProtocol)
.append ("MICAlgImportance", m_sMICAlgImportance)
.append ("MICAlgs", m_aMICAlgs)
.toString ();
}
/**
* Parse Strings like signed-receipt-protocol=optional, pkcs7-signature;
* signed-receipt-micalg=optional, sha1
*
* @param sOptions
* The string to parse. May be null
in which case an empty
* object will be returned.
* @return Never null
.
* @throws OpenAS2Exception
* In the very unlikely case of a programming error in
* {@link StringTokenizer}.
*/
@Nonnull
public static DispositionOptions createFromString (@Nullable final String sOptions) throws OpenAS2Exception
{
final DispositionOptions ret = new DispositionOptions ();
if (StringHelper.hasTextAfterTrim (sOptions))
{
try
{
// Split options into parameters by ";"
for (final String sParameter : StringHelper.getExplodedArray (';', sOptions.trim ()))
{
// Split parameter into name and value by "="
final String [] aParts = StringHelper.getExplodedArray ('=', sParameter.trim (), 2);
if (aParts.length == 2)
{
final String sAttribute = aParts[0].trim ();
// Split the value into importance and the main values by ","
final String [] aValues = StringHelper.getExplodedArray (',', aParts[1].trim (), 2);
if (aValues.length == 2)
{
if (sAttribute.equalsIgnoreCase (SIGNED_RECEIPT_PROTOCOL))
{
ret.setProtocolImportance (aValues[0].trim ());
ret.setProtocol (aValues[1].trim ());
}
else
if (sAttribute.equalsIgnoreCase (SIGNED_RECEIPT_MICALG))
{
ret.setMICAlgImportance (aValues[0].trim ());
ret.setMICAlg (aValues[1].trim ());
}
else
s_aLogger.warn ("Unsupported disposition attribute '" +
sAttribute +
"' with value '" +
aParts[1].trim () +
"' found!");
}
else
s_aLogger.warn ("Failed to split disposition options parameter '" +
sParameter +
"' value '" +
aParts[1].trim () +
"' into importance and values");
}
else
s_aLogger.warn ("Failed to split disposition options parameter '" +
sParameter +
"' into attribute and values");
}
}
catch (final NoSuchElementException ex)
{
throw new OpenAS2Exception ("Invalid disposition options format: " + sOptions);
}
}
return ret;
}
}
© 2015 - 2025 Weber Informatics LLC | Privacy Policy