EvaluationContextFactories.java
package pro.verron.officestamper.preset;
import org.springframework.expression.*;
import org.springframework.expression.spel.SpelEvaluationException;
import org.springframework.expression.spel.SpelMessage;
import org.springframework.expression.spel.support.*;
import pro.verron.officestamper.api.EvaluationContextFactory;
import pro.verron.officestamper.api.OfficeStamperException;
import java.util.ArrayList;
/// Utility class for configuring the [EvaluationContext] used by officestamper.
public class EvaluationContextFactories {
private EvaluationContextFactories() {
throw new OfficeStamperException("EvaluationContextConfigurers cannot be instantiated");
}
/// Returns an [EvaluationContextFactory] instance that does no customization.
/// This factory does nothing to the [StandardEvaluationContext] class, and therefore all the unfiltered features
/// are accessible. It should be used when there is a need to use the powerful features of the aforementioned class,
/// and there is a trust that the template won't contain any dangerous injections.
///
/// @return an [EvaluationContextFactory] instance
public static EvaluationContextFactory noopFactory() {
return object -> {
var standardEvaluationContext = new StandardEvaluationContext(object);
var reflectivePropertyAccessor = new ReflectivePropertyAccessor();
var mapAccessor = new MapAccessor();
var propertyAccessors = new ArrayList<PropertyAccessor>();
propertyAccessors.add(reflectivePropertyAccessor);
propertyAccessors.add(mapAccessor);
standardEvaluationContext.setPropertyAccessors(propertyAccessors);
return standardEvaluationContext;
};
}
/// Returns a default [EvaluationContextFactory] instance.
/// The default factory provides better default security for the [EvaluationContext] used by OfficeStamper. It
/// sets up the context with enhanced security measures, such as limited property accessors, constructor resolvers,
/// and method resolvers. It also sets a type locator, type converter, type comparator, and operator overloader.
/// This factory is recommended to be used when there is a need for improved security and protection against
/// potentially dangerous injections in the template.
///
/// @return an [EvaluationContextFactory] instance with enhanced security features
public static EvaluationContextFactory defaultFactory() {
return object -> {
var standardEvaluationContext = new StandardEvaluationContext(object);
var propertyAccessor = DataBindingPropertyAccessor.forReadWriteAccess();
var mapAccessor = new MapAccessor();
var propertyAccessors = new ArrayList<PropertyAccessor>();
propertyAccessors.add(propertyAccessor);
propertyAccessors.add(mapAccessor);
standardEvaluationContext.setPropertyAccessors(propertyAccessors);
standardEvaluationContext.setConstructorResolvers(new ArrayList<>());
var instanceMethodInvocation = DataBindingMethodResolver.forInstanceMethodInvocation();
var methodResolvers = new ArrayList<MethodResolver>();
methodResolvers.add(instanceMethodInvocation);
standardEvaluationContext.setMethodResolvers(methodResolvers);
BeanResolver beanResolver = (_, _) -> {
throw new AccessException("Bean resolution not supported for security reasons.");
};
standardEvaluationContext.setBeanResolver(beanResolver);
TypeLocator typeLocator = typeName -> {
throw new SpelEvaluationException(SpelMessage.TYPE_NOT_FOUND, typeName);
};
standardEvaluationContext.setTypeLocator(typeLocator);
standardEvaluationContext.setTypeConverter(new StandardTypeConverter());
standardEvaluationContext.setTypeComparator(new StandardTypeComparator());
standardEvaluationContext.setOperatorOverloader(new StandardOperatorOverloader());
return standardEvaluationContext;
};
}
}