package at.gv.egovernment.moa.spss.api.xmlbind;
import java.io.IOException;
import java.io.InputStream;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;
import org.w3c.dom.Element;
import org.w3c.dom.traversal.NodeIterator;
import at.gv.egovernment.moa.util.Base64Utils;
import at.gv.egovernment.moa.util.Constants;
import at.gv.egovernment.moa.util.DOMUtils;
import at.gv.egovernment.moa.util.XPathUtils;
import at.gv.egovernment.moa.spss.MOAApplicationException;
import at.gv.egovernment.moa.spss.api.SPSSFactory;
import at.gv.egovernment.moa.spss.api.common.MetaInfo;
import at.gv.egovernment.moa.spss.api.common.XMLDataObjectAssociation;
import at.gv.egovernment.moa.spss.api.xmlsign.CreateSignatureEnvironmentProfile;
import at.gv.egovernment.moa.spss.api.xmlsign.CreateSignatureLocation;
import at.gv.egovernment.moa.spss.api.xmlsign.CreateTransformsInfo;
import at.gv.egovernment.moa.spss.api.xmlsign.CreateTransformsInfoProfile;
import at.gv.egovernment.moa.spss.api.xmlverify.SupplementProfile;
import at.gv.egovernment.moa.spss.api.xmlverify.TransformParameter;
import at.gv.egovernment.moa.spss.api.xmlverify.VerifyTransformsInfoProfile;
/**
* Parse the various profile elements contained in the MOA web service requests
* and given as separate files in the MOA configuration.
*
* The profiles parsed must be schema valid according to the MOA XML schema.
*
* @author Patrick Peck
* @version $Id$
*/
public class ProfileParser {
//
// XPath expressions to select parts of the profiles
//
private static final String MOA = Constants.MOA_PREFIX + ":";
private static final String DSIG = Constants.DSIG_PREFIX + ":";
private static final String CREATE_TRANSFORMS_XPATH =
MOA + "CreateTransformsInfo/" + DSIG + "Transforms";
private static final String FINAL_DATA_META_INFO_XPATH =
MOA + "CreateTransformsInfo/" + MOA + "FinalDataMetaInfo";
private static final String CREATE_SIGNATURE_LOCATION_XPATH =
MOA + "CreateSignatureLocation";
private static final String SUPPLEMENT_XPATH = MOA + "Supplement";
private static final String VERIFY_TRANSFORMS_XPATH = DSIG + "Transforms";
private static final String TRANSFORM_PARAMETER_XPATH =
MOA + "TransformParameter";
private static final String TRANSFORM_PARAMETER_CONTENT_XPATH =
MOA + "Base64Content | " + MOA + "Hash";
private static final String DIGEST_METHOD_XPATH = DSIG + "DigestMethod";
private static final String DIGEST_VALUE_XPATH = DSIG + "DigestValue";
/** The factory used to create API objects. */
private SPSSFactory factory = SPSSFactory.getInstance();
/**
* Parse a CreateTransformsInfoProfile
DOM element.
*
* @param profileElem The CreateTransformsInfoProfile
element
* to parse.
* @return The CreateTransformsInfoProfile
API object containing
* the data from the profileElem
.
* @throws MOAApplicationException An error occurred parsing the DOM element.
*/
public CreateTransformsInfoProfile parseCreateTransformsInfoProfile(Element profileElem)
throws MOAApplicationException {
CreateTransformsInfo createTransformsInfo =
parseCreateTransformsInfo(profileElem);
List supplements = parseSupplements(profileElem);
return factory.createCreateTransformsInfoProfile(
createTransformsInfo,
supplements);
}
/**
* Parse the CreateTransformsInfo
DOM element contained in a
* CreateTransformsInfoProfile
.
*
* @param profileElem The CreateTransformsInfoProfile
DOM
* element containing the CreateTransformsInfo
.
* @return The CreateTransformsInfo
API object containinig the
* data from the CreateTransformsInfo
DOM element.
* @throws MOAApplicationException An error occurred parsing the
* CreateTransformsInfo
DOM element.
*/
private CreateTransformsInfo parseCreateTransformsInfo(Element profileElem)
throws MOAApplicationException {
Element transformsElem =
(Element) XPathUtils.selectSingleNode(
profileElem,
CREATE_TRANSFORMS_XPATH);
Element metaInfoElem =
(Element) XPathUtils.selectSingleNode(
profileElem,
FINAL_DATA_META_INFO_XPATH);
MetaInfo finalDataMetaInfo;
List transforms;
// parse the dsig:Transforms
if (transformsElem != null) {
TransformParser transformsParser = new TransformParser();
transforms = transformsParser.parseTransforms(transformsElem);
} else {
transforms = null;
}
// parse the meta info
finalDataMetaInfo = RequestParserUtils.parseMetaInfo(metaInfoElem);
return factory.createCreateTransformsInfo(transforms, finalDataMetaInfo);
}
/**
* Parse a CreateSignatureEnvironmentProfile
DOM element.
*
* @param profileElem The CreateSignatureEnvironmentProfile
* DOM element to parse.
* @return The CreateSignatureEnvironmentProfile
API object
* containing the data from the profileElem
.
*/
public CreateSignatureEnvironmentProfile parseCreateSignatureEnvironmentProfile(Element profileElem) {
CreateSignatureLocation createSignatureLocation =
parseCreateSignatureLocation(profileElem);
List supplements = parseSupplements(profileElem);
return factory.createCreateSignatureEnvironmentProfile(
createSignatureLocation,
supplements);
}
/**
* Parse a CreateSignatureLocation
DOM element contained in
* a CreateSignatureEnvironmentProfile
.
*
* @param profileElem The CreateSignatureEnvironmentProfile
DOM
* element containing the CreateSignatureLocation
.
* @return The CreateSignatureLocation
API object containing
* the data from the CreateSignatureLocation
DOM element.
*/
private CreateSignatureLocation parseCreateSignatureLocation(Element profileElem) {
Element locationElem =
(Element) XPathUtils.selectSingleNode(
profileElem,
CREATE_SIGNATURE_LOCATION_XPATH);
String xPathExpression = DOMUtils.getText(locationElem);
Map namespaceDeclarations = DOMUtils.getNamespaceDeclarations(locationElem);
String indexStr = locationElem.getAttribute("Index");
int index = Integer.parseInt(indexStr);
return factory.createCreateSignatureLocation(
xPathExpression,
index,
namespaceDeclarations);
}
/**
* Parse all Supplement
DOM elements contained in a given
* parent DOM element.
*
* @param supplementsParentElem The DOM element being the parent of the
* Supplement
s.
* @return A List
of Supplement
API objects
* containing the data from the Supplement
DOM elements.
*/
private List parseSupplements(Element supplementsParentElem) {
List supplements = new ArrayList();
NodeIterator supplementElems =
XPathUtils.selectNodeIterator(supplementsParentElem, SUPPLEMENT_XPATH);
Element supplementElem;
while ((supplementElem = (Element) supplementElems.nextNode()) != null) {
XMLDataObjectAssociation supplement =
RequestParserUtils.parseXMLDataObjectAssociation(supplementElem);
supplements.add(supplement);
}
return supplements;
}
/**
* Parse a SupplementProfile
DOM element.
*
* @param profileElem The SupplementProfile
DOM element to parse.
* @return The SupplementProfile
API object containing the
* data from the SupplementProfile
DOM element.
*/
public SupplementProfile parseSupplementProfile(Element profileElem) {
XMLDataObjectAssociation supplementProfile =
RequestParserUtils.parseXMLDataObjectAssociation(profileElem);
return factory.createSupplementProfile(supplementProfile);
}
/**
* Parse a VerifyTransformsInfoProfile
DOM element.
*
* @param profileElem The VerifyTransformsInfoProfile
DOM
* element to parse.
* @return A VerifyTransformsInfoProfile
API object containing
* the information from the VerifyTransformsInfoProfile
DOM
* element.
* @throws MOAApplicationException An error occurred parsing the
* VerifyTransformsInfoProfile
.
*/
public VerifyTransformsInfoProfile parseVerifyTransformsInfoProfile(Element profileElem)
throws MOAApplicationException {
Element transformsElem =
(Element) XPathUtils.selectSingleNode(
profileElem,
VERIFY_TRANSFORMS_XPATH);
List transforms = null;
NodeIterator paramElems =
XPathUtils.selectNodeIterator(profileElem, TRANSFORM_PARAMETER_XPATH);
Element paramElem;
List transformParameters = new ArrayList();
// parse the dsig:Transforms
if (transformsElem != null) {
TransformParser transformsParser = new TransformParser();
transforms = transformsParser.parseTransforms(transformsElem);
}
// parse the TransformParameter elements
while ((paramElem = (Element) paramElems.nextNode()) != null) {
transformParameters.add(parseTransformParameter(paramElem));
}
return factory.createVerifyTransformsInfoProfile(
transforms,
transformParameters);
}
/**
* Parse a TransformParameter
DOM element.
*
* @param paramElem The TransformParameter
DOM element to
* parse.
* @return The TransformParameter
API object containing the
* information from the TransformParameter
DOM element.
* @throws MOAApplicationException An error occurred parsing the
* TransformParameter
DOM element.
*/
private TransformParameter parseTransformParameter(Element paramElem)
throws MOAApplicationException {
String uri = paramElem.getAttribute("URI");
Element contentElem =
(Element) XPathUtils.selectSingleNode(
paramElem,
TRANSFORM_PARAMETER_CONTENT_XPATH);
if (contentElem == null) {
return factory.createTransformParameter(uri);
} else if ("Base64Content".equals(contentElem.getLocalName())) {
String base64Str = DOMUtils.getText(contentElem);
InputStream binaryContent = Base64Utils.decodeToStream(base64Str, true);
return factory.createTransformParameter(uri, binaryContent);
} else { // "Hash".equals(contentElem.getLocalName())
String digestMethodStr =
XPathUtils.getElementValue(contentElem, DIGEST_METHOD_XPATH, "");
String digestValueStr =
XPathUtils.getElementValue(contentElem, DIGEST_VALUE_XPATH, "");
byte[] digestValue = null;
try {
digestValue = Base64Utils.decode(digestValueStr, true);
} catch (IOException e) {
throw new MOAApplicationException("2270", null);
}
return factory.createTransformParameter(
uri,
digestMethodStr,
digestValue);
}
}
}