View Javadoc
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 static org.junit.jupiter.api.Assertions.assertNotNull;
21  import static org.junit.jupiter.api.Assertions.assertThrows;
22  import static org.junit.jupiter.api.Assertions.assertTrue;
23  
24  import javax.xml.parsers.DocumentBuilder;
25  import javax.xml.parsers.DocumentBuilderFactory;
26  import javax.xml.parsers.ParserConfigurationException;
27  import javax.xml.parsers.SAXParser;
28  import javax.xml.parsers.SAXParserFactory;
29  
30  import org.junit.jupiter.api.Test;
31  import org.xml.sax.SAXNotRecognizedException;
32  import org.xml.sax.SAXNotSupportedException;
33  
34  /**
35   * Verifies that an implementation which does not honor the required secure-processing feature surfaces {@link IllegalStateException} with a message naming the
36   * class.
37   */
38  class UnsupportedXmlImplementationTest {
39  
40      /**
41       * A stand-in factory that rejects the secure-processing feature, like a JAXP implementation that does not recognize it.
42       */
43      public static final class FakeDocumentBuilderFactory extends DocumentBuilderFactory {
44  
45          @Override
46          public Object getAttribute(final String name) {
47              return null;
48          }
49  
50          @Override
51          public boolean getFeature(final String name) {
52              return false;
53          }
54  
55          /**
56           * Always throws {@link UnsupportedOperationException}.
57           *
58           * @throws UnsupportedOperationException Thrown on every invocation.
59           */
60          @Override
61          public DocumentBuilder newDocumentBuilder() {
62              throw new UnsupportedOperationException();
63          }
64  
65          @Override
66          public void setAttribute(final String name, final Object value) {
67              // no-op
68          }
69  
70          /**
71           * Always throws {@link ParserConfigurationException}.
72           *
73           * @throws ParserConfigurationException Thrown on every invocation.
74           */
75          @Override
76          public void setFeature(final String name, final boolean value) throws ParserConfigurationException {
77              throw new ParserConfigurationException("feature not recognized: " + name);
78          }
79      }
80  
81      /**
82       * A stand-in SAX factory that rejects the secure-processing feature, like a JAXP implementation that does not recognize it.
83       */
84      public static final class FakeSAXParserFactory extends SAXParserFactory {
85  
86          /**
87           * Always throws {@link SAXNotSupportedException}.
88           *
89           * @throws SAXNotSupportedException Thrown on every invocation.
90           */
91          @Override
92          public boolean getFeature(final String name) throws SAXNotSupportedException {
93              throw new SAXNotSupportedException("feature not recognized: " + name);
94          }
95  
96          /**
97           * Always throws {@link UnsupportedOperationException}.
98           *
99           * @throws UnsupportedOperationException Thrown on every invocation.
100          */
101         @Override
102         public SAXParser newSAXParser() {
103             throw new UnsupportedOperationException();
104         }
105 
106         /**
107          * Always throws {@link SAXNotRecognizedException}.
108          *
109          * @throws SAXNotRecognizedException Thrown on every invocation.
110          */
111         @Override
112         public void setFeature(final String name, final boolean value) throws SAXNotRecognizedException {
113             throw new SAXNotRecognizedException("feature not recognized: " + name);
114         }
115     }
116 
117     @Test
118     void secureRejectsUnsecurableFactory() {
119         final IllegalStateException thrown = assertThrows(
120                 IllegalStateException.class,
121                 () -> SecureDocumentBuilderFactory.secure(new FakeDocumentBuilderFactory()));
122         assertNotNull(thrown.getMessage());
123         assertTrue(thrown.getMessage().contains(FakeDocumentBuilderFactory.class.getName()),
124                 "Exception message must name the unsupported class: " + thrown.getMessage());
125     }
126 
127     @Test
128     void secureRejectsUnsecurableSaxFactory() {
129         final IllegalStateException thrown = assertThrows(
130                 IllegalStateException.class,
131                 () -> SecureSAXParserFactory.secure(new FakeSAXParserFactory()));
132         assertNotNull(thrown.getMessage());
133         assertTrue(thrown.getMessage().contains(FakeSAXParserFactory.class.getName()),
134                 "Exception message must name the unsupported class: " + thrown.getMessage());
135     }
136 }