diff options
Diffstat (limited to 'spss.slinterface/WEB-INF/src/at/gv/egovernment/moa/spss')
7 files changed, 448 insertions, 34 deletions
diff --git a/spss.slinterface/WEB-INF/src/at/gv/egovernment/moa/spss/slinterface/Constants.java b/spss.slinterface/WEB-INF/src/at/gv/egovernment/moa/spss/slinterface/Constants.java index c6ea9e88d..b47f245fa 100644 --- a/spss.slinterface/WEB-INF/src/at/gv/egovernment/moa/spss/slinterface/Constants.java +++ b/spss.slinterface/WEB-INF/src/at/gv/egovernment/moa/spss/slinterface/Constants.java @@ -19,7 +19,8 @@ public class Constants public static final String IP_MOA2SL_STYLESHEET_ = "location.stylesheet.moa2sl"; public static final String IP_SL_SCHEMA_ = "location.schema.sl"; public static final String IP_MOA_SCHEMA_ = "location.schema.moa"; - public static final String IP_SP_ENDPOINT_ = "service.endpoint.sp"; + public static final String IP_SP_ENDPOINT_ = "service.sp.endpoint"; + public static final String IP_SP_TRUSTPROFILEID_ = "service.sp.trustProfileId"; // Logging hierarchies @@ -45,9 +46,18 @@ public class Constants // Namespace URIs + public static final String NSURI_SL_10_ = "http://www.buergerkarte.at/namespaces/securitylayer/20020225#"; public static final String NSURI_SL_11_ = "http://www.buergerkarte.at/namespaces/securitylayer/20020831#"; public static final String NSURI_SL_12_ = "http://www.buergerkarte.at/namespaces/securitylayer/20031231#"; public static final String NSURI_MOA_12_ = "http://reference.e-government.gv.at/namespace/moa/20020822#"; + public static final String NSURI_NAMESPACES_ = "http://www.w3.org/2000/xmlns/"; + public static final String NSURI_XML_ = "http://www.w3.org/XML/1998/namespace"; + + // Namespace prefixes + public static final String NSPRE_SL_10_ = "sl10"; + public static final String NSPRE_SL_11_ = "sl11"; + public static final String NSPRE_SL_12_ = "sl12"; + public static final String NSPRE_MOA_12_ = "moa"; // MOA invoker constants diff --git a/spss.slinterface/WEB-INF/src/at/gv/egovernment/moa/spss/slinterface/filters/SL2MOAFilter.java b/spss.slinterface/WEB-INF/src/at/gv/egovernment/moa/spss/slinterface/filters/SL2MOAFilter.java index 4632c80f5..77c1b9c0e 100644 --- a/spss.slinterface/WEB-INF/src/at/gv/egovernment/moa/spss/slinterface/filters/SL2MOAFilter.java +++ b/spss.slinterface/WEB-INF/src/at/gv/egovernment/moa/spss/slinterface/filters/SL2MOAFilter.java @@ -37,12 +37,17 @@ import org.apache.commons.fileupload.DiskFileUpload; import org.apache.commons.fileupload.FileItem; import org.apache.commons.fileupload.FileUpload; import org.apache.commons.fileupload.FileUploadException; +import org.apache.log4j.Level; import org.apache.log4j.Logger; import org.apache.xerces.parsers.DOMParser; import org.w3c.dom.Document; import org.xml.sax.InputSource; +import org.xml.sax.SAXException; import at.gv.egovernment.moa.spss.slinterface.Constants; +import at.gv.egovernment.moa.spss.slinterface.moainvoker.MOAInvoker; +import at.gv.egovernment.moa.spss.slinterface.transformers.MOA2SL; +import at.gv.egovernment.moa.spss.slinterface.transformers.SL2MOA; /** * @author Gregor Karlinger (mailto:gregor.karlinger@cio.gv.at) @@ -67,19 +72,19 @@ public class SL2MOAFilter implements Filter slRequest_ = new SLRequest(); // Initialize stylesheet transform SL2MOA - ServletContext context = config_.getServletContext(); - Transformer sl2MoaTransformer = (Transformer) context.getAttribute(Constants.WSCP_SL2MOA_TRANSFORMER_); - if (sl2MoaTransformer == null) - { - initTransformer(context, Constants.IP_SL2MOA_STYLESHEET_); - } +// ServletContext context = config_.getServletContext(); +// Transformer sl2MoaTransformer = (Transformer) context.getAttribute(Constants.WSCP_SL2MOA_TRANSFORMER_); +// if (sl2MoaTransformer == null) +// { +// initTransformer(context, Constants.IP_SL2MOA_STYLESHEET_); +// } // Initialize stylesheet transform MOA2SL - Transformer moa2SlTransformer = (Transformer) context.getAttribute(Constants.WSCP_MOA2SL_TRANSFORMER_); - if (moa2SlTransformer == null) - { - initTransformer(context, Constants.IP_MOA2SL_STYLESHEET_); - } +// Transformer moa2SlTransformer = (Transformer) context.getAttribute(Constants.WSCP_MOA2SL_TRANSFORMER_); +// if (moa2SlTransformer == null) +// { +// initTransformer(context, Constants.IP_MOA2SL_STYLESHEET_); +// } } @@ -103,22 +108,29 @@ public class SL2MOAFilter implements Filter Document slXMLRequestDoc = parseSlXmlRequest(slXmlRequestCAR); // Transform SL request into a MOA SPSS request - Transformer sl2MoaTransformer = - (Transformer) config_.getServletContext().getAttribute(Constants.WSCP_SL2MOA_TRANSFORMER_); - DOMSource slXMLRequestDS = new DOMSource(slXMLRequestDoc); +// Transformer sl2MoaTransformer = +// (Transformer) config_.getServletContext().getAttribute(Constants.WSCP_SL2MOA_TRANSFORMER_); +// DOMSource slXMLRequestDS = new DOMSource(slXMLRequestDoc); +// ByteArrayOutputStream moaRequestBOS = new ByteArrayOutputStream(); +// StreamResult moaRequestResult = new StreamResult(moaRequestBOS); +// try +// { +// sl2MoaTransformer.transform(slXMLRequestDS, moaRequestResult); +// } +// catch (TransformerException e) +// { +// String message = "Transforming SL XML request into MOA XML request failed."; +// logger_.error(message, e); +// throw new ServletException(message, e); +// } +// logger_.debug("MOA XML Request:\n" + moaRequestBOS.toString()); +// ByteArrayInputStream moaRequestIS = new ByteArrayInputStream(moaRequestBOS.toByteArray()); + Properties initProps = (Properties)config_.getServletContext().getAttribute(Constants.WSCP_INIT_PROPS_); + String trustProfileId = initProps.getProperty(Constants.IP_SP_TRUSTPROFILEID_); + Document moaXMLRequestDoc = SL2MOA.toMoaVerifyXMLSignatureRequest(slXMLRequestDoc, trustProfileId); ByteArrayOutputStream moaRequestBOS = new ByteArrayOutputStream(); - StreamResult moaRequestResult = new StreamResult(moaRequestBOS); - try - { - sl2MoaTransformer.transform(slXMLRequestDS, moaRequestResult); - } - catch (TransformerException e) - { - String message = "Transforming SL XML request into MOA XML request failed."; - logger_.error(message, e); - throw new ServletException(message, e); - } - logger_.debug("MOA XML Request:\n" + moaRequestBOS.toString()); + MOAInvoker.serializeDocument(moaXMLRequestDoc, moaRequestBOS); + logger_.debug("SL request transformed into MOA request:\n" + moaRequestBOS); ByteArrayInputStream moaRequestIS = new ByteArrayInputStream(moaRequestBOS.toByteArray()); // Invoke MOA SPSS @@ -130,22 +142,40 @@ public class SL2MOAFilter implements Filter response.setContentType("text/xml"); // Transform MOA response into a SL response and send SL response back to client - Transformer moa2SlTransformer = - (Transformer) config_.getServletContext().getAttribute(Constants.WSCP_MOA2SL_TRANSFORMER_); +// Transformer moa2SlTransformer = +// (Transformer) config_.getServletContext().getAttribute(Constants.WSCP_MOA2SL_TRANSFORMER_); +// ServletOutputStream moaResponseSOS = (ServletOutputStream) responseWrapper.getOutputStream(); +// ByteArrayInputStream moaResponseBIS = new ByteArrayInputStream(moaResponseSOS.toByteArray()); +// StreamSource moaResponseSource = new StreamSource(moaResponseBIS); +// StreamResult slResponseResult = new StreamResult(response.getOutputStream()); +// try +// { +// moa2SlTransformer.transform(moaResponseSource, slResponseResult); +// } +// catch (TransformerException e) +// { +// String message = "Transforming MOA XML response into SL XML response failed."; +// logger_.error(message, e); +// throw new ServletException(message, e); +// } + DOMParser xmlParser = (DOMParser) config_.getServletContext().getAttribute(Constants.WSCP_XMLPARSER_); ServletOutputStream moaResponseSOS = (ServletOutputStream) responseWrapper.getOutputStream(); ByteArrayInputStream moaResponseBIS = new ByteArrayInputStream(moaResponseSOS.toByteArray()); - StreamSource moaResponseSource = new StreamSource(moaResponseBIS); - StreamResult slResponseResult = new StreamResult(response.getOutputStream()); + InputSource responseSource = new InputSource(moaResponseBIS); try { - moa2SlTransformer.transform(moaResponseSource, slResponseResult); + xmlParser.parse(responseSource); + Document moaResponseDoc = xmlParser.getDocument(); + Document slResponseDoc = MOA2SL.toSlVerifyXMLSignatureResponse(moaResponseDoc); + MOAInvoker.serializeDocument(slResponseDoc, response.getOutputStream()); } - catch (TransformerException e) + catch (SAXException e) { String message = "Transforming MOA XML response into SL XML response failed."; logger_.error(message, e); throw new ServletException(message, e); - } + } + } /* ---------------------------------------------------------------------------------------------------- */ @@ -197,6 +227,7 @@ public class SL2MOAFilter implements Filter } context.setAttribute(contextAttrName, transformer); } + /* ---------------------------------------------------------------------------------------------------- */ /** @@ -298,6 +329,19 @@ public class SL2MOAFilter implements Filter logger_.error(message, e); throw new ServletException(message, e); } + if (logger_.getEffectiveLevel().isGreaterOrEqual(Level.DEBUG)) + { + ByteArrayOutputStream debugOutputStream = new ByteArrayOutputStream(); + try + { + MOAInvoker.serializeDocument(slXmlRequestDoc, debugOutputStream); + logger_.debug("XML-Request received:\n" + debugOutputStream); + } + catch (IOException e) + { + // No debug output if this fails + } + } // Check if namespace is correct String namespaceURI = slXmlRequestDoc.getDocumentElement().getNamespaceURI(); diff --git a/spss.slinterface/WEB-INF/src/at/gv/egovernment/moa/spss/slinterface/listeners/ContextListener.java b/spss.slinterface/WEB-INF/src/at/gv/egovernment/moa/spss/slinterface/listeners/ContextListener.java index 5b32a482b..0b3980a50 100644 --- a/spss.slinterface/WEB-INF/src/at/gv/egovernment/moa/spss/slinterface/listeners/ContextListener.java +++ b/spss.slinterface/WEB-INF/src/at/gv/egovernment/moa/spss/slinterface/listeners/ContextListener.java @@ -41,6 +41,8 @@ public class ContextListener implements ServletContextListener "http://apache.org/xml/features/dom/include-ignorable-whitespace"; private static final String XERCES_CREATE_ENTITY_REF_NODES_FEATURE = "http://apache.org/xml/features/dom/create-entity-ref-nodes"; + protected static final String XERCES_DEFER_NODE_EXPANSION_ = + "http://apache.org/xml/features/dom/defer-node-expansion"; private static final int BIG_PRIME = 2039; @@ -103,6 +105,8 @@ public class ContextListener implements ServletContextListener xmlParser.setFeature(XERCES_NORMALIZED_VALUE_FEATURE, false); xmlParser.setFeature(XERCES_INCLUDE_IGNORABLE_WHITESPACE_FEATURE, true); xmlParser.setFeature(XERCES_CREATE_ENTITY_REF_NODES_FEATURE, false); + xmlParser.setFeature(XERCES_DEFER_NODE_EXPANSION_, false); + } catch (SAXException e) { diff --git a/spss.slinterface/WEB-INF/src/at/gv/egovernment/moa/spss/slinterface/transformers/MOA2SL.java b/spss.slinterface/WEB-INF/src/at/gv/egovernment/moa/spss/slinterface/transformers/MOA2SL.java new file mode 100644 index 000000000..a85917d81 --- /dev/null +++ b/spss.slinterface/WEB-INF/src/at/gv/egovernment/moa/spss/slinterface/transformers/MOA2SL.java @@ -0,0 +1,88 @@ +/* + * Created on 20.11.2003 + * + * (c) Stabsstelle IKT-Strategie des Bundes + */ +package at.gv.egovernment.moa.spss.slinterface.transformers; + +import java.util.ArrayList; +import java.util.HashMap; + +import org.w3c.dom.Document; +import org.w3c.dom.Element; +import org.w3c.dom.NodeList; + +import at.gv.egovernment.moa.spss.slinterface.Constants; + +/** + * @author Gregor Karlinger (mailto:gregor.karlinger@cio.gv.at) + */ +public class MOA2SL +{ + /** + * Transforms an MOA VerifyXMLSignatureResponse into a SL VerifyXMLSignatureResponse. + * + * @param moaVerifyXMLSignatureResponse The MOA VerifyXMLSignatureResponse to be transformed. + * + * @return the specified response document, transformed into a SL VerifyXMLSignatureResponse. Please note + * that <code>moaVerifyXMLSignatureResponse</code> is modified into the sl response. + * + * @pre moaVerifyXMLSignatureResponse is a valid instance of the SL Schema (version 1.2 or 1.1). + */ + public static Document toSlVerifyXMLSignatureResponse(Document moaVerifyXMLSignatureResponse) + { + // Namespace to namespace prefix mapping + HashMap prefixMap = new HashMap(4); + prefixMap.put(Constants.NSURI_SL_10_, Constants.NSPRE_SL_10_); + prefixMap.put(Constants.NSURI_SL_11_, Constants.NSPRE_SL_11_); + prefixMap.put(Constants.NSURI_SL_12_, Constants.NSPRE_SL_12_); + prefixMap.put(Constants.NSURI_MOA_12_, Constants.NSPRE_MOA_12_); + + // Namespaces to be changed + HashMap nsTransforms = new HashMap(); + nsTransforms.put(Constants.NSURI_MOA_12_, Constants.NSURI_SL_11_); + + // Names to be changed + HashMap nameTransforms = new HashMap(); + nameTransforms.put( + new QName(Constants.NSURI_MOA_12_, "PublicAuthority"), + new QName(Constants.NSURI_MOA_12_,"PublicAuthority")); + + Element verifyResponseElem = moaVerifyXMLSignatureResponse.getDocumentElement(); + verifyResponseElem.setAttributeNS(Constants.NSURI_NAMESPACES_, + "xmlns:" + Constants.NSPRE_SL_10_, Constants.NSURI_SL_10_); + verifyResponseElem.setAttributeNS(Constants.NSURI_NAMESPACES_, + "xmlns:" + Constants.NSPRE_SL_11_, Constants.NSURI_SL_11_); + + // Convert SL request into MOA request + verifyResponseElem = + Utils.transformDeep(verifyResponseElem, prefixMap, nsTransforms, nameTransforms); + + // Add SignatureManifestCheck element (Code = 98) + Element signatureMFCheckElem = moaVerifyXMLSignatureResponse.createElementNS( + Constants.NSURI_SL_11_, Constants.NSPRE_SL_11_ + ":SignatureManifestCheck"); + Element smfCodeElem = moaVerifyXMLSignatureResponse.createElementNS( + Constants.NSURI_SL_11_, Constants.NSPRE_SL_11_ + ":Code"); + signatureMFCheckElem.appendChild(smfCodeElem); + smfCodeElem.appendChild(moaVerifyXMLSignatureResponse.createTextNode("98")); + Element signatureCheckElem = (Element) verifyResponseElem.getElementsByTagNameNS( + Constants.NSURI_SL_11_, "SignatureCheck").item(0); + verifyResponseElem.insertBefore(signatureMFCheckElem, signatureCheckElem.getNextSibling()); + + // Siblings of Certificate check must be in sl10 namespace + nsTransforms.clear(); + nsTransforms.put(Constants.NSURI_SL_11_, Constants.NSURI_SL_10_); + nameTransforms.clear(); + NodeList signatureCheckChildren = signatureCheckElem.getElementsByTagName("*"); + ArrayList signatureCheckChildrenList = new ArrayList(signatureCheckChildren.getLength()); + for (int i = 0; i < signatureCheckChildren.getLength(); i++) + { + signatureCheckChildrenList.add(signatureCheckChildren.item(i)); + } + for (int i = 0; i < signatureCheckChildrenList.size(); i++) + Utils.transformDeep((Element) signatureCheckChildrenList.get(i), prefixMap, nsTransforms, + nameTransforms); + + return moaVerifyXMLSignatureResponse; + } +} diff --git a/spss.slinterface/WEB-INF/src/at/gv/egovernment/moa/spss/slinterface/transformers/QName.java b/spss.slinterface/WEB-INF/src/at/gv/egovernment/moa/spss/slinterface/transformers/QName.java new file mode 100644 index 000000000..6da0c433f --- /dev/null +++ b/spss.slinterface/WEB-INF/src/at/gv/egovernment/moa/spss/slinterface/transformers/QName.java @@ -0,0 +1,51 @@ +/* + * Created on 20.11.2003 + * + * (c) Stabsstelle IKT-Strategie des Bundes + */ +package at.gv.egovernment.moa.spss.slinterface.transformers; + +/** + * @author Gregor Karlinger (mailto:gregor.karlinger@cio.gv.at) + */ +public class QName +{ + public String nsUrl_; + public String localName_; + + /* ---------------------------------------------------------------------------------------------------- */ + + public QName(String nsUrl, String localName) + { + nsUrl_ = nsUrl; + localName_ = localName; + } + + /* ---------------------------------------------------------------------------------------------------- */ + + public boolean equals(Object o) + { + if (o == null) return false; + if (o instanceof QName) + { + QName toBeCompared = (QName) o; + + boolean nsURLEquals = (nsUrl_ == null) + ? toBeCompared.nsUrl_ == null + : nsUrl_.equals(toBeCompared.nsUrl_); + boolean localNameEquals = (localName_ == null) + ? toBeCompared.localName_ == null + : localName_.equals(toBeCompared.localName_); + + return nsURLEquals && localNameEquals; + } + return false; + } + + /* ---------------------------------------------------------------------------------------------------- */ + + public int hashCode() + { + return new String(nsUrl_ + localName_).hashCode(); + } +} diff --git a/spss.slinterface/WEB-INF/src/at/gv/egovernment/moa/spss/slinterface/transformers/SL2MOA.java b/spss.slinterface/WEB-INF/src/at/gv/egovernment/moa/spss/slinterface/transformers/SL2MOA.java new file mode 100644 index 000000000..11855242e --- /dev/null +++ b/spss.slinterface/WEB-INF/src/at/gv/egovernment/moa/spss/slinterface/transformers/SL2MOA.java @@ -0,0 +1,88 @@ +/* + * Created on 20.11.2003 + * + * (c) Stabsstelle IKT-Strategie des Bundes + */ +package at.gv.egovernment.moa.spss.slinterface.transformers; + +import java.util.HashMap; + +import org.w3c.dom.Document; +import org.w3c.dom.Element; + +import at.gv.egovernment.moa.spss.slinterface.Constants; + +/** + * @author Gregor Karlinger (mailto:gregor.karlinger@cio.gv.at) + */ +public class SL2MOA +{ + /** + * Transforms an SL VerifyXMLSignatureRequest into a MOA VerifyXMLSignatureRequest. + * + * @param slVerifyXMLSignatureRequest The SL VerifyXMLSignatureRequest to be transformed. + * + * @return the specified request document, transformed into a MOA VerifyXMLSignatureRequest. Please note + * that <code>slVerifyXMLSignatureRequest</code> is modified into the moa request. + * + * @pre slVerifyXMLSignatureRequest is a valid instance of the SL Schema (version 1.2 or 1.1). + */ + public static Document toMoaVerifyXMLSignatureRequest(Document slVerifyXMLSignatureRequest, + String trustProfileID) + { + // Namespace to namespace prefix mapping + HashMap prefixMap = new HashMap(4); + prefixMap.put(Constants.NSURI_SL_10_, Constants.NSPRE_SL_10_); + prefixMap.put(Constants.NSURI_SL_11_, Constants.NSPRE_SL_11_); + prefixMap.put(Constants.NSURI_SL_12_, Constants.NSPRE_SL_12_); + prefixMap.put(Constants.NSURI_MOA_12_, Constants.NSPRE_MOA_12_); + + // Namespaces to be changed + HashMap nsTransforms = new HashMap(); + nsTransforms.put(Constants.NSURI_SL_10_, Constants.NSURI_MOA_12_); + nsTransforms.put(Constants.NSURI_SL_11_, Constants.NSURI_MOA_12_); + nsTransforms.put(Constants.NSURI_SL_12_, Constants.NSURI_MOA_12_); + + // Names to be changed + HashMap nameTransforms = new HashMap(); + nameTransforms.put( + new QName(Constants.NSURI_SL_11_, "SignatureInfo"), + new QName(Constants.NSURI_MOA_12_,"VerifySignatureInfo")); + nameTransforms.put( + new QName(Constants.NSURI_SL_12_, "SignatureInfo"), + new QName(Constants.NSURI_MOA_12_,"VerifySignatureInfo")); + nameTransforms.put( + new QName(Constants.NSURI_SL_11_, "SignatureEnvironment"), + new QName(Constants.NSURI_MOA_12_,"VerifySignatureEnvironment")); + nameTransforms.put( + new QName(Constants.NSURI_SL_12_, "SignatureEnvironment"), + new QName(Constants.NSURI_MOA_12_,"VerifySignatureEnvironment")); + nameTransforms.put( + new QName(Constants.NSURI_SL_11_, "SignatureLocation"), + new QName(Constants.NSURI_MOA_12_,"VerifySignatureLocation")); + nameTransforms.put( + new QName(Constants.NSURI_SL_12_, "SignatureLocation"), + new QName(Constants.NSURI_MOA_12_,"VerifySignatureLocation")); + nameTransforms.put( + new QName(Constants.NSURI_SL_11_, "Supplement"), + new QName(Constants.NSURI_MOA_12_,"SupplementProfile")); + nameTransforms.put( + new QName(Constants.NSURI_SL_12_, "Supplement"), + new QName(Constants.NSURI_MOA_12_,"SupplementProfile")); + + Element verifyRequestElem = slVerifyXMLSignatureRequest.getDocumentElement(); + verifyRequestElem.setAttributeNS(Constants.NSURI_NAMESPACES_, + "xmlns:" + Constants.NSPRE_MOA_12_, Constants.NSURI_MOA_12_); + + // Convert SL request into MOA request + verifyRequestElem = Utils.transformDeep(verifyRequestElem, prefixMap, nsTransforms, nameTransforms); + + // Add trust profile ID element + Element trustProfileIDElem = slVerifyXMLSignatureRequest.createElementNS( + Constants.NSURI_MOA_12_, Constants.NSPRE_MOA_12_ + ":TrustProfileID"); + trustProfileIDElem.appendChild(slVerifyXMLSignatureRequest.createTextNode(trustProfileID)); + verifyRequestElem.appendChild(trustProfileIDElem); + + return slVerifyXMLSignatureRequest; + } +} diff --git a/spss.slinterface/WEB-INF/src/at/gv/egovernment/moa/spss/slinterface/transformers/Utils.java b/spss.slinterface/WEB-INF/src/at/gv/egovernment/moa/spss/slinterface/transformers/Utils.java new file mode 100644 index 000000000..d03895efe --- /dev/null +++ b/spss.slinterface/WEB-INF/src/at/gv/egovernment/moa/spss/slinterface/transformers/Utils.java @@ -0,0 +1,129 @@ +/* + * Created on 20.11.2003 + * + * (c) Stabsstelle IKT-Strategie des Bundes + */ +package at.gv.egovernment.moa.spss.slinterface.transformers; + +import java.util.ArrayList; +import java.util.Iterator; +import java.util.LinkedList; +import java.util.List; +import java.util.Map; + +import org.apache.xerces.dom.DocumentImpl; +import org.w3c.dom.Attr; +import org.w3c.dom.Element; +import org.w3c.dom.NamedNodeMap; +import org.w3c.dom.Node; +import org.w3c.dom.NodeList; +import org.w3c.dom.traversal.DocumentTraversal; +import org.w3c.dom.traversal.NodeFilter; +import org.w3c.dom.traversal.NodeIterator; + +import at.gv.egovernment.moa.spss.slinterface.Constants; + +/** + * @author Gregor Karlinger (mailto:gregor.karlinger@cio.gv.at) + */ +public class Utils +{ + /** + * + * @param elem + * @param prefixes + * @param namespaces + * @param names + * + * @pre <code>elem</code> is backed by a <code>org.apache.xerces.dom.DocumentImpl</code>. + */ + public static Element transformDeep(Element elem, Map prefixes, Map namespaces, Map names) + { + // Get node iterator for element + DocumentTraversal docTraversal = (DocumentImpl) elem.getOwnerDocument(); + NodeIterator elemsIt = docTraversal.createNodeIterator(elem, NodeFilter.SHOW_ELEMENT, null, true); + + // Make iterator immutable + List elemsList = new LinkedList(); + while (true) + { + Node currNode = elemsIt.nextNode(); + if (currNode == null) break; + elemsList.add(currNode); + } + + Iterator elemsImmIt = elemsList.iterator(); + Element returnValue = null; + while (elemsImmIt.hasNext()) + { + Element currElem = (Element) elemsImmIt.next(); + + String nsUri = currElem.getNamespaceURI(); + String localName = currElem.getLocalName(); + QName qName = new QName(nsUri, localName); + + // Check if element is in "names" + QName newQName = (QName)names.get(qName); + if (newQName != null) + { + Element transformedElem = transformElem(currElem, newQName, prefixes); + if (returnValue == null) returnValue = transformedElem; + } + else + { + String newNamespace = (String)namespaces.get(nsUri); + if (newNamespace != null) + { + newQName = new QName(newNamespace, localName); + Element transformedElem = transformElem(currElem, newQName, prefixes); + if (returnValue == null) returnValue = transformedElem; + } + } + } + return returnValue; + } + + /* ---------------------------------------------------------------------------------------------------- */ + + private static Element transformElem(Element currElem, QName newQName, Map prefixes) + { + Element newElem = currElem.getOwnerDocument().createElementNS(newQName.nsUrl_, + (String) prefixes.get(newQName.nsUrl_) + ":" + newQName.localName_); + + currElem.getParentNode().replaceChild(newElem, currElem); + + // Treat attributes of currElem + NamedNodeMap currAttrs = currElem.getAttributes(); + ArrayList currAttrsList = new ArrayList(currAttrs.getLength()); + for (int i = 0; i < currAttrs.getLength(); i++) currAttrsList.add(currAttrs.item(i)); + for (int i = 0; i < currAttrsList.size(); i++) + { + Attr currAttr = (Attr)currAttrsList.get(i); + currAttr.getOwnerElement().removeAttributeNode(currAttr); + + // Workaround for bad Xerces behaviour: default attributes in the xml namespace are created without + // the xml prefix + if (Constants.NSURI_XML_.equals(currAttr.getNamespaceURI()) && "space".equals(currAttr.getLocalName())) + { + newElem.setAttributeNS(Constants.NSURI_XML_, "xml:space", currAttr.getValue()); + } + else + { + newElem.setAttributeNode(currAttr); + } + } + + // Treat child nodes of currElem + NodeList currChildren = currElem.getChildNodes(); + ArrayList currChildrenList = new ArrayList(currChildren.getLength()); + for (int i = 0; i < currChildren.getLength(); i++) currChildrenList.add(currChildren.item(i)); + for (int i = 0; i < currChildrenList.size(); i++) + { + Node currChild = (Node)currChildrenList.get(i); + currElem.removeChild(currChild); + newElem.appendChild(currChild); + } + + return newElem; + } +} |