/*
* 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);
}
}