Skip to content

Commit

Permalink
HV-912 Removing methods from ReflectionHelper which make privileged o…
Browse files Browse the repository at this point in the history
…perations publicly accessible
  • Loading branch information
gunnarmorling authored and hferentschik committed Jul 24, 2014
1 parent 7221f8d commit 477465b
Show file tree
Hide file tree
Showing 41 changed files with 764 additions and 522 deletions.
@@ -0,0 +1,71 @@
/*
* JBoss, Home of Professional Open Source
* Copyright 2014, Red Hat, Inc. and/or its affiliates, and individual contributors
* by the @authors tag. See the copyright.txt in the distribution for a
* full listing of individual contributors.
*
* 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
* http://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.hibernate.validator.internal.cdi;

import static org.hibernate.validator.internal.util.CollectionHelper.newArrayList;

import java.lang.reflect.Method;
import java.security.AccessController;
import java.security.PrivilegedAction;
import java.util.Collections;
import java.util.List;

import org.hibernate.validator.internal.util.Contracts;
import org.hibernate.validator.internal.util.classhierarchy.ClassHierarchyHelper;
import org.hibernate.validator.internal.util.privilegedactions.GetMethods;

/**
* Deals with methods of types in inheritance hierarchies.
*
* @author Hardy Ferentschik
* @author Gunnar Morling
*
*/
class InheritedMethodsHelper {

/**
* Get a list of all methods wich the given class declares, implements,
* overrides or inherits. Methods are added by adding first all methods of
* the class itself and its implemented interfaces, then the super class and
* its interfaces, etc.
*
* @param clazz the class for which to retrieve the methods
*
* @return set of all methods of the given class
*/
static List<Method> getAllMethods(Class<?> clazz) {
Contracts.assertNotNull( clazz );

List<Method> methods = newArrayList();

for ( Class<?> hierarchyClass : ClassHierarchyHelper.getHierarchy( clazz ) ) {
Collections.addAll( methods, run( GetMethods.action( hierarchyClass ) ) );
}

return methods;
}

/**
* Runs the given privileged action, using a privileged block if required.
* <p>
* <b>NOTE:</b> This must never be changed into a publicly available method to avoid execution of arbitrary
* privileged actions within HV's protection domain.
*/
private static <T> T run(PrivilegedAction<T> action) {
return System.getSecurityManager() != null ? AccessController.doPrivileged( action ) : action.run();
}
}
Expand Up @@ -26,6 +26,7 @@
import java.util.LinkedList;
import java.util.List;
import java.util.Set;

import javax.enterprise.event.Observes;
import javax.enterprise.inject.Default;
import javax.enterprise.inject.spi.AfterBeanDiscovery;
Expand Down Expand Up @@ -60,7 +61,6 @@
import org.hibernate.validator.internal.util.ExecutableHelper;
import org.hibernate.validator.internal.util.ReflectionHelper;
import org.hibernate.validator.internal.util.TypeResolutionHelper;
import org.hibernate.validator.internal.util.classhierarchy.ClassHierarchyHelper;
import org.hibernate.validator.internal.util.logging.Log;
import org.hibernate.validator.internal.util.logging.LoggerFactory;

Expand Down Expand Up @@ -267,7 +267,7 @@ private <T> Set<AnnotatedCallable<? super T>> determineConstrainedCallables(Anno
private <T> void determineConstrainedMethod(AnnotatedType<T> type,
BeanDescriptor beanDescriptor,
Set<AnnotatedCallable<? super T>> callables) {
List<Method> overriddenAndImplementedMethods = ClassHierarchyHelper.getAllMethods( type.getJavaClass() );
List<Method> overriddenAndImplementedMethods = InheritedMethodsHelper.getAllMethods( type.getJavaClass() );
for ( AnnotatedMethod<? super T> annotatedMethod : type.getMethods() ) {
Method method = annotatedMethod.getJavaMember();

Expand Down
Expand Up @@ -18,8 +18,11 @@

import java.lang.annotation.Annotation;
import java.lang.reflect.Type;
import java.security.AccessController;
import java.security.PrivilegedAction;
import java.util.Collections;
import java.util.Set;

import javax.enterprise.context.ApplicationScoped;
import javax.enterprise.context.spi.CreationalContext;
import javax.enterprise.inject.spi.Bean;
Expand All @@ -36,8 +39,8 @@
import javax.validation.ValidatorFactory;

import org.hibernate.validator.internal.util.CollectionHelper;
import org.hibernate.validator.internal.util.ReflectionHelper;
import org.hibernate.validator.internal.util.classhierarchy.ClassHierarchyHelper;
import org.hibernate.validator.internal.util.privilegedactions.LoadClass;

import static org.hibernate.validator.internal.util.CollectionHelper.newHashSet;

Expand Down Expand Up @@ -141,9 +144,11 @@ private MessageInterpolator createMessageInterpolator(Configuration<?> config) {
}

@SuppressWarnings("unchecked")
Class<MessageInterpolator> messageInterpolatorClass = (Class<MessageInterpolator>) ReflectionHelper.loadClass(
messageInterpolatorFqcn,
this.getClass()
Class<MessageInterpolator> messageInterpolatorClass = (Class<MessageInterpolator>) run(
LoadClass.action(
messageInterpolatorFqcn,
this.getClass()
)
);

return createInstance( messageInterpolatorClass );
Expand All @@ -158,9 +163,11 @@ private TraversableResolver createTraversableResolver(Configuration<?> config) {
}

@SuppressWarnings("unchecked")
Class<TraversableResolver> traversableResolverClass = (Class<TraversableResolver>) ReflectionHelper.loadClass(
traversableResolverFqcn,
this.getClass()
Class<TraversableResolver> traversableResolverClass = (Class<TraversableResolver>) run(
LoadClass.action(
traversableResolverFqcn,
this.getClass()
)
);

return createInstance( traversableResolverClass );
Expand All @@ -175,9 +182,11 @@ private ParameterNameProvider createParameterNameProvider(Configuration<?> confi
}

@SuppressWarnings("unchecked")
Class<ParameterNameProvider> parameterNameProviderClass = (Class<ParameterNameProvider>) ReflectionHelper.loadClass(
parameterNameProviderFqcn,
this.getClass()
Class<ParameterNameProvider> parameterNameProviderClass = (Class<ParameterNameProvider>) run(
LoadClass.action(
parameterNameProviderFqcn,
this.getClass()
)
);

return createInstance( parameterNameProviderClass );
Expand All @@ -193,11 +202,12 @@ private ConstraintValidatorFactory createConstraintValidatorFactory(Configuratio
}

@SuppressWarnings("unchecked")
Class<ConstraintValidatorFactory> constraintValidatorFactoryClass = (Class<ConstraintValidatorFactory>) ReflectionHelper
.loadClass(
Class<ConstraintValidatorFactory> constraintValidatorFactoryClass = (Class<ConstraintValidatorFactory>) run(
LoadClass.action(
constraintValidatorFactoryFqcn,
this.getClass()
);
)
);

return createInstance( constraintValidatorFactoryClass );
}
Expand All @@ -214,6 +224,16 @@ private Configuration<?> getConfiguration() {
Validation.byProvider( org.hibernate.validator.HibernateValidator.class ).configure();
}

/**
* Runs the given privileged action, using a privileged block if required.
* <p>
* <b>NOTE:</b> This must never be changed into a publicly available method to avoid execution of arbitrary
* privileged actions within HV's protection domain.
*/
private <T> T run(PrivilegedAction<T> action) {
return System.getSecurityManager() != null ? AccessController.doPrivileged( action ) : action.run();
}

@Override
public String getId() {
return ValidatorFactoryBean.class.getName() + "_" + ( validationProviderHelper.isDefaultProvider() ? "default" : "hv" );
Expand Down
Expand Up @@ -20,9 +20,12 @@
import java.lang.reflect.Constructor;
import java.lang.reflect.Member;
import java.lang.reflect.Method;
import java.security.AccessController;
import java.security.PrivilegedAction;
import java.util.Arrays;
import java.util.List;
import java.util.Set;

import javax.validation.ParameterNameProvider;

import org.hibernate.validator.cfg.ConstraintDef;
Expand All @@ -44,6 +47,11 @@
import org.hibernate.validator.internal.util.StringHelper;
import org.hibernate.validator.internal.util.logging.Log;
import org.hibernate.validator.internal.util.logging.LoggerFactory;
import org.hibernate.validator.internal.util.privilegedactions.GetDeclaredConstructor;
import org.hibernate.validator.internal.util.privilegedactions.GetDeclaredField;
import org.hibernate.validator.internal.util.privilegedactions.GetDeclaredMethod;
import org.hibernate.validator.internal.util.privilegedactions.GetMethod;
import org.hibernate.validator.internal.util.privilegedactions.NewInstance;
import org.hibernate.validator.spi.group.DefaultGroupSequenceProvider;

import static org.hibernate.validator.internal.util.CollectionHelper.newHashSet;
Expand Down Expand Up @@ -114,7 +122,7 @@ public PropertyConstraintMappingContext property(String property, ElementType el
Contracts.assertNotNull( elementType, "The element type must not be null." );
Contracts.assertNotEmpty( property, MESSAGES.propertyNameMustNotBeEmpty() );

Member member = ReflectionHelper.getMember(
Member member = getMember(
beanClass, property, elementType
);

Expand All @@ -140,7 +148,7 @@ public PropertyConstraintMappingContext property(String property, ElementType el
public MethodConstraintMappingContext method(String name, Class<?>... parameterTypes) {
Contracts.assertNotNull( name, MESSAGES.methodNameMustNotBeNull() );

Method method = ReflectionHelper.getDeclaredMethod( beanClass, name, parameterTypes );
Method method = run( GetDeclaredMethod.action( beanClass, name, parameterTypes ) );

if ( method == null || method.getDeclaringClass() != beanClass ) {
throw log.getUnableToFindMethodException(
Expand All @@ -165,7 +173,7 @@ public MethodConstraintMappingContext method(String name, Class<?>... parameterT

@Override
public ConstructorConstraintMappingContext constructor(Class<?>... parameterTypes) {
Constructor<C> constructor = ReflectionHelper.getDeclaredConstructor( beanClass, parameterTypes );
Constructor<C> constructor = run( GetDeclaredConstructor.action( beanClass, parameterTypes ) );

if ( constructor == null || constructor.getDeclaringClass() != beanClass ) {
throw log.getBeanDoesNotContainConstructorException(
Expand Down Expand Up @@ -227,9 +235,11 @@ private Set<ConstrainedElement> buildConstraintElements(ConstraintHelper constra
}

private DefaultGroupSequenceProvider<? super C> getDefaultGroupSequenceProvider() {
return defaultGroupSequenceProviderClass != null ? ReflectionHelper.newInstance(
defaultGroupSequenceProviderClass,
"default group sequence provider"
return defaultGroupSequenceProviderClass != null ? run(
NewInstance.action(
defaultGroupSequenceProviderClass,
"default group sequence provider"
)
) : null;
}

Expand All @@ -241,4 +251,50 @@ public Class<?> getBeanClass() {
protected ConstraintType getConstraintType() {
return ConstraintType.GENERIC;
}

/**
* Returns the member with the given name and type.
*
* @param clazz The class from which to retrieve the member. Cannot be {@code null}.
* @param property The property name without "is", "get" or "has". Cannot be {@code null} or empty.
* @param elementType The element type. Either {@code ElementType.FIELD} or {@code ElementType METHOD}.
*
* @return the member which matching the name and type or {@code null} if no such member exists.
*/
private Member getMember(Class<?> clazz, String property, ElementType elementType) {
Contracts.assertNotNull( clazz, MESSAGES.classCannotBeNull() );

if ( property == null || property.length() == 0 ) {
throw log.getPropertyNameCannotBeNullOrEmptyException();
}

if ( !( ElementType.FIELD.equals( elementType ) || ElementType.METHOD.equals( elementType ) ) ) {
throw log.getElementTypeHasToBeFieldOrMethodException();
}

Member member = null;
if ( ElementType.FIELD.equals( elementType ) ) {
member = run( GetDeclaredField.action( clazz, property ) );
}
else {
String methodName = property.substring( 0, 1 ).toUpperCase() + property.substring( 1 );
for ( String prefix : ReflectionHelper.PROPERTY_ACCESSOR_PREFIXES ) {
member = run( GetMethod.action( clazz, prefix + methodName ) );
if ( member != null ) {
break;
}
}
}
return member;
}

/**
* Runs the given privileged action, using a privileged block if required.
* <p>
* <b>NOTE:</b> This must never be changed into a publicly available method to avoid execution of arbitrary
* privileged actions within HV's protection domain.
*/
private <T> T run(PrivilegedAction<T> action) {
return System.getSecurityManager() != null ? AccessController.doPrivileged( action ) : action.run();
}
}
Expand Up @@ -16,12 +16,13 @@
*/
package org.hibernate.validator.internal.engine;

import java.security.AccessController;
import java.security.PrivilegedAction;
import java.util.Collections;
import java.util.IdentityHashMap;
import java.util.List;
import java.util.Map;
import java.util.Set;

import javax.validation.ConstraintValidatorFactory;
import javax.validation.MessageInterpolator;
import javax.validation.ParameterNameProvider;
Expand All @@ -40,10 +41,11 @@
import org.hibernate.validator.internal.metadata.provider.ProgrammaticMetaDataProvider;
import org.hibernate.validator.internal.metadata.provider.XmlMetaDataProvider;
import org.hibernate.validator.internal.util.ExecutableHelper;
import org.hibernate.validator.internal.util.ReflectionHelper;
import org.hibernate.validator.internal.util.TypeResolutionHelper;
import org.hibernate.validator.internal.util.logging.Log;
import org.hibernate.validator.internal.util.logging.LoggerFactory;
import org.hibernate.validator.internal.util.privilegedactions.LoadClass;
import org.hibernate.validator.internal.util.privilegedactions.NewInstance;
import org.hibernate.validator.spi.valuehandling.ValidatedValueUnwrapper;

import static org.hibernate.validator.internal.util.CollectionHelper.newArrayList;
Expand Down Expand Up @@ -324,12 +326,21 @@ private List<ValidatedValueUnwrapper<?>> getPropertyConfiguredValidatedValueHand

for ( String handlerName : handlerNames ) {
@SuppressWarnings("unchecked")
Class<? extends ValidatedValueUnwrapper<?>> handlerType = (Class<? extends ValidatedValueUnwrapper<?>>) ReflectionHelper
.loadClass( handlerName, ValidatorFactoryImpl.class );
handlers.add( ReflectionHelper.newInstance( handlerType, "validated value handler class" ) );
Class<? extends ValidatedValueUnwrapper<?>> handlerType = (Class<? extends ValidatedValueUnwrapper<?>>)
run( LoadClass.action( handlerName, ValidatorFactoryImpl.class ) );
handlers.add( run( NewInstance.action( handlerType, "validated value handler class" ) ) );
}

return handlers;
}

/**
* Runs the given privileged action, using a privileged block if required.
* <p>
* <b>NOTE:</b> This must never be changed into a publicly available method to avoid execution of arbitrary
* privileged actions within HV's protection domain.
*/
private <T> T run(PrivilegedAction<T> action) {
return System.getSecurityManager() != null ? AccessController.doPrivileged( action ) : action.run();
}
}

0 comments on commit 477465b

Please sign in to comment.