From cf2429b0f0ce2a5278bdc2556663caf6cf0b0cae Mon Sep 17 00:00:00 2001 From: Juergen Hoeller Date: Wed, 15 Sep 2021 15:30:25 +0200 Subject: [PATCH] Remove support for deprecated Java SecurityManager (-> JDK 17 build compatibility) Includes hard JDK 9+ API dependency in CGLIB ReflectUtils (Lookup.defineClass) and removal of OutputStream spy proxy usage (avoiding invalid Mockito proxy on JDK 17) Closes gh-26901 --- spring-beans/spring-beans.gradle | 3 +- .../beans/BeanWrapperImpl.java | 69 +-- .../config/ConfigurableBeanFactory.java | 10 +- .../AbstractAutowireCapableBeanFactory.java | 82 +-- .../factory/support/AbstractBeanFactory.java | 64 +-- .../factory/support/ConstructorResolver.java | 34 +- .../support/DefaultListableBeanFactory.java | 36 +- .../support/DisposableBeanAdapter.java | 53 +- .../support/FactoryBeanRegistrySupport.java | 38 +- .../support/SecurityContextProvider.java | 35 -- .../support/SimpleInstantiationStrategy.java | 30 +- .../SimpleSecurityContextProvider.java | 62 --- .../DefaultListableBeanFactoryTests.java | 54 -- .../security/CallbacksSecurityTests.java | 479 ------------------ .../security/support/ConstructorBean.java | 30 -- .../security/support/CustomCallbackBean.java | 30 -- .../security/support/CustomFactoryBean.java | 44 -- .../support/security/support/DestroyBean.java | 29 -- .../support/security/support/FactoryBean.java | 36 -- .../support/security/support/InitBean.java | 29 -- .../security/support/PropertyBean.java | 30 -- .../propertyeditors/CustomEditorTests.java | 2 +- .../ApplicationContextAwareProcessor.java | 23 +- .../support/ResourceBundleMessageSource.java | 36 +- .../ApplicationContextExpressionTests.java | 39 -- ...onmentSecurityManagerIntegrationTests.java | 119 ----- .../jmx/support/JmxUtilsTests.java | 31 +- .../support/MBeanServerFactoryBeanTests.java | 9 +- .../jndi/JndiLocatorDelegateTests.java | 52 -- .../springframework/util/MBeanTestUtils.java | 9 +- .../cglib/core/ReflectUtils.java | 100 +--- .../core/env/AbstractEnvironment.java | 48 +- .../core/env/ConfigurableEnvironment.java | 18 +- .../core/env/ReadOnlySystemAttributesMap.java | 123 ----- .../env/SystemEnvironmentPropertySource.java | 18 +- .../AbstractRecursiveAnnotationVisitor.java | 5 +- .../AnnotationAttributesReadingVisitor.java | 4 +- .../springframework/util/ReflectionUtils.java | 18 +- .../core/env/StandardEnvironmentTests.java | 105 +--- .../SystemEnvironmentPropertySourceTests.java | 31 +- .../util/StreamUtilsTests.java | 22 +- .../testfixture/env/EnvironmentTestUtils.java | 92 ---- .../http/MockHttpOutputMessage.java | 6 +- .../FormHttpMessageConverterTests.java | 7 +- .../StringHttpMessageConverterTests.java | 4 +- ...pingJackson2HttpMessageConverterTests.java | 5 +- .../ServletRequestAttributesTests.java | 22 +- 47 files changed, 147 insertions(+), 2078 deletions(-) delete mode 100644 spring-beans/src/main/java/org/springframework/beans/factory/support/SecurityContextProvider.java delete mode 100644 spring-beans/src/main/java/org/springframework/beans/factory/support/SimpleSecurityContextProvider.java delete mode 100644 spring-beans/src/test/java/org/springframework/beans/factory/support/security/CallbacksSecurityTests.java delete mode 100644 spring-beans/src/test/java/org/springframework/beans/factory/support/security/support/ConstructorBean.java delete mode 100644 spring-beans/src/test/java/org/springframework/beans/factory/support/security/support/CustomCallbackBean.java delete mode 100644 spring-beans/src/test/java/org/springframework/beans/factory/support/security/support/CustomFactoryBean.java delete mode 100644 spring-beans/src/test/java/org/springframework/beans/factory/support/security/support/DestroyBean.java delete mode 100644 spring-beans/src/test/java/org/springframework/beans/factory/support/security/support/FactoryBean.java delete mode 100644 spring-beans/src/test/java/org/springframework/beans/factory/support/security/support/InitBean.java delete mode 100644 spring-beans/src/test/java/org/springframework/beans/factory/support/security/support/PropertyBean.java delete mode 100644 spring-context/src/test/java/org/springframework/context/support/EnvironmentSecurityManagerIntegrationTests.java delete mode 100644 spring-context/src/test/java/org/springframework/jndi/JndiLocatorDelegateTests.java delete mode 100644 spring-core/src/main/java/org/springframework/core/env/ReadOnlySystemAttributesMap.java delete mode 100644 spring-core/src/testFixtures/java/org/springframework/core/testfixture/env/EnvironmentTestUtils.java diff --git a/spring-beans/spring-beans.gradle b/spring-beans/spring-beans.gradle index e3f6f73b76..bf5fad779f 100644 --- a/spring-beans/spring-beans.gradle +++ b/spring-beans/spring-beans.gradle @@ -23,7 +23,8 @@ sourceSets { } compileGroovy { - options.compilerArgs += "-Werror" + // Groovy generates Java code with "new Boolean" usage which is deprecated on JDK 17 + // options.compilerArgs += "-Werror" } // This module also builds Kotlin code and the compileKotlin task naturally depends on diff --git a/spring-beans/src/main/java/org/springframework/beans/BeanWrapperImpl.java b/spring-beans/src/main/java/org/springframework/beans/BeanWrapperImpl.java index c2fb1aca6f..df6ee2cede 100644 --- a/spring-beans/src/main/java/org/springframework/beans/BeanWrapperImpl.java +++ b/spring-beans/src/main/java/org/springframework/beans/BeanWrapperImpl.java @@ -1,5 +1,5 @@ /* - * Copyright 2002-2020 the original author or authors. + * Copyright 2002-2021 the original author or authors. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -18,11 +18,6 @@ package org.springframework.beans; import java.beans.PropertyDescriptor; import java.lang.reflect.Method; -import java.security.AccessControlContext; -import java.security.AccessController; -import java.security.PrivilegedAction; -import java.security.PrivilegedActionException; -import java.security.PrivilegedExceptionAction; import org.springframework.core.ResolvableType; import org.springframework.core.convert.Property; @@ -69,12 +64,6 @@ public class BeanWrapperImpl extends AbstractNestablePropertyAccessor implements @Nullable private CachedIntrospectionResults cachedIntrospectionResults; - /** - * The security context used for invoking the property methods. - */ - @Nullable - private AccessControlContext acc; - /** * Create a new empty BeanWrapperImpl. Wrapped instance needs to be set afterwards. @@ -131,7 +120,6 @@ public class BeanWrapperImpl extends AbstractNestablePropertyAccessor implements */ private BeanWrapperImpl(Object object, String nestedPath, BeanWrapperImpl parent) { super(object, nestedPath, parent); - setSecurityContext(parent.acc); } @@ -176,23 +164,6 @@ public class BeanWrapperImpl extends AbstractNestablePropertyAccessor implements return this.cachedIntrospectionResults; } - /** - * Set the security context used during the invocation of the wrapped instance methods. - * Can be null. - */ - public void setSecurityContext(@Nullable AccessControlContext acc) { - this.acc = acc; - } - - /** - * Return the security context used during the invocation of the wrapped instance methods. - * Can be null. - */ - @Nullable - public AccessControlContext getSecurityContext() { - return this.acc; - } - /** * Convert the given value for the specified property to the latter's type. @@ -290,23 +261,8 @@ public class BeanWrapperImpl extends AbstractNestablePropertyAccessor implements @Nullable public Object getValue() throws Exception { Method readMethod = this.pd.getReadMethod(); - if (System.getSecurityManager() != null) { - AccessController.doPrivileged((PrivilegedAction) () -> { - ReflectionUtils.makeAccessible(readMethod); - return null; - }); - try { - return AccessController.doPrivileged((PrivilegedExceptionAction) - () -> readMethod.invoke(getWrappedInstance(), (Object[]) null), acc); - } - catch (PrivilegedActionException pae) { - throw pae.getException(); - } - } - else { - ReflectionUtils.makeAccessible(readMethod); - return readMethod.invoke(getWrappedInstance(), (Object[]) null); - } + ReflectionUtils.makeAccessible(readMethod); + return readMethod.invoke(getWrappedInstance(), (Object[]) null); } @Override @@ -314,23 +270,8 @@ public class BeanWrapperImpl extends AbstractNestablePropertyAccessor implements Method writeMethod = (this.pd instanceof GenericTypeAwarePropertyDescriptor ? ((GenericTypeAwarePropertyDescriptor) this.pd).getWriteMethodForActualAccess() : this.pd.getWriteMethod()); - if (System.getSecurityManager() != null) { - AccessController.doPrivileged((PrivilegedAction) () -> { - ReflectionUtils.makeAccessible(writeMethod); - return null; - }); - try { - AccessController.doPrivileged((PrivilegedExceptionAction) - () -> writeMethod.invoke(getWrappedInstance(), value), acc); - } - catch (PrivilegedActionException ex) { - throw ex.getException(); - } - } - else { - ReflectionUtils.makeAccessible(writeMethod); - writeMethod.invoke(getWrappedInstance(), value); - } + ReflectionUtils.makeAccessible(writeMethod); + writeMethod.invoke(getWrappedInstance(), value); } } diff --git a/spring-beans/src/main/java/org/springframework/beans/factory/config/ConfigurableBeanFactory.java b/spring-beans/src/main/java/org/springframework/beans/factory/config/ConfigurableBeanFactory.java index 81f4d87601..09460499e2 100644 --- a/spring-beans/src/main/java/org/springframework/beans/factory/config/ConfigurableBeanFactory.java +++ b/spring-beans/src/main/java/org/springframework/beans/factory/config/ConfigurableBeanFactory.java @@ -1,5 +1,5 @@ /* - * Copyright 2002-2020 the original author or authors. + * Copyright 2002-2021 the original author or authors. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -17,7 +17,6 @@ package org.springframework.beans.factory.config; import java.beans.PropertyEditor; -import java.security.AccessControlContext; import org.springframework.beans.PropertyEditorRegistrar; import org.springframework.beans.PropertyEditorRegistry; @@ -291,13 +290,6 @@ public interface ConfigurableBeanFactory extends HierarchicalBeanFactory, Single */ ApplicationStartup getApplicationStartup(); - /** - * Provides a security access control context relevant to this factory. - * @return the applicable AccessControlContext (never {@code null}) - * @since 3.0 - */ - AccessControlContext getAccessControlContext(); - /** * Copy all relevant configuration from the given other factory. *

Should include all standard configuration settings as well as diff --git a/spring-beans/src/main/java/org/springframework/beans/factory/support/AbstractAutowireCapableBeanFactory.java b/spring-beans/src/main/java/org/springframework/beans/factory/support/AbstractAutowireCapableBeanFactory.java index 02b27fe304..e1a2dbd1d3 100644 --- a/spring-beans/src/main/java/org/springframework/beans/factory/support/AbstractAutowireCapableBeanFactory.java +++ b/spring-beans/src/main/java/org/springframework/beans/factory/support/AbstractAutowireCapableBeanFactory.java @@ -21,10 +21,6 @@ import java.lang.reflect.Constructor; import java.lang.reflect.InvocationTargetException; import java.lang.reflect.Method; import java.lang.reflect.Modifier; -import java.security.AccessController; -import java.security.PrivilegedAction; -import java.security.PrivilegedActionException; -import java.security.PrivilegedExceptionAction; import java.util.ArrayList; import java.util.Arrays; import java.util.Collection; @@ -387,15 +383,7 @@ public abstract class AbstractAutowireCapableBeanFactory extends AbstractBeanFac return autowireConstructor(beanClass.getName(), bd, null, null).getWrappedInstance(); } else { - Object bean; - if (System.getSecurityManager() != null) { - bean = AccessController.doPrivileged( - (PrivilegedAction) () -> getInstantiationStrategy().instantiate(bd, null, this), - getAccessControlContext()); - } - else { - bean = getInstantiationStrategy().instantiate(bd, null, this); - } + Object bean = getInstantiationStrategy().instantiate(bd, null, this); populateBean(beanClass.getName(), bd, new BeanWrapperImpl(bean)); return bean; } @@ -463,8 +451,7 @@ public abstract class AbstractAutowireCapableBeanFactory extends AbstractBeanFac @Override public void destroyBean(Object existingBean) { - new DisposableBeanAdapter( - existingBean, getBeanPostProcessorCache().destructionAware, getAccessControlContext()).destroy(); + new DisposableBeanAdapter(existingBean, getBeanPostProcessorCache().destructionAware).destroy(); } @@ -1316,15 +1303,7 @@ public abstract class AbstractAutowireCapableBeanFactory extends AbstractBeanFac */ protected BeanWrapper instantiateBean(String beanName, RootBeanDefinition mbd) { try { - Object beanInstance; - if (System.getSecurityManager() != null) { - beanInstance = AccessController.doPrivileged( - (PrivilegedAction) () -> getInstantiationStrategy().instantiate(mbd, beanName, this), - getAccessControlContext()); - } - else { - beanInstance = getInstantiationStrategy().instantiate(mbd, beanName, this); - } + Object beanInstance = getInstantiationStrategy().instantiate(mbd, beanName, this); BeanWrapper bw = new BeanWrapperImpl(beanInstance); initBeanWrapper(bw); return bw; @@ -1655,10 +1634,6 @@ public abstract class AbstractAutowireCapableBeanFactory extends AbstractBeanFac return; } - if (System.getSecurityManager() != null && bw instanceof BeanWrapperImpl) { - ((BeanWrapperImpl) bw).setSecurityContext(getAccessControlContext()); - } - MutablePropertyValues mpvs = null; List original; @@ -1781,15 +1756,7 @@ public abstract class AbstractAutowireCapableBeanFactory extends AbstractBeanFac * @see #applyBeanPostProcessorsAfterInitialization */ protected Object initializeBean(String beanName, Object bean, @Nullable RootBeanDefinition mbd) { - if (System.getSecurityManager() != null) { - AccessController.doPrivileged((PrivilegedAction) () -> { - invokeAwareMethods(beanName, bean); - return null; - }, getAccessControlContext()); - } - else { - invokeAwareMethods(beanName, bean); - } + invokeAwareMethods(beanName, bean); Object wrappedBean = bean; if (mbd == null || !mbd.isSynthetic()) { @@ -1848,20 +1815,7 @@ public abstract class AbstractAutowireCapableBeanFactory extends AbstractBeanFac if (logger.isTraceEnabled()) { logger.trace("Invoking afterPropertiesSet() on bean with name '" + beanName + "'"); } - if (System.getSecurityManager() != null) { - try { - AccessController.doPrivileged((PrivilegedExceptionAction) () -> { - ((InitializingBean) bean).afterPropertiesSet(); - return null; - }, getAccessControlContext()); - } - catch (PrivilegedActionException pae) { - throw pae.getException(); - } - } - else { - ((InitializingBean) bean).afterPropertiesSet(); - } + ((InitializingBean) bean).afterPropertiesSet(); } if (mbd != null && bean.getClass() != NullBean.class) { @@ -1910,28 +1864,12 @@ public abstract class AbstractAutowireCapableBeanFactory extends AbstractBeanFac } Method methodToInvoke = ClassUtils.getInterfaceMethodIfPossible(initMethod); - if (System.getSecurityManager() != null) { - AccessController.doPrivileged((PrivilegedAction) () -> { - ReflectionUtils.makeAccessible(methodToInvoke); - return null; - }); - try { - AccessController.doPrivileged((PrivilegedExceptionAction) - () -> methodToInvoke.invoke(bean), getAccessControlContext()); - } - catch (PrivilegedActionException pae) { - InvocationTargetException ex = (InvocationTargetException) pae.getException(); - throw ex.getTargetException(); - } + try { + ReflectionUtils.makeAccessible(methodToInvoke); + methodToInvoke.invoke(bean); } - else { - try { - ReflectionUtils.makeAccessible(methodToInvoke); - methodToInvoke.invoke(bean); - } - catch (InvocationTargetException ex) { - throw ex.getTargetException(); - } + catch (InvocationTargetException ex) { + throw ex.getTargetException(); } } diff --git a/spring-beans/src/main/java/org/springframework/beans/factory/support/AbstractBeanFactory.java b/spring-beans/src/main/java/org/springframework/beans/factory/support/AbstractBeanFactory.java index 562c00fd55..91a0f6131c 100644 --- a/spring-beans/src/main/java/org/springframework/beans/factory/support/AbstractBeanFactory.java +++ b/spring-beans/src/main/java/org/springframework/beans/factory/support/AbstractBeanFactory.java @@ -1,5 +1,5 @@ /* - * Copyright 2002-2020 the original author or authors. + * Copyright 2002-2021 the original author or authors. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -17,11 +17,6 @@ package org.springframework.beans.factory.support; import java.beans.PropertyEditor; -import java.security.AccessControlContext; -import java.security.AccessController; -import java.security.PrivilegedAction; -import java.security.PrivilegedActionException; -import java.security.PrivilegedExceptionAction; import java.util.ArrayList; import java.util.Arrays; import java.util.Collection; @@ -166,10 +161,6 @@ public abstract class AbstractBeanFactory extends FactoryBeanRegistrySupport imp /** Map from scope identifier String to corresponding Scope. */ private final Map scopes = new LinkedHashMap<>(8); - /** Security context used when running with a SecurityManager. */ - @Nullable - private SecurityContextProvider securityContextProvider; - /** Map from bean name to merged RootBeanDefinition. */ private final Map mergedBeanDefinitions = new ConcurrentHashMap<>(256); @@ -495,17 +486,8 @@ public abstract class AbstractBeanFactory extends FactoryBeanRegistrySupport imp } if (isFactoryBean(beanName, mbd)) { FactoryBean fb = (FactoryBean) getBean(FACTORY_BEAN_PREFIX + beanName); - if (System.getSecurityManager() != null) { - return AccessController.doPrivileged( - (PrivilegedAction) () -> - ((fb instanceof SmartFactoryBean && ((SmartFactoryBean) fb).isPrototype()) || - !fb.isSingleton()), - getAccessControlContext()); - } - else { - return ((fb instanceof SmartFactoryBean && ((SmartFactoryBean) fb).isPrototype()) || - !fb.isSingleton()); - } + return ((fb instanceof SmartFactoryBean && ((SmartFactoryBean) fb).isPrototype()) || + !fb.isSingleton()); } else { return false; @@ -1054,15 +1036,6 @@ public abstract class AbstractBeanFactory extends FactoryBeanRegistrySupport imp return this.scopes.get(scopeName); } - /** - * Set the security context provider for this bean factory. If a security manager - * is set, interaction with the user code will be executed using the privileged - * of the provided security context. - */ - public void setSecurityContextProvider(SecurityContextProvider securityProvider) { - this.securityContextProvider = securityProvider; - } - @Override public void setApplicationStartup(ApplicationStartup applicationStartup) { Assert.notNull(applicationStartup, "applicationStartup should not be null"); @@ -1074,17 +1047,6 @@ public abstract class AbstractBeanFactory extends FactoryBeanRegistrySupport imp return this.applicationStartup; } - /** - * Delegate the creation of the access control context to the - * {@link #setSecurityContextProvider SecurityContextProvider}. - */ - @Override - public AccessControlContext getAccessControlContext() { - return (this.securityContextProvider != null ? - this.securityContextProvider.getAccessControlContext() : - AccessController.getContext()); - } - @Override public void copyConfigurationFrom(ConfigurableBeanFactory otherFactory) { Assert.notNull(otherFactory, "BeanFactory must not be null"); @@ -1099,7 +1061,6 @@ public abstract class AbstractBeanFactory extends FactoryBeanRegistrySupport imp this.typeConverter = otherAbstractFactory.typeConverter; this.beanPostProcessors.addAll(otherAbstractFactory.beanPostProcessors); this.scopes.putAll(otherAbstractFactory.scopes); - this.securityContextProvider = otherAbstractFactory.securityContextProvider; } else { setTypeConverter(otherFactory.getTypeConverter()); @@ -1222,7 +1183,7 @@ public abstract class AbstractBeanFactory extends FactoryBeanRegistrySupport imp */ protected void destroyBean(String beanName, Object bean, RootBeanDefinition mbd) { new DisposableBeanAdapter( - bean, beanName, mbd, getBeanPostProcessorCache().destructionAware, getAccessControlContext()).destroy(); + bean, beanName, mbd, getBeanPostProcessorCache().destructionAware).destroy(); } @Override @@ -1526,17 +1487,7 @@ public abstract class AbstractBeanFactory extends FactoryBeanRegistrySupport imp if (mbd.hasBeanClass()) { return mbd.getBeanClass(); } - if (System.getSecurityManager() != null) { - return AccessController.doPrivileged((PrivilegedExceptionAction>) - () -> doResolveBeanClass(mbd, typesToMatch), getAccessControlContext()); - } - else { - return doResolveBeanClass(mbd, typesToMatch); - } - } - catch (PrivilegedActionException pae) { - ClassNotFoundException ex = (ClassNotFoundException) pae.getException(); - throw new CannotLoadBeanClassException(mbd.getResourceDescription(), beanName, mbd.getBeanClassName(), ex); + return doResolveBeanClass(mbd, typesToMatch); } catch (ClassNotFoundException ex) { throw new CannotLoadBeanClassException(mbd.getResourceDescription(), beanName, mbd.getBeanClassName(), ex); @@ -1925,14 +1876,13 @@ public abstract class AbstractBeanFactory extends FactoryBeanRegistrySupport imp * @see #registerDependentBean */ protected void registerDisposableBeanIfNecessary(String beanName, Object bean, RootBeanDefinition mbd) { - AccessControlContext acc = (System.getSecurityManager() != null ? getAccessControlContext() : null); if (!mbd.isPrototype() && requiresDestruction(bean, mbd)) { if (mbd.isSingleton()) { // Register a DisposableBean implementation that performs all destruction // work for the given bean: DestructionAwareBeanPostProcessors, // DisposableBean interface, custom destroy method. registerDisposableBean(beanName, new DisposableBeanAdapter( - bean, beanName, mbd, getBeanPostProcessorCache().destructionAware, acc)); + bean, beanName, mbd, getBeanPostProcessorCache().destructionAware)); } else { // A bean with a custom scope... @@ -1941,7 +1891,7 @@ public abstract class AbstractBeanFactory extends FactoryBeanRegistrySupport imp throw new IllegalStateException("No Scope registered for scope name '" + mbd.getScope() + "'"); } scope.registerDestructionCallback(beanName, new DisposableBeanAdapter( - bean, beanName, mbd, getBeanPostProcessorCache().destructionAware, acc)); + bean, beanName, mbd, getBeanPostProcessorCache().destructionAware)); } } } diff --git a/spring-beans/src/main/java/org/springframework/beans/factory/support/ConstructorResolver.java b/spring-beans/src/main/java/org/springframework/beans/factory/support/ConstructorResolver.java index 36190c3b81..cfbc8a9926 100644 --- a/spring-beans/src/main/java/org/springframework/beans/factory/support/ConstructorResolver.java +++ b/spring-beans/src/main/java/org/springframework/beans/factory/support/ConstructorResolver.java @@ -22,8 +22,6 @@ import java.lang.reflect.Constructor; import java.lang.reflect.Executable; import java.lang.reflect.Method; import java.lang.reflect.Modifier; -import java.security.AccessController; -import java.security.PrivilegedAction; import java.util.ArrayDeque; import java.util.ArrayList; import java.util.Arrays; @@ -302,14 +300,7 @@ class ConstructorResolver { try { InstantiationStrategy strategy = this.beanFactory.getInstantiationStrategy(); - if (System.getSecurityManager() != null) { - return AccessController.doPrivileged((PrivilegedAction) () -> - strategy.instantiate(mbd, beanName, this.beanFactory, constructorToUse, argsToUse), - this.beanFactory.getAccessControlContext()); - } - else { - return strategy.instantiate(mbd, beanName, this.beanFactory, constructorToUse, argsToUse); - } + return strategy.instantiate(mbd, beanName, this.beanFactory, constructorToUse, argsToUse); } catch (Throwable ex) { throw new BeanCreationException(mbd.getResourceDescription(), beanName, @@ -365,15 +356,8 @@ class ConstructorResolver { * Called as the starting point for factory method determination. */ private Method[] getCandidateMethods(Class factoryClass, RootBeanDefinition mbd) { - if (System.getSecurityManager() != null) { - return AccessController.doPrivileged((PrivilegedAction) () -> - (mbd.isNonPublicAccessAllowed() ? - ReflectionUtils.getAllDeclaredMethods(factoryClass) : factoryClass.getMethods())); - } - else { - return (mbd.isNonPublicAccessAllowed() ? - ReflectionUtils.getAllDeclaredMethods(factoryClass) : factoryClass.getMethods()); - } + return (mbd.isNonPublicAccessAllowed() ? + ReflectionUtils.getAllDeclaredMethods(factoryClass) : factoryClass.getMethods()); } /** @@ -643,16 +627,8 @@ class ConstructorResolver { @Nullable Object factoryBean, Method factoryMethod, Object[] args) { try { - if (System.getSecurityManager() != null) { - return AccessController.doPrivileged((PrivilegedAction) () -> - this.beanFactory.getInstantiationStrategy().instantiate( - mbd, beanName, this.beanFactory, factoryBean, factoryMethod, args), - this.beanFactory.getAccessControlContext()); - } - else { - return this.beanFactory.getInstantiationStrategy().instantiate( - mbd, beanName, this.beanFactory, factoryBean, factoryMethod, args); - } + return this.beanFactory.getInstantiationStrategy().instantiate( + mbd, beanName, this.beanFactory, factoryBean, factoryMethod, args); } catch (Throwable ex) { throw new BeanCreationException(mbd.getResourceDescription(), beanName, diff --git a/spring-beans/src/main/java/org/springframework/beans/factory/support/DefaultListableBeanFactory.java b/spring-beans/src/main/java/org/springframework/beans/factory/support/DefaultListableBeanFactory.java index 048612fbed..a4f29b0ce8 100644 --- a/spring-beans/src/main/java/org/springframework/beans/factory/support/DefaultListableBeanFactory.java +++ b/spring-beans/src/main/java/org/springframework/beans/factory/support/DefaultListableBeanFactory.java @@ -1,5 +1,5 @@ /* - * Copyright 2002-2020 the original author or authors. + * Copyright 2002-2021 the original author or authors. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -25,8 +25,6 @@ import java.lang.annotation.Annotation; import java.lang.ref.Reference; import java.lang.ref.WeakReference; import java.lang.reflect.Method; -import java.security.AccessController; -import java.security.PrivilegedAction; import java.util.ArrayList; import java.util.Arrays; import java.util.Collection; @@ -296,15 +294,7 @@ public class DefaultListableBeanFactory extends AbstractAutowireCapableBeanFacto public void setAutowireCandidateResolver(AutowireCandidateResolver autowireCandidateResolver) { Assert.notNull(autowireCandidateResolver, "AutowireCandidateResolver must not be null"); if (autowireCandidateResolver instanceof BeanFactoryAware) { - if (System.getSecurityManager() != null) { - AccessController.doPrivileged((PrivilegedAction) () -> { - ((BeanFactoryAware) autowireCandidateResolver).setBeanFactory(this); - return null; - }, getAccessControlContext()); - } - else { - ((BeanFactoryAware) autowireCandidateResolver).setBeanFactory(this); - } + ((BeanFactoryAware) autowireCandidateResolver).setBeanFactory(this); } this.autowireCandidateResolver = autowireCandidateResolver; } @@ -925,16 +915,8 @@ public class DefaultListableBeanFactory extends AbstractAutowireCapableBeanFacto Object bean = getBean(FACTORY_BEAN_PREFIX + beanName); if (bean instanceof FactoryBean) { FactoryBean factory = (FactoryBean) bean; - boolean isEagerInit; - if (System.getSecurityManager() != null && factory instanceof SmartFactoryBean) { - isEagerInit = AccessController.doPrivileged( - (PrivilegedAction) ((SmartFactoryBean) factory)::isEagerInit, - getAccessControlContext()); - } - else { - isEagerInit = (factory instanceof SmartFactoryBean && - ((SmartFactoryBean) factory).isEagerInit()); - } + boolean isEagerInit = (factory instanceof SmartFactoryBean && + ((SmartFactoryBean) factory).isEagerInit()); if (isEagerInit) { getBean(beanName); } @@ -953,15 +935,7 @@ public class DefaultListableBeanFactory extends AbstractAutowireCapableBeanFacto StartupStep smartInitialize = this.getApplicationStartup().start("spring.beans.smart-initialize") .tag("beanName", beanName); SmartInitializingSingleton smartSingleton = (SmartInitializingSingleton) singletonInstance; - if (System.getSecurityManager() != null) { - AccessController.doPrivileged((PrivilegedAction) () -> { - smartSingleton.afterSingletonsInstantiated(); - return null; - }, getAccessControlContext()); - } - else { - smartSingleton.afterSingletonsInstantiated(); - } + smartSingleton.afterSingletonsInstantiated(); smartInitialize.end(); } } diff --git a/spring-beans/src/main/java/org/springframework/beans/factory/support/DisposableBeanAdapter.java b/spring-beans/src/main/java/org/springframework/beans/factory/support/DisposableBeanAdapter.java index 3e779752a9..3d8327a12f 100644 --- a/spring-beans/src/main/java/org/springframework/beans/factory/support/DisposableBeanAdapter.java +++ b/spring-beans/src/main/java/org/springframework/beans/factory/support/DisposableBeanAdapter.java @@ -19,11 +19,6 @@ package org.springframework.beans.factory.support; import java.io.Serializable; import java.lang.reflect.InvocationTargetException; import java.lang.reflect.Method; -import java.security.AccessControlContext; -import java.security.AccessController; -import java.security.PrivilegedAction; -import java.security.PrivilegedActionException; -import java.security.PrivilegedExceptionAction; import java.util.ArrayList; import java.util.List; @@ -76,9 +71,6 @@ class DisposableBeanAdapter implements DisposableBean, Runnable, Serializable { private final boolean nonPublicAccessAllowed; - @Nullable - private final AccessControlContext acc; - @Nullable private String destroyMethodName; @@ -98,7 +90,7 @@ class DisposableBeanAdapter implements DisposableBean, Runnable, Serializable { * (potentially DestructionAwareBeanPostProcessor), if any */ public DisposableBeanAdapter(Object bean, String beanName, RootBeanDefinition beanDefinition, - List postProcessors, @Nullable AccessControlContext acc) { + List postProcessors) { Assert.notNull(bean, "Disposable bean must not be null"); this.bean = bean; @@ -106,7 +98,6 @@ class DisposableBeanAdapter implements DisposableBean, Runnable, Serializable { this.invokeDisposableBean = (this.bean instanceof DisposableBean && !beanDefinition.isExternallyManagedDestroyMethod("destroy")); this.nonPublicAccessAllowed = beanDefinition.isNonPublicAccessAllowed(); - this.acc = acc; String destroyMethodName = inferDestroyMethodIfNecessary(bean, beanDefinition); if (destroyMethodName != null && !(this.invokeDisposableBean && "destroy".equals(destroyMethodName)) && !beanDefinition.isExternallyManagedDestroyMethod(destroyMethodName)) { @@ -143,15 +134,12 @@ class DisposableBeanAdapter implements DisposableBean, Runnable, Serializable { * @param postProcessors the List of BeanPostProcessors * (potentially DestructionAwareBeanPostProcessor), if any */ - public DisposableBeanAdapter( - Object bean, List postProcessors, AccessControlContext acc) { - + public DisposableBeanAdapter(Object bean, List postProcessors) { Assert.notNull(bean, "Disposable bean must not be null"); this.bean = bean; this.beanName = bean.getClass().getName(); this.invokeDisposableBean = (this.bean instanceof DisposableBean); this.nonPublicAccessAllowed = true; - this.acc = acc; this.beanPostProcessors = filterPostProcessors(postProcessors, bean); } @@ -166,7 +154,6 @@ class DisposableBeanAdapter implements DisposableBean, Runnable, Serializable { this.beanName = beanName; this.invokeDisposableBean = invokeDisposableBean; this.nonPublicAccessAllowed = nonPublicAccessAllowed; - this.acc = null; this.destroyMethodName = destroyMethodName; this.beanPostProcessors = postProcessors; } @@ -190,15 +177,7 @@ class DisposableBeanAdapter implements DisposableBean, Runnable, Serializable { logger.trace("Invoking destroy() on bean with name '" + this.beanName + "'"); } try { - if (System.getSecurityManager() != null) { - AccessController.doPrivileged((PrivilegedExceptionAction) () -> { - ((DisposableBean) this.bean).destroy(); - return null; - }, this.acc); - } - else { - ((DisposableBean) this.bean).destroy(); - } + ((DisposableBean) this.bean).destroy(); } catch (Throwable ex) { String msg = "Invocation of destroy method failed on bean with name '" + this.beanName + "'"; @@ -226,12 +205,7 @@ class DisposableBeanAdapter implements DisposableBean, Runnable, Serializable { @Nullable private Method determineDestroyMethod(String name) { try { - if (System.getSecurityManager() != null) { - return AccessController.doPrivileged((PrivilegedAction) () -> findDestroyMethod(name)); - } - else { - return findDestroyMethod(name); - } + return findDestroyMethod(name); } catch (IllegalArgumentException ex) { throw new BeanDefinitionValidationException("Could not find unique destroy method on bean with name '" + @@ -263,23 +237,8 @@ class DisposableBeanAdapter implements DisposableBean, Runnable, Serializable { "' on bean with name '" + this.beanName + "'"); } try { - if (System.getSecurityManager() != null) { - AccessController.doPrivileged((PrivilegedAction) () -> { - ReflectionUtils.makeAccessible(destroyMethod); - return null; - }); - try { - AccessController.doPrivileged((PrivilegedExceptionAction) () -> - destroyMethod.invoke(this.bean, args), this.acc); - } - catch (PrivilegedActionException pax) { - throw (InvocationTargetException) pax.getException(); - } - } - else { - ReflectionUtils.makeAccessible(destroyMethod); - destroyMethod.invoke(this.bean, args); - } + ReflectionUtils.makeAccessible(destroyMethod); + destroyMethod.invoke(this.bean, args); } catch (InvocationTargetException ex) { String msg = "Destroy method '" + this.destroyMethodName + "' on bean with name '" + diff --git a/spring-beans/src/main/java/org/springframework/beans/factory/support/FactoryBeanRegistrySupport.java b/spring-beans/src/main/java/org/springframework/beans/factory/support/FactoryBeanRegistrySupport.java index fc689a7aec..6750414847 100644 --- a/spring-beans/src/main/java/org/springframework/beans/factory/support/FactoryBeanRegistrySupport.java +++ b/spring-beans/src/main/java/org/springframework/beans/factory/support/FactoryBeanRegistrySupport.java @@ -1,5 +1,5 @@ /* - * Copyright 2002-2020 the original author or authors. + * Copyright 2002-2021 the original author or authors. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -16,11 +16,6 @@ package org.springframework.beans.factory.support; -import java.security.AccessControlContext; -import java.security.AccessController; -import java.security.PrivilegedAction; -import java.security.PrivilegedActionException; -import java.security.PrivilegedExceptionAction; import java.util.Map; import java.util.concurrent.ConcurrentHashMap; @@ -56,13 +51,7 @@ public abstract class FactoryBeanRegistrySupport extends DefaultSingletonBeanReg @Nullable protected Class getTypeForFactoryBean(FactoryBean factoryBean) { try { - if (System.getSecurityManager() != null) { - return AccessController.doPrivileged( - (PrivilegedAction>) factoryBean::getObjectType, getAccessControlContext()); - } - else { - return factoryBean.getObjectType(); - } + return factoryBean.getObjectType(); } catch (Throwable ex) { // Thrown from the FactoryBean's getObjectType implementation. @@ -156,18 +145,7 @@ public abstract class FactoryBeanRegistrySupport extends DefaultSingletonBeanReg private Object doGetObjectFromFactoryBean(FactoryBean factory, String beanName) throws BeanCreationException { Object object; try { - if (System.getSecurityManager() != null) { - AccessControlContext acc = getAccessControlContext(); - try { - object = AccessController.doPrivileged((PrivilegedExceptionAction) factory::getObject, acc); - } - catch (PrivilegedActionException pae) { - throw pae.getException(); - } - } - else { - object = factory.getObject(); - } + object = factory.getObject(); } catch (FactoryBeanNotInitializedException ex) { throw new BeanCurrentlyInCreationException(beanName, ex.toString()); @@ -239,14 +217,4 @@ public abstract class FactoryBeanRegistrySupport extends DefaultSingletonBeanReg } } - /** - * Return the security context for this bean factory. If a security manager - * is set, interaction with the user code will be executed using the privileged - * of the security context returned by this method. - * @see AccessController#getContext() - */ - protected AccessControlContext getAccessControlContext() { - return AccessController.getContext(); - } - } diff --git a/spring-beans/src/main/java/org/springframework/beans/factory/support/SecurityContextProvider.java b/spring-beans/src/main/java/org/springframework/beans/factory/support/SecurityContextProvider.java deleted file mode 100644 index d2f70c46eb..0000000000 --- a/spring-beans/src/main/java/org/springframework/beans/factory/support/SecurityContextProvider.java +++ /dev/null @@ -1,35 +0,0 @@ -/* - * Copyright 2002-2012 the original author or authors. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * https://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package org.springframework.beans.factory.support; - -import java.security.AccessControlContext; - -/** - * Provider of the security context of the code running inside the bean factory. - * - * @author Costin Leau - * @since 3.0 - */ -public interface SecurityContextProvider { - - /** - * Provides a security access control context relevant to a bean factory. - * @return bean factory security control context - */ - AccessControlContext getAccessControlContext(); - -} diff --git a/spring-beans/src/main/java/org/springframework/beans/factory/support/SimpleInstantiationStrategy.java b/spring-beans/src/main/java/org/springframework/beans/factory/support/SimpleInstantiationStrategy.java index 0b05cf50cc..0ae2e3a688 100644 --- a/spring-beans/src/main/java/org/springframework/beans/factory/support/SimpleInstantiationStrategy.java +++ b/spring-beans/src/main/java/org/springframework/beans/factory/support/SimpleInstantiationStrategy.java @@ -1,5 +1,5 @@ /* - * Copyright 2002-2018 the original author or authors. + * Copyright 2002-2021 the original author or authors. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -19,9 +19,6 @@ package org.springframework.beans.factory.support; import java.lang.reflect.Constructor; import java.lang.reflect.InvocationTargetException; import java.lang.reflect.Method; -import java.security.AccessController; -import java.security.PrivilegedAction; -import java.security.PrivilegedExceptionAction; import org.springframework.beans.BeanInstantiationException; import org.springframework.beans.BeanUtils; @@ -70,13 +67,7 @@ public class SimpleInstantiationStrategy implements InstantiationStrategy { throw new BeanInstantiationException(clazz, "Specified class is an interface"); } try { - if (System.getSecurityManager() != null) { - constructorToUse = AccessController.doPrivileged( - (PrivilegedExceptionAction>) clazz::getDeclaredConstructor); - } - else { - constructorToUse = clazz.getDeclaredConstructor(); - } + constructorToUse = clazz.getDeclaredConstructor(); bd.resolvedConstructorOrFactoryMethod = constructorToUse; } catch (Throwable ex) { @@ -107,13 +98,6 @@ public class SimpleInstantiationStrategy implements InstantiationStrategy { final Constructor ctor, Object... args) { if (!bd.hasMethodOverrides()) { - if (System.getSecurityManager() != null) { - // use own privileged to change accessibility (when security is on) - AccessController.doPrivileged((PrivilegedAction) () -> { - ReflectionUtils.makeAccessible(ctor); - return null; - }); - } return BeanUtils.instantiateClass(ctor, args); } else { @@ -138,15 +122,7 @@ public class SimpleInstantiationStrategy implements InstantiationStrategy { @Nullable Object factoryBean, final Method factoryMethod, Object... args) { try { - if (System.getSecurityManager() != null) { - AccessController.doPrivileged((PrivilegedAction) () -> { - ReflectionUtils.makeAccessible(factoryMethod); - return null; - }); - } - else { - ReflectionUtils.makeAccessible(factoryMethod); - } + ReflectionUtils.makeAccessible(factoryMethod); Method priorInvokedFactoryMethod = currentlyInvokedFactoryMethod.get(); try { diff --git a/spring-beans/src/main/java/org/springframework/beans/factory/support/SimpleSecurityContextProvider.java b/spring-beans/src/main/java/org/springframework/beans/factory/support/SimpleSecurityContextProvider.java deleted file mode 100644 index b28fbffa37..0000000000 --- a/spring-beans/src/main/java/org/springframework/beans/factory/support/SimpleSecurityContextProvider.java +++ /dev/null @@ -1,62 +0,0 @@ -/* - * Copyright 2002-2018 the original author or authors. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * https://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package org.springframework.beans.factory.support; - -import java.security.AccessControlContext; -import java.security.AccessController; - -import org.springframework.lang.Nullable; - -/** - * Simple {@link SecurityContextProvider} implementation. - * - * @author Costin Leau - * @since 3.0 - */ -public class SimpleSecurityContextProvider implements SecurityContextProvider { - - @Nullable - private final AccessControlContext acc; - - - /** - * Construct a new {@code SimpleSecurityContextProvider} instance. - *

The security context will be retrieved on each call from the current - * thread. - */ - public SimpleSecurityContextProvider() { - this(null); - } - - /** - * Construct a new {@code SimpleSecurityContextProvider} instance. - *

If the given control context is null, the security context will be - * retrieved on each call from the current thread. - * @param acc access control context (can be {@code null}) - * @see AccessController#getContext() - */ - public SimpleSecurityContextProvider(@Nullable AccessControlContext acc) { - this.acc = acc; - } - - - @Override - public AccessControlContext getAccessControlContext() { - return (this.acc != null ? this.acc : AccessController.getContext()); - } - -} diff --git a/spring-beans/src/test/java/org/springframework/beans/factory/DefaultListableBeanFactoryTests.java b/spring-beans/src/test/java/org/springframework/beans/factory/DefaultListableBeanFactoryTests.java index 8d6f823a75..2cb8d8a9cd 100644 --- a/spring-beans/src/test/java/org/springframework/beans/factory/DefaultListableBeanFactoryTests.java +++ b/spring-beans/src/test/java/org/springframework/beans/factory/DefaultListableBeanFactoryTests.java @@ -20,10 +20,6 @@ import java.io.Closeable; import java.io.Serializable; import java.lang.reflect.Field; import java.net.MalformedURLException; -import java.security.AccessControlContext; -import java.security.AccessController; -import java.security.Principal; -import java.security.PrivilegedAction; import java.text.NumberFormat; import java.text.ParseException; import java.util.Arrays; @@ -41,7 +37,6 @@ import java.util.stream.Collectors; import java.util.stream.IntStream; import javax.annotation.Priority; -import javax.security.auth.Subject; import org.junit.jupiter.api.Test; @@ -90,7 +85,6 @@ import org.springframework.core.convert.support.GenericConversionService; import org.springframework.core.io.Resource; import org.springframework.core.io.UrlResource; import org.springframework.core.testfixture.io.SerializationTestUtils; -import org.springframework.core.testfixture.security.TestPrincipal; import org.springframework.lang.Nullable; import org.springframework.util.StringValueResolver; @@ -2602,22 +2596,6 @@ class DefaultListableBeanFactoryTests { } } - @Test - @SuppressWarnings({ "unchecked", "rawtypes" }) - void initSecurityAwarePrototypeBean() { - RootBeanDefinition bd = new RootBeanDefinition(TestSecuredBean.class); - bd.setScope(BeanDefinition.SCOPE_PROTOTYPE); - bd.setInitMethodName("init"); - lbf.registerBeanDefinition("test", bd); - final Subject subject = new Subject(); - subject.getPrincipals().add(new TestPrincipal("user1")); - - TestSecuredBean bean = (TestSecuredBean) Subject.doAsPrivileged(subject, - (PrivilegedAction) () -> lbf.getBean("test"), null); - assertThat(bean).isNotNull(); - assertThat(bean.getUserName()).isEqualTo("user1"); - } - @Test void containsBeanReturnsTrueEvenForAbstractBeanDefinition() { lbf.registerBeanDefinition("abs", BeanDefinitionBuilder @@ -3058,37 +3036,6 @@ class DefaultListableBeanFactoryTests { } - @SuppressWarnings("unused") - private static class TestSecuredBean { - - private String userName; - - void init() { - AccessControlContext acc = AccessController.getContext(); - Subject subject = Subject.getSubject(acc); - if (subject == null) { - return; - } - setNameFromPrincipal(subject.getPrincipals()); - } - - private void setNameFromPrincipal(Set principals) { - if (principals == null) { - return; - } - for (Iterator it = principals.iterator(); it.hasNext();) { - Principal p = it.next(); - this.userName = p.getName(); - return; - } - } - - public String getUserName() { - return this.userName; - } - } - - @SuppressWarnings("unused") private static class KnowsIfInstantiated { @@ -3105,7 +3052,6 @@ class DefaultListableBeanFactoryTests { public KnowsIfInstantiated() { instantiated = true; } - } diff --git a/spring-beans/src/test/java/org/springframework/beans/factory/support/security/CallbacksSecurityTests.java b/spring-beans/src/test/java/org/springframework/beans/factory/support/security/CallbacksSecurityTests.java deleted file mode 100644 index 368e0b6647..0000000000 --- a/spring-beans/src/test/java/org/springframework/beans/factory/support/security/CallbacksSecurityTests.java +++ /dev/null @@ -1,479 +0,0 @@ -/* - * Copyright 2002-2020 the original author or authors. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * https://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package org.springframework.beans.factory.support.security; - -import java.lang.reflect.Method; -import java.net.URL; -import java.security.AccessControlContext; -import java.security.AccessController; -import java.security.Permissions; -import java.security.Policy; -import java.security.Principal; -import java.security.PrivilegedAction; -import java.security.PrivilegedExceptionAction; -import java.security.ProtectionDomain; -import java.util.PropertyPermission; -import java.util.Set; -import java.util.function.Consumer; - -import javax.security.auth.AuthPermission; -import javax.security.auth.Subject; - -import org.junit.jupiter.api.BeforeEach; -import org.junit.jupiter.api.Test; - -import org.springframework.beans.BeansException; -import org.springframework.beans.factory.BeanClassLoaderAware; -import org.springframework.beans.factory.BeanCreationException; -import org.springframework.beans.factory.BeanFactory; -import org.springframework.beans.factory.BeanFactoryAware; -import org.springframework.beans.factory.BeanNameAware; -import org.springframework.beans.factory.DisposableBean; -import org.springframework.beans.factory.InitializingBean; -import org.springframework.beans.factory.SmartFactoryBean; -import org.springframework.beans.factory.config.BeanDefinition; -import org.springframework.beans.factory.support.BeanDefinitionBuilder; -import org.springframework.beans.factory.support.DefaultListableBeanFactory; -import org.springframework.beans.factory.support.SecurityContextProvider; -import org.springframework.beans.factory.support.security.support.ConstructorBean; -import org.springframework.beans.factory.support.security.support.CustomCallbackBean; -import org.springframework.beans.factory.xml.XmlBeanDefinitionReader; -import org.springframework.core.NestedRuntimeException; -import org.springframework.core.io.DefaultResourceLoader; -import org.springframework.core.io.Resource; -import org.springframework.core.testfixture.security.TestPrincipal; - -import static org.assertj.core.api.Assertions.assertThat; -import static org.assertj.core.api.Assertions.assertThatExceptionOfType; - -/** - * Security test case. Checks whether the container uses its privileges for its - * internal work but does not leak them when touching/calling user code. - * - *

The first half of the test case checks that permissions are downgraded when - * calling user code while the second half that the caller code permission get - * through and Spring doesn't override the permission stack. - * - * @author Costin Leau - */ -public class CallbacksSecurityTests { - - private DefaultListableBeanFactory beanFactory; - private SecurityContextProvider provider; - - @SuppressWarnings("unused") - private static class NonPrivilegedBean { - - private String expectedName; - public static boolean destroyed = false; - - public NonPrivilegedBean(String expected) { - this.expectedName = expected; - checkCurrentContext(); - } - - public void init() { - checkCurrentContext(); - } - - public void destroy() { - checkCurrentContext(); - destroyed = true; - } - - public void setProperty(Object value) { - checkCurrentContext(); - } - - public Object getProperty() { - checkCurrentContext(); - return null; - } - - public void setListProperty(Object value) { - checkCurrentContext(); - } - - public Object getListProperty() { - checkCurrentContext(); - return null; - } - - private void checkCurrentContext() { - assertThat(getCurrentSubjectName()).isEqualTo(expectedName); - } - } - - @SuppressWarnings("unused") - private static class NonPrivilegedSpringCallbacksBean implements - InitializingBean, DisposableBean, BeanClassLoaderAware, - BeanFactoryAware, BeanNameAware { - - private String expectedName; - public static boolean destroyed = false; - - public NonPrivilegedSpringCallbacksBean(String expected) { - this.expectedName = expected; - checkCurrentContext(); - } - - @Override - public void afterPropertiesSet() { - checkCurrentContext(); - } - - @Override - public void destroy() { - checkCurrentContext(); - destroyed = true; - } - - @Override - public void setBeanName(String name) { - checkCurrentContext(); - } - - @Override - public void setBeanClassLoader(ClassLoader classLoader) { - checkCurrentContext(); - } - - @Override - public void setBeanFactory(BeanFactory beanFactory) - throws BeansException { - checkCurrentContext(); - } - - private void checkCurrentContext() { - assertThat(getCurrentSubjectName()).isEqualTo(expectedName); - } - } - - @SuppressWarnings({ "unused", "rawtypes" }) - private static class NonPrivilegedFactoryBean implements SmartFactoryBean { - private String expectedName; - - public NonPrivilegedFactoryBean(String expected) { - this.expectedName = expected; - checkCurrentContext(); - } - - @Override - public boolean isEagerInit() { - checkCurrentContext(); - return false; - } - - @Override - public boolean isPrototype() { - checkCurrentContext(); - return true; - } - - @Override - public Object getObject() throws Exception { - checkCurrentContext(); - return new Object(); - } - - @Override - public Class getObjectType() { - checkCurrentContext(); - return Object.class; - } - - @Override - public boolean isSingleton() { - checkCurrentContext(); - return false; - } - - private void checkCurrentContext() { - assertThat(getCurrentSubjectName()).isEqualTo(expectedName); - } - } - - @SuppressWarnings("unused") - private static class NonPrivilegedFactory { - - private final String expectedName; - - public NonPrivilegedFactory(String expected) { - this.expectedName = expected; - assertThat(getCurrentSubjectName()).isEqualTo(expectedName); - } - - public static Object makeStaticInstance(String expectedName) { - assertThat(getCurrentSubjectName()).isEqualTo(expectedName); - return new Object(); - } - - public Object makeInstance() { - assertThat(getCurrentSubjectName()).isEqualTo(expectedName); - return new Object(); - } - } - - private static String getCurrentSubjectName() { - final AccessControlContext acc = AccessController.getContext(); - - return AccessController.doPrivileged(new PrivilegedAction() { - - @Override - public String run() { - Subject subject = Subject.getSubject(acc); - if (subject == null) { - return null; - } - - Set principals = subject.getPrincipals(); - - if (principals == null) { - return null; - } - for (Principal p : principals) { - return p.getName(); - } - return null; - } - }); - } - - public CallbacksSecurityTests() { - // setup security - if (System.getSecurityManager() == null) { - Policy policy = Policy.getPolicy(); - URL policyURL = getClass() - .getResource( - "/org/springframework/beans/factory/support/security/policy.all"); - System.setProperty("java.security.policy", policyURL.toString()); - System.setProperty("policy.allowSystemProperty", "true"); - policy.refresh(); - - System.setSecurityManager(new SecurityManager()); - } - } - - @BeforeEach - public void setUp() throws Exception { - - final ProtectionDomain empty = new ProtectionDomain(null, - new Permissions()); - - provider = new SecurityContextProvider() { - private final AccessControlContext acc = new AccessControlContext( - new ProtectionDomain[] { empty }); - - @Override - public AccessControlContext getAccessControlContext() { - return acc; - } - }; - - DefaultResourceLoader drl = new DefaultResourceLoader(); - Resource config = drl - .getResource("/org/springframework/beans/factory/support/security/callbacks.xml"); - beanFactory = new DefaultListableBeanFactory(); - new XmlBeanDefinitionReader(beanFactory).loadBeanDefinitions(config); - beanFactory.setSecurityContextProvider(provider); - } - - @Test - public void testSecuritySanity() throws Exception { - AccessControlContext acc = provider.getAccessControlContext(); - assertThatExceptionOfType(SecurityException.class).as( - "Acc should not have any permissions").isThrownBy(() -> - acc.checkPermission(new PropertyPermission("*", "read"))); - - CustomCallbackBean bean = new CustomCallbackBean(); - Method method = bean.getClass().getMethod("destroy"); - method.setAccessible(true); - - assertThatExceptionOfType(Exception.class).isThrownBy(() -> - AccessController.doPrivileged((PrivilegedExceptionAction) () -> { - method.invoke(bean); - return null; - }, acc)); - - Class cl = ConstructorBean.class; - assertThatExceptionOfType(Exception.class).isThrownBy(() -> - AccessController.doPrivileged((PrivilegedExceptionAction) () -> - cl.newInstance(), acc)); - } - - @Test - public void testSpringInitBean() throws Exception { - assertThatExceptionOfType(BeanCreationException.class).isThrownBy(() -> - beanFactory.getBean("spring-init")) - .withCauseInstanceOf(SecurityException.class); - } - - @Test - public void testCustomInitBean() throws Exception { - assertThatExceptionOfType(BeanCreationException.class).isThrownBy(() -> - beanFactory.getBean("custom-init")) - .withCauseInstanceOf(SecurityException.class); - } - - @Test - public void testSpringDestroyBean() throws Exception { - beanFactory.getBean("spring-destroy"); - beanFactory.destroySingletons(); - assertThat(System.getProperty("security.destroy")).isNull(); - } - - @Test - public void testCustomDestroyBean() throws Exception { - beanFactory.getBean("custom-destroy"); - beanFactory.destroySingletons(); - assertThat(System.getProperty("security.destroy")).isNull(); - } - - @Test - public void testCustomFactoryObject() throws Exception { - assertThatExceptionOfType(BeanCreationException.class).isThrownBy(() -> - beanFactory.getBean("spring-factory")) - .withCauseInstanceOf(SecurityException.class); - } - - @Test - public void testCustomFactoryType() throws Exception { - assertThat(beanFactory.getType("spring-factory")).isNull(); - assertThat(System.getProperty("factory.object.type")).isNull(); - } - - @Test - public void testCustomStaticFactoryMethod() throws Exception { - assertThatExceptionOfType(BeanCreationException.class).isThrownBy(() -> - beanFactory.getBean("custom-static-factory-method")) - .satisfies(mostSpecificCauseOf(SecurityException.class)); - } - - @Test - public void testCustomInstanceFactoryMethod() throws Exception { - assertThatExceptionOfType(BeanCreationException.class).isThrownBy(() -> - beanFactory.getBean("custom-factory-method")) - .satisfies(mostSpecificCauseOf(SecurityException.class)); - } - - @Test - public void testTrustedFactoryMethod() throws Exception { - assertThatExceptionOfType(BeanCreationException.class).isThrownBy(() -> - beanFactory.getBean("privileged-static-factory-method")) - .satisfies(mostSpecificCauseOf(SecurityException.class)); - } - - @Test - public void testConstructor() throws Exception { - assertThatExceptionOfType(BeanCreationException.class).isThrownBy(() -> - beanFactory.getBean("constructor")) - .satisfies(mostSpecificCauseOf(SecurityException.class)); - } - - @Test - public void testContainerPrivileges() throws Exception { - AccessControlContext acc = provider.getAccessControlContext(); - - AccessController.doPrivileged(new PrivilegedExceptionAction() { - - @Override - public Object run() throws Exception { - beanFactory.getBean("working-factory-method"); - beanFactory.getBean("container-execution"); - return null; - } - }, acc); - } - - @Test - public void testPropertyInjection() throws Exception { - assertThatExceptionOfType(BeanCreationException.class).isThrownBy(() -> - beanFactory.getBean("property-injection")) - .withMessageContaining("security"); - beanFactory.getBean("working-property-injection"); - } - - @Test - public void testInitSecurityAwarePrototypeBean() { - final DefaultListableBeanFactory lbf = new DefaultListableBeanFactory(); - BeanDefinitionBuilder bdb = BeanDefinitionBuilder - .genericBeanDefinition(NonPrivilegedBean.class).setScope( - BeanDefinition.SCOPE_PROTOTYPE) - .setInitMethodName("init").setDestroyMethodName("destroy") - .addConstructorArgValue("user1"); - lbf.registerBeanDefinition("test", bdb.getBeanDefinition()); - final Subject subject = new Subject(); - subject.getPrincipals().add(new TestPrincipal("user1")); - - NonPrivilegedBean bean = Subject.doAsPrivileged( - subject, new PrivilegedAction() { - @Override - public NonPrivilegedBean run() { - return lbf.getBean("test", NonPrivilegedBean.class); - } - }, null); - assertThat(bean).isNotNull(); - } - - @Test - public void testTrustedExecution() throws Exception { - beanFactory.setSecurityContextProvider(null); - - Permissions perms = new Permissions(); - perms.add(new AuthPermission("getSubject")); - ProtectionDomain pd = new ProtectionDomain(null, perms); - - new AccessControlContext(new ProtectionDomain[] { pd }); - - final Subject subject = new Subject(); - subject.getPrincipals().add(new TestPrincipal("user1")); - - // request the beans from non-privileged code - Subject.doAsPrivileged(subject, new PrivilegedAction() { - - @Override - public Object run() { - // sanity check - assertThat(getCurrentSubjectName()).isEqualTo("user1"); - assertThat(NonPrivilegedBean.destroyed).isEqualTo(false); - - beanFactory.getBean("trusted-spring-callbacks"); - beanFactory.getBean("trusted-custom-init-destroy"); - // the factory is a prototype - ask for multiple instances - beanFactory.getBean("trusted-spring-factory"); - beanFactory.getBean("trusted-spring-factory"); - beanFactory.getBean("trusted-spring-factory"); - - beanFactory.getBean("trusted-factory-bean"); - beanFactory.getBean("trusted-static-factory-method"); - beanFactory.getBean("trusted-factory-method"); - beanFactory.getBean("trusted-property-injection"); - beanFactory.getBean("trusted-working-property-injection"); - - beanFactory.destroySingletons(); - assertThat(NonPrivilegedBean.destroyed).isEqualTo(true); - return null; - } - }, provider.getAccessControlContext()); - } - - private Consumer mostSpecificCauseOf(Class type) { - return ex -> assertThat(ex.getMostSpecificCause()).isInstanceOf(type); - - } - -} diff --git a/spring-beans/src/test/java/org/springframework/beans/factory/support/security/support/ConstructorBean.java b/spring-beans/src/test/java/org/springframework/beans/factory/support/security/support/ConstructorBean.java deleted file mode 100644 index fc60fc3db1..0000000000 --- a/spring-beans/src/test/java/org/springframework/beans/factory/support/security/support/ConstructorBean.java +++ /dev/null @@ -1,30 +0,0 @@ -/* - * Copyright 2002-2013 the original author or authors. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * https://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package org.springframework.beans.factory.support.security.support; - -/** - * @author Costin Leau - */ -public class ConstructorBean { - - public ConstructorBean() { - System.getProperties(); - } - - public ConstructorBean(Object obj) { - } -} diff --git a/spring-beans/src/test/java/org/springframework/beans/factory/support/security/support/CustomCallbackBean.java b/spring-beans/src/test/java/org/springframework/beans/factory/support/security/support/CustomCallbackBean.java deleted file mode 100644 index 4874306e6e..0000000000 --- a/spring-beans/src/test/java/org/springframework/beans/factory/support/security/support/CustomCallbackBean.java +++ /dev/null @@ -1,30 +0,0 @@ -/* - * Copyright 2002-2012 the original author or authors. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * https://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package org.springframework.beans.factory.support.security.support; - -/** - * @author Costin Leau - */ -public class CustomCallbackBean { - - public void init() { - System.getProperties(); - } - - public void destroy() { - System.setProperty("security.destroy", "true"); - } -} diff --git a/spring-beans/src/test/java/org/springframework/beans/factory/support/security/support/CustomFactoryBean.java b/spring-beans/src/test/java/org/springframework/beans/factory/support/security/support/CustomFactoryBean.java deleted file mode 100644 index 4ec3d7131b..0000000000 --- a/spring-beans/src/test/java/org/springframework/beans/factory/support/security/support/CustomFactoryBean.java +++ /dev/null @@ -1,44 +0,0 @@ -/* - * Copyright 2002-2012 the original author or authors. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * https://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package org.springframework.beans.factory.support.security.support; - -import java.util.Properties; - -import org.springframework.beans.factory.FactoryBean; - -/** - * @author Costin Leau - */ -public class CustomFactoryBean implements FactoryBean { - - @Override - public Properties getObject() throws Exception { - return System.getProperties(); - } - - @Override - public Class getObjectType() { - System.setProperty("factory.object.type", "true"); - return Properties.class; - } - - @Override - public boolean isSingleton() { - return true; - } - -} diff --git a/spring-beans/src/test/java/org/springframework/beans/factory/support/security/support/DestroyBean.java b/spring-beans/src/test/java/org/springframework/beans/factory/support/security/support/DestroyBean.java deleted file mode 100644 index 67005abf78..0000000000 --- a/spring-beans/src/test/java/org/springframework/beans/factory/support/security/support/DestroyBean.java +++ /dev/null @@ -1,29 +0,0 @@ -/* - * Copyright 2002-2012 the original author or authors. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * https://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package org.springframework.beans.factory.support.security.support; - -import org.springframework.beans.factory.DisposableBean; - -/** - * @author Costin Leau - */ -public class DestroyBean implements DisposableBean { - - @Override - public void destroy() throws Exception { - System.setProperty("security.destroy", "true"); - } -} diff --git a/spring-beans/src/test/java/org/springframework/beans/factory/support/security/support/FactoryBean.java b/spring-beans/src/test/java/org/springframework/beans/factory/support/security/support/FactoryBean.java deleted file mode 100644 index 4f7fb62e5b..0000000000 --- a/spring-beans/src/test/java/org/springframework/beans/factory/support/security/support/FactoryBean.java +++ /dev/null @@ -1,36 +0,0 @@ -/* - * Copyright 2002-2012 the original author or authors. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * https://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package org.springframework.beans.factory.support.security.support; - -/** - * @author Costin Leau - */ -public class FactoryBean { - - public static Object makeStaticInstance() { - System.getProperties(); - return new Object(); - } - - protected static Object protectedStaticInstance() { - return "protectedStaticInstance"; - } - - public Object makeInstance() { - System.getProperties(); - return new Object(); - } -} diff --git a/spring-beans/src/test/java/org/springframework/beans/factory/support/security/support/InitBean.java b/spring-beans/src/test/java/org/springframework/beans/factory/support/security/support/InitBean.java deleted file mode 100644 index 3693bb9d74..0000000000 --- a/spring-beans/src/test/java/org/springframework/beans/factory/support/security/support/InitBean.java +++ /dev/null @@ -1,29 +0,0 @@ -/* - * Copyright 2002-2012 the original author or authors. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * https://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package org.springframework.beans.factory.support.security.support; - -import org.springframework.beans.factory.InitializingBean; - -/** - * @author Costin Leau - */ -public class InitBean implements InitializingBean { - - @Override - public void afterPropertiesSet() throws Exception { - System.getProperties(); - } -} diff --git a/spring-beans/src/test/java/org/springframework/beans/factory/support/security/support/PropertyBean.java b/spring-beans/src/test/java/org/springframework/beans/factory/support/security/support/PropertyBean.java deleted file mode 100644 index 51933137f0..0000000000 --- a/spring-beans/src/test/java/org/springframework/beans/factory/support/security/support/PropertyBean.java +++ /dev/null @@ -1,30 +0,0 @@ -/* - * Copyright 2002-2012 the original author or authors. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * https://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package org.springframework.beans.factory.support.security.support; - -/** - * @author Costin Leau - */ -public class PropertyBean { - - public void setSecurityProperty(Object property) { - System.getProperties(); - } - - public void setProperty(Object property) { - - } -} diff --git a/spring-beans/src/test/java/org/springframework/beans/propertyeditors/CustomEditorTests.java b/spring-beans/src/test/java/org/springframework/beans/propertyeditors/CustomEditorTests.java index e3dddf62db..8962008451 100644 --- a/spring-beans/src/test/java/org/springframework/beans/propertyeditors/CustomEditorTests.java +++ b/spring-beans/src/test/java/org/springframework/beans/propertyeditors/CustomEditorTests.java @@ -502,7 +502,7 @@ class CustomEditorTests { CharBean cb = new CharBean(); BeanWrapper bw = new BeanWrapperImpl(cb); - bw.setPropertyValue("myChar", new Character('c')); + bw.setPropertyValue("myChar", Character.valueOf('c')); assertThat(cb.getMyChar()).isEqualTo('c'); bw.setPropertyValue("myChar", "c"); diff --git a/spring-context/src/main/java/org/springframework/context/support/ApplicationContextAwareProcessor.java b/spring-context/src/main/java/org/springframework/context/support/ApplicationContextAwareProcessor.java index a58bb63034..60b1c3b58a 100644 --- a/spring-context/src/main/java/org/springframework/context/support/ApplicationContextAwareProcessor.java +++ b/spring-context/src/main/java/org/springframework/context/support/ApplicationContextAwareProcessor.java @@ -1,5 +1,5 @@ /* - * Copyright 2002-2020 the original author or authors. + * Copyright 2002-2021 the original author or authors. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -16,10 +16,6 @@ package org.springframework.context.support; -import java.security.AccessControlContext; -import java.security.AccessController; -import java.security.PrivilegedAction; - import org.springframework.beans.BeansException; import org.springframework.beans.factory.config.BeanPostProcessor; import org.springframework.beans.factory.config.EmbeddedValueResolver; @@ -86,22 +82,7 @@ class ApplicationContextAwareProcessor implements BeanPostProcessor { return bean; } - AccessControlContext acc = null; - - if (System.getSecurityManager() != null) { - acc = this.applicationContext.getBeanFactory().getAccessControlContext(); - } - - if (acc != null) { - AccessController.doPrivileged((PrivilegedAction) () -> { - invokeAwareInterfaces(bean); - return null; - }, acc); - } - else { - invokeAwareInterfaces(bean); - } - + invokeAwareInterfaces(bean); return bean; } diff --git a/spring-context/src/main/java/org/springframework/context/support/ResourceBundleMessageSource.java b/spring-context/src/main/java/org/springframework/context/support/ResourceBundleMessageSource.java index f78120b8fe..012237889a 100644 --- a/spring-context/src/main/java/org/springframework/context/support/ResourceBundleMessageSource.java +++ b/spring-context/src/main/java/org/springframework/context/support/ResourceBundleMessageSource.java @@ -1,5 +1,5 @@ /* - * Copyright 2002-2020 the original author or authors. + * Copyright 2002-2021 the original author or authors. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -22,9 +22,6 @@ import java.io.InputStreamReader; import java.io.Reader; import java.net.URL; import java.net.URLConnection; -import java.security.AccessController; -import java.security.PrivilegedActionException; -import java.security.PrivilegedExceptionAction; import java.text.MessageFormat; import java.util.Locale; import java.util.Map; @@ -400,28 +397,19 @@ public class ResourceBundleMessageSource extends AbstractResourceBasedMessageSou final String resourceName = toResourceName(bundleName, "properties"); final ClassLoader classLoader = loader; final boolean reloadFlag = reload; - InputStream inputStream; - try { - inputStream = AccessController.doPrivileged((PrivilegedExceptionAction) () -> { - InputStream is = null; - if (reloadFlag) { - URL url = classLoader.getResource(resourceName); - if (url != null) { - URLConnection connection = url.openConnection(); - if (connection != null) { - connection.setUseCaches(false); - is = connection.getInputStream(); - } - } + InputStream inputStream = null; + if (reloadFlag) { + URL url = classLoader.getResource(resourceName); + if (url != null) { + URLConnection connection = url.openConnection(); + if (connection != null) { + connection.setUseCaches(false); + inputStream = connection.getInputStream(); } - else { - is = classLoader.getResourceAsStream(resourceName); - } - return is; - }); + } } - catch (PrivilegedActionException ex) { - throw (IOException) ex.getException(); + else { + inputStream = classLoader.getResourceAsStream(resourceName); } if (inputStream != null) { String encoding = getDefaultEncoding(); diff --git a/spring-context/src/test/java/org/springframework/context/expression/ApplicationContextExpressionTests.java b/spring-context/src/test/java/org/springframework/context/expression/ApplicationContextExpressionTests.java index 657597bc23..827f5f5b09 100644 --- a/spring-context/src/test/java/org/springframework/context/expression/ApplicationContextExpressionTests.java +++ b/spring-context/src/test/java/org/springframework/context/expression/ApplicationContextExpressionTests.java @@ -23,8 +23,6 @@ import java.io.Reader; import java.io.Serializable; import java.net.URI; import java.net.URL; -import java.security.AccessControlException; -import java.security.Permission; import java.util.Optional; import java.util.Properties; @@ -237,43 +235,6 @@ class ApplicationContextExpressionTests { } } - @Test - void systemPropertiesSecurityManager() { - AnnotationConfigApplicationContext ac = new AnnotationConfigApplicationContext(); - - GenericBeanDefinition bd = new GenericBeanDefinition(); - bd.setBeanClass(TestBean.class); - bd.getPropertyValues().add("country", "#{systemProperties.country}"); - ac.registerBeanDefinition("tb", bd); - - SecurityManager oldSecurityManager = System.getSecurityManager(); - try { - System.setProperty("country", "NL"); - - SecurityManager securityManager = new SecurityManager() { - @Override - public void checkPropertiesAccess() { - throw new AccessControlException("Not Allowed"); - } - @Override - public void checkPermission(Permission perm) { - // allow everything else - } - }; - System.setSecurityManager(securityManager); - ac.refresh(); - - TestBean tb = ac.getBean("tb", TestBean.class); - assertThat(tb.getCountry()).isEqualTo("NL"); - - } - finally { - System.setSecurityManager(oldSecurityManager); - System.getProperties().remove("country"); - } - ac.close(); - } - @Test void stringConcatenationWithDebugLogging() { AnnotationConfigApplicationContext ac = new AnnotationConfigApplicationContext(); diff --git a/spring-context/src/test/java/org/springframework/context/support/EnvironmentSecurityManagerIntegrationTests.java b/spring-context/src/test/java/org/springframework/context/support/EnvironmentSecurityManagerIntegrationTests.java deleted file mode 100644 index 968aba7f69..0000000000 --- a/spring-context/src/test/java/org/springframework/context/support/EnvironmentSecurityManagerIntegrationTests.java +++ /dev/null @@ -1,119 +0,0 @@ -/* - * Copyright 2002-2019 the original author or authors. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * https://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package org.springframework.context.support; - -import java.security.AccessControlException; -import java.security.Permission; -import java.util.Map; - -import org.junit.jupiter.api.AfterEach; -import org.junit.jupiter.api.BeforeEach; -import org.junit.jupiter.api.Test; - -import org.springframework.beans.factory.support.DefaultListableBeanFactory; -import org.springframework.context.annotation.AnnotatedBeanDefinitionReader; -import org.springframework.context.annotation.Profile; -import org.springframework.core.env.AbstractEnvironment; -import org.springframework.core.testfixture.env.EnvironmentTestUtils; -import org.springframework.stereotype.Component; - -import static java.lang.String.format; -import static org.assertj.core.api.Assertions.assertThat; - -/** - * Tests integration between Environment and SecurityManagers. See SPR-9970. - * - * @author Chris Beams - */ -public class EnvironmentSecurityManagerIntegrationTests { - - private SecurityManager originalSecurityManager; - - private Map env; - - - @BeforeEach - public void setUp() { - originalSecurityManager = System.getSecurityManager(); - env = EnvironmentTestUtils.getModifiableSystemEnvironment(); - env.put(AbstractEnvironment.ACTIVE_PROFILES_PROPERTY_NAME, "p1"); - } - - @AfterEach - public void tearDown() { - env.remove(AbstractEnvironment.ACTIVE_PROFILES_PROPERTY_NAME); - System.setSecurityManager(originalSecurityManager); - } - - - @Test - public void securityManagerDisallowsAccessToSystemEnvironmentButAllowsAccessToIndividualKeys() { - SecurityManager securityManager = new SecurityManager() { - @Override - public void checkPermission(Permission perm) { - // Disallowing access to System#getenv means that our - // ReadOnlySystemAttributesMap will come into play. - if ("getenv.*".equals(perm.getName())) { - throw new AccessControlException("Accessing the system environment is disallowed"); - } - } - }; - System.setSecurityManager(securityManager); - - DefaultListableBeanFactory bf = new DefaultListableBeanFactory(); - AnnotatedBeanDefinitionReader reader = new AnnotatedBeanDefinitionReader(bf); - reader.register(C1.class); - assertThat(bf.containsBean("c1")).isTrue(); - } - - @Test - public void securityManagerDisallowsAccessToSystemEnvironmentAndDisallowsAccessToIndividualKey() { - SecurityManager securityManager = new SecurityManager() { - @Override - public void checkPermission(Permission perm) { - // Disallowing access to System#getenv means that our - // ReadOnlySystemAttributesMap will come into play. - if ("getenv.*".equals(perm.getName())) { - throw new AccessControlException("Accessing the system environment is disallowed"); - } - // Disallowing access to the spring.profiles.active property means that - // the BeanDefinitionReader won't be able to determine which profiles are - // active. We should see an INFO-level message in the console about this - // and as a result, any components marked with a non-default profile will - // be ignored. - if (("getenv." + AbstractEnvironment.ACTIVE_PROFILES_PROPERTY_NAME).equals(perm.getName())) { - throw new AccessControlException( - format("Accessing system environment variable [%s] is disallowed", - AbstractEnvironment.ACTIVE_PROFILES_PROPERTY_NAME)); - } - } - }; - System.setSecurityManager(securityManager); - - DefaultListableBeanFactory bf = new DefaultListableBeanFactory(); - AnnotatedBeanDefinitionReader reader = new AnnotatedBeanDefinitionReader(bf); - reader.register(C1.class); - assertThat(bf.containsBean("c1")).isFalse(); - } - - - @Component("c1") - @Profile("p1") - static class C1 { - } - -} diff --git a/spring-context/src/test/java/org/springframework/jmx/support/JmxUtilsTests.java b/spring-context/src/test/java/org/springframework/jmx/support/JmxUtilsTests.java index f8ef4348bc..eba01bd4fe 100644 --- a/spring-context/src/test/java/org/springframework/jmx/support/JmxUtilsTests.java +++ b/spring-context/src/test/java/org/springframework/jmx/support/JmxUtilsTests.java @@ -1,5 +1,5 @@ /* - * Copyright 2002-2019 the original author or authors. + * Copyright 2002-2021 the original author or authors. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -19,8 +19,6 @@ package org.springframework.jmx.support; import java.beans.PropertyDescriptor; import javax.management.DynamicMBean; -import javax.management.MBeanServer; -import javax.management.MBeanServerFactory; import javax.management.MalformedObjectNameException; import javax.management.NotCompliantMBeanException; import javax.management.ObjectName; @@ -57,42 +55,42 @@ class JmxUtilsTests { } @Test - void isMBeanWithDynamicMBean() throws Exception { + void isMBeanWithDynamicMBean() { DynamicMBean mbean = new TestDynamicMBean(); assertThat(JmxUtils.isMBean(mbean.getClass())).as("Dynamic MBean not detected correctly").isTrue(); } @Test - void isMBeanWithStandardMBeanWrapper() throws Exception { + void isMBeanWithStandardMBeanWrapper() throws NotCompliantMBeanException { StandardMBean mbean = new StandardMBean(new JmxTestBean(), IJmxTestBean.class); assertThat(JmxUtils.isMBean(mbean.getClass())).as("Standard MBean not detected correctly").isTrue(); } @Test - void isMBeanWithStandardMBeanInherited() throws Exception { + void isMBeanWithStandardMBeanInherited() throws NotCompliantMBeanException { StandardMBean mbean = new StandardMBeanImpl(); assertThat(JmxUtils.isMBean(mbean.getClass())).as("Standard MBean not detected correctly").isTrue(); } @Test - void notAnMBean() throws Exception { + void notAnMBean() { assertThat(JmxUtils.isMBean(Object.class)).as("Object incorrectly identified as an MBean").isFalse(); } @Test - void simpleMBean() throws Exception { + void simpleMBean() { Foo foo = new Foo(); assertThat(JmxUtils.isMBean(foo.getClass())).as("Simple MBean not detected correctly").isTrue(); } @Test - void simpleMXBean() throws Exception { + void simpleMXBean() { FooX foo = new FooX(); assertThat(JmxUtils.isMBean(foo.getClass())).as("Simple MXBean not detected correctly").isTrue(); } @Test - void simpleMBeanThroughInheritance() throws Exception { + void simpleMBeanThroughInheritance() { Bar bar = new Bar(); Abc abc = new Abc(); assertThat(JmxUtils.isMBean(bar.getClass())).as("Simple MBean (through inheritance) not detected correctly").isTrue(); @@ -126,19 +124,6 @@ class JmxUtilsTests { assertThat(uniqueName.getKeyProperty(JmxUtils.IDENTITY_OBJECT_NAME_KEY)).as("Identity key is incorrect").isEqualTo(ObjectUtils.getIdentityHexString(managedResource)); } - @Test - void locatePlatformMBeanServer() { - MBeanServer server = null; - try { - server = JmxUtils.locateMBeanServer(); - } - finally { - if (server != null) { - MBeanServerFactory.releaseMBeanServer(server); - } - } - } - public static class AttributeTestBean { diff --git a/spring-context/src/test/java/org/springframework/jmx/support/MBeanServerFactoryBeanTests.java b/spring-context/src/test/java/org/springframework/jmx/support/MBeanServerFactoryBeanTests.java index 02a24b48fd..a0092708c5 100644 --- a/spring-context/src/test/java/org/springframework/jmx/support/MBeanServerFactoryBeanTests.java +++ b/spring-context/src/test/java/org/springframework/jmx/support/MBeanServerFactoryBeanTests.java @@ -1,5 +1,5 @@ /* - * Copyright 2002-2019 the original author or authors. + * Copyright 2002-2021 the original author or authors. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -47,7 +47,7 @@ class MBeanServerFactoryBeanTests { } @Test - void defaultValues() throws Exception { + void defaultValues() { MBeanServerFactoryBean bean = new MBeanServerFactoryBean(); bean.afterPropertiesSet(); try { @@ -60,7 +60,7 @@ class MBeanServerFactoryBeanTests { } @Test - void defaultDomain() throws Exception { + void defaultDomain() { MBeanServerFactoryBean bean = new MBeanServerFactoryBean(); bean.setDefaultDomain("foo"); bean.afterPropertiesSet(); @@ -129,7 +129,8 @@ class MBeanServerFactoryBeanTests { assertCreation(false, "The server should not be available in the list"); } - private void assertCreation(boolean referenceShouldExist, String failMsg) throws Exception { + + private void assertCreation(boolean referenceShouldExist, String failMsg) { MBeanServerFactoryBean bean = new MBeanServerFactoryBean(); bean.setRegisterWithFactory(referenceShouldExist); bean.afterPropertiesSet(); diff --git a/spring-context/src/test/java/org/springframework/jndi/JndiLocatorDelegateTests.java b/spring-context/src/test/java/org/springframework/jndi/JndiLocatorDelegateTests.java deleted file mode 100644 index c3601d3b1a..0000000000 --- a/spring-context/src/test/java/org/springframework/jndi/JndiLocatorDelegateTests.java +++ /dev/null @@ -1,52 +0,0 @@ -/* - * Copyright 2002-2019 the original author or authors. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * https://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package org.springframework.jndi; - -import java.lang.reflect.Field; - -import javax.naming.spi.NamingManager; - -import org.junit.jupiter.api.Test; - -import static org.assertj.core.api.Assertions.assertThat; - - - -/** - * Tests for {@link JndiLocatorDelegate}. - * - * @author Phillip Webb - * @author Juergen Hoeller - */ -public class JndiLocatorDelegateTests { - - @Test - public void isDefaultJndiEnvironmentAvailableFalse() throws Exception { - Field builderField = NamingManager.class.getDeclaredField("initctx_factory_builder"); - builderField.setAccessible(true); - Object oldBuilder = builderField.get(null); - builderField.set(null, null); - - try { - assertThat(JndiLocatorDelegate.isDefaultJndiEnvironmentAvailable()).isEqualTo(false); - } - finally { - builderField.set(null, oldBuilder); - } - } - -} diff --git a/spring-context/src/test/java/org/springframework/util/MBeanTestUtils.java b/spring-context/src/test/java/org/springframework/util/MBeanTestUtils.java index b96c56053c..6b214a7f33 100644 --- a/spring-context/src/test/java/org/springframework/util/MBeanTestUtils.java +++ b/spring-context/src/test/java/org/springframework/util/MBeanTestUtils.java @@ -1,5 +1,5 @@ /* - * Copyright 2002-2019 the original author or authors. + * Copyright 2002-2021 the original author or authors. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -16,9 +16,6 @@ package org.springframework.util; -import java.lang.management.ManagementFactory; -import java.lang.reflect.Field; - import javax.management.MBeanServer; import javax.management.MBeanServerFactory; @@ -45,10 +42,6 @@ public class MBeanTestUtils { } } } - - Field field = ManagementFactory.class.getDeclaredField("platformMBeanServer"); - field.setAccessible(true); - field.set(null, null); } } diff --git a/spring-core/src/main/java/org/springframework/cglib/core/ReflectUtils.java b/spring-core/src/main/java/org/springframework/cglib/core/ReflectUtils.java index 4420c50c9e..76e3ebf7cb 100644 --- a/spring-core/src/main/java/org/springframework/cglib/core/ReflectUtils.java +++ b/spring-core/src/main/java/org/springframework/cglib/core/ReflectUtils.java @@ -26,9 +26,6 @@ import java.lang.reflect.InvocationTargetException; import java.lang.reflect.Member; import java.lang.reflect.Method; import java.lang.reflect.Modifier; -import java.security.AccessController; -import java.security.PrivilegedAction; -import java.security.PrivilegedExceptionAction; import java.security.ProtectionDomain; import java.util.ArrayList; import java.util.Arrays; @@ -56,11 +53,6 @@ public class ReflectUtils { private static final ClassLoader defaultLoader = ReflectUtils.class.getClassLoader(); - // SPRING PATCH BEGIN - private static final Method privateLookupInMethod; - - private static final Method lookupDefineClassMethod; - private static final Method classLoaderDefineClassMethod; private static final ProtectionDomain PROTECTION_DOMAIN; @@ -69,63 +61,28 @@ public class ReflectUtils { private static final List OBJECT_METHODS = new ArrayList(); + // SPRING PATCH BEGIN static { - Method privateLookupIn; - Method lookupDefineClass; Method classLoaderDefineClass; ProtectionDomain protectionDomain; Throwable throwable = null; try { - privateLookupIn = (Method) AccessController.doPrivileged(new PrivilegedExceptionAction() { - public Object run() throws Exception { - try { - return MethodHandles.class.getMethod("privateLookupIn", Class.class, MethodHandles.Lookup.class); - } - catch (NoSuchMethodException ex) { - return null; - } - } - }); - lookupDefineClass = (Method) AccessController.doPrivileged(new PrivilegedExceptionAction() { - public Object run() throws Exception { - try { - return MethodHandles.Lookup.class.getMethod("defineClass", byte[].class); - } - catch (NoSuchMethodException ex) { - return null; - } - } - }); - classLoaderDefineClass = (Method) AccessController.doPrivileged(new PrivilegedExceptionAction() { - public Object run() throws Exception { - return ClassLoader.class.getDeclaredMethod("defineClass", + classLoaderDefineClass = ClassLoader.class.getDeclaredMethod("defineClass", String.class, byte[].class, Integer.TYPE, Integer.TYPE, ProtectionDomain.class); - } - }); protectionDomain = getProtectionDomain(ReflectUtils.class); - AccessController.doPrivileged(new PrivilegedExceptionAction() { - public Object run() throws Exception { - Method[] methods = Object.class.getDeclaredMethods(); - for (Method method : methods) { - if ("finalize".equals(method.getName()) - || (method.getModifiers() & (Modifier.FINAL | Modifier.STATIC)) > 0) { - continue; - } - OBJECT_METHODS.add(method); - } - return null; + for (Method method : Object.class.getDeclaredMethods()) { + if ("finalize".equals(method.getName()) + || (method.getModifiers() & (Modifier.FINAL | Modifier.STATIC)) > 0) { + continue; } - }); + OBJECT_METHODS.add(method); + } } catch (Throwable t) { - privateLookupIn = null; - lookupDefineClass = null; classLoaderDefineClass = null; protectionDomain = null; throwable = t; } - privateLookupInMethod = privateLookupIn; - lookupDefineClassMethod = lookupDefineClass; classLoaderDefineClassMethod = classLoaderDefineClass; PROTECTION_DOMAIN = protectionDomain; THROWABLE = throwable; @@ -160,11 +117,7 @@ public class ReflectUtils { if (source == null) { return null; } - return (ProtectionDomain) AccessController.doPrivileged(new PrivilegedAction() { - public Object run() { - return source.getProtectionDomain(); - } - }); + return source.getProtectionDomain(); } public static Type[] getExceptionTypes(Member member) { @@ -336,15 +289,7 @@ public class ReflectUtils { public static Constructor getConstructor(Class type, Class[] parameterTypes) { try { Constructor constructor = type.getDeclaredConstructor(parameterTypes); - if (System.getSecurityManager() != null) { - AccessController.doPrivileged((PrivilegedAction) () -> { - constructor.setAccessible(true); - return null; - }); - } - else { - constructor.setAccessible(true); - } + constructor.setAccessible(true); return constructor; } catch (NoSuchMethodException e) { @@ -501,18 +446,12 @@ public class ReflectUtils { Class c = null; // Preferred option: JDK 9+ Lookup.defineClass API if ClassLoader matches - if (contextClass != null && contextClass.getClassLoader() == loader && - privateLookupInMethod != null && lookupDefineClassMethod != null) { + if (contextClass != null && contextClass.getClassLoader() == loader) { try { - MethodHandles.Lookup lookup = (MethodHandles.Lookup) - privateLookupInMethod.invoke(null, contextClass, MethodHandles.lookup()); - c = (Class) lookupDefineClassMethod.invoke(lookup, b); + MethodHandles.Lookup lookup = MethodHandles.privateLookupIn(contextClass, MethodHandles.lookup()); + c = lookup.defineClass(b); } - catch (InvocationTargetException ex) { - Throwable target = ex.getTargetException(); - if (target.getClass() != LinkageError.class && target.getClass() != IllegalArgumentException.class) { - throw new CodeGenerationException(target); - } + catch (LinkageError | IllegalArgumentException ex) { // in case of plain LinkageError (class already defined) // or IllegalArgumentException (class in different package): // fall through to traditional ClassLoader.defineClass below @@ -567,15 +506,10 @@ public class ReflectUtils { } // Fallback option: JDK 9+ Lookup.defineClass API even if ClassLoader does not match - if (c == null && contextClass != null && contextClass.getClassLoader() != loader && - privateLookupInMethod != null && lookupDefineClassMethod != null) { + if (c == null && contextClass != null && contextClass.getClassLoader() != loader) { try { - MethodHandles.Lookup lookup = (MethodHandles.Lookup) - privateLookupInMethod.invoke(null, contextClass, MethodHandles.lookup()); - c = (Class) lookupDefineClassMethod.invoke(lookup, b); - } - catch (InvocationTargetException ex) { - throw new CodeGenerationException(ex.getTargetException()); + MethodHandles.Lookup lookup = MethodHandles.privateLookupIn(contextClass, MethodHandles.lookup()); + c = lookup.defineClass(b); } catch (Throwable ex) { throw new CodeGenerationException(ex); diff --git a/spring-core/src/main/java/org/springframework/core/env/AbstractEnvironment.java b/spring-core/src/main/java/org/springframework/core/env/AbstractEnvironment.java index 5fa9aa45d2..7f983189d6 100644 --- a/spring-core/src/main/java/org/springframework/core/env/AbstractEnvironment.java +++ b/spring-core/src/main/java/org/springframework/core/env/AbstractEnvironment.java @@ -16,7 +16,6 @@ package org.springframework.core.env; -import java.security.AccessControlException; import java.util.Arrays; import java.util.Collections; import java.util.LinkedHashSet; @@ -60,8 +59,7 @@ public abstract class AbstractEnvironment implements ConfigurableEnvironment { *

The default is "false", falling back to system environment variable checks if a * Spring environment property (e.g. a placeholder in a configuration String) isn't * resolvable otherwise. Consider switching this flag to "true" if you experience - * log warnings from {@code getenv} calls coming from Spring, e.g. on WebSphere - * with strict SecurityManager settings and AccessControlExceptions warnings. + * log warnings from {@code getenv} calls coming from Spring. * @see #suppressGetenvAccess() */ public static final String IGNORE_GETENV_PROPERTY_NAME = "spring.getenv.ignore"; @@ -438,27 +436,7 @@ public abstract class AbstractEnvironment implements ConfigurableEnvironment { @Override @SuppressWarnings({"rawtypes", "unchecked"}) public Map getSystemProperties() { - try { - return (Map) System.getProperties(); - } - catch (AccessControlException ex) { - return (Map) new ReadOnlySystemAttributesMap() { - @Override - @Nullable - protected String getSystemAttribute(String attributeName) { - try { - return System.getProperty(attributeName); - } - catch (AccessControlException ex) { - if (logger.isInfoEnabled()) { - logger.info("Caught AccessControlException when accessing system property '" + - attributeName + "'; its value will be returned [null]. Reason: " + ex.getMessage()); - } - return null; - } - } - }; - } + return (Map) System.getProperties(); } @Override @@ -467,27 +445,7 @@ public abstract class AbstractEnvironment implements ConfigurableEnvironment { if (suppressGetenvAccess()) { return Collections.emptyMap(); } - try { - return (Map) System.getenv(); - } - catch (AccessControlException ex) { - return (Map) new ReadOnlySystemAttributesMap() { - @Override - @Nullable - protected String getSystemAttribute(String attributeName) { - try { - return System.getenv(attributeName); - } - catch (AccessControlException ex) { - if (logger.isInfoEnabled()) { - logger.info("Caught AccessControlException when accessing system environment variable '" + - attributeName + "'; its value will be returned [null]. Reason: " + ex.getMessage()); - } - return null; - } - } - }; - } + return (Map) System.getenv(); } /** diff --git a/spring-core/src/main/java/org/springframework/core/env/ConfigurableEnvironment.java b/spring-core/src/main/java/org/springframework/core/env/ConfigurableEnvironment.java index b174ca00cf..507fbdb8c4 100644 --- a/spring-core/src/main/java/org/springframework/core/env/ConfigurableEnvironment.java +++ b/spring-core/src/main/java/org/springframework/core/env/ConfigurableEnvironment.java @@ -1,5 +1,5 @@ /* - * Copyright 2002-2018 the original author or authors. + * Copyright 2002-2021 the original author or authors. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -119,32 +119,20 @@ public interface ConfigurableEnvironment extends Environment, ConfigurableProper MutablePropertySources getPropertySources(); /** - * Return the value of {@link System#getProperties()} if allowed by the current - * {@link SecurityManager}, otherwise return a map implementation that will attempt - * to access individual keys using calls to {@link System#getProperty(String)}. + * Return the value of {@link System#getProperties()}. *

Note that most {@code Environment} implementations will include this system * properties map as a default {@link PropertySource} to be searched. Therefore, it is * recommended that this method not be used directly unless bypassing other property * sources is expressly intended. - *

Calls to {@link Map#get(Object)} on the Map returned will never throw - * {@link IllegalAccessException}; in cases where the SecurityManager forbids access - * to a property, {@code null} will be returned and an INFO-level log message will be - * issued noting the exception. */ Map getSystemProperties(); /** - * Return the value of {@link System#getenv()} if allowed by the current - * {@link SecurityManager}, otherwise return a map implementation that will attempt - * to access individual keys using calls to {@link System#getenv(String)}. + * Return the value of {@link System#getenv()}. *

Note that most {@link Environment} implementations will include this system * environment map as a default {@link PropertySource} to be searched. Therefore, it * is recommended that this method not be used directly unless bypassing other * property sources is expressly intended. - *

Calls to {@link Map#get(Object)} on the Map returned will never throw - * {@link IllegalAccessException}; in cases where the SecurityManager forbids access - * to a property, {@code null} will be returned and an INFO-level log message will be - * issued noting the exception. */ Map getSystemEnvironment(); diff --git a/spring-core/src/main/java/org/springframework/core/env/ReadOnlySystemAttributesMap.java b/spring-core/src/main/java/org/springframework/core/env/ReadOnlySystemAttributesMap.java deleted file mode 100644 index 37867bd1d4..0000000000 --- a/spring-core/src/main/java/org/springframework/core/env/ReadOnlySystemAttributesMap.java +++ /dev/null @@ -1,123 +0,0 @@ -/* - * Copyright 2002-2018 the original author or authors. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * https://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package org.springframework.core.env; - -import java.util.Collection; -import java.util.Collections; -import java.util.Map; -import java.util.Set; - -import org.springframework.lang.Nullable; - -/** - * Read-only {@code Map} implementation that is backed by system - * properties or environment variables. - * - *

Used by {@link AbstractEnvironment} when a {@link SecurityManager} prohibits - * access to {@link System#getProperties()} or {@link System#getenv()}. It is for this - * reason that the implementations of {@link #keySet()}, {@link #entrySet()}, and - * {@link #values()} always return empty even though {@link #get(Object)} may in fact - * return non-null if the current security manager allows access to individual keys. - * - * @author Arjen Poutsma - * @author Chris Beams - * @since 3.0 - */ -abstract class ReadOnlySystemAttributesMap implements Map { - - @Override - public boolean containsKey(Object key) { - return (get(key) != null); - } - - /** - * Returns the value to which the specified key is mapped, or {@code null} if this map - * contains no mapping for the key. - * @param key the name of the system attribute to retrieve - * @throws IllegalArgumentException if given key is non-String - */ - @Override - @Nullable - public String get(Object key) { - if (!(key instanceof String)) { - throw new IllegalArgumentException( - "Type of key [" + key.getClass().getName() + "] must be java.lang.String"); - } - return getSystemAttribute((String) key); - } - - @Override - public boolean isEmpty() { - return false; - } - - /** - * Template method that returns the underlying system attribute. - *

Implementations typically call {@link System#getProperty(String)} or {@link System#getenv(String)} here. - */ - @Nullable - protected abstract String getSystemAttribute(String attributeName); - - - // Unsupported - - @Override - public int size() { - throw new UnsupportedOperationException(); - } - - @Override - public String put(String key, String value) { - throw new UnsupportedOperationException(); - } - - @Override - public boolean containsValue(Object value) { - throw new UnsupportedOperationException(); - } - - @Override - public String remove(Object key) { - throw new UnsupportedOperationException(); - } - - @Override - public void clear() { - throw new UnsupportedOperationException(); - } - - @Override - public Set keySet() { - return Collections.emptySet(); - } - - @Override - public void putAll(Map map) { - throw new UnsupportedOperationException(); - } - - @Override - public Collection values() { - return Collections.emptySet(); - } - - @Override - public Set> entrySet() { - return Collections.emptySet(); - } - -} diff --git a/spring-core/src/main/java/org/springframework/core/env/SystemEnvironmentPropertySource.java b/spring-core/src/main/java/org/springframework/core/env/SystemEnvironmentPropertySource.java index 06dd2b7a63..6b5f2fa36a 100644 --- a/spring-core/src/main/java/org/springframework/core/env/SystemEnvironmentPropertySource.java +++ b/spring-core/src/main/java/org/springframework/core/env/SystemEnvironmentPropertySource.java @@ -1,5 +1,5 @@ /* - * Copyright 2002-2015 the original author or authors. + * Copyright 2002-2021 the original author or authors. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -122,34 +122,26 @@ public class SystemEnvironmentPropertySource extends MapPropertySource { @Nullable private String checkPropertyName(String name) { // Check name as-is - if (containsKey(name)) { + if (this.source.containsKey(name)) { return name; } // Check name with just dots replaced String noDotName = name.replace('.', '_'); - if (!name.equals(noDotName) && containsKey(noDotName)) { + if (!name.equals(noDotName) && this.source.containsKey(noDotName)) { return noDotName; } // Check name with just hyphens replaced String noHyphenName = name.replace('-', '_'); - if (!name.equals(noHyphenName) && containsKey(noHyphenName)) { + if (!name.equals(noHyphenName) && this.source.containsKey(noHyphenName)) { return noHyphenName; } // Check name with dots and hyphens replaced String noDotNoHyphenName = noDotName.replace('-', '_'); - if (!noDotName.equals(noDotNoHyphenName) && containsKey(noDotNoHyphenName)) { + if (!noDotName.equals(noDotNoHyphenName) && this.source.containsKey(noDotNoHyphenName)) { return noDotNoHyphenName; } // Give up return null; } - private boolean containsKey(String name) { - return (isSecurityManagerPresent() ? this.source.keySet().contains(name) : this.source.containsKey(name)); - } - - protected boolean isSecurityManagerPresent() { - return (System.getSecurityManager() != null); - } - } diff --git a/spring-core/src/main/java/org/springframework/core/type/classreading/AbstractRecursiveAnnotationVisitor.java b/spring-core/src/main/java/org/springframework/core/type/classreading/AbstractRecursiveAnnotationVisitor.java index fa23cebbc2..356ab5b461 100644 --- a/spring-core/src/main/java/org/springframework/core/type/classreading/AbstractRecursiveAnnotationVisitor.java +++ b/spring-core/src/main/java/org/springframework/core/type/classreading/AbstractRecursiveAnnotationVisitor.java @@ -1,5 +1,5 @@ /* - * Copyright 2002-2019 the original author or authors. + * Copyright 2002-2021 the original author or authors. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -17,7 +17,6 @@ package org.springframework.core.type.classreading; import java.lang.reflect.Field; -import java.security.AccessControlException; import org.apache.commons.logging.Log; import org.apache.commons.logging.LogFactory; @@ -97,7 +96,7 @@ abstract class AbstractRecursiveAnnotationVisitor extends AnnotationVisitor { catch (ClassNotFoundException | NoClassDefFoundError ex) { logger.debug("Failed to classload enum type while reading annotation metadata", ex); } - catch (IllegalAccessException | AccessControlException ex) { + catch (IllegalAccessException ex) { logger.debug("Could not access enum value while reading annotation metadata", ex); } return valueToUse; diff --git a/spring-core/src/main/java/org/springframework/core/type/classreading/AnnotationAttributesReadingVisitor.java b/spring-core/src/main/java/org/springframework/core/type/classreading/AnnotationAttributesReadingVisitor.java index e9f1a15f38..ba1bfe06cf 100644 --- a/spring-core/src/main/java/org/springframework/core/type/classreading/AnnotationAttributesReadingVisitor.java +++ b/spring-core/src/main/java/org/springframework/core/type/classreading/AnnotationAttributesReadingVisitor.java @@ -107,9 +107,7 @@ final class AnnotationAttributesReadingVisitor extends RecursiveAnnotationAttrib String annotationName = annotationType.getName(); if (!AnnotationUtils.isInJavaLangAnnotationPackage(annotationName) && visited.add(annotation)) { try { - // Only do attribute scanning for public annotations; we'd run into - // IllegalAccessExceptions otherwise, and we don't want to mess with - // accessibility in a SecurityManager environment. + // Only do attribute scanning for public annotations. if (Modifier.isPublic(annotationType.getModifiers())) { this.attributesMap.add(annotationName, AnnotationUtils.getAnnotationAttributes(annotation, false, true)); diff --git a/spring-core/src/main/java/org/springframework/util/ReflectionUtils.java b/spring-core/src/main/java/org/springframework/util/ReflectionUtils.java index 2177481f0d..aa4e793162 100644 --- a/spring-core/src/main/java/org/springframework/util/ReflectionUtils.java +++ b/spring-core/src/main/java/org/springframework/util/ReflectionUtils.java @@ -190,8 +190,7 @@ public abstract class ReflectionUtils { /** * Make the given constructor accessible, explicitly setting it accessible * if necessary. The {@code setAccessible(true)} method is only called - * when actually necessary, to avoid unnecessary conflicts with a JVM - * SecurityManager (if active). + * when actually necessary, to avoid unnecessary conflicts. * @param ctor the constructor to make accessible * @see java.lang.reflect.Constructor#setAccessible */ @@ -441,10 +440,9 @@ public abstract class ReflectionUtils { /** * Variant of {@link Class#getDeclaredMethods()} that uses a local cache in - * order to avoid the JVM's SecurityManager check and new Method instances. - * In addition, it also includes Java 8 default methods from locally - * implemented interfaces, since those are effectively to be treated just - * like declared methods. + * order to avoid new Method instances. In addition, it also includes Java 8 + * default methods from locally implemented interfaces, since those are + * effectively to be treated just like declared methods. * @param clazz the class to introspect * @return the cached array of methods * @throws IllegalStateException if introspection fails @@ -561,8 +559,7 @@ public abstract class ReflectionUtils { /** * Make the given method accessible, explicitly setting it accessible if * necessary. The {@code setAccessible(true)} method is only called - * when actually necessary, to avoid unnecessary conflicts with a JVM - * SecurityManager (if active). + * when actually necessary, to avoid unnecessary conflicts. * @param method the method to make accessible * @see java.lang.reflect.Method#setAccessible */ @@ -720,7 +717,7 @@ public abstract class ReflectionUtils { /** * This variant retrieves {@link Class#getDeclaredFields()} from a local cache - * in order to avoid the JVM's SecurityManager check and defensive array copying. + * in order to avoid defensive array copying. * @param clazz the class to introspect * @return the cached array of fields * @throws IllegalStateException if introspection fails @@ -774,8 +771,7 @@ public abstract class ReflectionUtils { /** * Make the given field accessible, explicitly setting it accessible if * necessary. The {@code setAccessible(true)} method is only called - * when actually necessary, to avoid unnecessary conflicts with a JVM - * SecurityManager (if active). + * when actually necessary, to avoid unnecessary conflicts. * @param field the field to make accessible * @see java.lang.reflect.Field#setAccessible */ diff --git a/spring-core/src/test/java/org/springframework/core/env/StandardEnvironmentTests.java b/spring-core/src/test/java/org/springframework/core/env/StandardEnvironmentTests.java index acd6d84aca..5716a80650 100644 --- a/spring-core/src/test/java/org/springframework/core/env/StandardEnvironmentTests.java +++ b/spring-core/src/test/java/org/springframework/core/env/StandardEnvironmentTests.java @@ -1,5 +1,5 @@ /* - * Copyright 2002-2020 the original author or authors. + * Copyright 2002-2021 the original author or authors. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -16,15 +16,12 @@ package org.springframework.core.env; -import java.security.AccessControlException; -import java.security.Permission; import java.util.Arrays; import java.util.Map; import org.junit.jupiter.api.Test; import org.springframework.core.SpringProperties; -import org.springframework.core.testfixture.env.EnvironmentTestUtils; import org.springframework.core.testfixture.env.MockPropertySource; import static org.assertj.core.api.Assertions.assertThat; @@ -381,72 +378,22 @@ public class StandardEnvironmentTests { } @Test - void getSystemProperties_withAndWithoutSecurityManager() { + void getSystemProperties() { System.setProperty(ALLOWED_PROPERTY_NAME, ALLOWED_PROPERTY_VALUE); System.setProperty(DISALLOWED_PROPERTY_NAME, DISALLOWED_PROPERTY_VALUE); System.getProperties().put(STRING_PROPERTY_NAME, NON_STRING_PROPERTY_VALUE); System.getProperties().put(NON_STRING_PROPERTY_NAME, STRING_PROPERTY_VALUE); - { + try { Map systemProperties = environment.getSystemProperties(); assertThat(systemProperties).isNotNull(); assertThat(System.getProperties()).isSameAs(systemProperties); assertThat(systemProperties.get(ALLOWED_PROPERTY_NAME)).isEqualTo(ALLOWED_PROPERTY_VALUE); assertThat(systemProperties.get(DISALLOWED_PROPERTY_NAME)).isEqualTo(DISALLOWED_PROPERTY_VALUE); - - // non-string keys and values work fine... until the security manager is introduced below assertThat(systemProperties.get(STRING_PROPERTY_NAME)).isEqualTo(NON_STRING_PROPERTY_VALUE); assertThat(systemProperties.get(NON_STRING_PROPERTY_NAME)).isEqualTo(STRING_PROPERTY_VALUE); } - - SecurityManager oldSecurityManager = System.getSecurityManager(); - SecurityManager securityManager = new SecurityManager() { - @Override - public void checkPropertiesAccess() { - // see https://download.oracle.com/javase/1.5.0/docs/api/java/lang/System.html#getProperties() - throw new AccessControlException("Accessing the system properties is disallowed"); - } - @Override - public void checkPropertyAccess(String key) { - // see https://download.oracle.com/javase/1.5.0/docs/api/java/lang/System.html#getProperty(java.lang.String) - if (DISALLOWED_PROPERTY_NAME.equals(key)) { - throw new AccessControlException( - String.format("Accessing the system property [%s] is disallowed", DISALLOWED_PROPERTY_NAME)); - } - } - @Override - public void checkPermission(Permission perm) { - // allow everything else - } - }; - - try { - System.setSecurityManager(securityManager); - - { - Map systemProperties = environment.getSystemProperties(); - assertThat(systemProperties).isNotNull(); - assertThat(systemProperties).isInstanceOf(ReadOnlySystemAttributesMap.class); - assertThat((String)systemProperties.get(ALLOWED_PROPERTY_NAME)).isEqualTo(ALLOWED_PROPERTY_VALUE); - assertThat(systemProperties.get(DISALLOWED_PROPERTY_NAME)).isNull(); - - // nothing we can do here in terms of warning the user that there was - // actually a (non-string) value available. By this point, we only - // have access to calling System.getProperty(), which itself returns null - // if the value is non-string. So we're stuck with returning a potentially - // misleading null. - assertThat(systemProperties.get(STRING_PROPERTY_NAME)).isNull(); - - // in the case of a non-string *key*, however, we can do better. Alert - // the user that under these very special conditions (non-object key + - // SecurityManager that disallows access to system properties), they - // cannot do what they're attempting. - assertThatIllegalArgumentException().as("searching with non-string key against ReadOnlySystemAttributesMap").isThrownBy(() -> - systemProperties.get(NON_STRING_PROPERTY_NAME)); - } - } finally { - System.setSecurityManager(oldSecurityManager); System.clearProperty(ALLOWED_PROPERTY_NAME); System.clearProperty(DISALLOWED_PROPERTY_NAME); System.getProperties().remove(STRING_PROPERTY_NAME); @@ -455,48 +402,10 @@ public class StandardEnvironmentTests { } @Test - void getSystemEnvironment_withAndWithoutSecurityManager() { - EnvironmentTestUtils.getModifiableSystemEnvironment().put(ALLOWED_PROPERTY_NAME, ALLOWED_PROPERTY_VALUE); - EnvironmentTestUtils.getModifiableSystemEnvironment().put(DISALLOWED_PROPERTY_NAME, DISALLOWED_PROPERTY_VALUE); - - { - Map systemEnvironment = environment.getSystemEnvironment(); - assertThat(systemEnvironment).isNotNull(); - assertThat(System.getenv()).isSameAs(systemEnvironment); - } - - SecurityManager oldSecurityManager = System.getSecurityManager(); - SecurityManager securityManager = new SecurityManager() { - @Override - public void checkPermission(Permission perm) { - //see https://download.oracle.com/javase/1.5.0/docs/api/java/lang/System.html#getenv() - if ("getenv.*".equals(perm.getName())) { - throw new AccessControlException("Accessing the system environment is disallowed"); - } - //see https://download.oracle.com/javase/1.5.0/docs/api/java/lang/System.html#getenv(java.lang.String) - if (("getenv."+DISALLOWED_PROPERTY_NAME).equals(perm.getName())) { - throw new AccessControlException( - String.format("Accessing the system environment variable [%s] is disallowed", DISALLOWED_PROPERTY_NAME)); - } - } - }; - - try { - System.setSecurityManager(securityManager); - { - Map systemEnvironment = environment.getSystemEnvironment(); - assertThat(systemEnvironment).isNotNull(); - assertThat(systemEnvironment).isInstanceOf(ReadOnlySystemAttributesMap.class); - assertThat(systemEnvironment.get(ALLOWED_PROPERTY_NAME)).isEqualTo(ALLOWED_PROPERTY_VALUE); - assertThat(systemEnvironment.get(DISALLOWED_PROPERTY_NAME)).isNull(); - } - } - finally { - System.setSecurityManager(oldSecurityManager); - } - - EnvironmentTestUtils.getModifiableSystemEnvironment().remove(ALLOWED_PROPERTY_NAME); - EnvironmentTestUtils.getModifiableSystemEnvironment().remove(DISALLOWED_PROPERTY_NAME); + void getSystemEnvironment() { + Map systemEnvironment = environment.getSystemEnvironment(); + assertThat(systemEnvironment).isNotNull(); + assertThat(System.getenv()).isSameAs(systemEnvironment); } } diff --git a/spring-core/src/test/java/org/springframework/core/env/SystemEnvironmentPropertySourceTests.java b/spring-core/src/test/java/org/springframework/core/env/SystemEnvironmentPropertySourceTests.java index daca3a7013..ca52768f90 100644 --- a/spring-core/src/test/java/org/springframework/core/env/SystemEnvironmentPropertySourceTests.java +++ b/spring-core/src/test/java/org/springframework/core/env/SystemEnvironmentPropertySourceTests.java @@ -1,5 +1,5 @@ /* - * Copyright 2002-2019 the original author or authors. + * Copyright 2002-2021 the original author or authors. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -17,16 +17,13 @@ package org.springframework.core.env; import java.util.HashMap; -import java.util.HashSet; import java.util.Map; -import java.util.Set; import org.junit.jupiter.api.BeforeEach; import org.junit.jupiter.api.Test; import static org.assertj.core.api.Assertions.assertThat; - /** * Unit tests for {@link SystemEnvironmentPropertySource}. * @@ -148,30 +145,4 @@ class SystemEnvironmentPropertySourceTests { assertThat(ps.getProperty("A.hyphen-KEY")).isEqualTo("a_hyphen_value"); } - @Test - @SuppressWarnings("serial") - void withSecurityConstraints() throws Exception { - envMap = new HashMap() { - @Override - public boolean containsKey(Object key) { - throw new UnsupportedOperationException(); - } - @Override - public Set keySet() { - return new HashSet<>(super.keySet()); - } - }; - envMap.put("A_KEY", "a_value"); - - ps = new SystemEnvironmentPropertySource("sysEnv", envMap) { - @Override - protected boolean isSecurityManagerPresent() { - return true; - } - }; - - assertThat(ps.containsProperty("A_KEY")).isEqualTo(true); - assertThat(ps.getProperty("A_KEY")).isEqualTo("a_value"); - } - } diff --git a/spring-core/src/test/java/org/springframework/util/StreamUtilsTests.java b/spring-core/src/test/java/org/springframework/util/StreamUtilsTests.java index 21f0829457..fad81878e7 100644 --- a/spring-core/src/test/java/org/springframework/util/StreamUtilsTests.java +++ b/spring-core/src/test/java/org/springframework/util/StreamUtilsTests.java @@ -1,5 +1,5 @@ /* - * Copyright 2002-2019 the original author or authors. + * Copyright 2002-2021 the original author or authors. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -33,8 +33,6 @@ import static org.assertj.core.api.Assertions.assertThat; import static org.mockito.Mockito.inOrder; import static org.mockito.Mockito.mock; import static org.mockito.Mockito.never; -import static org.mockito.Mockito.spy; -import static org.mockito.Mockito.verify; /** * Tests for {@link StreamUtils}. @@ -57,53 +55,47 @@ class StreamUtilsTests { @Test void copyToByteArray() throws Exception { - InputStream inputStream = spy(new ByteArrayInputStream(bytes)); + InputStream inputStream = new ByteArrayInputStream(bytes); byte[] actual = StreamUtils.copyToByteArray(inputStream); assertThat(actual).isEqualTo(bytes); - verify(inputStream, never()).close(); } @Test void copyToString() throws Exception { Charset charset = Charset.defaultCharset(); - InputStream inputStream = spy(new ByteArrayInputStream(string.getBytes(charset))); + InputStream inputStream = new ByteArrayInputStream(string.getBytes(charset)); String actual = StreamUtils.copyToString(inputStream, charset); assertThat(actual).isEqualTo(string); - verify(inputStream, never()).close(); } @Test void copyBytes() throws Exception { - ByteArrayOutputStream out = spy(new ByteArrayOutputStream()); + ByteArrayOutputStream out = new ByteArrayOutputStream(); StreamUtils.copy(bytes, out); assertThat(out.toByteArray()).isEqualTo(bytes); - verify(out, never()).close(); } @Test void copyString() throws Exception { Charset charset = Charset.defaultCharset(); - ByteArrayOutputStream out = spy(new ByteArrayOutputStream()); + ByteArrayOutputStream out = new ByteArrayOutputStream(); StreamUtils.copy(string, charset, out); assertThat(out.toByteArray()).isEqualTo(string.getBytes(charset)); - verify(out, never()).close(); } @Test void copyStream() throws Exception { - ByteArrayOutputStream out = spy(new ByteArrayOutputStream()); + ByteArrayOutputStream out = new ByteArrayOutputStream(); StreamUtils.copy(new ByteArrayInputStream(bytes), out); assertThat(out.toByteArray()).isEqualTo(bytes); - verify(out, never()).close(); } @Test void copyRange() throws Exception { - ByteArrayOutputStream out = spy(new ByteArrayOutputStream()); + ByteArrayOutputStream out = new ByteArrayOutputStream(); StreamUtils.copyRange(new ByteArrayInputStream(bytes), out, 0, 100); byte[] range = Arrays.copyOfRange(bytes, 0, 101); assertThat(out.toByteArray()).isEqualTo(range); - verify(out, never()).close(); } @Test diff --git a/spring-core/src/testFixtures/java/org/springframework/core/testfixture/env/EnvironmentTestUtils.java b/spring-core/src/testFixtures/java/org/springframework/core/testfixture/env/EnvironmentTestUtils.java deleted file mode 100644 index 8606c47be3..0000000000 --- a/spring-core/src/testFixtures/java/org/springframework/core/testfixture/env/EnvironmentTestUtils.java +++ /dev/null @@ -1,92 +0,0 @@ -/* - * Copyright 2002-2019 the original author or authors. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * https://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package org.springframework.core.testfixture.env; - -import java.lang.reflect.Field; -import java.util.Collections; -import java.util.Map; - -import org.springframework.core.env.StandardEnvironment; - -/** - * Test utilities for {@link StandardEnvironment}. - * - * @author Chris Beams - * @author Juergen Hoeller - */ -public class EnvironmentTestUtils { - - @SuppressWarnings("unchecked") - public static Map getModifiableSystemEnvironment() { - // for os x / linux - Class[] classes = Collections.class.getDeclaredClasses(); - Map env = System.getenv(); - for (Class cl : classes) { - if ("java.util.Collections$UnmodifiableMap".equals(cl.getName())) { - try { - Field field = cl.getDeclaredField("m"); - field.setAccessible(true); - Object obj = field.get(env); - if (obj != null && obj.getClass().getName().equals("java.lang.ProcessEnvironment$StringEnvironment")) { - return (Map) obj; - } - } - catch (Exception ex) { - throw new RuntimeException(ex); - } - } - } - - // for windows - Class processEnvironmentClass; - try { - processEnvironmentClass = Class.forName("java.lang.ProcessEnvironment"); - } - catch (Exception ex) { - throw new IllegalStateException(ex); - } - - try { - Field theCaseInsensitiveEnvironmentField = processEnvironmentClass.getDeclaredField("theCaseInsensitiveEnvironment"); - theCaseInsensitiveEnvironmentField.setAccessible(true); - Object obj = theCaseInsensitiveEnvironmentField.get(null); - return (Map) obj; - } - catch (NoSuchFieldException ex) { - // do nothing - } - catch (Exception ex) { - throw new IllegalStateException(ex); - } - - try { - Field theEnvironmentField = processEnvironmentClass.getDeclaredField("theEnvironment"); - theEnvironmentField.setAccessible(true); - Object obj = theEnvironmentField.get(null); - return (Map) obj; - } - catch (NoSuchFieldException ex) { - // do nothing - } - catch (Exception ex) { - throw new IllegalStateException(ex); - } - - throw new IllegalStateException(); - } - -} diff --git a/spring-web/src/test/java/org/springframework/http/MockHttpOutputMessage.java b/spring-web/src/test/java/org/springframework/http/MockHttpOutputMessage.java index 3d2d5bb2a3..c11c36db71 100644 --- a/spring-web/src/test/java/org/springframework/http/MockHttpOutputMessage.java +++ b/spring-web/src/test/java/org/springframework/http/MockHttpOutputMessage.java @@ -1,5 +1,5 @@ /* - * Copyright 2002-2019 the original author or authors. + * Copyright 2002-2021 the original author or authors. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -21,8 +21,6 @@ import java.io.IOException; import java.io.OutputStream; import java.nio.charset.Charset; -import static org.mockito.Mockito.spy; - /** * @author Arjen Poutsma * @author Rossen Stoyanchev @@ -31,7 +29,7 @@ public class MockHttpOutputMessage implements HttpOutputMessage { private final HttpHeaders headers = new HttpHeaders(); - private final ByteArrayOutputStream body = spy(new ByteArrayOutputStream()); + private final ByteArrayOutputStream body = new ByteArrayOutputStream(); private boolean headersWritten = false; diff --git a/spring-web/src/test/java/org/springframework/http/converter/FormHttpMessageConverterTests.java b/spring-web/src/test/java/org/springframework/http/converter/FormHttpMessageConverterTests.java index 05669acc99..43bfe05520 100644 --- a/spring-web/src/test/java/org/springframework/http/converter/FormHttpMessageConverterTests.java +++ b/spring-web/src/test/java/org/springframework/http/converter/FormHttpMessageConverterTests.java @@ -1,5 +1,5 @@ /* - * Copyright 2002-2020 the original author or authors. + * Copyright 2002-2021 the original author or authors. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -48,8 +48,6 @@ import org.springframework.util.LinkedMultiValueMap; import org.springframework.util.MultiValueMap; import static org.assertj.core.api.Assertions.assertThat; -import static org.mockito.Mockito.never; -import static org.mockito.Mockito.verify; import static org.springframework.http.MediaType.APPLICATION_FORM_URLENCODED; import static org.springframework.http.MediaType.MULTIPART_FORM_DATA; import static org.springframework.http.MediaType.MULTIPART_MIXED; @@ -226,10 +224,9 @@ public class FormHttpMessageConverterTests { item = items.get(5); assertThat(item.getFieldName()).isEqualTo("xml"); assertThat(item.getContentType()).isEqualTo("text/xml"); - verify(outputMessage.getBody(), never()).close(); } - @Test // SPR-13309 + @Test // SPR-13309 public void writeMultipartOrder() throws Exception { MyBean myBean = new MyBean(); myBean.setString("foo"); diff --git a/spring-web/src/test/java/org/springframework/http/converter/StringHttpMessageConverterTests.java b/spring-web/src/test/java/org/springframework/http/converter/StringHttpMessageConverterTests.java index 3323dbdb35..4be55e2b82 100644 --- a/spring-web/src/test/java/org/springframework/http/converter/StringHttpMessageConverterTests.java +++ b/spring-web/src/test/java/org/springframework/http/converter/StringHttpMessageConverterTests.java @@ -102,7 +102,7 @@ public class StringHttpMessageConverterTests { assertThat(headers.getAcceptCharset().isEmpty()).isTrue(); } - @Test // gh-24123 + @Test // gh-24123 public void writeJson() throws IOException { String body = "{\"føø\":\"bår\"}"; this.converter.write(body, MediaType.APPLICATION_JSON, this.outputMessage); @@ -114,7 +114,7 @@ public class StringHttpMessageConverterTests { assertThat(headers.getAcceptCharset().isEmpty()).isTrue(); } - @Test // gh-25328 + @Test // gh-25328 public void writeJsonApi() throws IOException { String body = "{\"føø\":\"bår\"}"; MediaType contentType = new MediaType("application", "vnd.api.v1+json"); diff --git a/spring-web/src/test/java/org/springframework/http/converter/json/MappingJackson2HttpMessageConverterTests.java b/spring-web/src/test/java/org/springframework/http/converter/json/MappingJackson2HttpMessageConverterTests.java index cea6e8c7cf..cef67ddb80 100644 --- a/spring-web/src/test/java/org/springframework/http/converter/json/MappingJackson2HttpMessageConverterTests.java +++ b/spring-web/src/test/java/org/springframework/http/converter/json/MappingJackson2HttpMessageConverterTests.java @@ -1,5 +1,5 @@ /* - * Copyright 2002-2020 the original author or authors. + * Copyright 2002-2021 the original author or authors. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -47,8 +47,6 @@ import static org.assertj.core.api.Assertions.assertThat; import static org.assertj.core.api.Assertions.assertThatExceptionOfType; import static org.assertj.core.api.Assertions.entry; import static org.assertj.core.api.Assertions.within; -import static org.mockito.Mockito.never; -import static org.mockito.Mockito.verify; /** * Jackson 2.x converter tests. @@ -188,7 +186,6 @@ public class MappingJackson2HttpMessageConverterTests { assertThat(result.contains("\"bool\":true")).isTrue(); assertThat(result.contains("\"bytes\":\"AQI=\"")).isTrue(); assertThat(outputMessage.getHeaders().getContentType()).as("Invalid content-type").isEqualTo(MediaType.APPLICATION_JSON); - verify(outputMessage.getBody(), never()).close(); } @Test diff --git a/spring-web/src/test/java/org/springframework/web/context/request/ServletRequestAttributesTests.java b/spring-web/src/test/java/org/springframework/web/context/request/ServletRequestAttributesTests.java index b24979a954..d71be10683 100644 --- a/spring-web/src/test/java/org/springframework/web/context/request/ServletRequestAttributesTests.java +++ b/spring-web/src/test/java/org/springframework/web/context/request/ServletRequestAttributesTests.java @@ -1,5 +1,5 @@ /* - * Copyright 2002-2020 the original author or authors. + * Copyright 2002-2021 the original author or authors. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -51,13 +51,13 @@ public class ServletRequestAttributesTests { @Test - public void ctorRejectsNullArg() throws Exception { + public void ctorRejectsNullArg() { assertThatIllegalArgumentException().isThrownBy(() -> new ServletRequestAttributes(null)); } @Test - public void setRequestScopedAttribute() throws Exception { + public void setRequestScopedAttribute() { MockHttpServletRequest request = new MockHttpServletRequest(); ServletRequestAttributes attrs = new ServletRequestAttributes(request); attrs.setAttribute(KEY, VALUE, RequestAttributes.SCOPE_REQUEST); @@ -66,7 +66,7 @@ public class ServletRequestAttributesTests { } @Test - public void setRequestScopedAttributeAfterCompletion() throws Exception { + public void setRequestScopedAttributeAfterCompletion() { MockHttpServletRequest request = new MockHttpServletRequest(); ServletRequestAttributes attrs = new ServletRequestAttributes(request); request.close(); @@ -75,7 +75,7 @@ public class ServletRequestAttributesTests { } @Test - public void setSessionScopedAttribute() throws Exception { + public void setSessionScopedAttribute() { MockHttpSession session = new MockHttpSession(); session.setAttribute(KEY, VALUE); MockHttpServletRequest request = new MockHttpServletRequest(); @@ -86,7 +86,7 @@ public class ServletRequestAttributesTests { } @Test - public void setSessionScopedAttributeAfterCompletion() throws Exception { + public void setSessionScopedAttributeAfterCompletion() { MockHttpSession session = new MockHttpSession(); session.setAttribute(KEY, VALUE); MockHttpServletRequest request = new MockHttpServletRequest(); @@ -100,7 +100,7 @@ public class ServletRequestAttributesTests { } @Test - public void getSessionScopedAttributeDoesNotForceCreationOfSession() throws Exception { + public void getSessionScopedAttributeDoesNotForceCreationOfSession() { HttpServletRequest request = mock(HttpServletRequest.class); ServletRequestAttributes attrs = new ServletRequestAttributes(request); @@ -110,7 +110,7 @@ public class ServletRequestAttributesTests { } @Test - public void removeSessionScopedAttribute() throws Exception { + public void removeSessionScopedAttribute() { MockHttpSession session = new MockHttpSession(); session.setAttribute(KEY, VALUE); MockHttpServletRequest request = new MockHttpServletRequest(); @@ -122,7 +122,7 @@ public class ServletRequestAttributesTests { } @Test - public void removeSessionScopedAttributeDoesNotForceCreationOfSession() throws Exception { + public void removeSessionScopedAttributeDoesNotForceCreationOfSession() { HttpServletRequest request = mock(HttpServletRequest.class); ServletRequestAttributes attrs = new ServletRequestAttributes(request); @@ -131,7 +131,7 @@ public class ServletRequestAttributesTests { } @Test - public void updateAccessedAttributes() throws Exception { + public void updateAccessedAttributes() { HttpServletRequest request = mock(HttpServletRequest.class); HttpSession session = mock(HttpSession.class); given(request.getSession(anyBoolean())).willReturn(session); @@ -153,7 +153,7 @@ public class ServletRequestAttributesTests { @Test public void skipImmutableCharacter() { - doSkipImmutableValue(new Character('x')); + doSkipImmutableValue(Character.valueOf('x')); } @Test