src/java.xml.crypto/share/classes/org/jcp/xml/dsig/internal/dom/Marshaller.java
branchmetal-prototype-branch
changeset 57247 48f2dc62ba77
parent 57243 8c3a74033daf
parent 54029 4ff6c8365b69
child 57251 86ed45a9dedb
equal deleted inserted replaced
57243:8c3a74033daf 57247:48f2dc62ba77
     1 /*
       
     2  * reserved comment block
       
     3  * DO NOT REMOVE OR ALTER!
       
     4  */
       
     5 /**
       
     6  * Licensed to the Apache Software Foundation (ASF) under one
       
     7  * or more contributor license agreements. See the NOTICE file
       
     8  * distributed with this work for additional information
       
     9  * regarding copyright ownership. The ASF licenses this file
       
    10  * to you under the Apache License, Version 2.0 (the
       
    11  * "License"); you may not use this file except in compliance
       
    12  * with the License. You may obtain a copy of the License at
       
    13  *
       
    14  * http://www.apache.org/licenses/LICENSE-2.0
       
    15  *
       
    16  * Unless required by applicable law or agreed to in writing,
       
    17  * software distributed under the License is distributed on an
       
    18  * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
       
    19  * KIND, either express or implied. See the License for the
       
    20  * specific language governing permissions and limitations
       
    21  * under the License.
       
    22  */
       
    23 package org.jcp.xml.dsig.internal.dom;
       
    24 
       
    25 import java.util.ArrayList;
       
    26 import java.util.Base64;
       
    27 import java.util.List;
       
    28 
       
    29 import javax.xml.XMLConstants;
       
    30 import javax.xml.crypto.MarshalException;
       
    31 import javax.xml.crypto.XMLCryptoContext;
       
    32 import javax.xml.crypto.XMLStructure;
       
    33 import javax.xml.crypto.dsig.DigestMethod;
       
    34 import javax.xml.crypto.dsig.Manifest;
       
    35 import javax.xml.crypto.dsig.SignatureProperties;
       
    36 import javax.xml.crypto.dsig.SignatureProperty;
       
    37 import javax.xml.crypto.dsig.XMLSignature;
       
    38 import javax.xml.crypto.dsig.keyinfo.KeyInfo;
       
    39 import javax.xml.crypto.dsig.keyinfo.KeyName;
       
    40 import javax.xml.crypto.dsig.keyinfo.KeyValue;
       
    41 import javax.xml.crypto.dsig.keyinfo.PGPData;
       
    42 import javax.xml.crypto.dsig.keyinfo.X509Data;
       
    43 import javax.xml.crypto.dsig.keyinfo.X509IssuerSerial;
       
    44 
       
    45 import org.w3c.dom.Attr;
       
    46 import org.w3c.dom.NamedNodeMap;
       
    47 import org.w3c.dom.Node;
       
    48 
       
    49 /**
       
    50  * Defines the individual marshallers for each of the different javax.xml.crypto structures.
       
    51  */
       
    52 class Marshaller {
       
    53 
       
    54     private Marshaller() {
       
    55         // complete
       
    56     }
       
    57 
       
    58     public static List<XmlWriter.ToMarshal<? extends XMLStructure>> getMarshallers() {
       
    59         return MARSHALLERS;
       
    60     }
       
    61 
       
    62     /**
       
    63      * Marshals a {@link KeyName}.
       
    64      *
       
    65      * @param xwriter
       
    66      * @param keyName
       
    67      * @param dsPrefix
       
    68      */
       
    69     public static void marshalKeyName(XmlWriter xwriter, KeyName keyName, String dsPrefix) {
       
    70         xwriter.writeTextElement(dsPrefix, "KeyName", XMLSignature.XMLNS, keyName.getName());
       
    71     }
       
    72 
       
    73     /**
       
    74      * Marshals a {@link PGPData}
       
    75      *
       
    76      * @param xwriter
       
    77      * @param pgpData
       
    78      * @param dsPrefix
       
    79      * @param context
       
    80      * @throws MarshalException
       
    81      */
       
    82     public static void marshalPGPData(XmlWriter xwriter, PGPData pgpData, String dsPrefix, XMLCryptoContext context)
       
    83     throws MarshalException {
       
    84         xwriter.writeStartElement(dsPrefix, "PGPData", XMLSignature.XMLNS);
       
    85 
       
    86         // create and append PGPKeyID element
       
    87         byte[] keyId = pgpData.getKeyId();
       
    88         if (keyId != null) {
       
    89             xwriter.writeTextElement(dsPrefix, "PGPKeyID", XMLSignature.XMLNS,
       
    90                                      Base64.getMimeEncoder().encodeToString(keyId));
       
    91         }
       
    92 
       
    93         // create and append PGPKeyPacket element
       
    94         byte[] keyPacket = pgpData.getKeyPacket();
       
    95         if (keyPacket != null) {
       
    96             xwriter.writeTextElement(dsPrefix, "XMLSignature.XMLNS", XMLSignature.XMLNS,
       
    97                                      Base64.getMimeEncoder().encodeToString(keyPacket));
       
    98         }
       
    99 
       
   100         // create and append any elements
       
   101         @SuppressWarnings("unchecked")
       
   102         List<XMLStructure> externalElements = pgpData.getExternalElements();
       
   103         for (XMLStructure externalItem : externalElements) {
       
   104             xwriter.marshalStructure(externalItem, dsPrefix, context);
       
   105         }
       
   106 
       
   107         xwriter.writeEndElement(); // "PGPData"
       
   108     }
       
   109 
       
   110     /**
       
   111      * Marshals an {@link X509IssuerSerial}
       
   112      *
       
   113      * @param xwriter
       
   114      * @param issuerSerial
       
   115      * @param dsPrefix
       
   116      */
       
   117     public static void marshalX509IssuerSerial(XmlWriter xwriter, X509IssuerSerial issuerSerial, String dsPrefix) {
       
   118         xwriter.writeStartElement(dsPrefix, "X509IssuerSerial", XMLSignature.XMLNS);
       
   119         xwriter.writeTextElement(dsPrefix, "X509IssuerName", XMLSignature.XMLNS,
       
   120                 issuerSerial.getIssuerName());
       
   121 
       
   122         xwriter.writeTextElement(dsPrefix, "X509SerialNumber", XMLSignature.XMLNS,
       
   123                 issuerSerial.getSerialNumber().toString());
       
   124 
       
   125         xwriter.writeEndElement(); // "X509IssuerSerial"
       
   126     }
       
   127 
       
   128     private static XmlWriter.ToMarshal<KeyName> Marshal_KeyName = new XmlWriter.ToMarshal<KeyName>(KeyName.class) {
       
   129         @Override
       
   130         public void marshalObject(XmlWriter xwriter, KeyName toMarshal, String dsPrefix,
       
   131                 XMLCryptoContext context) throws MarshalException {
       
   132             Marshaller.marshalKeyName(xwriter, toMarshal, dsPrefix);
       
   133         }
       
   134     };
       
   135 
       
   136     private static XmlWriter.ToMarshal<KeyInfo> Marshal_KeyInfo = new XmlWriter.ToMarshal<KeyInfo>(KeyInfo.class) {
       
   137         @Override
       
   138         public void marshalObject(XmlWriter xwriter, KeyInfo toMarshal, String dsPrefix,
       
   139                 XMLCryptoContext context) throws MarshalException {
       
   140             DOMKeyInfo.marshal(xwriter, toMarshal, dsPrefix, context);
       
   141         }
       
   142     };
       
   143 
       
   144     private static XmlWriter.ToMarshal<KeyValue> Marshal_KeyValue = new XmlWriter.ToMarshal<KeyValue>(KeyValue.class) {
       
   145         @Override
       
   146         public void marshalObject(XmlWriter xwriter, KeyValue toMarshal, String dsPrefix,
       
   147                 XMLCryptoContext context) throws MarshalException {
       
   148             // Since DOMKeyValue allows for deserializing unrecognized keys, and that
       
   149             // capability isn't available via the KeyValue interface, this must continue
       
   150             // to cast to DOMKeyValue.
       
   151             DOMKeyValue<?> dkv = (DOMKeyValue<?>) toMarshal;
       
   152             dkv.marshal( xwriter, dsPrefix, context);
       
   153         }
       
   154     };
       
   155 
       
   156     private static XmlWriter.ToMarshal<X509IssuerSerial> Marshal_X509IssuerSerial =
       
   157             new XmlWriter.ToMarshal<X509IssuerSerial>(X509IssuerSerial.class) {
       
   158         @Override
       
   159         public void marshalObject(XmlWriter xwriter, X509IssuerSerial toMarshal, String dsPrefix,
       
   160                 XMLCryptoContext context) throws MarshalException {
       
   161             Marshaller.marshalX509IssuerSerial( xwriter, toMarshal, dsPrefix);
       
   162         }
       
   163     };
       
   164 
       
   165     private static XmlWriter.ToMarshal<X509Data> Marshal_X509Data =
       
   166             new XmlWriter.ToMarshal<X509Data>(X509Data.class) {
       
   167         @Override
       
   168         public void marshalObject(XmlWriter xwriter, X509Data toMarshal, String dsPrefix,
       
   169                 XMLCryptoContext context) throws MarshalException {
       
   170             DOMX509Data.marshal( xwriter, toMarshal, dsPrefix, context);
       
   171         }
       
   172     };
       
   173 
       
   174     private static XmlWriter.ToMarshal<DigestMethod> Marshal_DigestMethod =
       
   175             new XmlWriter.ToMarshal<DigestMethod>(DigestMethod.class) {
       
   176         @Override
       
   177         public void marshalObject(XmlWriter xwriter, DigestMethod toMarshal, String dsPrefix,
       
   178                 XMLCryptoContext context) throws MarshalException {
       
   179             DOMDigestMethod.marshal( xwriter, toMarshal, dsPrefix);
       
   180         }
       
   181     };
       
   182 
       
   183     private static XmlWriter.ToMarshal<PGPData> Marshal_PGPData =
       
   184             new XmlWriter.ToMarshal<PGPData>(PGPData.class) {
       
   185         @Override
       
   186         public void marshalObject(XmlWriter xwriter, PGPData toMarshal, String dsPrefix,
       
   187                 XMLCryptoContext context) throws MarshalException {
       
   188             Marshaller.marshalPGPData( xwriter, toMarshal, dsPrefix, context);
       
   189         }
       
   190     };
       
   191 
       
   192     private static XmlWriter.ToMarshal<SignatureProperty> Marshal_SignatureProperty =
       
   193             new XmlWriter.ToMarshal<SignatureProperty>(SignatureProperty.class) {
       
   194         @Override
       
   195         public void marshalObject(XmlWriter xwriter, SignatureProperty toMarshal, String dsPrefix,
       
   196                 XMLCryptoContext context) throws MarshalException {
       
   197             DOMSignatureProperty.marshal(xwriter, toMarshal, dsPrefix, context);
       
   198         }
       
   199     };
       
   200 
       
   201     private static XmlWriter.ToMarshal<SignatureProperties> Marshal_SignatureProperties =
       
   202             new XmlWriter.ToMarshal<SignatureProperties>(SignatureProperties.class) {
       
   203         @Override
       
   204         public void marshalObject(XmlWriter xwriter, SignatureProperties toMarshal, String dsPrefix,
       
   205                 XMLCryptoContext context) throws MarshalException {
       
   206             DOMSignatureProperties.marshal(xwriter, toMarshal, dsPrefix, context);
       
   207         }
       
   208     };
       
   209 
       
   210     private static XmlWriter.ToMarshal<DOMSignatureMethod> Marshal_DOMSignatureMethod =
       
   211             new XmlWriter.ToMarshal<DOMSignatureMethod>(DOMSignatureMethod.class) {
       
   212         @Override
       
   213         public void marshalObject(XmlWriter xwriter, DOMSignatureMethod toMarshal, String dsPrefix,
       
   214                 XMLCryptoContext context) throws MarshalException {
       
   215             toMarshal.marshal(xwriter, dsPrefix);
       
   216         }
       
   217     };
       
   218 
       
   219     private static XmlWriter.ToMarshal<DOMTransform> Marshal_DOMTransform =
       
   220             new XmlWriter.ToMarshal<DOMTransform>(DOMTransform.class) {
       
   221         @Override
       
   222         public void marshalObject(XmlWriter xwriter, DOMTransform toMarshal, String dsPrefix,
       
   223                 XMLCryptoContext context) throws MarshalException {
       
   224             toMarshal.marshal(xwriter, dsPrefix, context);
       
   225         }
       
   226     };
       
   227 
       
   228     private static XmlWriter.ToMarshal<Manifest> Marshal_Manifest =
       
   229             new XmlWriter.ToMarshal<Manifest>(Manifest.class) {
       
   230         @Override
       
   231         public void marshalObject(XmlWriter xwriter, Manifest toMarshal, String dsPrefix,
       
   232                 XMLCryptoContext context) throws MarshalException {
       
   233             DOMManifest.marshal(xwriter, toMarshal, dsPrefix, context);
       
   234         }
       
   235     };
       
   236 
       
   237     private static XmlWriter.ToMarshal<DOMStructure> Marshal_DOMStructure =
       
   238             new XmlWriter.ToMarshal<DOMStructure>(DOMStructure.class) {
       
   239         @Override
       
   240         public void marshalObject(XmlWriter xwriter, DOMStructure toMarshal, String dsPrefix,
       
   241                 XMLCryptoContext context) throws MarshalException {
       
   242             toMarshal.marshal(xwriter, dsPrefix, context);
       
   243         }
       
   244     };
       
   245 
       
   246     private static XmlWriter.ToMarshal<javax.xml.crypto.dom.DOMStructure> Marshal_JavaXDOMStructure =
       
   247             new XmlWriter.ToMarshal<javax.xml.crypto.dom.DOMStructure>(javax.xml.crypto.dom.DOMStructure.class) {
       
   248         @Override
       
   249         public void marshalObject(XmlWriter xwriter, javax.xml.crypto.dom.DOMStructure toMarshal, String dsPrefix,
       
   250                 XMLCryptoContext context) throws MarshalException {
       
   251             marshalGenericNode(xwriter, toMarshal);
       
   252         }
       
   253     };
       
   254 
       
   255     private static final List<XmlWriter.ToMarshal<? extends XMLStructure>> MARSHALLERS =
       
   256         new ArrayList<XmlWriter.ToMarshal<? extends XMLStructure>>();
       
   257 
       
   258     static {
       
   259         MARSHALLERS.add(Marshal_KeyName);
       
   260         MARSHALLERS.add(Marshal_KeyInfo);
       
   261         MARSHALLERS.add(Marshal_KeyValue);
       
   262         MARSHALLERS.add(Marshal_X509IssuerSerial);
       
   263         MARSHALLERS.add(Marshal_X509Data);
       
   264         MARSHALLERS.add(Marshal_DigestMethod);
       
   265         MARSHALLERS.add(Marshal_PGPData);
       
   266         MARSHALLERS.add(Marshal_SignatureProperty);
       
   267         MARSHALLERS.add(Marshal_SignatureProperties);
       
   268         MARSHALLERS.add(Marshal_DOMSignatureMethod);
       
   269         MARSHALLERS.add(Marshal_DOMTransform);
       
   270         MARSHALLERS.add(Marshal_Manifest);
       
   271         MARSHALLERS.add(Marshal_DOMStructure);
       
   272         MARSHALLERS.add(Marshal_JavaXDOMStructure);
       
   273     }
       
   274 
       
   275     private static void marshalGenericNode(XmlWriter xwriter, javax.xml.crypto.dom.DOMStructure xmlStruct) {
       
   276         Node node = xmlStruct.getNode();
       
   277 
       
   278         // if it is a namespace, make a copy.
       
   279         if (DOMUtils.isNamespace(node)) {
       
   280             xwriter.writeNamespace(node.getLocalName(), node.getTextContent());
       
   281         }
       
   282         else if (Node.ATTRIBUTE_NODE == node.getNodeType() ) {
       
   283             sendAttributeToWriter(xwriter, (Attr) node);
       
   284         }
       
   285         else {
       
   286             marshalGenericNode(xwriter, node);
       
   287         }
       
   288     }
       
   289 
       
   290     private static void marshalGenericNode(XmlWriter xwriter, Node node) {
       
   291 
       
   292         short nodeType = node.getNodeType();
       
   293         if (DOMUtils.isNamespace(node)) {
       
   294             xwriter.writeNamespace(node.getLocalName(), node.getTextContent());
       
   295         }
       
   296         else if (nodeType == Node.ATTRIBUTE_NODE) {
       
   297             // if it is an attribute, make a copy.
       
   298             sendAttributeToWriter(xwriter, (Attr) node);
       
   299         }
       
   300         else {
       
   301             switch (nodeType) {
       
   302             case Node.ELEMENT_NODE:
       
   303                 xwriter.writeStartElement(node.getPrefix(), node.getLocalName(), node.getNamespaceURI());
       
   304 
       
   305                 // emit all the namespaces and attributes.
       
   306                 NamedNodeMap nnm = node.getAttributes();
       
   307                 for (int idx = 0 ; idx < nnm.getLength() ; idx++) {
       
   308                     Attr attr = (Attr) nnm.item(idx);
       
   309                     // is this a namespace node?
       
   310                     if (XMLConstants.XMLNS_ATTRIBUTE_NS_URI.equals(node.getNamespaceURI())) {
       
   311                         xwriter.writeNamespace(attr.getLocalName(), attr.getValue());
       
   312                     }
       
   313                     else {
       
   314                         // nope - standard attribute.
       
   315                         sendAttributeToWriter(xwriter, attr);
       
   316                     }
       
   317                 }
       
   318                 // now loop through all the children.
       
   319                 for (Node child = node.getFirstChild() ; child != null ; child = child.getNextSibling()) {
       
   320                     marshalGenericNode(xwriter, child);
       
   321                 }
       
   322                 xwriter.writeEndElement();
       
   323                 break;
       
   324             case Node.COMMENT_NODE:
       
   325                 xwriter.writeComment(node.getTextContent());
       
   326                 break;
       
   327             case Node.TEXT_NODE:
       
   328                 xwriter.writeCharacters(node.getTextContent());
       
   329                 break;
       
   330             default:
       
   331                 // unhandled - don't care to deal with processing instructions.
       
   332                 break;
       
   333             }
       
   334         }
       
   335     }
       
   336 
       
   337     private static void sendAttributeToWriter(XmlWriter xwriter, Attr attr) {
       
   338         if (attr.isId()) {
       
   339             xwriter.writeIdAttribute(attr.getPrefix(), attr.getNamespaceURI(),
       
   340                     attr.getLocalName(), attr.getTextContent());
       
   341         }
       
   342         else {
       
   343             if (attr.getNamespaceURI() == null && attr.getLocalName() == null) {
       
   344                 // Level 1 DOM attribute
       
   345                 xwriter.writeAttribute(null, null, attr.getName(), attr.getTextContent());
       
   346             } else {
       
   347                 xwriter.writeAttribute(attr.getPrefix(), attr.getNamespaceURI(), attr.getLocalName(),
       
   348                                        attr.getTextContent());
       
   349             }
       
   350         }
       
   351     }
       
   352 
       
   353 }