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.beanutils2.bugs;
19  
20  import static org.junit.jupiter.api.Assertions.assertEquals;
21  import static org.junit.jupiter.api.Assertions.assertInstanceOf;
22  import static org.junit.jupiter.api.Assertions.assertNotNull;
23  import static org.junit.jupiter.api.Assertions.assertThrows;
24  
25  import org.apache.commons.beanutils2.BeanUtilsBean;
26  import org.apache.commons.beanutils2.PropertyUtilsBean;
27  import org.apache.commons.beanutils2.SuppressPropertiesBeanIntrospector;
28  import org.apache.commons.beanutils2.TestEnum;
29  import org.junit.jupiter.api.Test;
30  
31  public class EnumDeclaringClassTest {
32  
33      public static class Fixture {
34  
35          String name = "default";
36          TestEnum testEnum = TestEnum.A;
37  
38          public String getName() {
39              return name;
40          }
41  
42          public TestEnum getTestEnum() {
43              return testEnum;
44          }
45  
46          public void setName(final String name) {
47              this.name = name;
48          }
49  
50          public void setTestEnum(final TestEnum day) {
51              this.testEnum = day;
52          }
53      }
54  
55      /**
56       * Allow opt-out to make your app less secure but allow access to "declaringClass".
57       */
58      @Test
59      public void testAllowAccessToClassPropertyFromBeanUtilsBean() throws ReflectiveOperationException {
60          final BeanUtilsBean bub = new BeanUtilsBean();
61          final PropertyUtilsBean propertyUtilsBean = bub.getPropertyUtils();
62          propertyUtilsBean.removeBeanIntrospector(SuppressPropertiesBeanIntrospector.SUPPRESS_DECLARING_CLASS);
63          final Fixture fixture = new Fixture();
64          final String string = bub.getProperty(fixture, "testEnum.declaringClass");
65          assertEquals(TestEnum.class.getName(), string);
66          final Class<TestEnum> teClass = assertInstanceOf(Class.class, propertyUtilsBean.getNestedProperty(fixture, "testEnum.declaringClass"));
67          final ClassLoader classLoader = teClass.getClassLoader();
68          assertNotNull(classLoader);
69          assertNotNull(bub.getProperty(fixture, "testEnum.declaringClass.classLoader"));
70          assertInstanceOf(ClassLoader.class, propertyUtilsBean.getNestedProperty(fixture, "testEnum.declaringClass.classLoader"));
71      }
72  
73      /**
74       * Allow opt-out to make your app less secure but allow access to "declaringClass".
75       */
76      @Test
77      public void testAllowAccessToClassPropertyFromPropertyUtilsBean() throws ReflectiveOperationException {
78          final PropertyUtilsBean propertyUtilsBean = new PropertyUtilsBean();
79          propertyUtilsBean.removeBeanIntrospector(SuppressPropertiesBeanIntrospector.SUPPRESS_DECLARING_CLASS);
80          final Fixture fixture = new Fixture();
81          final Object cls = propertyUtilsBean.getNestedProperty(fixture, "testEnum.declaringClass");
82          final Class<TestEnum> teClass = assertInstanceOf(Class.class, cls);
83          final ClassLoader classLoader = teClass.getClassLoader();
84          assertNotNull(classLoader);
85          assertInstanceOf(ClassLoader.class, propertyUtilsBean.getNestedProperty(fixture, "testEnum.declaringClass.classLoader"));
86      }
87  
88      /**
89       * By default opt-in to security that does not allow access to "declaringClass".
90       */
91      @Test
92      public void testSuppressClassPropertyByDefaultFromBeanUtilsBean() throws ReflectiveOperationException {
93          final Fixture fixture = new Fixture();
94          final BeanUtilsBean bub = new BeanUtilsBean();
95          assertThrows(NoSuchMethodException.class, () -> bub.getProperty(fixture, "testEnum.declaringClass.classLoader"));
96          assertThrows(NoSuchMethodException.class, () -> bub.getPropertyUtils().getNestedProperty(fixture, "testEnum.declaringClass.classLoader"));
97      }
98  
99      /**
100      * By default opt-in to security that does not allow access to "declaringClass".
101      */
102     @Test
103     public void testSuppressClassPropertyByDefaultFromPropertyUtilsBean() throws ReflectiveOperationException {
104         final Fixture fixture = new Fixture();
105         final PropertyUtilsBean propertyUtilsBean = new PropertyUtilsBean();
106         assertThrows(NoSuchMethodException.class, () -> propertyUtilsBean.getNestedProperty(fixture, "testEnum.declaringClass.classLoader"));
107     }
108 }