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 <code>CreateTransformsInfoProfile</code> DOM element. * * @param profileElem The <code>CreateTransformsInfoProfile</code> element * to parse. * @return The <code>CreateTransformsInfoProfile</code> API object containing * the data from the <code>profileElem</code>. * @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 <code>CreateTransformsInfo</code> DOM element contained in a * <code>CreateTransformsInfoProfile</code>. * * @param profileElem The <code>CreateTransformsInfoProfile</code> DOM * element containing the <code>CreateTransformsInfo</code>. * @return The <code>CreateTransformsInfo</code> API object containinig the * data from the <code>CreateTransformsInfo</code> DOM element. * @throws MOAApplicationException An error occurred parsing the * <code>CreateTransformsInfo</code> 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 <code>CreateSignatureEnvironmentProfile</code> DOM element. * * @param profileElem The <code>CreateSignatureEnvironmentProfile</code> * DOM element to parse. * @return The <code>CreateSignatureEnvironmentProfile</code> API object * containing the data from the <code>profileElem</code>. */ public CreateSignatureEnvironmentProfile parseCreateSignatureEnvironmentProfile(Element profileElem) { CreateSignatureLocation createSignatureLocation = parseCreateSignatureLocation(profileElem); List supplements = parseSupplements(profileElem); return factory.createCreateSignatureEnvironmentProfile( createSignatureLocation, supplements); } /** * Parse a <code>CreateSignatureLocation</code> DOM element contained in * a <code>CreateSignatureEnvironmentProfile</code>. * * @param profileElem The <code>CreateSignatureEnvironmentProfile</code> DOM * element containing the <code>CreateSignatureLocation</code>. * @return The <code>CreateSignatureLocation</code> API object containing * the data from the <code>CreateSignatureLocation</code> 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 <code>Supplement</code> DOM elements contained in a given * parent DOM element. * * @param supplementsParentElem The DOM element being the parent of the * <code>Supplement</code>s. * @return A <code>List</code> of <code>Supplement</code> API objects * containing the data from the <code>Supplement</code> 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 <code>SupplementProfile</code> DOM element. * * @param profileElem The <code>SupplementProfile</code> DOM element to parse. * @return The <code>SupplementProfile</code> API object containing the * data from the <code>SupplementProfile</code> DOM element. */ public SupplementProfile parseSupplementProfile(Element profileElem) { XMLDataObjectAssociation supplementProfile = RequestParserUtils.parseXMLDataObjectAssociation(profileElem); return factory.createSupplementProfile(supplementProfile); } /** * Parse a <code>VerifyTransformsInfoProfile</code> DOM element. * * @param profileElem The <code>VerifyTransformsInfoProfile</code> DOM * element to parse. * @return A <code>VerifyTransformsInfoProfile</code> API object containing * the information from the <code>VerifyTransformsInfoProfile</code> DOM * element. * @throws MOAApplicationException An error occurred parsing the * <code>VerifyTransformsInfoProfile</code>. */ 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 <code>TransformParameter</code> DOM element. * * @param paramElem The <code>TransformParameter</code> DOM element to * parse. * @return The <code>TransformParameter</code> API object containing the * information from the <code>TransformParameter</code> DOM element. * @throws MOAApplicationException An error occurred parsing the * <code>TransformParameter</code> 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); } } }