/*
* 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.text.SimpleDateFormat;
import java.util.Date;
import java.util.GregorianCalendar;
import java.util.Calendar;
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 iaik.utils.RFC2253NameParser;
import iaik.utils.RFC2253NameParserException;
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;
/**
* 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) {
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 {
DocumentBuilder docBuilder =
DocumentBuilderFactory.newInstance().newDocumentBuilder();
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 (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 {
Element signerInfoElem = response.createElementNS(MOA_NS_URI, "SignerInfo");
Element x509DataElem =
response.createElementNS(DSIG_NS_URI, DSIG + "X509Data");
Element x509IssuerSerialElem =
response.createElementNS(DSIG_NS_URI, DSIG + "X509IssuerSerial");
Element x509IssuerElem =
response.createElementNS(DSIG_NS_URI, DSIG + "X509IssuerName");
String issuer = cert.getIssuerDN().getName();
Element x509SerialNumberElem =
response.createElementNS(DSIG_NS_URI, DSIG + "X509SerialNumber");
String serialNumber = cert.getSerialNumber().toString();
Element x509SubjectNameElem =
response.createElementNS(DSIG_NS_URI, DSIG + "X509SubjectName");
Element x509CertificateElem =
response.createElementNS(DSIG_NS_URI, DSIG + "X509Certificate");
Element qualifiedCertificateElem =
isQualified
? response.createElementNS(MOA_NS_URI, "QualifiedCertificate")
: null;
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())); {
Element tslIssuerCountryCodeElem = response.createElementNS(MOA_NS_URI, "TSLIssuerCountryCode");
tslIssuerCountryCodeElem.setTextContent(tslInfos.getTslIssuerCountry());
tslInfoElement.appendChild(tslIssuerCountryCodeElem);
}
//append Service-Type Status
if (MiscUtil.isNotEmpty(tslInfos.getServiceTypeStatus())); {
Element tslServiceInfo = response.createElementNS(MOA_NS_URI, "ServiceTypeStatus");
tslServiceInfo.setTextContent(tslInfos.getServiceTypeStatus());
tslInfoElement.appendChild(tslServiceInfo);
}
//append Service-Type Identifier
if (MiscUtil.isNotEmpty(tslInfos.getServiceTypeIdentifier())); {
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) {
Element tslQualifiers = response.createElementNS(MOA_NS_URI, "Qualifiers");
for (String el : tslInfos.getQualifiers()) {
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) {
Element tslAdditionalServiceInformations = response.createElementNS(MOA_NS_URI, "AdditionalServiceInformations");
for (String el : tslInfos.getAdditionalServiceInformation()) {
Element tslAdditionalServiceInformation = response.createElementNS(MOA_NS_URI, "AdditionalServiceInformation");
tslAdditionalServiceInformation.setTextContent(el);
tslAdditionalServiceInformations.appendChild(tslAdditionalServiceInformation);
}
tslInfoElement.appendChild(tslAdditionalServiceInformations);
}
}
Element publicAuthorityElem =
isPublicAuthority
? response.createElementNS(MOA_NS_URI, "PublicAuthority")
: null;
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 {
RFC2253NameParser parser =
new RFC2253NameParser(cert.getSubjectDN().getName());
String subjectRfc2253 = parser.parse().getRFC2253String();
x509SubjectNameElem.appendChild(response.createTextNode(subjectRfc2253));
} catch (RFC2253NameParserException e) {
x509SubjectNameElem.appendChild(
response.createTextNode(cert.getSubjectDN().getName()));
}
try {
x509CertificateElem.appendChild(
response.createTextNode(Base64Utils.encode(cert.getEncoded())));
} catch (CertificateEncodingException e) {
throw new MOAApplicationException("2245", null, e);
} catch (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) {
Element codeInfoElem = response.createElementNS(MOA_NS_URI, elementName);
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) {
Element codeInfoElem = response.createElementNS(MOA_NS_URI, elementName);
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");
infoElem.appendChild(response.createTextNode(info));
codeInfoElem.appendChild(infoElem);
}
root.appendChild(codeInfoElem);
}
public static void addSigningTime(Document response,
Element root,
Date signingTime) {
if(signingTime != null) {
Element extElem = response.createElementNS(MOA_NS_URI, "SigningTime");
TimeZone tz = TimeZone.getTimeZone("UTC");
Calendar calendar = new GregorianCalendar();
calendar.setTimeZone(tz);
calendar.setTime(signingTime);
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) {
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) {
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 (int el : byteRange)
byteRangeTextual += "," + String.valueOf(el);
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) {
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) {
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) {
Element extElem = response.createElementNS(MOA_NS_URI, "ExtendedCertificateCheck");
Element extMajorElem = response.createElementNS(MOA_NS_URI, "Major");
Element codeMajorCodeElem = response.createElementNS(MOA_NS_URI, "Code");
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) {
Element extMinorElem = response.createElementNS(MOA_NS_URI, "Minor");
Element codeMinorCodeElem = response.createElementNS(MOA_NS_URI, "Code");
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) {
Element codeInfoElem = response.createElementNS(MOA_NS_URI, elementName);
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);
}
}