1 /*
2 * Licensed to the Apache Software Foundation (ASF) under one or more
3 * contributor license agreements. See the NOTICE file distributed with
4 * this work for additional information regarding copyright ownership.
5 * The ASF licenses this file to You under the Apache License, Version 2.0
6 * (the "License"); you may not use this file except in compliance with
7 * the License. You may obtain a copy of the License at
8 *
9 * https://www.apache.org/licenses/LICENSE-2.0
10 *
11 * Unless required by applicable law or agreed to in writing, software
12 * distributed under the License is distributed on an "AS IS" BASIS,
13 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14 * See the License for the specific language governing permissions and
15 * limitations under the License.
16 */
17
18 package org.apache.commons.xml.secure;
19
20 import java.util.Objects;
21 import java.util.Properties;
22 import java.util.function.Supplier;
23
24 import javax.xml.transform.Source;
25 import javax.xml.transform.Templates;
26 import javax.xml.transform.Transformer;
27 import javax.xml.transform.TransformerConfigurationException;
28 import javax.xml.transform.URIResolver;
29
30 /**
31 * {@link Templates} wrapper whose only purpose is to return a {@link SecureTransformer} from {@link Templates#newTransformer()}, with the factory's
32 * compile-time {@link URIResolver} pre-installed.
33 * <p>
34 * Both Apache Xalan 2.7 and stock-JDK XSLTC fail to propagate the factory's URIResolver through {@code Templates.newTransformer()}: the produced runtime
35 * Transformer has a null URIResolver unless the caller sets one, leaving runtime {@code document()} calls unguarded. Snapshotting the resolver at compile time
36 * and restoring it onto the runtime Transformer matches the JAXP-conformant intuition that the factory's resolver is the default for any Transformer the
37 * factory ultimately produces.
38 * </p>
39 */
40 final class SecureTemplates implements Templates {
41
42 private final Templates delegate;
43
44 /**
45 * Compile-time URIResolver snapshot; the underlying implementation does not propagate the factory's resolver onto Transformers obtained from Templates.
46 */
47 private final URIResolver uriResolver;
48
49 /**
50 * Empty-{@link Source} supplier for the produced Transformer's floor; {@code null} means the default empty DOM.
51 */
52 private final Supplier<Source> emptySource;
53
54 /**
55 * Snapshot of the factory's {@value SecureSAXParserFactory#OVERRIDE_DEFAULT_PARSER} outcome, carried onto every produced Transformer and self-provisioned
56 * filter reader.
57 */
58 final boolean overrideDefaultParser;
59
60 /**
61 * Constructs a new instance.
62 *
63 * @param delegate the delegate to wrap; must not be {@code null}.
64 * @param uriResolver the compile-time URIResolver snapshot to restore onto Transformers produced from the compiled Templates; may be {@code null}.
65 * @param emptySource the empty-{@link Source} supplier for the produced Transformers.
66 * @param overrideDefaultParser whether the produced Transformers' source rewrites should use the pluggable parser lookup instead of the platform's built-in parser.
67 * @throws NullPointerException if {@code delegate} is {@code null}.
68 */
69 SecureTemplates(final Templates delegate, final URIResolver uriResolver, final Supplier<Source> emptySource, final boolean overrideDefaultParser) {
70 this.delegate = Objects.requireNonNull(delegate, "delegate");
71 this.uriResolver = uriResolver;
72 this.emptySource = emptySource;
73 this.overrideDefaultParser = overrideDefaultParser;
74 }
75
76 /**
77 * Gets the wrapped implementation Templates, for factory methods whose implementations cast {@code newTransformer()} to their own type.
78 *
79 * @return the wrapped {@link Templates} implementation.
80 */
81 Templates getDelegate() {
82 return delegate;
83 }
84
85 @Override
86 public Properties getOutputProperties() {
87 return delegate.getOutputProperties();
88 }
89
90 @Override
91 public Transformer newTransformer() throws TransformerConfigurationException {
92 final Transformer transformer = delegate.newTransformer();
93 return transformer != null ? new SecureTransformer(transformer, uriResolver, emptySource, overrideDefaultParser) : null;
94 }
95 }