/*
* Copyright 2003 Federal Chancellery Austria
* MOA-SPSS has been developed in a cooperation between BRZ, the Federal
* Chancellery Austria - ICT staff unit, and Graz University of Technology.
*
* Licensed under the EUPL, Version 1.1 or - as soon they will be approved by
* the European Commission - subsequent versions of the EUPL (the "Licence");
* You may not use this work except in compliance with the Licence.
* You may obtain a copy of the Licence at:
* http://www.osor.eu/eupl/
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the Licence is distributed on an "AS IS" basis,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the Licence for the specific language governing permissions and
* limitations under the Licence.
*
* This product combines work with different licenses. See the "NOTICE" text
* file for details on the various modules and licenses.
* The "NOTICE" text file is part of the distribution. Any derivative works
* that you distribute must include a readable copy of the "NOTICE" text file.
*/
package at.gv.egovernment.moa.spss.api.xmlbind;
import java.io.IOException;
import java.security.cert.CertificateEncodingException;
import java.security.cert.X509Certificate;
import java.util.Calendar;
import java.util.Date;
import java.util.GregorianCalendar;
import java.util.TimeZone;
import javax.xml.bind.DatatypeConverter;
import javax.xml.parsers.DocumentBuilder;
import javax.xml.parsers.DocumentBuilderFactory;
import javax.xml.parsers.ParserConfigurationException;
import org.apache.commons.lang3.StringUtils;
import org.w3c.dom.DOMImplementation;
import org.w3c.dom.Document;
import org.w3c.dom.Element;
import org.w3c.dom.NodeList;
import at.gv.egovernment.moa.spss.MOAApplicationException;
import at.gv.egovernment.moa.spss.MOASystemException;
import at.gv.egovernment.moa.spss.api.common.ExtendedCertificateCheckResult;
import at.gv.egovernment.moa.spss.api.common.TslInfos;
import at.gv.egovernment.moaspss.util.Base64Utils;
import at.gv.egovernment.moaspss.util.Constants;
import at.gv.egovernment.moaspss.util.MiscUtil;
import iaik.utils.RFC2253NameParser;
import iaik.utils.RFC2253NameParserException;
/**
* Utility methods used by the verious ResponseBuilder
classes.
*
* @author Patrick Peck
* @version $Id$
*/
public class ResponseBuilderUtils {
//
// shortcuts to various XML namespace constants
//
private static final String MOA_NS_URI = Constants.MOA_NS_URI;
private static final String DSIG = Constants.DSIG_PREFIX + ":";
private static final String DSIG_NS_URI = Constants.DSIG_NS_URI;
private static final String XMLNS_NS_URI = Constants.XMLNS_NS_URI;
/**
* Add an DOM element with a specific name as child to a root element
*
* @param elementName Name of the DOM element
* @param response Full document with namespace information
* @param rootElement Root element
* @return new child DOM element
*/
public static Element addChildElement(String elementName, Document response,
Element rootElement) {
final Element childElement = response.createElementNS(MOA_NS_URI, elementName);
rootElement.appendChild(childElement);
return childElement;
}
/**
* Create a response element with all the namespaces set.
*
* @param responseName The name of the response root element.
* @return A DOM document containing the response root element and predefined
* MOA, DSIG and XML namespace declarations.
* @throws MOASystemException An error building the response document.
*/
public static Document createResponse(String responseName)
throws MOASystemException {
try {
final DocumentBuilder docBuilder =
DocumentBuilderFactory.newInstance().newDocumentBuilder();
final DOMImplementation impl = docBuilder.getDOMImplementation();
Document response;
Element root;
String attrValue;
response = impl.createDocument(MOA_NS_URI, responseName, null);
root = response.getDocumentElement();
// add namespace prefix declarations
root.setAttributeNS(XMLNS_NS_URI, "xmlns", MOA_NS_URI);
attrValue = "xmlns:" + Constants.DSIG_PREFIX;
root.setAttributeNS(XMLNS_NS_URI, attrValue, DSIG_NS_URI);
return response;
} catch (final ParserConfigurationException e) {
throw new MOASystemException("2200", null, e);
}
}
/**
* Add a SignerInfo
element to the response.
*
* @param response The response document, in order to create new
* elements in it.
* @param root The root element into which the
* SignerInfo
element will be inserted.
* @param cert The signer certificate to add.
* @param isQualified Indicates, whether cert
is a qualified
* certificate.
* @param isPublicAuthority Indicates, whether cert
is certificate
* owned by a public authority.
* @param publicAuthorityID Information about the public authority owning
* cert
. Must not be null
, if
* isPublicAuthority ! = null
.
* @throws MOAApplicationException An error occurred reading data from the
* certificate.
*/
public static void addSignerInfo(
Document response,
Element root,
X509Certificate cert,
boolean isQualified,
String qcSource,
boolean isPublicAuthority,
String publicAuthorityID,
boolean isSSCD,
String sscdSource,
String issuerCountryCode,
TslInfos tslInfos)
throws MOAApplicationException {
final Element signerInfoElem = response.createElementNS(MOA_NS_URI, "SignerInfo");
final Element x509DataElem =
response.createElementNS(DSIG_NS_URI, DSIG + "X509Data");
final Element x509IssuerSerialElem =
response.createElementNS(DSIG_NS_URI, DSIG + "X509IssuerSerial");
final Element x509IssuerElem =
response.createElementNS(DSIG_NS_URI, DSIG + "X509IssuerName");
final String issuer = cert.getIssuerDN().getName();
final Element x509SerialNumberElem =
response.createElementNS(DSIG_NS_URI, DSIG + "X509SerialNumber");
final String serialNumber = cert.getSerialNumber().toString();
final Element x509SubjectNameElem =
response.createElementNS(DSIG_NS_URI, DSIG + "X509SubjectName");
final Element x509CertificateElem =
response.createElementNS(DSIG_NS_URI, DSIG + "X509Certificate");
final Element qualifiedCertificateElem =
isQualified
? response.createElementNS(MOA_NS_URI, "QualifiedCertificate")
: null;
final Element sscdElem =
isSSCD
? response.createElementNS(MOA_NS_URI, "SecureSignatureCreationDevice")
: null;
Element issuerCountryCodeElem = null;
if (issuerCountryCode != null) {
issuerCountryCodeElem = response.createElementNS(MOA_NS_URI, "IssuerCountryCode");
issuerCountryCodeElem.setTextContent(issuerCountryCode);
}
// add TSL infos
Element tslInfoElement = null;
if (tslInfos != null) {
tslInfoElement = response.createElementNS(MOA_NS_URI, "TSLInformation");
// append TSL issuer country-code
if (MiscUtil.isNotEmpty(tslInfos.getTslIssuerCountry())) {
;
}
{
final Element tslIssuerCountryCodeElem = response.createElementNS(MOA_NS_URI, "TSLIssuerCountryCode");
tslIssuerCountryCodeElem.setTextContent(tslInfos.getTslIssuerCountry());
tslInfoElement.appendChild(tslIssuerCountryCodeElem);
}
// append Service-Type Status
if (MiscUtil.isNotEmpty(tslInfos.getServiceTypeStatus())) {
;
}
{
final Element tslServiceInfo = response.createElementNS(MOA_NS_URI, "ServiceTypeStatus");
tslServiceInfo.setTextContent(tslInfos.getServiceTypeStatus());
tslInfoElement.appendChild(tslServiceInfo);
}
// append Service-Type Identifier
if (MiscUtil.isNotEmpty(tslInfos.getServiceTypeIdentifier())) {
;
}
{
final Element tslServiceInfo = response.createElementNS(MOA_NS_URI, "ServiceTypeIdentifier");
tslServiceInfo.setTextContent(tslInfos.getServiceTypeIdentifier());
tslInfoElement.appendChild(tslServiceInfo);
}
// append qualifiers
if (tslInfos.getQualifiers() != null && tslInfos.getQualifiers().size() > 0) {
final Element tslQualifiers = response.createElementNS(MOA_NS_URI, "Qualifiers");
for (final String el : tslInfos.getQualifiers()) {
final Element tslQualifier = response.createElementNS(MOA_NS_URI, "Qualifier");
tslQualifier.setTextContent(el);
tslQualifiers.appendChild(tslQualifier);
}
tslInfoElement.appendChild(tslQualifiers);
}
// append additional service information
if (tslInfos.getAdditionalServiceInformation() != null
&& tslInfos.getAdditionalServiceInformation().size() > 0) {
final Element tslAdditionalServiceInformations = response.createElementNS(MOA_NS_URI,
"AdditionalServiceInformations");
for (final String el : tslInfos.getAdditionalServiceInformation()) {
final Element tslAdditionalServiceInformation = response.createElementNS(MOA_NS_URI,
"AdditionalServiceInformation");
tslAdditionalServiceInformation.setTextContent(el);
tslAdditionalServiceInformations.appendChild(tslAdditionalServiceInformation);
}
tslInfoElement.appendChild(tslAdditionalServiceInformations);
}
}
final Element publicAuthorityElem =
isPublicAuthority
? response.createElementNS(MOA_NS_URI, "PublicAuthority")
: null;
final Element codeElem =
publicAuthorityID != null
? response.createElementNS(MOA_NS_URI, "Code")
: null;
// fill in text
x509IssuerElem.appendChild(response.createTextNode(issuer));
x509SerialNumberElem.appendChild(response.createTextNode(serialNumber));
try {
final RFC2253NameParser parser =
new RFC2253NameParser(cert.getSubjectDN().getName());
final String subjectRfc2253 = parser.parse().getRFC2253String();
x509SubjectNameElem.appendChild(response.createTextNode(subjectRfc2253));
} catch (final RFC2253NameParserException e) {
x509SubjectNameElem.appendChild(
response.createTextNode(cert.getSubjectDN().getName()));
}
try {
x509CertificateElem.appendChild(
response.createTextNode(Base64Utils.encode(cert.getEncoded())));
} catch (final CertificateEncodingException e) {
throw new MOAApplicationException("2245", null, e);
} catch (final IOException e) {
throw new MOAApplicationException("2245", null, e);
}
// build structure
x509DataElem.appendChild(x509SubjectNameElem);
x509IssuerSerialElem.appendChild(x509IssuerElem);
x509IssuerSerialElem.appendChild(x509SerialNumberElem);
x509DataElem.appendChild(x509IssuerSerialElem);
x509DataElem.appendChild(x509CertificateElem);
if (isQualified) {
if (qcSource.compareToIgnoreCase("TSL") == 0) {
qualifiedCertificateElem.setAttributeNS(MOA_NS_URI, "Source", qcSource);
}
x509DataElem.appendChild(qualifiedCertificateElem);
}
if (isPublicAuthority) {
x509DataElem.appendChild(publicAuthorityElem);
if (publicAuthorityID != null) {
codeElem.appendChild(response.createTextNode(publicAuthorityID));
publicAuthorityElem.appendChild(codeElem);
}
}
if (isSSCD) {
sscdElem.setAttributeNS(MOA_NS_URI, "Source", sscdSource);
x509DataElem.appendChild(sscdElem);
}
if (issuerCountryCodeElem != null) {
x509DataElem.appendChild(issuerCountryCodeElem);
}
// add TSL infos to X509Date if TSL infos exists
if (tslInfoElement != null) {
x509DataElem.appendChild(tslInfoElement);
}
signerInfoElem.appendChild(x509DataElem);
root.appendChild(signerInfoElem);
}
/**
* Add an element containing Code
and Info
* subelements.
*
* @param response The response document, in order to create new elements in
* it.
* @param root The root element into which to insert the newly created
* element.
* @param elementName The name of the newly created element.
* @param code The content of the Code
subelement.
* @param info The content of the Info
subelement.
*/
public static void addCodeInfoElement(
Document response,
Element root,
String elementName,
int code,
NodeList info) {
final Element codeInfoElem = response.createElementNS(MOA_NS_URI, elementName);
final Element codeElem = response.createElementNS(MOA_NS_URI, "Code");
Element infoElem;
int i;
codeElem.appendChild(response.createTextNode(Integer.toString(code)));
codeInfoElem.appendChild(codeElem);
if (info != null) {
infoElem = response.createElementNS(MOA_NS_URI, "Info");
for (i = 0; i < info.getLength(); i++) {
infoElem.appendChild(info.item(i).cloneNode(true));
}
codeInfoElem.appendChild(infoElem);
}
root.appendChild(codeInfoElem);
}
/**
* Add an element containing Code
and Info
* subelements.
*
* @param response The response document, in order to create new elements in
* it.
* @param root The root element into which to insert the newly created
* element.
* @param elementName The name of the newly created element.
* @param code The content of the Code
subelement.
* @param info The content of the Info
subelement.
*/
public static void addCodeInfoElement(
Document response,
Element root,
String elementName,
int code,
String info) {
final Element codeInfoElem = response.createElementNS(MOA_NS_URI, elementName);
final Element codeElem = response.createElementNS(MOA_NS_URI, "Code");
Element infoElem;
final int i;
codeElem.appendChild(response.createTextNode(Integer.toString(code)));
codeInfoElem.appendChild(codeElem);
if (info != null) {
infoElem = response.createElementNS(MOA_NS_URI, "Info");
infoElem.appendChild(response.createTextNode(info));
codeInfoElem.appendChild(infoElem);
}
root.appendChild(codeInfoElem);
}
public static void addSigningTime(Document response,
Element root,
Date signingTime) {
if (signingTime != null) {
final Element extElem = response.createElementNS(MOA_NS_URI, "SigningTime");
final TimeZone tz = TimeZone.getTimeZone("UTC");
final Calendar calendar = new GregorianCalendar();
calendar.setTimeZone(tz);
calendar.setTime(signingTime);
final String date = DatatypeConverter.printDateTime(calendar);
extElem.appendChild(response.createTextNode(date));
root.appendChild(extElem);
}
}
public static void addSignatureAlgorithm(Document response,
Element root,
String algorithm) {
if (algorithm != null) {
final Element extElem = response.createElementNS(MOA_NS_URI, "SignatureAlgorithm");
extElem.appendChild(response.createTextNode(algorithm));
root.appendChild(extElem);
}
}
public static void addSignatureCoversFullPDF(Document response,
Element root,
Boolean coversFull) {
if (coversFull != null) {
final Element extElem = response.createElementNS(MOA_NS_URI, "SignatureCoversFullPDF");
extElem.appendChild(response.createTextNode(String.valueOf(coversFull)));
root.appendChild(extElem);
}
}
public static void addSignatureByteRange(Document response,
Element root,
int[] byteRange) {
if (byteRange != null) {
String byteRangeTextual = StringUtils.EMPTY;
for (final int el : byteRange) {
byteRangeTextual += "," + String.valueOf(el);
}
final Element extElem = response.createElementNS(MOA_NS_URI, "SignatureByteRange");
extElem.appendChild(response.createTextNode(byteRangeTextual.substring(1)));
root.appendChild(extElem);
}
}
public static Element createAndAddChildElement(Document response, Element root, String name) {
final Element element = response.createElementNS(MOA_NS_URI, name);
root.appendChild(element);
return element;
}
public static void addHashAlgorithm(Document response,
Element root,
String algorithm) {
if (algorithm != null) {
final Element extElem = response.createElementNS(MOA_NS_URI, "HashAlgorithm");
extElem.appendChild(response.createTextNode(algorithm));
root.appendChild(extElem);
}
}
public static void addExtendendResult(Document response,
Element root,
ExtendedCertificateCheckResult result) {
final Element extElem = response.createElementNS(MOA_NS_URI, "ExtendedCertificateCheck");
final Element extMajorElem = response.createElementNS(MOA_NS_URI, "Major");
final Element codeMajorCodeElem = response.createElementNS(MOA_NS_URI, "Code");
final Element codeMajorNameElem = response.createElementNS(MOA_NS_URI, "Name");
codeMajorCodeElem.appendChild(response.createTextNode(Integer.toString(
result.getMajorCode())));
codeMajorNameElem.appendChild(response.createTextNode(result.getMajorInfo()));
extMajorElem.appendChild(codeMajorCodeElem);
extMajorElem.appendChild(codeMajorNameElem);
extElem.appendChild(extMajorElem);
if (result.getMinorCode() >= 0) {
final Element extMinorElem = response.createElementNS(MOA_NS_URI, "Minor");
final Element codeMinorCodeElem = response.createElementNS(MOA_NS_URI, "Code");
final Element codeMinorNameElem = response.createElementNS(MOA_NS_URI, "Name");
codeMinorCodeElem.appendChild(response.createTextNode(Integer.toString(
result.getMinorCode())));
codeMinorNameElem.appendChild(response.createTextNode(result.getMinorInfo()));
extMinorElem.appendChild(codeMinorCodeElem);
extMinorElem.appendChild(codeMinorNameElem);
extElem.appendChild(extMinorElem);
}
root.appendChild(extElem);
}
/**
* Add an element containing Code
and Info
* subelements.
*
* @param response The response document, in order to create new elements in
* it.
* @param root The root element into which to insert the newly created
* element.
* @param elementName The name of the newly created element.
* @param code The content of the Code
subelement.
* @param info The content of the Info
subelement.
*/
public static void addFormCheckElement(
Document response,
Element root,
String elementName,
int code,
String name) {
final Element codeInfoElem = response.createElementNS(MOA_NS_URI, elementName);
final Element codeElem = response.createElementNS(MOA_NS_URI, "Code");
Element infoElem;
codeElem.appendChild(response.createTextNode(Integer.toString(code)));
codeInfoElem.appendChild(codeElem);
infoElem = response.createElementNS(MOA_NS_URI, "Name");
infoElem.appendChild(response.createTextNode(name));
codeInfoElem.appendChild(infoElem);
root.appendChild(codeInfoElem);
}
}