/* * 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.server.webservice.binding; import java.io.ByteArrayInputStream; import java.io.IOException; import java.io.Serializable; import java.io.StringBufferInputStream; import java.util.ArrayList; import java.util.HashMap; import java.util.Iterator; import java.util.List; import java.util.Map; import java.util.StringTokenizer; import javax.xml.bind.JAXBElement; import javax.xml.parsers.DocumentBuilder; import javax.xml.parsers.DocumentBuilderFactory; import javax.xml.parsers.ParserConfigurationException; import org.w3c.dom.Element; import org.w3c.dom.traversal.NodeIterator; import org.xml.sax.SAXException; import at.gv.egiz.moasig.MoaTransformType; import at.gv.egiz.moasig.MoaTransformsType; import at.gv.egovernment.moa.spss.MOAApplicationException; import at.gv.egovernment.moa.spss.api.SPSSFactory; import at.gv.egovernment.moa.spss.api.common.Base64Transform; import at.gv.egovernment.moa.spss.api.common.CanonicalizationTransform; import at.gv.egovernment.moa.spss.api.common.EnvelopedSignatureTransform; import at.gv.egovernment.moa.spss.api.common.ExclusiveCanonicalizationTransform; import at.gv.egovernment.moa.spss.api.common.Transform; import at.gv.egovernment.moa.spss.api.common.XPathFilter; import at.gv.egovernment.moa.spss.api.common.XPathFilter2Transform; import at.gv.egovernment.moa.spss.api.common.XPathTransform; import at.gv.egovernment.moa.spss.api.common.XSLTTransform; import at.gv.egovernment.moa.util.Constants; import at.gv.egovernment.moa.util.DOMUtils; import at.gv.egovernment.moa.util.XPathUtils; /** * A parser to parse XMLDsig Transform DOM elements into their MOA * SPSS API representation. * * @author Patrick Peck * @version $Id$ */ public class TransformParser { // // XPath expressions for selecting information from the DOM tree // private static final String DSIG = Constants.DSIG_PREFIX + ":"; private static final String DSIG_FILTER2 = Constants.DSIG_FILTER2_PREFIX + ":"; private static final String XSLT = Constants.XSLT_PREFIX + ":"; private static final String EC = Constants.DSIG_EC_PREFIX + ":"; private static final String TRANSFORM_XPATH = DSIG + "Transform"; private static final String XPATH_XPATH = DSIG + "XPath"; private static final String XSLT_ELEMENT_XPATH = XSLT + "stylesheet"; private static final String XPATH2_XPATH = (DSIG_FILTER2 + "XPath[@Filter=\"intersect\"] | ") + (DSIG_FILTER2 + "XPath[@Filter=\"subtract\"] | ") + (DSIG_FILTER2 + "XPath[@Filter=\"union\"]"); private static final String INCLUSIVE_NAMESPACES_XPATH = EC + "InclusiveNamespaces"; /** * The SPSSFactory to use for creating new API objects. */ private SPSSFactory factory = SPSSFactory.getInstance(); /** * Parse an XMLDsig Transforms DOM element. * * @param transformsElem * The Transforms DOM element to parse. * @return A List of Transform API objects * containing the data from the individual Transform * DOM elements. * @throws MOAApplicationException * An error occurred parsing the Transforms DOM * element. */ public List parseTransforms(MoaTransformsType moaTransformsType) throws MOAApplicationException { List transforms = new ArrayList(); if (moaTransformsType.getMoaTransform() != null) { Iterator transformIterator = moaTransformsType.getMoaTransform().iterator(); while (transformIterator.hasNext()) { MoaTransformType transformType = transformIterator.next(); Transform transform = parseTransform(transformType); transforms.add(transform); } } return transforms; } /** * Parse an XMLDsig Transform DOM element. * * @param transformElem * Transform DOM element to parse. * @return The Transform API object containing the data from * the Transform DOM element. * @throws MOAApplicationException * An error occurred parsing the Transform DOM * element. */ public Transform parseTransform(MoaTransformType transformType) throws MOAApplicationException { String algorithmUri = transformType.getAlgorithm();// transformElem.getAttribute("Algorithm"); if (CanonicalizationTransform.CANONICAL_XML.equals(algorithmUri) || CanonicalizationTransform.CANONICAL_XML_WITH_COMMENTS.equals(algorithmUri)) { return factory.createCanonicalizationTransform(algorithmUri); } else if (ExclusiveCanonicalizationTransform.EXCLUSIVE_CANONICAL_XML.equals(algorithmUri) || ExclusiveCanonicalizationTransform.EXCLUSIVE_CANONICAL_XML_WITH_COMMENTS.equals(algorithmUri)) { return parseExclusiveC14nTransform(algorithmUri, transformType); } else if (Base64Transform.BASE64_DECODING.equals(algorithmUri)) { return factory.createBase64Transform(); } else if (EnvelopedSignatureTransform.ENVELOPED_SIGNATURE.equals(algorithmUri)) { return factory.createEnvelopedSignatureTransform(); } else if (XPathTransform.XPATH.equals(algorithmUri)) { return parseXPathTransform(transformType); } else if (XPathFilter2Transform.XPATH_FILTER2.equals(algorithmUri)) { return parseXPathFilter2Transform(transformType); } else if (XSLTTransform.XSLT.equals(algorithmUri)) { return parseXSLTTransform(transformType); } else { throw new MOAApplicationException("1108", new Object[] { algorithmUri }); } } private List getDataObjectFromMoaTransform(MoaTransformType transformType) { Iterator objectsIterator = transformType.getContent().iterator(); List dataObjects = new ArrayList(); while (objectsIterator.hasNext()) { Serializable serializable = objectsIterator.next(); if (serializable instanceof JAXBElement) { JAXBElement jaxb = (JAXBElement) serializable; if (jaxb.getDeclaredType() == byte[].class) { JAXBElement jaxbString = (JAXBElement) serializable; dataObjects.add(jaxbString.getValue()); } } } return dataObjects; } private List getStringFromMoaTransform(MoaTransformType transformType) { Iterator objectsIterator = transformType.getContent().iterator(); List dataObjects = new ArrayList(); while (objectsIterator.hasNext()) { Serializable serializable = objectsIterator.next(); if (serializable instanceof JAXBElement) { JAXBElement jaxb = (JAXBElement) serializable; if (jaxb.getDeclaredType() == String.class) { JAXBElement jaxbString = (JAXBElement) serializable; dataObjects.add(jaxbString.getValue()); } } else if (serializable instanceof String) { dataObjects.add((String) serializable); } } return dataObjects; } /** * Parse an exclusive canonicalization type of transform. * * @param algorithmUri * The algorithm URI of the canonicalization algorithm. * @param transformElem * The Transform DOM element to parse. * @return An ExclusiveCanonicalizationTransform API object * containing the data from the transformElem. * @throws MOAApplicationException */ private Transform parseExclusiveC14nTransform(String algorithmUri, MoaTransformType transformType) throws MOAApplicationException { List data = getDataObjectFromMoaTransform(transformType); List inclusiveNamespaces = new ArrayList(); Iterator dataIterator = data.iterator(); while (dataIterator.hasNext()) { byte[] dataObject = dataIterator.next(); Element transform; try { transform = DOMUtils.parseXmlNonValidating(new ByteArrayInputStream(dataObject)); } catch (ParserConfigurationException e) { throw new MOAApplicationException("failed to parse transform element", null, e); } catch (SAXException e) { throw new MOAApplicationException("failed to parse transform element", null, e); } catch (IOException e) { throw new MOAApplicationException("failed to parse transform element", null, e); } Element inclusiveNamespacesElem = (Element) XPathUtils.selectSingleNode(transform, INCLUSIVE_NAMESPACES_XPATH); if (inclusiveNamespacesElem != null) { StringTokenizer tokenizer = new StringTokenizer(inclusiveNamespacesElem.getAttribute("PrefixList")); while (tokenizer.hasMoreTokens()) { inclusiveNamespaces.add(tokenizer.nextToken()); } } } return factory.createExclusiveCanonicalizationTransform(algorithmUri, inclusiveNamespaces); } /** * Parse an XPath type of Transform. * * @param transformElem * The Transform DOM element to parse. * @return The Transform API object representation of the * Transform DOM element. * @throws MOAApplicationException * An error occurred parsing the Transform DOM * element. */ private Transform parseXPathTransform(MoaTransformType transformType) throws MOAApplicationException { // TODO: XPATH Namespace Declarations List xPathTransforms = getStringFromMoaTransform(transformType); Map nsDecls; if (xPathTransforms.isEmpty()) { throw new MOAApplicationException("2202", null); } nsDecls = new HashMap(); return factory.createXPathTransform(xPathTransforms.get(0), nsDecls); /* * Element xPathElem = (Element) * XPathUtils.selectSingleNode(transformElem, XPATH_XPATH); * * * if (xPathElem == null) { throw new MOAApplicationException("2202", * null); } * * nsDecls = DOMUtils.getNamespaceDeclarations(xPathElem); * nsDecls.remove(""); * * return factory.createXPathTransform(DOMUtils.getText(xPathElem), * nsDecls); */ } /** * Parse an XPathFilter2 type of Transform. * * @param transformElem * The Transform DOM element to parse. * @return The Transform API object representation of the * Transform DOM element. * @throws MOAApplicationException * An error occurred parsing the Transform DOM * element. */ private Transform parseXPathFilter2Transform(MoaTransformType transformType) throws MOAApplicationException { List data = getDataObjectFromMoaTransform(transformType); List filters = new ArrayList(); Iterator dataIterator = data.iterator(); while (dataIterator.hasNext()) { byte[] dataObject = dataIterator.next(); Element transform; try { transform = DOMUtils.parseXmlNonValidating(new ByteArrayInputStream(dataObject)); } catch (ParserConfigurationException e) { throw new MOAApplicationException("failed to parse transform element", null, e); } catch (SAXException e) { throw new MOAApplicationException("failed to parse transform element", null, e); } catch (IOException e) { throw new MOAApplicationException("failed to parse transform element", null, e); } NodeIterator iter = XPathUtils.selectNodeIterator(transform, XPATH2_XPATH); Element filterElem; while ((filterElem = (Element) iter.nextNode()) != null) { String filterAttr = filterElem.getAttribute("Filter"); String filterType; String expression; Map nsDecls; if (filterAttr.equals("intersect")) { filterType = XPathFilter.INTERSECT_TYPE; } else if (filterAttr.equals("subtract")) { filterType = XPathFilter.SUBTRACT_TYPE; } else { filterType = XPathFilter.UNION_TYPE; } expression = DOMUtils.getText(filterElem); nsDecls = DOMUtils.getNamespaceDeclarations(filterElem); nsDecls.remove(""); filters.add(factory.createXPathFilter(filterType, expression, nsDecls)); } } if (filters.size() == 0) { throw new MOAApplicationException("2216", null); } return factory.createXPathFilter2Transform(filters); } /** * Parse an XSLT type of Transform. * * @param transformElem * The Transform DOM element to parse. * @return The Transform API object representation of the * Transform DOM element. * @throws MOAApplicationException * An error occurred parsing the Transform DOM * element. */ private Transform parseXSLTTransform(MoaTransformType transformType) throws MOAApplicationException { List data = getDataObjectFromMoaTransform(transformType); if (data.isEmpty()) { throw new MOAApplicationException("2215", null); } byte[] dataObject = data.get(0); Element transform; try { transform = DOMUtils.parseXmlNonValidating(new ByteArrayInputStream(dataObject)); } catch (ParserConfigurationException e) { throw new MOAApplicationException("failed to parse transform element", null, e); } catch (SAXException e) { throw new MOAApplicationException("failed to parse transform element", null, e); } catch (IOException e) { throw new MOAApplicationException("failed to parse transform element", null, e); } Element xsltElem = (Element) XPathUtils.selectSingleNode(transform, XSLT_ELEMENT_XPATH); if (xsltElem == null) { } return factory.createXSLTTransform(xsltElem); } }