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/*
24 * Copyright (c) 2005, 2014, Oracle and/or its affiliates. All rights reserved.
25 */
26/*
27 * $Id: DOMExcC14NMethod.java 1197150 2011-11-03 14:34:57Z coheigea $
28 */
29package org.jcp.xml.dsig.internal.dom;
30
31import javax.xml.crypto.*;
32import javax.xml.crypto.dsig.*;
33import javax.xml.crypto.dsig.spec.C14NMethodParameterSpec;
34import javax.xml.crypto.dsig.spec.ExcC14NParameterSpec;
35import javax.xml.crypto.dsig.spec.TransformParameterSpec;
36
37import java.security.InvalidAlgorithmParameterException;
38import java.security.spec.AlgorithmParameterSpec;
39import java.util.*;
40import org.w3c.dom.Element;
41
42import com.sun.org.apache.xml.internal.security.c14n.Canonicalizer;
43import com.sun.org.apache.xml.internal.security.c14n.InvalidCanonicalizerException;
44
45/**
46 * DOM-based implementation of CanonicalizationMethod for Exclusive
47 * Canonical XML algorithm (with or without comments).
48 * Uses Apache XML-Sec Canonicalizer.
49 *
50 * @author Sean Mullan
51 */
52public final class DOMExcC14NMethod extends ApacheCanonicalizer {
53
54    public void init(TransformParameterSpec params)
55        throws InvalidAlgorithmParameterException
56    {
57        if (params != null) {
58            if (!(params instanceof ExcC14NParameterSpec)) {
59                throw new InvalidAlgorithmParameterException
60                    ("params must be of type ExcC14NParameterSpec");
61            }
62            this.params = (C14NMethodParameterSpec)params;
63        }
64    }
65
66    public void init(XMLStructure parent, XMLCryptoContext context)
67        throws InvalidAlgorithmParameterException
68    {
69        super.init(parent, context);
70        Element paramsElem = DOMUtils.getFirstChildElement(transformElem);
71        if (paramsElem == null) {
72            this.params = null;
73            this.inclusiveNamespaces = null;
74            return;
75        }
76        unmarshalParams(paramsElem);
77    }
78
79    private void unmarshalParams(Element paramsElem) {
80        String prefixListAttr = paramsElem.getAttributeNS(null, "PrefixList");
81        this.inclusiveNamespaces = prefixListAttr;
82        int begin = 0;
83        int end = prefixListAttr.indexOf(' ');
84        List<String> prefixList = new ArrayList<String>();
85        while (end != -1) {
86            prefixList.add(prefixListAttr.substring(begin, end));
87            begin = end + 1;
88            end = prefixListAttr.indexOf(' ', begin);
89        }
90        if (begin <= prefixListAttr.length()) {
91            prefixList.add(prefixListAttr.substring(begin));
92        }
93        this.params = new ExcC14NParameterSpec(prefixList);
94    }
95
96    public void marshalParams(XMLStructure parent, XMLCryptoContext context)
97        throws MarshalException
98    {
99        super.marshalParams(parent, context);
100        AlgorithmParameterSpec spec = getParameterSpec();
101        if (spec == null) {
102            return;
103        }
104
105        String prefix = DOMUtils.getNSPrefix(context,
106                                             CanonicalizationMethod.EXCLUSIVE);
107        Element eElem = DOMUtils.createElement(ownerDoc,
108                                               "InclusiveNamespaces",
109                                               CanonicalizationMethod.EXCLUSIVE,
110                                               prefix);
111        if (prefix == null || prefix.length() == 0) {
112            eElem.setAttributeNS("http://www.w3.org/2000/xmlns/", "xmlns",
113                                 CanonicalizationMethod.EXCLUSIVE);
114        } else {
115            eElem.setAttributeNS("http://www.w3.org/2000/xmlns/",
116                                   "xmlns:" + prefix,
117                                   CanonicalizationMethod.EXCLUSIVE);
118        }
119
120        ExcC14NParameterSpec params = (ExcC14NParameterSpec)spec;
121        StringBuilder prefixListAttr = new StringBuilder("");
122        List<String> prefixList = params.getPrefixList();
123        for (int i = 0, size = prefixList.size(); i < size; i++) {
124            prefixListAttr.append(prefixList.get(i));
125            if (i < size - 1) {
126                prefixListAttr.append(" ");
127            }
128        }
129        DOMUtils.setAttribute(eElem, "PrefixList", prefixListAttr.toString());
130        this.inclusiveNamespaces = prefixListAttr.toString();
131        transformElem.appendChild(eElem);
132    }
133
134    public String getParamsNSURI() {
135        return CanonicalizationMethod.EXCLUSIVE;
136    }
137
138    public Data transform(Data data, XMLCryptoContext xc)
139        throws TransformException
140    {
141        // ignore comments if dereferencing same-document URI that require
142        // you to omit comments, even if the Transform says otherwise -
143        // this is to be compliant with section 4.3.3.3 of W3C Rec.
144        if (data instanceof DOMSubTreeData) {
145            DOMSubTreeData subTree = (DOMSubTreeData)data;
146            if (subTree.excludeComments()) {
147                try {
148                    apacheCanonicalizer = Canonicalizer.getInstance
149                        (CanonicalizationMethod.EXCLUSIVE);
150                } catch (InvalidCanonicalizerException ice) {
151                    throw new TransformException
152                        ("Couldn't find Canonicalizer for: " +
153                         CanonicalizationMethod.EXCLUSIVE + ": " +
154                         ice.getMessage(), ice);
155                }
156            }
157        }
158
159        return canonicalize(data, xc);
160    }
161}
162