1 /*
   2  * reserved comment block
   3  * DO NOT REMOVE OR ALTER!
   4  */
   5 /*
   6  * Copyright 2005 The Apache Software Foundation.
   7  *
   8  *  Licensed under the Apache License, Version 2.0 (the "License");
   9  *  you may not use this file except in compliance with the License.
  10  *  You may obtain a copy of the License at
  11  *
  12  *      http://www.apache.org/licenses/LICENSE-2.0
  13  *
  14  *  Unless required by applicable law or agreed to in writing, software
  15  *  distributed under the License is distributed on an "AS IS" BASIS,
  16  *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  17  *  See the License for the specific language governing permissions and
  18  *  limitations under the License.
  19  *
  20  */
  21 /*
  22  * Copyright (c) 2005, 2008, Oracle and/or its affiliates. All rights reserved.
  23  */
  24 /*
  25  * $Id: DOMExcC14NMethod.java,v 1.2 2008/07/24 15:20:32 mullan Exp $
  26  */
  27 package org.jcp.xml.dsig.internal.dom;
  28 
  29 import javax.xml.crypto.*;
  30 import javax.xml.crypto.dsig.*;
  31 import javax.xml.crypto.dsig.spec.C14NMethodParameterSpec;
  32 import javax.xml.crypto.dsig.spec.ExcC14NParameterSpec;
  33 import javax.xml.crypto.dsig.spec.TransformParameterSpec;
  34 
  35 import java.security.InvalidAlgorithmParameterException;
  36 import java.security.spec.AlgorithmParameterSpec;
  37 import java.util.*;
  38 import org.w3c.dom.Element;
  39 
  40 import com.sun.org.apache.xml.internal.security.c14n.Canonicalizer;
  41 import com.sun.org.apache.xml.internal.security.c14n.InvalidCanonicalizerException;
  42 
  43 /**
  44  * DOM-based implementation of CanonicalizationMethod for Exclusive
  45  * Canonical XML algorithm (with or without comments).
  46  * Uses Apache XML-Sec Canonicalizer.
  47  *
  48  * @author Sean Mullan
  49  */
  50 public final class DOMExcC14NMethod extends ApacheCanonicalizer {
  51 
  52     public void init(TransformParameterSpec params)
  53         throws InvalidAlgorithmParameterException {
  54         if (params != null) {
  55             if (!(params instanceof ExcC14NParameterSpec)) {
  56                 throw new InvalidAlgorithmParameterException
  57                     ("params must be of type ExcC14NParameterSpec");
  58             }
  59             this.params = (C14NMethodParameterSpec) params;
  60         }
  61     }
  62 
  63     public void init(XMLStructure parent, XMLCryptoContext context)
  64         throws InvalidAlgorithmParameterException {
  65         super.init(parent, context);
  66         Element paramsElem = DOMUtils.getFirstChildElement(transformElem);
  67         if (paramsElem == null) {
  68             this.params = null;
  69             this.inclusiveNamespaces = null;
  70             return;
  71         }
  72         unmarshalParams(paramsElem);
  73     }
  74 
  75     private void unmarshalParams(Element paramsElem) {
  76         String prefixListAttr = paramsElem.getAttributeNS(null, "PrefixList");
  77         this.inclusiveNamespaces = prefixListAttr;
  78         int begin = 0;
  79         int end = prefixListAttr.indexOf(' ');
  80         List prefixList = new ArrayList();
  81         while (end != -1) {
  82             prefixList.add(prefixListAttr.substring(begin, end));
  83             begin = end + 1;
  84             end = prefixListAttr.indexOf(' ', begin);
  85         }
  86         if (begin <= prefixListAttr.length()) {
  87             prefixList.add(prefixListAttr.substring(begin));
  88         }
  89         this.params = new ExcC14NParameterSpec(prefixList);
  90     }
  91 
  92     public void marshalParams(XMLStructure parent, XMLCryptoContext context)
  93         throws MarshalException {
  94 
  95         super.marshalParams(parent, context);
  96         AlgorithmParameterSpec spec = getParameterSpec();
  97         if (spec == null) {
  98             return;
  99         }
 100 
 101         String prefix =
 102             DOMUtils.getNSPrefix(context, CanonicalizationMethod.EXCLUSIVE);
 103         Element excElem = DOMUtils.createElement
 104             (ownerDoc, "InclusiveNamespaces",
 105              CanonicalizationMethod.EXCLUSIVE, prefix);
 106         if (prefix == null || prefix.length() == 0) {
 107             excElem.setAttributeNS("http://www.w3.org/2000/xmlns/", "xmlns",
 108                 CanonicalizationMethod.EXCLUSIVE);
 109         } else {
 110             excElem.setAttributeNS("http://www.w3.org/2000/xmlns/",
 111                 "xmlns:" + prefix, CanonicalizationMethod.EXCLUSIVE);
 112         }
 113 
 114         ExcC14NParameterSpec params = (ExcC14NParameterSpec) spec;
 115         StringBuffer prefixListAttr = new StringBuffer("");
 116         List prefixList = params.getPrefixList();
 117         for (int i = 0, size = prefixList.size(); i < size; i++) {
 118             prefixListAttr.append((String) prefixList.get(i));
 119             if (i < size - 1) {
 120                 prefixListAttr.append(" ");
 121             }
 122         }
 123         DOMUtils.setAttribute(excElem, "PrefixList", prefixListAttr.toString());
 124         this.inclusiveNamespaces = prefixListAttr.toString();
 125         transformElem.appendChild(excElem);
 126     }
 127 
 128     public String getParamsNSURI() {
 129         return CanonicalizationMethod.EXCLUSIVE;
 130     }
 131 
 132     public Data transform(Data data, XMLCryptoContext xc)
 133         throws TransformException {
 134 
 135         // ignore comments if dereferencing same-document URI that require
 136         // you to omit comments, even if the Transform says otherwise -
 137         // this is to be compliant with section 4.3.3.3 of W3C Rec.
 138         if (data instanceof DOMSubTreeData) {
 139             DOMSubTreeData subTree = (DOMSubTreeData) data;
 140             if (subTree.excludeComments()) {
 141                 try {
 142                     apacheCanonicalizer = Canonicalizer.getInstance
 143                         (CanonicalizationMethod.EXCLUSIVE);
 144                 } catch (InvalidCanonicalizerException ice) {
 145                     throw new TransformException
 146                         ("Couldn't find Canonicalizer for: " +
 147                          CanonicalizationMethod.EXCLUSIVE + ": " +
 148                          ice.getMessage(), ice);
 149                 }
 150             }
 151         }
 152 
 153         return canonicalize(data, xc);
 154     }
 155 }