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, 2016, Oracle and/or its affiliates. All rights reserved.
25 */
26/*
27 * $Id: ApacheTransform.java 1333869 2012-05-04 10:42:44Z coheigea $
28 */
29package org.jcp.xml.dsig.internal.dom;
30
31import java.io.OutputStream;
32import java.security.InvalidAlgorithmParameterException;
33import java.security.spec.AlgorithmParameterSpec;
34import java.util.Set;
35import org.w3c.dom.Document;
36import org.w3c.dom.Element;
37import org.w3c.dom.Node;
38
39import com.sun.org.apache.xml.internal.security.signature.XMLSignatureInput;
40import com.sun.org.apache.xml.internal.security.transforms.Transform;
41
42import javax.xml.crypto.*;
43import javax.xml.crypto.dom.DOMCryptoContext;
44import javax.xml.crypto.dsig.*;
45import javax.xml.crypto.dsig.spec.TransformParameterSpec;
46
47/**
48 * This is a wrapper/glue class which invokes the Apache XML-Security
49 * Transform.
50 *
51 * @author Sean Mullan
52 * @author Erwin van der Koogh
53 */
54public abstract class ApacheTransform extends TransformService {
55
56    static {
57        com.sun.org.apache.xml.internal.security.Init.init();
58    }
59
60    private static java.util.logging.Logger log =
61        java.util.logging.Logger.getLogger("org.jcp.xml.dsig.internal.dom");
62    private Transform apacheTransform;
63    protected Document ownerDoc;
64    protected Element transformElem;
65    protected TransformParameterSpec params;
66
67    public final AlgorithmParameterSpec getParameterSpec() {
68        return params;
69    }
70
71    public void init(XMLStructure parent, XMLCryptoContext context)
72        throws InvalidAlgorithmParameterException
73    {
74        if (context != null && !(context instanceof DOMCryptoContext)) {
75            throw new ClassCastException
76                ("context must be of type DOMCryptoContext");
77        }
78        if (parent == null) {
79            throw new NullPointerException();
80        }
81        if (!(parent instanceof javax.xml.crypto.dom.DOMStructure)) {
82            throw new ClassCastException("parent must be of type DOMStructure");
83        }
84        transformElem = (Element)
85            ((javax.xml.crypto.dom.DOMStructure) parent).getNode();
86        ownerDoc = DOMUtils.getOwnerDocument(transformElem);
87    }
88
89    public void marshalParams(XMLStructure parent, XMLCryptoContext context)
90        throws MarshalException
91    {
92        if (context != null && !(context instanceof DOMCryptoContext)) {
93            throw new ClassCastException
94                ("context must be of type DOMCryptoContext");
95        }
96        if (parent == null) {
97            throw new NullPointerException();
98        }
99        if (!(parent instanceof javax.xml.crypto.dom.DOMStructure)) {
100            throw new ClassCastException("parent must be of type DOMStructure");
101        }
102        transformElem = (Element)
103            ((javax.xml.crypto.dom.DOMStructure) parent).getNode();
104        ownerDoc = DOMUtils.getOwnerDocument(transformElem);
105    }
106
107    public Data transform(Data data, XMLCryptoContext xc)
108        throws TransformException
109    {
110        if (data == null) {
111            throw new NullPointerException("data must not be null");
112        }
113        return transformIt(data, xc, (OutputStream)null);
114    }
115
116    public Data transform(Data data, XMLCryptoContext xc, OutputStream os)
117        throws TransformException
118    {
119        if (data == null) {
120            throw new NullPointerException("data must not be null");
121        }
122        if (os == null) {
123            throw new NullPointerException("output stream must not be null");
124        }
125        return transformIt(data, xc, os);
126    }
127
128    private Data transformIt(Data data, XMLCryptoContext xc, OutputStream os)
129        throws TransformException
130    {
131        if (ownerDoc == null) {
132            throw new TransformException("transform must be marshalled");
133        }
134
135        if (apacheTransform == null) {
136            try {
137                apacheTransform =
138                    new Transform(ownerDoc, getAlgorithm(), transformElem.getChildNodes());
139                apacheTransform.setElement(transformElem, xc.getBaseURI());
140                if (log.isLoggable(java.util.logging.Level.FINE)) {
141                    log.log(java.util.logging.Level.FINE, "Created transform for algorithm: " +
142                            getAlgorithm());
143                }
144            } catch (Exception ex) {
145                throw new TransformException("Couldn't find Transform for: " +
146                                             getAlgorithm(), ex);
147            }
148        }
149
150        if (Utils.secureValidation(xc)) {
151            String algorithm = getAlgorithm();
152            if (Policy.restrictAlg(algorithm)) {
153                throw new TransformException(
154                    "Transform " + algorithm + " is forbidden when secure validation is enabled"
155                );
156            }
157        }
158
159        XMLSignatureInput in;
160        if (data instanceof ApacheData) {
161            if (log.isLoggable(java.util.logging.Level.FINE)) {
162                log.log(java.util.logging.Level.FINE, "ApacheData = true");
163            }
164            in = ((ApacheData)data).getXMLSignatureInput();
165        } else if (data instanceof NodeSetData) {
166            if (log.isLoggable(java.util.logging.Level.FINE)) {
167                log.log(java.util.logging.Level.FINE, "isNodeSet() = true");
168            }
169            if (data instanceof DOMSubTreeData) {
170                if (log.isLoggable(java.util.logging.Level.FINE)) {
171                    log.log(java.util.logging.Level.FINE, "DOMSubTreeData = true");
172                }
173                DOMSubTreeData subTree = (DOMSubTreeData)data;
174                in = new XMLSignatureInput(subTree.getRoot());
175                in.setExcludeComments(subTree.excludeComments());
176            } else {
177                Set<Node> nodeSet =
178                    Utils.toNodeSet(((NodeSetData)data).iterator());
179                in = new XMLSignatureInput(nodeSet);
180            }
181        } else {
182            if (log.isLoggable(java.util.logging.Level.FINE)) {
183                log.log(java.util.logging.Level.FINE, "isNodeSet() = false");
184            }
185            try {
186                in = new XMLSignatureInput
187                    (((OctetStreamData)data).getOctetStream());
188            } catch (Exception ex) {
189                throw new TransformException(ex);
190            }
191        }
192
193        try {
194            if (os != null) {
195                in = apacheTransform.performTransform(in, os);
196                if (!in.isNodeSet() && !in.isElement()) {
197                    return null;
198                }
199            } else {
200                in = apacheTransform.performTransform(in);
201            }
202            if (in.isOctetStream()) {
203                return new ApacheOctetStreamData(in);
204            } else {
205                return new ApacheNodeSetData(in);
206            }
207        } catch (Exception ex) {
208            throw new TransformException(ex);
209        }
210    }
211
212    public final boolean isFeatureSupported(String feature) {
213        if (feature == null) {
214            throw new NullPointerException();
215        } else {
216            return false;
217        }
218    }
219}
220