Use consistent class design
Update all classes so that inner classes are always last. Also ensure that utility classes are always final and have a private constructor and make exceptions final whenever possible. Issue: SPR-16968
This commit is contained in:
committed by
Juergen Hoeller
parent
0ad0f341bd
commit
eeebd51f57
@@ -29,7 +29,7 @@ import org.springframework.lang.Nullable;
|
||||
public class ExpressionException extends RuntimeException {
|
||||
|
||||
@Nullable
|
||||
protected String expressionString;
|
||||
protected final String expressionString;
|
||||
|
||||
protected int position; // -1 if not known; should be known in all reasonable cases
|
||||
|
||||
@@ -40,6 +40,8 @@ public class ExpressionException extends RuntimeException {
|
||||
*/
|
||||
public ExpressionException(String message) {
|
||||
super(message);
|
||||
this.expressionString = null;
|
||||
this.position = 0;
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -49,6 +51,8 @@ public class ExpressionException extends RuntimeException {
|
||||
*/
|
||||
public ExpressionException(String message, Throwable cause) {
|
||||
super(message, cause);
|
||||
this.expressionString = null;
|
||||
this.position = 0;
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -81,6 +85,7 @@ public class ExpressionException extends RuntimeException {
|
||||
*/
|
||||
public ExpressionException(int position, String message) {
|
||||
super(message);
|
||||
this.expressionString = null;
|
||||
this.position = position;
|
||||
}
|
||||
|
||||
@@ -92,6 +97,7 @@ public class ExpressionException extends RuntimeException {
|
||||
*/
|
||||
public ExpressionException(int position, String message, Throwable cause) {
|
||||
super(message, cause);
|
||||
this.expressionString = null;
|
||||
this.position = position;
|
||||
}
|
||||
|
||||
|
||||
@@ -1009,6 +1009,21 @@ public class CodeFlow implements Opcodes {
|
||||
}
|
||||
}
|
||||
|
||||
public static final String toBoxedDescriptor(String primitiveDescriptor) {
|
||||
switch (primitiveDescriptor.charAt(0)) {
|
||||
case 'I': return "Ljava/lang/Integer";
|
||||
case 'J': return "Ljava/lang/Long";
|
||||
case 'F': return "Ljava/lang/Float";
|
||||
case 'D': return "Ljava/lang/Double";
|
||||
case 'B': return "Ljava/lang/Byte";
|
||||
case 'C': return "Ljava/lang/Character";
|
||||
case 'S': return "Ljava/lang/Short";
|
||||
case 'Z': return "Ljava/lang/Boolean";
|
||||
default:
|
||||
throw new IllegalArgumentException("Unexpected non primitive descriptor "+primitiveDescriptor);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Interface used to generate fields.
|
||||
@@ -1029,19 +1044,5 @@ public class CodeFlow implements Opcodes {
|
||||
void generateCode(MethodVisitor mv, CodeFlow codeflow);
|
||||
}
|
||||
|
||||
public static String toBoxedDescriptor(String primitiveDescriptor) {
|
||||
switch (primitiveDescriptor.charAt(0)) {
|
||||
case 'I': return "Ljava/lang/Integer";
|
||||
case 'J': return "Ljava/lang/Long";
|
||||
case 'F': return "Ljava/lang/Float";
|
||||
case 'D': return "Ljava/lang/Double";
|
||||
case 'B': return "Ljava/lang/Byte";
|
||||
case 'C': return "Ljava/lang/Character";
|
||||
case 'S': return "Ljava/lang/Short";
|
||||
case 'Z': return "Ljava/lang/Boolean";
|
||||
default:
|
||||
throw new IllegalArgumentException("Unexpected non primitive descriptor "+primitiveDescriptor);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -41,7 +41,7 @@ import org.springframework.util.ObjectUtils;
|
||||
public abstract class Operator extends SpelNodeImpl {
|
||||
|
||||
private final String operatorName;
|
||||
|
||||
|
||||
// The descriptors of the runtime operand values are used if the discovered declared
|
||||
// descriptors are not providing enough information (for example a generic type
|
||||
// whose accessors seem to only be returning 'Object' - the actual descriptors may
|
||||
@@ -104,8 +104,8 @@ public abstract class Operator extends SpelNodeImpl {
|
||||
return (dc.areNumbers && dc.areCompatible);
|
||||
}
|
||||
|
||||
/**
|
||||
* Numeric comparison operators share very similar generated code, only differing in
|
||||
/**
|
||||
* Numeric comparison operators share very similar generated code, only differing in
|
||||
* two comparison instructions.
|
||||
*/
|
||||
protected void generateComparisonCode(MethodVisitor mv, CodeFlow cf, int compInstruction1, int compInstruction2) {
|
||||
@@ -113,20 +113,20 @@ public abstract class Operator extends SpelNodeImpl {
|
||||
SpelNodeImpl right = getRightOperand();
|
||||
String leftDesc = left.exitTypeDescriptor;
|
||||
String rightDesc = right.exitTypeDescriptor;
|
||||
|
||||
|
||||
boolean unboxLeft = !CodeFlow.isPrimitive(leftDesc);
|
||||
boolean unboxRight = !CodeFlow.isPrimitive(rightDesc);
|
||||
DescriptorComparison dc = DescriptorComparison.checkNumericCompatibility(
|
||||
leftDesc, rightDesc, this.leftActualDescriptor, this.rightActualDescriptor);
|
||||
char targetType = dc.compatibleType; // CodeFlow.toPrimitiveTargetDesc(leftDesc);
|
||||
|
||||
|
||||
cf.enterCompilationScope();
|
||||
left.generateCode(mv, cf);
|
||||
cf.exitCompilationScope();
|
||||
if (unboxLeft) {
|
||||
CodeFlow.insertUnboxInsns(mv, targetType, leftDesc);
|
||||
}
|
||||
|
||||
|
||||
cf.enterCompilationScope();
|
||||
right.generateCode(mv, cf);
|
||||
cf.exitCompilationScope();
|
||||
@@ -142,11 +142,11 @@ public abstract class Operator extends SpelNodeImpl {
|
||||
mv.visitJumpInsn(compInstruction1, elseTarget);
|
||||
}
|
||||
else if (targetType == 'F') {
|
||||
mv.visitInsn(FCMPG);
|
||||
mv.visitInsn(FCMPG);
|
||||
mv.visitJumpInsn(compInstruction1, elseTarget);
|
||||
}
|
||||
else if (targetType == 'J') {
|
||||
mv.visitInsn(LCMP);
|
||||
mv.visitInsn(LCMP);
|
||||
mv.visitJumpInsn(compInstruction1, elseTarget);
|
||||
}
|
||||
else if (targetType == 'I') {
|
||||
@@ -231,13 +231,13 @@ public abstract class Operator extends SpelNodeImpl {
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* A descriptor comparison encapsulates the result of comparing descriptor
|
||||
* for two operands and describes at what level they are compatible.
|
||||
*/
|
||||
protected static class DescriptorComparison {
|
||||
protected static final class DescriptorComparison {
|
||||
|
||||
static final DescriptorComparison NOT_NUMBERS = new DescriptorComparison(false, false, ' ');
|
||||
|
||||
@@ -254,7 +254,7 @@ public abstract class Operator extends SpelNodeImpl {
|
||||
this.areCompatible = areCompatible;
|
||||
this.compatibleType = compatibleType;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Return an object that indicates whether the input descriptors are compatible.
|
||||
* <p>A declared descriptor is what could statically be determined (e.g. from looking
|
||||
@@ -278,7 +278,7 @@ public abstract class Operator extends SpelNodeImpl {
|
||||
|
||||
boolean leftNumeric = CodeFlow.isPrimitiveOrUnboxableSupportedNumberOrBoolean(ld);
|
||||
boolean rightNumeric = CodeFlow.isPrimitiveOrUnboxableSupportedNumberOrBoolean(rd);
|
||||
|
||||
|
||||
// If the declared descriptors aren't providing the information, try the actual descriptors
|
||||
if (!leftNumeric && !ObjectUtils.nullSafeEquals(ld, leftActualDescriptor)) {
|
||||
ld = leftActualDescriptor;
|
||||
@@ -288,7 +288,7 @@ public abstract class Operator extends SpelNodeImpl {
|
||||
rd = rightActualDescriptor;
|
||||
rightNumeric = CodeFlow.isPrimitiveOrUnboxableSupportedNumberOrBoolean(rd);
|
||||
}
|
||||
|
||||
|
||||
if (leftNumeric && rightNumeric) {
|
||||
if (CodeFlow.areBoxingCompatible(ld, rd)) {
|
||||
return new DescriptorComparison(true, true, CodeFlow.toPrimitiveTargetDesc(ld));
|
||||
@@ -299,7 +299,7 @@ public abstract class Operator extends SpelNodeImpl {
|
||||
}
|
||||
else {
|
||||
return DescriptorComparison.NOT_NUMBERS;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2002-2017 the original author or authors.
|
||||
* 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.
|
||||
@@ -64,7 +64,7 @@ import org.springframework.util.ReflectionUtils;
|
||||
* @author Andy Clement
|
||||
* @since 4.1
|
||||
*/
|
||||
public class SpelCompiler implements Opcodes {
|
||||
public final class SpelCompiler implements Opcodes {
|
||||
|
||||
private static final Log logger = LogFactory.getLog(SpelCompiler.class);
|
||||
|
||||
|
||||
@@ -24,7 +24,7 @@ import org.springframework.expression.TypedValue;
|
||||
* @author Andy Clement
|
||||
* @since 3.0
|
||||
*/
|
||||
public class BooleanTypedValue extends TypedValue {
|
||||
public final class BooleanTypedValue extends TypedValue {
|
||||
|
||||
/**
|
||||
* True.
|
||||
|
||||
@@ -39,7 +39,7 @@ import org.springframework.lang.Nullable;
|
||||
* @see #forInstanceMethodInvocation()
|
||||
* @see DataBindingPropertyAccessor
|
||||
*/
|
||||
public class DataBindingMethodResolver extends ReflectiveMethodResolver {
|
||||
public final class DataBindingMethodResolver extends ReflectiveMethodResolver {
|
||||
|
||||
private DataBindingMethodResolver() {
|
||||
super();
|
||||
|
||||
@@ -37,7 +37,7 @@ import java.lang.reflect.Method;
|
||||
* @see StandardEvaluationContext
|
||||
* @see ReflectivePropertyAccessor
|
||||
*/
|
||||
public class DataBindingPropertyAccessor extends ReflectivePropertyAccessor {
|
||||
public final class DataBindingPropertyAccessor extends ReflectivePropertyAccessor {
|
||||
|
||||
/**
|
||||
* Create a new property accessor for reading and possibly also writing.
|
||||
|
||||
@@ -86,7 +86,7 @@ import org.springframework.lang.Nullable;
|
||||
* @see StandardTypeConverter
|
||||
* @see DataBindingPropertyAccessor
|
||||
*/
|
||||
public class SimpleEvaluationContext implements EvaluationContext {
|
||||
public final class SimpleEvaluationContext implements EvaluationContext {
|
||||
|
||||
private static final TypeLocator typeNotFoundTypeLocator = typeName -> {
|
||||
throw new SpelEvaluationException(SpelMessage.TYPE_NOT_FOUND, typeName);
|
||||
|
||||
Reference in New Issue
Block a user