SEC-1035: Switch to using spring-el from the Spring 3 build
This commit is contained in:
parent
bd9b199599
commit
df26b2447c
16
core/pom.xml
16
core/pom.xml
|
@ -11,9 +11,19 @@
|
|||
|
||||
<dependencies>
|
||||
<dependency>
|
||||
<groupId>org.springframework.security</groupId>
|
||||
<artifactId>spring-el-security</artifactId>
|
||||
<version>${project.version}</version>
|
||||
<groupId>org.springframework</groupId>
|
||||
<artifactId>org.springframework.expression</artifactId>
|
||||
<version>3.0.0.BUILD-SNAPSHOT</version>
|
||||
<exclusions>
|
||||
<exclusion>
|
||||
<groupId>org.springframework</groupId>
|
||||
<artifactId>org.springframework.core</artifactId>
|
||||
</exclusion>
|
||||
<exclusion>
|
||||
<groupId>org.apache.commons</groupId>
|
||||
<artifactId>com.springsource.org.apache.commons.logging</artifactId>
|
||||
</exclusion>
|
||||
</exclusions>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.springframework</groupId>
|
||||
|
|
3
pom.xml
3
pom.xml
|
@ -17,7 +17,6 @@
|
|||
<module>acl</module>
|
||||
<module>taglibs</module>
|
||||
<module>itest</module>
|
||||
<module>spring-el</module>
|
||||
</modules>
|
||||
|
||||
<description>Spring Security</description>
|
||||
|
@ -691,7 +690,7 @@
|
|||
</dependencies>
|
||||
</dependencyManagement>
|
||||
<properties>
|
||||
<spring.version>2.5.5</spring.version>
|
||||
<spring.version>2.5.6</spring.version>
|
||||
<jstl.version>1.1.2</jstl.version>
|
||||
<jetty.version>6.1.11</jetty.version>
|
||||
|
||||
|
|
|
@ -1,46 +0,0 @@
|
|||
<?xml version="1.0"?>
|
||||
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd">
|
||||
<modelVersion>4.0.0</modelVersion>
|
||||
<parent>
|
||||
<groupId>org.springframework.security</groupId>
|
||||
<artifactId>spring-security-parent</artifactId>
|
||||
<version>2.5.0-SNAPSHOT</version>
|
||||
</parent>
|
||||
<artifactId>spring-el-security</artifactId>
|
||||
<packaging>jar</packaging>
|
||||
<name>Spring Expression Language for Security</name>
|
||||
<dependencies>
|
||||
<dependency>
|
||||
<groupId>commons-logging</groupId>
|
||||
<artifactId>commons-logging</artifactId>
|
||||
<version>1.1.1</version>
|
||||
<optional>true</optional>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.antlr</groupId>
|
||||
<artifactId>antlr</artifactId>
|
||||
<version>3.0.1</version>
|
||||
</dependency>
|
||||
<!--
|
||||
<dependency>
|
||||
<groupId>org.springframework</groupId>
|
||||
<artifactId>spring-core</artifactId>
|
||||
<version>2.5.5</version>
|
||||
</dependency>
|
||||
-->
|
||||
</dependencies>
|
||||
<build>
|
||||
<plugins>
|
||||
<plugin>
|
||||
<groupId>org.apache.maven.plugins</groupId>
|
||||
<artifactId>maven-surefire-plugin</artifactId>
|
||||
<version>2.4.2</version>
|
||||
<configuration>
|
||||
<excludes>
|
||||
<exclude>**/*Tests.class</exclude>
|
||||
</excludes>
|
||||
</configuration>
|
||||
</plugin>
|
||||
</plugins>
|
||||
</build>
|
||||
</project>
|
|
@ -1,44 +0,0 @@
|
|||
/*
|
||||
* Copyright 2004-2008 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
|
||||
*
|
||||
* 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.springframework.expression;
|
||||
|
||||
/**
|
||||
* An AccessException is thrown by an accessor if it has an unexpected problem.
|
||||
*
|
||||
* @author Andy Clement
|
||||
*/
|
||||
public class AccessException extends Exception {
|
||||
|
||||
/**
|
||||
* Create an AccessException with a specific message and cause.
|
||||
*
|
||||
* @param message the message
|
||||
* @param cause the cause
|
||||
*/
|
||||
public AccessException(String message, Exception cause) {
|
||||
super(message, cause);
|
||||
}
|
||||
|
||||
/**
|
||||
* Create an AccessException with a specific message.
|
||||
*
|
||||
* @param message the message
|
||||
*/
|
||||
public AccessException(String message) {
|
||||
super(message);
|
||||
}
|
||||
|
||||
}
|
|
@ -1,57 +0,0 @@
|
|||
package org.springframework.expression;
|
||||
|
||||
/**
|
||||
* A CacheablePropertyAccessor is an optimized PropertyAccessor where the two parts of accessing the property are
|
||||
* separated: (1) resolving the property and (2) retrieving its value. In some cases there is a large cost to
|
||||
* discovering which property an expression refers to and once discovered it will always resolve to the same property.
|
||||
* In these situations a CacheablePropertyAccessor enables the resolution to be done once and a reusable object (an
|
||||
* executor) returned that can be called over and over to retrieve the property value without going through resolution
|
||||
* again.
|
||||
* <p>
|
||||
*
|
||||
* @author Andy Clement
|
||||
*/
|
||||
public abstract class CacheablePropertyAccessor implements PropertyAccessor {
|
||||
|
||||
/**
|
||||
* Attempt to resolve the named property and return an executor that can be called to get the value of that
|
||||
* property. Return null if the property cannot be resolved.
|
||||
*
|
||||
* @param context the evaluation context
|
||||
* @param target the target upon which the property is being accessed
|
||||
* @param name the name of the property being accessed
|
||||
* @return a reusable executor that can retrieve the property value
|
||||
*/
|
||||
public abstract PropertyReaderExecutor getReaderAccessor(EvaluationContext context, Object target, Object name);
|
||||
|
||||
/**
|
||||
* Attempt to resolve the named property and return an executor that can be called to set the value of that
|
||||
* property. Return null if the property cannot be resolved.
|
||||
*
|
||||
* @param context the evaluation context
|
||||
* @param target the target upon which the property is being accessed
|
||||
* @param name the name of the property to be set
|
||||
* @return a reusable executor that can set the property value
|
||||
*/
|
||||
public abstract PropertyWriterExecutor getWriterAccessor(EvaluationContext context, Object target, Object name);
|
||||
|
||||
// Implementation of PropertyAccessor follows, based on the resolver/executor model
|
||||
|
||||
public final boolean canRead(EvaluationContext context, Object target, Object name) throws AccessException {
|
||||
return getReaderAccessor(context, target, name) != null;
|
||||
}
|
||||
|
||||
public final boolean canWrite(EvaluationContext context, Object target, Object name) throws AccessException {
|
||||
return getWriterAccessor(context, target, name) != null;
|
||||
}
|
||||
|
||||
public final Object read(EvaluationContext context, Object target, Object name) throws AccessException {
|
||||
return getReaderAccessor(context, target, name).execute(context, target);
|
||||
}
|
||||
|
||||
public final void write(EvaluationContext context, Object target, Object name, Object newValue)
|
||||
throws AccessException {
|
||||
getWriterAccessor(context, target, name).execute(context, target, newValue);
|
||||
}
|
||||
|
||||
}
|
|
@ -1,43 +0,0 @@
|
|||
/*
|
||||
* Copyright 2004-2008 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
|
||||
*
|
||||
* 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.springframework.expression;
|
||||
|
||||
// TODO Is the resolver/executor model too pervasive in this package?
|
||||
/**
|
||||
* Executors are built by resolvers and can be cached by the infrastructure to repeat an operation quickly without going
|
||||
* back to the resolvers. For example, the particular constructor to run on a class may be discovered by the reflection
|
||||
* constructor resolver - it will then build a ConstructorExecutor that executes that constructor and the
|
||||
* ConstructorExecutor can be reused without needing to go back to the resolver to discover the constructor again.
|
||||
*
|
||||
* They can become stale, and in that case should throw an AccessException - this will cause the infrastructure to go
|
||||
* back to the resolvers to ask for a new one.
|
||||
*
|
||||
* @author Andy Clement
|
||||
*/
|
||||
public interface ConstructorExecutor {
|
||||
|
||||
/**
|
||||
* Execute a constructor in the specified context using the specified arguments.
|
||||
*
|
||||
* @param context the evaluation context in which the command is being executed
|
||||
* @param arguments the arguments to the constructor call, should match (in terms of number and type) whatever the
|
||||
* command will need to run
|
||||
* @return the new object
|
||||
* @throws AccessException if there is a problem executing the command or the CommandExecutor is no longer valid
|
||||
*/
|
||||
Object execute(EvaluationContext context, Object... arguments) throws AccessException;
|
||||
|
||||
}
|
|
@ -1,39 +0,0 @@
|
|||
/*
|
||||
* Copyright 2004-2008 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
|
||||
*
|
||||
* 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.springframework.expression;
|
||||
|
||||
/**
|
||||
* A constructor resolver attempts locate a constructor and returns a ConstructorExecutor that can be used to invoke
|
||||
* that constructor. The ConstructorExecutor will be cached but if it 'goes stale' the resolvers will be called again.
|
||||
*
|
||||
* @author Andy Clement
|
||||
*/
|
||||
public interface ConstructorResolver {
|
||||
|
||||
/**
|
||||
* Within the supplied context determine a suitable constructor on the supplied type that can handle the specified
|
||||
* arguments. Return a ConstructorExecutor that can be used to invoke that constructor (or null if no constructor
|
||||
* could be found).
|
||||
*
|
||||
* @param context the current evaluation context
|
||||
* @param typename the type upon which to look for the constructor
|
||||
* @param argumentTypes the arguments that the constructor must be able to handle
|
||||
* @return a ConstructorExecutor that can invoke the constructor, or null if non found
|
||||
*/
|
||||
ConstructorExecutor resolve(EvaluationContext context, String typename, Class<?>[] argumentTypes)
|
||||
throws AccessException;
|
||||
|
||||
}
|
|
@ -1,87 +0,0 @@
|
|||
/*
|
||||
* Copyright 2004-2008 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
|
||||
*
|
||||
* 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.springframework.expression;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
import org.springframework.expression.spel.standard.StandardEvaluationContext;
|
||||
import org.springframework.expression.spel.standard.StandardTypeUtilities;
|
||||
|
||||
/**
|
||||
* Expressions are executed in an evaluation context. It is in this context that references are resolved when
|
||||
* encountered during expression evaluation.
|
||||
*
|
||||
* There is a default implementation of the EvaluationContext, {@link StandardEvaluationContext} that can be extended,
|
||||
* rather than having to implement everything.
|
||||
*
|
||||
* @author Andy Clement
|
||||
*/
|
||||
public interface EvaluationContext {
|
||||
|
||||
/**
|
||||
* @return the root context object against which unqualified properties/methods/etc should be resolved
|
||||
*/
|
||||
Object getRootContextObject();
|
||||
|
||||
/**
|
||||
* @return a TypeUtilities implementation that can be used for looking up types, converting types, comparing types,
|
||||
* and overloading basic operators for types. A standard implementation is provided in {@link StandardTypeUtilities}
|
||||
*/
|
||||
TypeUtils getTypeUtils();
|
||||
|
||||
/**
|
||||
* Look up a named variable within this execution context.
|
||||
*
|
||||
* @param name variable to lookup
|
||||
* @return the value of the variable
|
||||
*/
|
||||
Object lookupVariable(String name);
|
||||
|
||||
/**
|
||||
* Set a named variable within this execution context to a specified value.
|
||||
*
|
||||
* @param name variable to set
|
||||
* @param value value to be placed in the variable
|
||||
*/
|
||||
void setVariable(String name, Object value);
|
||||
|
||||
// TODO lookupReference() - is it too expensive to return all objects within a context?
|
||||
/**
|
||||
* Look up an object reference in a particular context. If no contextName is specified (null), assume the default
|
||||
* context. If no objectName is specified (null), return all objects in the specified context (List<Object>).
|
||||
*
|
||||
* @param contextName the context in which to perform the lookup (or null for default context)
|
||||
* @param objectName the object to lookup in the context (or null to get all objects)
|
||||
* @return a specific object or List<Object>
|
||||
*/
|
||||
Object lookupReference(Object contextName, Object objectName) throws EvaluationException;
|
||||
|
||||
/**
|
||||
* @return a list of resolvers that will be asked in turn to locate a constructor
|
||||
*/
|
||||
List<ConstructorResolver> getConstructorResolvers();
|
||||
|
||||
/**
|
||||
* @return a list of resolvers that will be asked in turn to locate a method
|
||||
*/
|
||||
List<MethodResolver> getMethodResolvers();
|
||||
|
||||
/**
|
||||
* @return a list of accessors that will be asked in turn to read/write a property
|
||||
*/
|
||||
List<PropertyAccessor> getPropertyAccessors();
|
||||
|
||||
}
|
|
@ -1,99 +0,0 @@
|
|||
/*
|
||||
* Copyright 2004-2008 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
|
||||
*
|
||||
* 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.springframework.expression;
|
||||
|
||||
/**
|
||||
* Base class for exceptions occurring during expression parsing and evaluation.
|
||||
*
|
||||
* @author Andy Clement
|
||||
*/
|
||||
public class EvaluationException extends Exception {
|
||||
|
||||
/**
|
||||
* The expression string.
|
||||
*/
|
||||
private String expressionString;
|
||||
|
||||
/**
|
||||
* Creates a new expression exception. The expressionString field should be set by a later call to
|
||||
* setExpressionString().
|
||||
*
|
||||
* @param cause the underlying cause of this exception
|
||||
*/
|
||||
public EvaluationException(Throwable cause) {
|
||||
super(cause);
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates a new expression parsing exception.
|
||||
*
|
||||
* @param expressionString the expression string that could not be parsed
|
||||
* @param cause the underlying cause of this exception
|
||||
*/
|
||||
public EvaluationException(String expressionString, Throwable cause) {
|
||||
this(expressionString, "Exception occurred whilst handling '" + expressionString + "'", cause);
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates a new expression exception.
|
||||
*
|
||||
* @param expressionString the expression string
|
||||
* @param message a descriptive message
|
||||
* @param cause the underlying cause of this exception
|
||||
*/
|
||||
public EvaluationException(String expressionString, String message, Throwable cause) {
|
||||
super(message, cause);
|
||||
this.expressionString = expressionString;
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates a new expression exception.
|
||||
*
|
||||
* @param expressionString the expression string
|
||||
* @param message a descriptive message
|
||||
*/
|
||||
public EvaluationException(String expressionString, String message) {
|
||||
super(message);
|
||||
this.expressionString = expressionString;
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates a new expression exception. The expressionString field should be set by a later call to
|
||||
* setExpressionString().
|
||||
*
|
||||
* @param message a descriptive message
|
||||
*/
|
||||
public EvaluationException(String message) {
|
||||
super(message);
|
||||
}
|
||||
|
||||
/**
|
||||
* Set the expression string, called on exceptions where the expressionString is not known at the time of exception
|
||||
* creation.
|
||||
*
|
||||
* @param expressionString the expression string
|
||||
*/
|
||||
protected final void setExpressionString(String expressionString) {
|
||||
this.expressionString = expressionString;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return the expression string
|
||||
*/
|
||||
public final String getExpressionString() {
|
||||
return expressionString;
|
||||
}
|
||||
}
|
|
@ -1,110 +0,0 @@
|
|||
/*
|
||||
* Copyright 2004-2008 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
|
||||
*
|
||||
* 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.springframework.expression;
|
||||
|
||||
/**
|
||||
* An expression capable of evaluating itself against context objects. Encapsulates the details of a previously parsed
|
||||
* expression string. Provides a common abstraction for expression evaluation independent of any language like OGNL or
|
||||
* the Unified EL.
|
||||
*
|
||||
* @author Keith Donald
|
||||
* @author Andy Clement
|
||||
*/
|
||||
public interface Expression {
|
||||
|
||||
/**
|
||||
* Evaluate this expression in the default standard context.
|
||||
*
|
||||
* @return the evaluation result
|
||||
* @throws EvaluationException if there is a problem during evaluation
|
||||
*/
|
||||
public Object getValue() throws EvaluationException;
|
||||
|
||||
/**
|
||||
* Evaluate the expression in the default standard context. If the result of the evaluation does not match (and
|
||||
* cannot be converted to) the expected result type then an exception will be returned.
|
||||
*
|
||||
* @param desiredResultType the class the caller would like the result to be
|
||||
* @return the evaluation result
|
||||
* @throws EvaluationException if there is a problem during evaluation
|
||||
*/
|
||||
public Object getValue(Class<?> desiredResultType) throws EvaluationException;
|
||||
|
||||
/**
|
||||
* Evaluate this expression in the provided context and return the result of evaluation.
|
||||
*
|
||||
* @param context the context in which to evaluate the expression
|
||||
* @return the evaluation result
|
||||
* @throws EvaluationException if there is a problem during evaluation
|
||||
*/
|
||||
public Object getValue(EvaluationContext context) throws EvaluationException;
|
||||
|
||||
/**
|
||||
* Evaluate the expression in a specified context which can resolve references to properties, methods, types, etc -
|
||||
* the type of the evaluation result is expected to be of a particular class and an exception will be thrown if it
|
||||
* is not and cannot be converted to that type.
|
||||
*
|
||||
* @param context the context in which to evaluate the expression
|
||||
* @param desiredResultType the class the caller would like the result to be
|
||||
* @return the evaluation result
|
||||
* @throws EvaluationException if there is a problem during evaluation
|
||||
*/
|
||||
public Object getValue(EvaluationContext context, Class<?> desiredResultType) throws EvaluationException;
|
||||
|
||||
/**
|
||||
* Set this expression in the provided context to the value provided.
|
||||
*
|
||||
* @param context the context in which to set the value of the expression
|
||||
* @param value the new value
|
||||
* @throws EvaluationException if there is a problem during evaluation
|
||||
*/
|
||||
public void setValue(EvaluationContext context, Object value) throws EvaluationException;
|
||||
|
||||
/**
|
||||
* Returns the most general type that can be passed to the {@link #setValue(EvaluationContext, Object)} method for
|
||||
* the given context.
|
||||
*
|
||||
* @param context the context in which to evaluate the expression
|
||||
* @return the most general type of value that can be set on this context
|
||||
* @throws EvaluationException if there is a problem determining the type
|
||||
*/
|
||||
public Class getValueType(EvaluationContext context) throws EvaluationException;
|
||||
|
||||
/**
|
||||
* Returns the most general type that can be passed to the {@link #setValue(EvaluationContext, Object)} method using
|
||||
* the default context.
|
||||
*
|
||||
* @return the most general type of value that can be set on this context
|
||||
* @throws EvaluationException if there is a problem determining the type
|
||||
*/
|
||||
public Class getValueType() throws EvaluationException;
|
||||
|
||||
/**
|
||||
* Returns the original string used to create this expression, unmodified.
|
||||
*
|
||||
* @return the original expression string
|
||||
*/
|
||||
public String getExpressionString();
|
||||
|
||||
/**
|
||||
* Determine if an expression can be written to, i.e. setValue() can be called.
|
||||
*
|
||||
* @param context the context in which the expression should be checked
|
||||
* @return true if the expression is writable
|
||||
* @throws EvaluationException if there is a problem determining if it is writable
|
||||
*/
|
||||
public boolean isWritable(EvaluationContext context) throws EvaluationException;
|
||||
}
|
|
@ -1,56 +0,0 @@
|
|||
/*
|
||||
* Copyright 2004-2008 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
|
||||
*
|
||||
* 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.springframework.expression;
|
||||
|
||||
/**
|
||||
* Parses expression strings into compiled expressions that can be evaluated. Supports parsing templates as well as
|
||||
* standard expression strings.
|
||||
*
|
||||
* @author Keith Donald
|
||||
* @author Andy Clement
|
||||
*/
|
||||
public interface ExpressionParser {
|
||||
|
||||
/**
|
||||
* Parse the expression string and return an Expression object you can use for repeated evaluation. Some examples:
|
||||
*
|
||||
* <pre>
|
||||
* 3 + 4
|
||||
* name.firstName
|
||||
* </pre>
|
||||
*
|
||||
* @param expressionString the raw expression string to parse
|
||||
* @param context a context for influencing this expression parsing routine (optional)
|
||||
* @return an evaluator for the parsed expression
|
||||
* @throws ParseException an exception occurred during parsing
|
||||
*/
|
||||
public Expression parseExpression(String expressionString, ParserContext context) throws ParseException;
|
||||
|
||||
/**
|
||||
* Parse the expression string and return an Expression object you can use for repeated evaluation. Some examples:
|
||||
*
|
||||
* <pre>
|
||||
* 3 + 4
|
||||
* name.firstName
|
||||
* </pre>
|
||||
*
|
||||
* @param expressionString the raw expression string to parse
|
||||
* @return an evaluator for the parsed expression
|
||||
* @throws ParseException an exception occurred during parsing
|
||||
*/
|
||||
public Expression parseExpression(String expressionString) throws ParseException;
|
||||
|
||||
}
|
|
@ -1,43 +0,0 @@
|
|||
/*
|
||||
* Copyright 2004-2008 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
|
||||
*
|
||||
* 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.springframework.expression;
|
||||
|
||||
/**
|
||||
* MethodExecutors are built by the resolvers and can be cached by the infrastructure to repeat an operation quickly
|
||||
* without going back to the resolvers. For example, the particular method to run on an object may be discovered by the
|
||||
* reflection method resolver - it will then build a MethodExecutor that executes that method and the MethodExecutor can
|
||||
* be reused without needing to go back to the resolver to discover the method again.
|
||||
* <p>
|
||||
* They can become stale, and in that case should throw an AccessException - this will cause the infrastructure to go
|
||||
* back to the resolvers to ask for a new one.
|
||||
*
|
||||
* @author Andy Clement
|
||||
*/
|
||||
public interface MethodExecutor {
|
||||
|
||||
/**
|
||||
* Execute a command using the specified arguments, and using the specified expression state.
|
||||
*
|
||||
* @param context the evaluation context in which the command is being executed
|
||||
* @param target the target object of the call - null for static methods
|
||||
* @param methodArguments the arguments to the executor, should match (in terms of number and type) whatever the
|
||||
* command will need to run
|
||||
* @return the value returned from execution
|
||||
* @throws AccessException if there is a problem executing the command or the MethodExecutor is no longer valid
|
||||
*/
|
||||
Object execute(EvaluationContext context, Object target, Object... methodArguments) throws AccessException;
|
||||
|
||||
}
|
|
@ -1,38 +0,0 @@
|
|||
/*
|
||||
* Copyright 2004-2008 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
|
||||
*
|
||||
* 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.springframework.expression;
|
||||
|
||||
/**
|
||||
* A method resolver attempts locate a method and returns a command executor that can be used to invoke that method. The
|
||||
* command executor will be cached but if it 'goes stale' the resolvers will be called again.
|
||||
*
|
||||
* @author Andy Clement
|
||||
*/
|
||||
public interface MethodResolver {
|
||||
|
||||
/**
|
||||
* Within the supplied context determine a suitable method on the supplied object that can handle the specified
|
||||
* arguments. Return a MethodExecutor that can be used to invoke that method (or null if no method
|
||||
* could be found).
|
||||
*
|
||||
* @param context the current evaluation context
|
||||
* @param targetObject the object upon which the method is being called
|
||||
* @param argumentTypes the arguments that the constructor must be able to handle
|
||||
* @return a MethodExecutor that can invoke the method, or null if the method cannot be found
|
||||
*/
|
||||
MethodExecutor resolve(EvaluationContext context, Object targetObject, String name, Class<?>[] argumentTypes) throws AccessException;
|
||||
|
||||
}
|
|
@ -1,26 +0,0 @@
|
|||
/*
|
||||
* Copyright 2004-2008 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
|
||||
*
|
||||
* 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.springframework.expression;
|
||||
|
||||
|
||||
/**
|
||||
* Supported operations that an {@link OperatorOverloader} can implement for any pair of operands.
|
||||
*
|
||||
* @author Andy Clement
|
||||
*/
|
||||
public enum Operation {
|
||||
ADD, SUBTRACT, DIVIDE, MULTIPLY, MODULUS;
|
||||
}
|
|
@ -1,37 +0,0 @@
|
|||
package org.springframework.expression;
|
||||
|
||||
/**
|
||||
* By default the mathematical operators {@link Operation} support simple types like numbers. By providing an
|
||||
* implementation of OperatorOverloader, a user of the expression language can support these operations on other types.
|
||||
*
|
||||
* @author Andy Clement
|
||||
*/
|
||||
public interface OperatorOverloader {
|
||||
|
||||
// TODO does type OperatorOverloader need a better name?
|
||||
// TODO Operator overloading needs some testing!
|
||||
|
||||
/**
|
||||
* Return true if the operator overloader supports the specified operation between the two operands and so should be
|
||||
* invoked to handle it.
|
||||
*
|
||||
* @param operation the operation to be performed
|
||||
* @param leftOperand the left operand
|
||||
* @param rightOperand the right operand
|
||||
* @return true if the OperatorOverloader supports the specified operation between the two operands
|
||||
* @throws EvaluationException if there is a problem performing the operation
|
||||
*/
|
||||
boolean overridesOperation(Operation operation, Object leftOperand, Object rightOperand) throws EvaluationException;
|
||||
|
||||
/**
|
||||
* Execute the specified operation on two operands, returning a result. See {@link Operation} for supported
|
||||
* operations.
|
||||
*
|
||||
* @param operation the operation to be performed
|
||||
* @param leftOperand the left operand
|
||||
* @param rightOperand the right operand
|
||||
* @return the result of performing the operation on the two operands
|
||||
* @throws EvaluationException if there is a problem performing the operation
|
||||
*/
|
||||
Object operate(Operation operation, Object leftOperand, Object rightOperand) throws EvaluationException;
|
||||
}
|
|
@ -1,89 +0,0 @@
|
|||
/*
|
||||
* Copyright 2004-2008 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
|
||||
*
|
||||
* 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.springframework.expression;
|
||||
|
||||
/**
|
||||
* Base class for exceptions occurring during expression parsing and evaluation.
|
||||
*
|
||||
* @author Andy Clement
|
||||
*/
|
||||
public class ParseException extends Exception {
|
||||
|
||||
/**
|
||||
* The expression string.
|
||||
*/
|
||||
private String expressionString;
|
||||
|
||||
/**
|
||||
* Creates a new expression exception. The expressionString field should be set by a later call to
|
||||
* setExpressionString().
|
||||
*
|
||||
* @param cause the underlying cause of this exception
|
||||
*/
|
||||
public ParseException(Throwable cause) {
|
||||
super(cause);
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates a new expression parsing exception.
|
||||
*
|
||||
* @param expressionString the expression string that could not be parsed
|
||||
* @param cause the underlying cause of this exception
|
||||
*/
|
||||
public ParseException(String expressionString, Throwable cause) {
|
||||
this(expressionString, "Exception occurred whilst handling '" + expressionString + "'", cause);
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates a new expression exception.
|
||||
*
|
||||
* @param expressionString the expression string
|
||||
* @param message a descriptive message
|
||||
* @param cause the underlying cause of this exception
|
||||
*/
|
||||
public ParseException(String expressionString, String message, Throwable cause) {
|
||||
super(message, cause);
|
||||
this.expressionString = expressionString;
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates a new expression exception.
|
||||
*
|
||||
* @param expressionString the expression string
|
||||
* @param message a descriptive message
|
||||
*/
|
||||
public ParseException(String expressionString, String message) {
|
||||
super(message);
|
||||
this.expressionString = expressionString;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set the expression string, called on exceptions where the expressionString is not known at the time of exception
|
||||
* creation.
|
||||
*
|
||||
* @param expressionString the expression string
|
||||
*/
|
||||
protected final void setExpressionString(String expressionString) {
|
||||
this.expressionString = expressionString;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return the expression string
|
||||
*/
|
||||
public final String getExpressionString() {
|
||||
return expressionString;
|
||||
}
|
||||
}
|
|
@ -1,55 +0,0 @@
|
|||
/*
|
||||
* Copyright 2004-2008 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
|
||||
*
|
||||
* 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.springframework.expression;
|
||||
|
||||
/**
|
||||
* Input provided to an expression parser that can influence an expression parsing/compilation routine.
|
||||
*
|
||||
* @author Keith Donald
|
||||
* @author Andy Clement
|
||||
*/
|
||||
public interface ParserContext {
|
||||
|
||||
/**
|
||||
* Whether or not the expression being parsed is a template. A template expression consists of literal text that can
|
||||
* be mixed with evaluatable blocks. Some examples:
|
||||
*
|
||||
* <pre>
|
||||
* Some literal text
|
||||
* Hello ${name.firstName}!
|
||||
* ${3 + 4}
|
||||
* </pre>
|
||||
*
|
||||
* @return true if the expression is a template, false otherwise
|
||||
*/
|
||||
public boolean isTemplate();
|
||||
|
||||
/**
|
||||
* For template expressions, returns the prefix that identifies the start of an expression block within a string.
|
||||
* For example "${"
|
||||
*
|
||||
* @return the prefix that identifies the start of an expression
|
||||
*/
|
||||
public String getExpressionPrefix();
|
||||
|
||||
/**
|
||||
* For template expressions, return the prefix that identifies the end of an expression block within a string. For
|
||||
* example "}$"
|
||||
*
|
||||
* @return the suffix that identifies the end of an expression
|
||||
*/
|
||||
public String getExpressionSuffix();
|
||||
}
|
|
@ -1,88 +0,0 @@
|
|||
/*
|
||||
* Copyright 2004-2008 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
|
||||
*
|
||||
* 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.springframework.expression;
|
||||
|
||||
/**
|
||||
* A property accessor is able to read (and possibly write) to object properties. The interface places no restrictions
|
||||
* and so implementors are free to access properties directly as fields or through getters or in any other way they see
|
||||
* as appropriate. A resolver can optionally specify an array of target classes for which it should be called - but if
|
||||
* it returns null from getSpecificTargetClasses() then it will be called for all property references and given a chance
|
||||
* to determine if it can read or write them. Property resolvers are considered to be ordered and each will be called in
|
||||
* turn. The only rule that affects the call order is that any naming the target class directly in
|
||||
* getSpecifiedTargetClasses() will be called first, before the general resolvers.
|
||||
* <p>
|
||||
* If the cost of locating the property is expensive, in relation to actually retrieving its value, consider extending
|
||||
* CacheablePropertyAccessor rather than directly implementing PropertyAccessor. A CacheablePropertyAccessor enables the
|
||||
* discovery (resolution) of the property to be done once and then an object (an executor) returned and cached by the
|
||||
* infrastructure that can be used repeatedly to retrieve the property value.
|
||||
*
|
||||
* @author Andy Clement
|
||||
*/
|
||||
public interface PropertyAccessor {
|
||||
|
||||
/**
|
||||
* Return an array of classes for which this resolver should be called. Returning null indicates this is a general
|
||||
* resolver that can be called in an attempt to resolve a property on any type.
|
||||
*
|
||||
* @return an array of classes that this resolver is suitable for (or null if a general resolver)
|
||||
*/
|
||||
public Class[] getSpecificTargetClasses();
|
||||
|
||||
/**
|
||||
* Called to determine if a resolver instance is able to access a specified property on a specified target object.
|
||||
*
|
||||
* @param context the evaluation context in which the access is being attempted
|
||||
* @param target the target object upon which the property is being accessed
|
||||
* @param name the name of the property being accessed
|
||||
* @return true if this resolver is able to read the property
|
||||
* @throws AccessException if there is any problem determining whether the property can be read
|
||||
*/
|
||||
public boolean canRead(EvaluationContext context, Object target, Object name) throws AccessException;
|
||||
|
||||
/**
|
||||
* Called to read a property from a specified target object
|
||||
*
|
||||
* @param context the evaluation context in which the access is being attempted
|
||||
* @param target the target object upon which the property is being accessed
|
||||
* @param name the name of the property being accessed
|
||||
* @return Object the value of the property
|
||||
* @throws AccessException if there is any problem accessing the property value
|
||||
*/
|
||||
public Object read(EvaluationContext context, Object target, Object name) throws AccessException;
|
||||
|
||||
/**
|
||||
* Called to determine if a resolver instance is able to write to a specified property on a specified target object.
|
||||
*
|
||||
* @param context the evaluation context in which the access is being attempted
|
||||
* @param target the target object upon which the property is being accessed
|
||||
* @param name the name of the property being accessed
|
||||
* @return true if this resolver is able to write to the property
|
||||
* @throws AccessException if there is any problem determining whether the property can be written to
|
||||
*/
|
||||
public boolean canWrite(EvaluationContext context, Object target, Object name) throws AccessException;
|
||||
|
||||
/**
|
||||
* Called to write to a property on a specified target object. Should only succeed if canWrite() also returns true.
|
||||
*
|
||||
* @param context the evaluation context in which the access is being attempted
|
||||
* @param target the target object upon which the property is being accessed
|
||||
* @param name the name of the property being accessed
|
||||
* @param newValue the new value for the property
|
||||
* @throws AccessException if there is any problem writing to the property value
|
||||
*/
|
||||
public void write(EvaluationContext context, Object target, Object name, Object newValue) throws AccessException;
|
||||
|
||||
}
|
|
@ -1,40 +0,0 @@
|
|||
/*
|
||||
* Copyright 2004-2008 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
|
||||
*
|
||||
* 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.springframework.expression;
|
||||
|
||||
/**
|
||||
* If a property accessor is built upon the CacheablePropertyAccessor class then once the property
|
||||
* has been resolved the accessor will return an instance of this PropertyReaderExecutor interface
|
||||
* that can be cached and repeatedly called to access the value of the property.
|
||||
* <p>
|
||||
* They can become stale, and in that case should throw an AccessException - this will cause the
|
||||
* infrastructure to go back to the resolvers to ask for a new one.
|
||||
*
|
||||
* @author Andy Clement
|
||||
*/
|
||||
public interface PropertyReaderExecutor {
|
||||
|
||||
/**
|
||||
* Return the value of a property for the specified target.
|
||||
*
|
||||
* @param context the evaluation context in which the command is being executed
|
||||
* @param targetObject the target object on which property access is being attempted
|
||||
* @return the property value
|
||||
* @throws AccessException if there is a problem accessing the property or this executor has become stale
|
||||
*/
|
||||
Object execute(EvaluationContext context, Object targetObject) throws AccessException;
|
||||
|
||||
}
|
|
@ -1,40 +0,0 @@
|
|||
/*
|
||||
* Copyright 2004-2008 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
|
||||
*
|
||||
* 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.springframework.expression;
|
||||
|
||||
/**
|
||||
* If a property accessor is built upon the CacheablePropertyAccessor class then once the property
|
||||
* has been resolved the accessor will return an instance of this PropertyWriterExecutor interface
|
||||
* that can be cached and repeatedly called to set the value of the property.
|
||||
* <p>
|
||||
* They can become stale, and in that case should throw an AccessException - this will cause the
|
||||
* infrastructure to go back to the resolvers to ask for a new one.
|
||||
*
|
||||
* @author Andy Clement
|
||||
*/
|
||||
public interface PropertyWriterExecutor {
|
||||
|
||||
/**
|
||||
* Set the value of a property to the supplied new value.
|
||||
*
|
||||
* @param context the evaluation context in which the command is being executed
|
||||
* @param targetObject the target object on which property write is being attempted
|
||||
* @param newValue the new value for the property
|
||||
* @throws AccessException if there is a problem setting the property or this executor has become stale
|
||||
*/
|
||||
void execute(EvaluationContext evaluationContext, Object targetObject, Object newValue) throws AccessException;
|
||||
|
||||
}
|
|
@ -1,46 +0,0 @@
|
|||
/*
|
||||
* Copyright 2004-2008 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
|
||||
*
|
||||
* 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.springframework.expression;
|
||||
|
||||
/**
|
||||
* Instances of a type comparator should be able to compare pairs of objects for equality, the specification of the
|
||||
* return value is the same as for {@link Comparable}.
|
||||
*
|
||||
* @author Andy Clement
|
||||
*/
|
||||
public interface TypeComparator {
|
||||
|
||||
/**
|
||||
* Compare two objects.
|
||||
*
|
||||
* @param firstObject the first object
|
||||
* @param secondObject the second object
|
||||
* @return 0 if they are equal, <0 if the first is smaller than the second, or >0 if the first is larger than the
|
||||
* second
|
||||
* @throws EvaluationException if a problem occurs during comparison (or they are not comparable)
|
||||
*/
|
||||
int compare(Object firstObject, Object secondObject) throws EvaluationException;
|
||||
|
||||
/**
|
||||
* Return true if the comparator can compare these two objects
|
||||
*
|
||||
* @param firstObject the first object
|
||||
* @param secondObject the second object
|
||||
* @return true if the comparator can compare these objects
|
||||
*/
|
||||
public boolean canCompare(Object firstObject, Object secondObject);
|
||||
|
||||
}
|
|
@ -1,52 +0,0 @@
|
|||
/*
|
||||
* Copyright 2004-2008 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
|
||||
*
|
||||
* 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.springframework.expression;
|
||||
|
||||
import org.springframework.expression.spel.standard.StandardIndividualTypeConverter;
|
||||
import org.springframework.expression.spel.standard.StandardTypeConverter;
|
||||
|
||||
/**
|
||||
* A type converter can convert values between different types. There is a default implementation called
|
||||
* {@link StandardTypeConverter} that supports some basic conversions. That default implementation can be extended
|
||||
* through subclassing or via registration of new {@link StandardIndividualTypeConverter} instances with the
|
||||
* StandardTypeConverter.
|
||||
*
|
||||
* @author Andy Clement
|
||||
*/
|
||||
public interface TypeConverter {
|
||||
// TODO replace this stuff with Keiths spring-binding conversion code
|
||||
// TODO should ExpressionException be thrown for lost precision in the case of coercion?
|
||||
|
||||
/**
|
||||
* Convert (may coerce) a value from one type to another, for example from a boolean to a string.
|
||||
*
|
||||
* @param value the value to be converted
|
||||
* @param targetType the type that the value should be converted to if possible
|
||||
* @return the converted value
|
||||
* @throws EvaluationException if conversion is not possible
|
||||
*/
|
||||
Object convertValue(Object value, Class<?> targetType) throws EvaluationException;
|
||||
|
||||
/**
|
||||
* Return true if the type converter can convert the specified type to the desired target type.
|
||||
*
|
||||
* @param sourceType the type to be converted from
|
||||
* @param targetType the type to be converted to
|
||||
* @return true if that conversion can be performed
|
||||
*/
|
||||
public boolean canConvert(Class<?> sourceType, Class<?> targetType);
|
||||
|
||||
}
|
|
@ -1,38 +0,0 @@
|
|||
/*
|
||||
* Copyright 2004-2008 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
|
||||
*
|
||||
* 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.springframework.expression;
|
||||
|
||||
import org.springframework.expression.spel.standard.StandardTypeLocator;
|
||||
|
||||
/**
|
||||
* Implementors of this interface are expected to be able to locate types. They may use custom classloaders or the
|
||||
* and deal with common package prefixes (java.lang, etc) however they wish. See
|
||||
* {@link StandardTypeLocator} for an example implementation.
|
||||
*
|
||||
* @author Andy Clement
|
||||
*/
|
||||
public interface TypeLocator {
|
||||
|
||||
/**
|
||||
* Find a type by name. The name may or may not be fully qualified (eg. String or java.lang.String)
|
||||
*
|
||||
* @param type the type to be located
|
||||
* @return the class object representing that type
|
||||
* @throw ExpressionException if there is a problem finding it
|
||||
*/
|
||||
Class<?> findType(String typename) throws EvaluationException;
|
||||
|
||||
}
|
|
@ -1,54 +0,0 @@
|
|||
/*
|
||||
* Copyright 2004-2008 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
|
||||
*
|
||||
* 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.springframework.expression;
|
||||
|
||||
/**
|
||||
* TypeUtilities brings together the various kinds of type related function that may occur
|
||||
* whilst working with expressions. An implementor is providing support for four type related
|
||||
* facilities:
|
||||
* <ul>
|
||||
* <li>a mechanism for finding types
|
||||
* <li>a mechanism for comparing types
|
||||
* <li>a mechanism for type conversion/coercion
|
||||
* <li>a mechanism for overloading mathematical operations (add/subtract/etc)
|
||||
* </ul>
|
||||
*
|
||||
* @author Andy Clement
|
||||
*/
|
||||
public interface TypeUtils {
|
||||
|
||||
/**
|
||||
* @return a type locator that can be used to find types, either by short or fully qualified name.
|
||||
*/
|
||||
TypeLocator getTypeLocator();
|
||||
|
||||
/**
|
||||
* @return a type comparator for comparing pairs of objects for equality.
|
||||
*/
|
||||
TypeComparator getTypeComparator();
|
||||
|
||||
/**
|
||||
* @return a type converter that can convert (or coerce) a value from one type to another.
|
||||
*/
|
||||
TypeConverter getTypeConverter();
|
||||
|
||||
/**
|
||||
* @return an operator overloader that may support mathematical operations between more than the standard set of
|
||||
* types
|
||||
*/
|
||||
OperatorOverloader getOperatorOverloader();
|
||||
|
||||
}
|
|
@ -1,78 +0,0 @@
|
|||
package org.springframework.expression.common;
|
||||
|
||||
import org.springframework.expression.EvaluationContext;
|
||||
import org.springframework.expression.EvaluationException;
|
||||
import org.springframework.expression.Expression;
|
||||
|
||||
/**
|
||||
* Represents a template expression broken into pieces. Each piece will be an Expression but pure text parts to the
|
||||
* template will be represented as LiteralExpression objects. An example of a template expression might be: <code><pre>
|
||||
* "Hello ${getName()}"
|
||||
* </pre></code> which will be represented as a CompositeStringExpression of two parts. The first part being a
|
||||
* LiteralExpression representing 'Hello ' and the second part being a real expression that will call getName() when
|
||||
* invoked.
|
||||
*
|
||||
* @author Andy Clement
|
||||
*/
|
||||
public class CompositeStringExpression implements Expression {
|
||||
|
||||
private final String expressionString;
|
||||
|
||||
/**
|
||||
* The array of expressions that make up the composite expression
|
||||
*/
|
||||
private final Expression[] expressions;
|
||||
|
||||
public CompositeStringExpression(String expressionString, Expression[] expressions) {
|
||||
this.expressionString = expressionString;
|
||||
this.expressions = expressions;
|
||||
}
|
||||
|
||||
public String getExpressionString() {
|
||||
return expressionString;
|
||||
}
|
||||
|
||||
public String getValue() throws EvaluationException {
|
||||
StringBuilder sb = new StringBuilder();
|
||||
for (int i = 0; i < expressions.length; i++) {
|
||||
// TODO is stringify ok for the non literal components? or should the converters be used? see another
|
||||
// case below
|
||||
sb.append(expressions[i].getValue());
|
||||
}
|
||||
return sb.toString();
|
||||
}
|
||||
|
||||
public String getValue(EvaluationContext context) throws EvaluationException {
|
||||
StringBuilder sb = new StringBuilder();
|
||||
for (int i = 0; i < expressions.length; i++) {
|
||||
sb.append(expressions[i].getValue(context));
|
||||
}
|
||||
return sb.toString();
|
||||
}
|
||||
|
||||
public Class getValueType(EvaluationContext context) throws EvaluationException {
|
||||
return String.class;
|
||||
}
|
||||
|
||||
public Class getValueType() throws EvaluationException {
|
||||
return String.class;
|
||||
}
|
||||
|
||||
public void setValue(EvaluationContext context, Object value) throws EvaluationException {
|
||||
throw new EvaluationException(expressionString, "Cannot call setValue() on a composite expression");
|
||||
}
|
||||
|
||||
public Object getValue(EvaluationContext context, Class<?> expectedResultType) throws EvaluationException {
|
||||
Object value = getValue(context);
|
||||
return ExpressionUtils.convert(context, value, expectedResultType);
|
||||
}
|
||||
|
||||
public Object getValue(Class<?> expectedResultType) throws EvaluationException {
|
||||
Object value = getValue();
|
||||
return ExpressionUtils.convert(null, value, expectedResultType);
|
||||
}
|
||||
|
||||
public boolean isWritable(EvaluationContext context) throws EvaluationException {
|
||||
return false;
|
||||
}
|
||||
}
|
|
@ -1,24 +0,0 @@
|
|||
package org.springframework.expression.common;
|
||||
|
||||
import org.springframework.expression.ParserContext;
|
||||
|
||||
public class DefaultNonTemplateParserContext implements ParserContext {
|
||||
|
||||
public static final DefaultNonTemplateParserContext INSTANCE = new DefaultNonTemplateParserContext();
|
||||
|
||||
private DefaultNonTemplateParserContext() {
|
||||
}
|
||||
|
||||
public String getExpressionPrefix() {
|
||||
return null;
|
||||
}
|
||||
|
||||
public String getExpressionSuffix() {
|
||||
return null;
|
||||
}
|
||||
|
||||
public boolean isTemplate() {
|
||||
return false;
|
||||
}
|
||||
|
||||
}
|
|
@ -1,24 +0,0 @@
|
|||
package org.springframework.expression.common;
|
||||
|
||||
import org.springframework.expression.ParserContext;
|
||||
|
||||
public class DefaultTemplateParserContext implements ParserContext {
|
||||
|
||||
public static final DefaultTemplateParserContext INSTANCE = new DefaultTemplateParserContext();
|
||||
|
||||
private DefaultTemplateParserContext() {
|
||||
}
|
||||
|
||||
public String getExpressionPrefix() {
|
||||
return "${";
|
||||
}
|
||||
|
||||
public String getExpressionSuffix() {
|
||||
return "}";
|
||||
}
|
||||
|
||||
public boolean isTemplate() {
|
||||
return true;
|
||||
}
|
||||
|
||||
}
|
|
@ -1,55 +0,0 @@
|
|||
/*
|
||||
* Copyright 2004-2008 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
|
||||
*
|
||||
* 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.springframework.expression.common;
|
||||
|
||||
import org.springframework.expression.EvaluationContext;
|
||||
import org.springframework.expression.EvaluationException;
|
||||
import org.springframework.expression.TypeConverter;
|
||||
import org.springframework.expression.TypeUtils;
|
||||
|
||||
/**
|
||||
* Common utility functions that may be used by any Expression Language provider.
|
||||
*
|
||||
* @author Andy Clement
|
||||
*/
|
||||
public class ExpressionUtils {
|
||||
|
||||
/**
|
||||
* Determines if there is a type converter available in the specified context and attempts to use it to convert the
|
||||
* supplied value to the specified type. Throws an exception if conversion is not possible.
|
||||
*
|
||||
* @param context the evaluation context that may define a type converter
|
||||
* @param value the value to convert (may be null)
|
||||
* @param toType the type to attempt conversion to
|
||||
* @return the converted value
|
||||
* @throws EvaluationException if there is a problem during conversion or conversion of the value to the specified
|
||||
* type is not supported
|
||||
*/
|
||||
public static Object convert(EvaluationContext context, Object value, Class<?> toType) throws EvaluationException {
|
||||
if (value == null || toType == null || toType.isAssignableFrom(value.getClass())) {
|
||||
return value;
|
||||
}
|
||||
if (context != null) {
|
||||
TypeUtils typeUtils = context.getTypeUtils();
|
||||
if (typeUtils != null) {
|
||||
TypeConverter typeConverter = typeUtils.getTypeConverter();
|
||||
return typeConverter.convertValue(value, toType);
|
||||
}
|
||||
}
|
||||
throw new EvaluationException("Cannot convert value '" + value + "' to type '" + toType.getName() + "'");
|
||||
}
|
||||
|
||||
}
|
|
@ -1,65 +0,0 @@
|
|||
package org.springframework.expression.common;
|
||||
|
||||
import org.springframework.expression.EvaluationContext;
|
||||
import org.springframework.expression.EvaluationException;
|
||||
import org.springframework.expression.Expression;
|
||||
|
||||
/**
|
||||
* A very simple hardcoded implementation of the Expression interface that represents a string literal. It is used with
|
||||
* CompositeStringExpression when representing a template expression which is made up of pieces - some being real
|
||||
* expressions to be handled by an EL implementation like Spel, and some being just textual elements.
|
||||
*
|
||||
* @author Andy Clement
|
||||
*
|
||||
*/
|
||||
public class LiteralExpression implements Expression {
|
||||
|
||||
/**
|
||||
* Fixed literal value of this expression
|
||||
*/
|
||||
private final String literalValue;
|
||||
|
||||
public LiteralExpression(String literalValue) {
|
||||
this.literalValue = literalValue;
|
||||
}
|
||||
|
||||
public String getExpressionString() {
|
||||
return literalValue;
|
||||
// return new StringBuilder().append("'").append(literalValue).append("'").toString();
|
||||
}
|
||||
|
||||
public String getValue() throws EvaluationException {
|
||||
return literalValue;
|
||||
}
|
||||
|
||||
public String getValue(EvaluationContext context) throws EvaluationException {
|
||||
return literalValue;
|
||||
}
|
||||
|
||||
public Class getValueType(EvaluationContext context) throws EvaluationException {
|
||||
return String.class;
|
||||
}
|
||||
|
||||
public void setValue(EvaluationContext context, Object value) throws EvaluationException {
|
||||
throw new EvaluationException(literalValue, "Cannot call setValue() on a LiteralExpression");
|
||||
}
|
||||
|
||||
public Object getValue(EvaluationContext context, Class<?> expectedResultType) throws EvaluationException {
|
||||
Object value = getValue(context);
|
||||
return ExpressionUtils.convert(context, value, expectedResultType);
|
||||
}
|
||||
|
||||
public Object getValue(Class<?> expectedResultType) throws EvaluationException {
|
||||
Object value = getValue();
|
||||
return ExpressionUtils.convert(null, value, expectedResultType);
|
||||
}
|
||||
|
||||
public boolean isWritable(EvaluationContext context) throws EvaluationException {
|
||||
return false;
|
||||
}
|
||||
|
||||
public Class getValueType() throws EvaluationException {
|
||||
return String.class;
|
||||
}
|
||||
|
||||
}
|
|
@ -1,115 +0,0 @@
|
|||
package org.springframework.expression.common;
|
||||
|
||||
import java.util.LinkedList;
|
||||
import java.util.List;
|
||||
|
||||
import org.springframework.expression.Expression;
|
||||
import org.springframework.expression.ExpressionParser;
|
||||
import org.springframework.expression.ParseException;
|
||||
import org.springframework.expression.ParserContext;
|
||||
|
||||
/**
|
||||
* An expression parser that understands templates. It can be subclassed by expression parsers that do not offer first
|
||||
* class support for templating.
|
||||
*
|
||||
* @author Keith Donald
|
||||
* @author Andy Clement
|
||||
*/
|
||||
public abstract class TemplateAwareExpressionParser implements ExpressionParser {
|
||||
|
||||
public Expression parseExpression(String expressionString) throws ParseException {
|
||||
return parseExpression(expressionString, DefaultNonTemplateParserContext.INSTANCE);
|
||||
}
|
||||
|
||||
public final Expression parseExpression(String expressionString, ParserContext context) throws ParseException {
|
||||
if (context == null) {
|
||||
context = DefaultNonTemplateParserContext.INSTANCE;
|
||||
}
|
||||
if (context.isTemplate()) {
|
||||
return parseTemplate(expressionString, context);
|
||||
} else {
|
||||
return doParseExpression(expressionString, context);
|
||||
}
|
||||
}
|
||||
|
||||
private Expression parseTemplate(String expressionString, ParserContext context) throws ParseException {
|
||||
if (expressionString.length() == 0) {
|
||||
// TODO throw exception if there are template prefix/suffixes and it is length 0?
|
||||
return new LiteralExpression("");
|
||||
}
|
||||
Expression[] expressions = parseExpressions(expressionString, context);
|
||||
if (expressions.length == 1) {
|
||||
return expressions[0];
|
||||
} else {
|
||||
return new CompositeStringExpression(expressionString, expressions);
|
||||
}
|
||||
}
|
||||
|
||||
// helper methods
|
||||
|
||||
/**
|
||||
* Helper that parses given expression string using the configured parser. The expression string can contain any
|
||||
* number of expressions all contained in "${...}" markers. For instance: "foo${expr0}bar${expr1}". The static
|
||||
* pieces of text will also be returned as Expressions that just return that static piece of text. As a result,
|
||||
* evaluating all returned expressions and concatenating the results produces the complete evaluated string.
|
||||
* Unwrapping is only done of the outermost delimiters found, so the string 'hello ${foo${abc}}' would break into
|
||||
* the pieces 'hello ' and 'foo${abc}'. This means that expression languages that used ${..} as part of their
|
||||
* functionality are supported without any problem
|
||||
*
|
||||
* @param expressionString the expression string
|
||||
* @return the parsed expressions
|
||||
* @throws ParseException when the expressions cannot be parsed
|
||||
*/
|
||||
private final Expression[] parseExpressions(String expressionString, ParserContext context) throws ParseException {
|
||||
// TODO this needs to handle nested delimiters for cases where the expression uses the delim chars
|
||||
List<Expression> expressions = new LinkedList<Expression>();
|
||||
int startIdx = 0;
|
||||
String prefix = context.getExpressionPrefix();
|
||||
String suffix = context.getExpressionSuffix();
|
||||
while (startIdx < expressionString.length()) {
|
||||
int prefixIndex = expressionString.indexOf(prefix, startIdx);
|
||||
if (prefixIndex >= startIdx) {
|
||||
// a inner expression was found - this is a composite
|
||||
if (prefixIndex > startIdx) {
|
||||
expressions.add(new LiteralExpression(expressionString.substring(startIdx, prefixIndex)));
|
||||
startIdx = prefixIndex;
|
||||
}
|
||||
int nextPrefixIndex = expressionString.indexOf(prefix, prefixIndex + prefix.length());
|
||||
int suffixIndex;
|
||||
if (nextPrefixIndex == -1) {
|
||||
// this is the last expression in the expression string
|
||||
suffixIndex = expressionString.lastIndexOf(suffix);
|
||||
|
||||
} else {
|
||||
// another expression exists after this one in the expression string
|
||||
suffixIndex = expressionString.lastIndexOf(suffix, nextPrefixIndex);
|
||||
}
|
||||
if (suffixIndex < (prefixIndex + prefix.length())) {
|
||||
throw new ParseException(expressionString, "No ending suffix '" + suffix
|
||||
+ "' for expression starting at character " + prefixIndex + ": "
|
||||
+ expressionString.substring(prefixIndex), null);
|
||||
} else if (suffixIndex == prefixIndex + prefix.length()) {
|
||||
throw new ParseException(expressionString, "No expression defined within delimiter '" + prefix
|
||||
+ suffix + "' at character " + prefixIndex, null);
|
||||
} else {
|
||||
String expr = expressionString.substring(prefixIndex + prefix.length(), suffixIndex);
|
||||
expressions.add(doParseExpression(expr, context));
|
||||
startIdx = suffixIndex + suffix.length();
|
||||
}
|
||||
} else {
|
||||
if (startIdx == 0) {
|
||||
expressions.add(doParseExpression(expressionString, context));
|
||||
} else {
|
||||
// no more ${expressions} found in string, add rest as static text
|
||||
expressions.add(new LiteralExpression(expressionString.substring(startIdx)));
|
||||
}
|
||||
startIdx = expressionString.length();
|
||||
}
|
||||
}
|
||||
return expressions.toArray(new Expression[expressions.size()]);
|
||||
}
|
||||
|
||||
protected abstract Expression doParseExpression(String expressionString, ParserContext context)
|
||||
throws ParseException;
|
||||
|
||||
}
|
|
@ -1,202 +0,0 @@
|
|||
/*
|
||||
* Copyright 2004-2008 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
|
||||
*
|
||||
* 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.springframework.expression.spel;
|
||||
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.Stack;
|
||||
|
||||
import org.springframework.expression.EvaluationContext;
|
||||
import org.springframework.expression.EvaluationException;
|
||||
import org.springframework.expression.Operation;
|
||||
import org.springframework.expression.OperatorOverloader;
|
||||
import org.springframework.expression.PropertyAccessor;
|
||||
import org.springframework.expression.TypeComparator;
|
||||
import org.springframework.expression.TypeConverter;
|
||||
import org.springframework.expression.TypeUtils;
|
||||
import org.springframework.expression.spel.internal.VariableScope;
|
||||
|
||||
/**
|
||||
* An ExpressionState is for maintaining per-expression-evaluation state, any changes to it are not seen by other
|
||||
* expressions but it gives a place to hold local variables and for component expressions in a compound expression to
|
||||
* communicate state. This is in contrast to the EvaluationContext, which is shared amongst expression evaluations, and
|
||||
* any changes to it will be seen by other expressions or any code that chooses to ask questions of the context.
|
||||
*
|
||||
* It also acts as a place for to define common utility routines that the various Ast nodes might need.
|
||||
*
|
||||
* @author Andy Clement
|
||||
*/
|
||||
public class ExpressionState {
|
||||
|
||||
private EvaluationContext relatedContext;
|
||||
|
||||
private final Stack<VariableScope> variableScopes = new Stack<VariableScope>();
|
||||
|
||||
private final Stack<Object> contextObjects = new Stack<Object>();
|
||||
|
||||
public ExpressionState(EvaluationContext context) {
|
||||
relatedContext = context;
|
||||
createVariableScope();
|
||||
}
|
||||
|
||||
public ExpressionState() {
|
||||
createVariableScope();
|
||||
}
|
||||
|
||||
private void createVariableScope() {
|
||||
variableScopes.add(new VariableScope()); // create an empty top level VariableScope
|
||||
}
|
||||
|
||||
/**
|
||||
* The active context object is what unqualified references to properties/etc are resolved against.
|
||||
*/
|
||||
public Object getActiveContextObject() {
|
||||
if (contextObjects.isEmpty()) {
|
||||
return relatedContext.getRootContextObject();
|
||||
}
|
||||
return contextObjects.peek();
|
||||
}
|
||||
|
||||
public void pushActiveContextObject(Object obj) {
|
||||
contextObjects.push(obj);
|
||||
}
|
||||
|
||||
public void popActiveContextObject() {
|
||||
contextObjects.pop();
|
||||
}
|
||||
|
||||
public Object getRootContextObject() {
|
||||
return relatedContext.getRootContextObject();
|
||||
}
|
||||
|
||||
public Object lookupReference(Object contextName, Object objectName) throws EvaluationException {
|
||||
return relatedContext.lookupReference(contextName, objectName);
|
||||
}
|
||||
|
||||
public TypeUtils getTypeUtilities() {
|
||||
return relatedContext.getTypeUtils();
|
||||
}
|
||||
|
||||
public TypeComparator getTypeComparator() {
|
||||
return relatedContext.getTypeUtils().getTypeComparator();
|
||||
}
|
||||
|
||||
public Class<?> findType(String type) throws EvaluationException {
|
||||
return getTypeUtilities().getTypeLocator().findType(type);
|
||||
}
|
||||
|
||||
// TODO all these methods that grab the type converter will fail badly if there isn't one...
|
||||
public boolean toBoolean(Object value) throws EvaluationException {
|
||||
return ((Boolean) getTypeConverter().convertValue(value, Boolean.TYPE)).booleanValue();
|
||||
}
|
||||
|
||||
public char toCharacter(Object value) throws EvaluationException {
|
||||
return ((Character) getTypeConverter().convertValue(value, Character.TYPE)).charValue();
|
||||
}
|
||||
|
||||
public short toShort(Object value) throws EvaluationException {
|
||||
return ((Short) getTypeConverter().convertValue(value, Short.TYPE)).shortValue();
|
||||
}
|
||||
|
||||
public int toInteger(Object value) throws EvaluationException {
|
||||
return ((Integer) getTypeConverter().convertValue(value, Integer.TYPE)).intValue();
|
||||
}
|
||||
|
||||
public double toDouble(Object value) throws EvaluationException {
|
||||
return ((Double) getTypeConverter().convertValue(value, Double.TYPE)).doubleValue();
|
||||
}
|
||||
|
||||
public float toFloat(Object value) throws EvaluationException {
|
||||
return ((Float) getTypeConverter().convertValue(value, Float.TYPE)).floatValue();
|
||||
}
|
||||
|
||||
public long toLong(Object value) throws EvaluationException {
|
||||
return ((Long) getTypeConverter().convertValue(value, Long.TYPE)).longValue();
|
||||
}
|
||||
|
||||
public byte toByte(Object value) throws EvaluationException {
|
||||
return ((Byte) getTypeConverter().convertValue(value, Byte.TYPE)).byteValue();
|
||||
}
|
||||
|
||||
public TypeConverter getTypeConverter() {
|
||||
// TODO cache TypeConverter when it is set/changed?
|
||||
return getTypeUtilities().getTypeConverter();
|
||||
}
|
||||
|
||||
public void setVariable(String name, Object value) {
|
||||
relatedContext.setVariable(name, value);
|
||||
}
|
||||
|
||||
public Object lookupVariable(String name) {
|
||||
return relatedContext.lookupVariable(name);
|
||||
}
|
||||
|
||||
/**
|
||||
* A new scope is entered when a function is invoked
|
||||
*/
|
||||
public void enterScope(Map<String, Object> argMap) {
|
||||
variableScopes.push(new VariableScope(argMap));
|
||||
}
|
||||
|
||||
public void enterScope(String name, Object value) {
|
||||
variableScopes.push(new VariableScope(name, value));
|
||||
}
|
||||
|
||||
public void exitScope() {
|
||||
variableScopes.pop();
|
||||
}
|
||||
|
||||
public void setLocalVariable(String name, Object value) {
|
||||
variableScopes.peek().setVariable(name, value);
|
||||
}
|
||||
|
||||
public Object lookupLocalVariable(String name) {
|
||||
int scopeNumber = variableScopes.size() - 1;
|
||||
for (int i = scopeNumber; i >= 0; i--) {
|
||||
if (variableScopes.get(i).definesVariable(name)) {
|
||||
return variableScopes.get(i).lookupVariable(name);
|
||||
}
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
public Object operate(Operation op, Object left, Object right) throws SpelException {
|
||||
OperatorOverloader overloader = relatedContext.getTypeUtils().getOperatorOverloader();
|
||||
try {
|
||||
if (overloader != null && overloader.overridesOperation(op, left, right)) {
|
||||
return overloader.operate(op, left, right);
|
||||
} else {
|
||||
throw new SpelException(SpelMessages.OPERATOR_NOT_SUPPORTED_BETWEEN_TYPES, op, left, right);
|
||||
}
|
||||
} catch (EvaluationException e) {
|
||||
if (e instanceof SpelException) {
|
||||
throw (SpelException) e;
|
||||
} else {
|
||||
throw new SpelException(e, SpelMessages.UNEXPECTED_PROBLEM_INVOKING_OPERATOR, op, left, right, e
|
||||
.getMessage());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public List<PropertyAccessor> getPropertyAccessors() {
|
||||
return relatedContext.getPropertyAccessors();
|
||||
}
|
||||
|
||||
public EvaluationContext getEvaluationContext() {
|
||||
return relatedContext;
|
||||
}
|
||||
|
||||
}
|
|
@ -1,108 +0,0 @@
|
|||
/*
|
||||
* Copyright 2004-2008 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
|
||||
*
|
||||
* 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.springframework.expression.spel;
|
||||
|
||||
import org.springframework.expression.EvaluationException;
|
||||
|
||||
/**
|
||||
* Root exception for Spring EL related exceptions. Rather than holding a hard coded string indicating the problem, it
|
||||
* records a message key and the inserts for the message. See {@link SpelMessages} for the list of all possible messages
|
||||
* that can occur.
|
||||
*
|
||||
* @author Andy Clement
|
||||
*
|
||||
*/
|
||||
public class SpelException extends EvaluationException {
|
||||
|
||||
private SpelMessages message;
|
||||
private int position = -1;
|
||||
private Object[] inserts;
|
||||
|
||||
public SpelException(int position, Throwable cause, SpelMessages message, Object... inserts) {
|
||||
super(cause);
|
||||
this.position = position;
|
||||
this.message = message;
|
||||
this.inserts = inserts;
|
||||
}
|
||||
|
||||
public SpelException(Throwable cause, SpelMessages message, Object... inserts) {
|
||||
super(cause);
|
||||
this.message = message;
|
||||
this.inserts = inserts;
|
||||
}
|
||||
|
||||
public SpelException(int position, SpelMessages message, Object... inserts) {
|
||||
super((Throwable)null);
|
||||
this.position = position;
|
||||
this.message = message;
|
||||
this.inserts = inserts;
|
||||
}
|
||||
|
||||
public SpelException(SpelMessages message, Object... inserts) {
|
||||
super((Throwable)null);
|
||||
this.message = message;
|
||||
this.inserts = inserts;
|
||||
}
|
||||
|
||||
public SpelException(String expressionString, int position, Throwable cause, SpelMessages message, Object... inserts) {
|
||||
super(expressionString, cause);
|
||||
this.position = position;
|
||||
this.message = message;
|
||||
this.inserts = inserts;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return a formatted message with inserts applied
|
||||
*/
|
||||
@Override
|
||||
public String getMessage() {
|
||||
if (message != null)
|
||||
return message.formatMessage(position, inserts);
|
||||
else
|
||||
return super.getMessage();
|
||||
}
|
||||
|
||||
/**
|
||||
* @return the position within the expression that gave rise to the exception (or -1 if unknown)
|
||||
*/
|
||||
public int getPosition() {
|
||||
return this.position;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return the unformatted message
|
||||
*/
|
||||
public SpelMessages getMessageUnformatted() {
|
||||
return this.message;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set the position in the related expression which gave rise to this exception.
|
||||
*
|
||||
* @param position the position in the expression that gave rise to the exception
|
||||
*/
|
||||
public void setPosition(int position) {
|
||||
this.position = position;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return the message inserts
|
||||
*/
|
||||
public Object[] getInserts() {
|
||||
return inserts;
|
||||
}
|
||||
|
||||
}
|
|
@ -1,153 +0,0 @@
|
|||
/*
|
||||
* Copyright 2004-2008 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
|
||||
*
|
||||
* 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.springframework.expression.spel;
|
||||
|
||||
import org.springframework.expression.EvaluationContext;
|
||||
import org.springframework.expression.EvaluationException;
|
||||
import org.springframework.expression.Expression;
|
||||
import org.springframework.expression.common.ExpressionUtils;
|
||||
import org.springframework.expression.spel.ast.SpelNode;
|
||||
import org.springframework.expression.spel.standard.StandardEvaluationContext;
|
||||
|
||||
/**
|
||||
* A SpelExpressions represents a parsed (valid) expression that is ready to be evaluated in a specified context. An
|
||||
* expression can be evaluated standalone or in a specified context. During expression evaluation the context may be
|
||||
* asked to resolve references to types, beans, properties, methods.
|
||||
*
|
||||
* @author Andy Clement
|
||||
*
|
||||
*/
|
||||
public class SpelExpression implements Expression {
|
||||
private final String expression;
|
||||
public final SpelNode ast;
|
||||
|
||||
/**
|
||||
* Construct an expression, only used by the parser.
|
||||
*
|
||||
* @param expression
|
||||
* @param ast
|
||||
*/
|
||||
SpelExpression(String expression, SpelNode ast) {
|
||||
this.expression = expression;
|
||||
this.ast = ast;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return the expression string that was parsed to create this expression instance
|
||||
*/
|
||||
public String getExpressionString() {
|
||||
return expression;
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritDoc}
|
||||
*/
|
||||
public Object getValue() throws EvaluationException {
|
||||
EvaluationContext eContext = new StandardEvaluationContext();
|
||||
return ast.getValue(new ExpressionState(eContext));
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritDoc}
|
||||
*/
|
||||
public Object getValue(EvaluationContext context) throws EvaluationException {
|
||||
return ast.getValue(new ExpressionState(context));
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritDoc}
|
||||
*/
|
||||
public Object getValue(EvaluationContext context, Class<?> expectedResultType) throws EvaluationException {
|
||||
Object result = ast.getValue(new ExpressionState(context));
|
||||
|
||||
if (result != null && expectedResultType != null) {
|
||||
Class<?> resultType = result.getClass();
|
||||
if (expectedResultType.isAssignableFrom(resultType)) {
|
||||
return result;
|
||||
}
|
||||
// Attempt conversion to the requested type, may throw an exception
|
||||
return context.getTypeUtils().getTypeConverter().convertValue(result, expectedResultType);
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritDoc}
|
||||
*/
|
||||
public void setValue(EvaluationContext context, Object value) throws EvaluationException {
|
||||
ast.setValue(new ExpressionState(context), value);
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritDoc}
|
||||
*/
|
||||
public boolean isWritable(EvaluationContext context) throws EvaluationException {
|
||||
return ast.isWritable(new ExpressionState(context));
|
||||
}
|
||||
|
||||
/**
|
||||
* @return return the Abstract Syntax Tree for the expression
|
||||
*/
|
||||
public SpelNode getAST() {
|
||||
return ast;
|
||||
}
|
||||
|
||||
/**
|
||||
* Produce a string representation of the Abstract Syntax Tree for the expression, this should ideally look like the
|
||||
* input expression, but properly formatted since any unnecessary whitespace will have been discarded during the
|
||||
* parse of the expression.
|
||||
*
|
||||
* @return the string representation of the AST
|
||||
*/
|
||||
public String toStringAST() {
|
||||
return ast.toStringAST();
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritDoc}
|
||||
*/
|
||||
public Class getValueType(EvaluationContext context) throws EvaluationException {
|
||||
// TODO is this a legal implementation? The null return value could be very unhelpful. See other getValueType()
|
||||
// also.
|
||||
Object value = getValue(context);
|
||||
if (value == null) {
|
||||
return null;
|
||||
} else {
|
||||
return value.getClass();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritDoc}
|
||||
*/
|
||||
public Class getValueType() throws EvaluationException {
|
||||
Object value = getValue();
|
||||
if (value == null) {
|
||||
return null;
|
||||
} else {
|
||||
return value.getClass();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritDoc}
|
||||
*/
|
||||
public Object getValue(Class<?> expectedResultType) throws EvaluationException {
|
||||
Object result = getValue();
|
||||
return ExpressionUtils.convert(null, result, expectedResultType);
|
||||
}
|
||||
|
||||
}
|
|
@ -1,91 +0,0 @@
|
|||
/*
|
||||
* Copyright 2004-2008 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
|
||||
*
|
||||
* 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.springframework.expression.spel;
|
||||
|
||||
import org.antlr.runtime.ANTLRStringStream;
|
||||
import org.antlr.runtime.CommonTokenStream;
|
||||
import org.antlr.runtime.RecognitionException;
|
||||
import org.springframework.expression.Expression;
|
||||
import org.springframework.expression.ParseException;
|
||||
import org.springframework.expression.ParserContext;
|
||||
import org.springframework.expression.common.DefaultNonTemplateParserContext;
|
||||
import org.springframework.expression.common.TemplateAwareExpressionParser;
|
||||
import org.springframework.expression.spel.ast.SpelNode;
|
||||
import org.springframework.expression.spel.generated.SpringExpressionsLexer;
|
||||
import org.springframework.expression.spel.generated.SpringExpressionsParser.expr_return;
|
||||
import org.springframework.expression.spel.internal.InternalELException;
|
||||
import org.springframework.expression.spel.internal.SpelTreeAdaptor;
|
||||
import org.springframework.expression.spel.internal.SpringExpressionsLexerExtender;
|
||||
import org.springframework.expression.spel.internal.SpringExpressionsParserExtender;
|
||||
|
||||
/**
|
||||
* Instances of this parser class can process Spring Expression Language format expressions. The result of parsing an
|
||||
* expression is a SpelExpression instance that can be repeatedly evaluated (possibly against different evaluation
|
||||
* contexts) or serialized for later evaluation.
|
||||
*
|
||||
* @author Andy Clement
|
||||
*/
|
||||
public class SpelExpressionParser extends TemplateAwareExpressionParser {
|
||||
|
||||
private final SpringExpressionsLexer lexer;
|
||||
private final SpringExpressionsParserExtender parser;
|
||||
|
||||
/**
|
||||
* Should be constructed through the SpelParserFactory
|
||||
*/
|
||||
public SpelExpressionParser() {
|
||||
lexer = new SpringExpressionsLexerExtender();
|
||||
CommonTokenStream tokens = new CommonTokenStream(lexer);
|
||||
parser = new SpringExpressionsParserExtender(tokens);
|
||||
parser.setTreeAdaptor(new SpelTreeAdaptor());
|
||||
}
|
||||
|
||||
/**
|
||||
* Parse an expression string.
|
||||
*
|
||||
* @param expressionString the expression to parse
|
||||
* @param context the parser context in which to perform the parse
|
||||
* @return a parsed expression object
|
||||
* @throws ParseException if the expression is invalid
|
||||
*/
|
||||
@Override
|
||||
protected Expression doParseExpression(String expressionString, ParserContext context) throws ParseException {
|
||||
try {
|
||||
lexer.setCharStream(new ANTLRStringStream(expressionString));
|
||||
CommonTokenStream tokens = new CommonTokenStream(lexer);
|
||||
parser.setTokenStream(tokens);
|
||||
expr_return exprReturn = parser.expr();
|
||||
SpelExpression newExpression = new SpelExpression(expressionString, (SpelNode) exprReturn.getTree());
|
||||
return newExpression;
|
||||
} catch (RecognitionException re) {
|
||||
ParseException exception = new ParseException(expressionString, "Recognition error at position: "
|
||||
+ re.charPositionInLine + ": " + re.getMessage(), re);
|
||||
throw exception;
|
||||
} catch (InternalELException e) {
|
||||
SpelException wrappedException = e.getCause();
|
||||
throw new ParseException(expressionString, "Parsing problem: " + wrappedException.getMessage(),
|
||||
wrappedException);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Simple override with covariance to return a nicer type
|
||||
*/
|
||||
@Override
|
||||
public SpelExpression parseExpression(String expressionString) throws ParseException {
|
||||
return (SpelExpression) super.parseExpression(expressionString, DefaultNonTemplateParserContext.INSTANCE);
|
||||
}
|
||||
}
|
|
@ -1,163 +0,0 @@
|
|||
/*
|
||||
* Copyright 2004-2008 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
|
||||
*
|
||||
* 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.springframework.expression.spel;
|
||||
|
||||
import java.text.MessageFormat;
|
||||
|
||||
/**
|
||||
* Contains all the messages that can be produced by the Spring Expression Language. Each message has a kind (info,
|
||||
* warn, error) and a code number. Tests can be written to expect particular code numbers rather than particular text,
|
||||
* enabling the message text to more easily be modified and the tests to run successfully in different locales.
|
||||
* <p>
|
||||
* When a message is formatted, it will have this kind of form
|
||||
*
|
||||
* <pre>
|
||||
* <code>
|
||||
* EL1004E: (pos 34): Type cannot be found 'String'
|
||||
* </pre>
|
||||
*
|
||||
* </code> The prefix captures the code and the error kind, whilst the position is included if it is known and the
|
||||
* message has had all relevant inserts applied to it.
|
||||
*
|
||||
* @author Andy Clement
|
||||
*
|
||||
*/
|
||||
public enum SpelMessages {
|
||||
// TODO put keys and messages into bundles for easy NLS
|
||||
// TODO review if any messages are not used
|
||||
// TODO sort messages into better groups if possible, sharing a name prefix perhaps
|
||||
|
||||
INITIALIZER_LENGTH_INCORRECT(Kind.ERROR, 1001,
|
||||
"Array constructor call: initializer size of {0} does not match declared length of {1}"), TYPE_CONVERSION_ERROR(
|
||||
Kind.ERROR, 1002, "Type conversion problem, cannot convert from {0} to {1}"), CONSTRUCTOR_NOT_FOUND(
|
||||
Kind.ERROR, 1003, "Constructor call: No suitable constructor on type {0} for arguments {1}"), TYPE_NOT_FOUND(
|
||||
Kind.ERROR, 1004, "Type cannot be found ''{0}''"), ADDITION_NOT_DEFINED(Kind.ERROR, 1005,
|
||||
"Addition not defined between operands of type {0} and {1}"), METHOD_NOT_FOUND(Kind.ERROR, 1006,
|
||||
"Method call: Method {0} cannot be found on {1} type"), ATTEMPTED_METHOD_CALL_ON_NULL_CONTEXT_OBJECT(
|
||||
Kind.ERROR, 1007, "Method call: Attempted to call method {0} on null context object"), ATTEMPTED_PROPERTY_FIELD_REF_ON_NULL_CONTEXT_OBJECT(
|
||||
Kind.ERROR, 1008,
|
||||
"Field or property reference: Attempted to refer to field or property ''{0}'' on null context object"), PROPERTY_OR_FIELD_NOT_FOUND(
|
||||
Kind.ERROR, 1009, "Field or property ''{0}'' cannot be found on object of type ''{1}''"), PROPERTY_OR_FIELD_SETTER_NOT_FOUND(
|
||||
Kind.ERROR, 1010, "Field or property ''{0}'' cannot be set on object of type ''{1}''"), MULTIPLY_NOT_DEFINED(
|
||||
Kind.ERROR, 1011, "Multiply not defined between operands of type {0} and {1}"), NOT_COMPARABLE(Kind.ERROR,
|
||||
1012, "Cannot compare instances of {0} and {1}"), NOT_COMPARABLE_CANNOT_COERCE(Kind.ERROR, 1013,
|
||||
"Cannot compare instances of {0} and {1} because they cannot be coerced to the same type"), VARIABLE_NOT_FOUND(
|
||||
Kind.ERROR, 1014, "Variable named ''{0}'' cannot be found"), INCORRECT_NUMBER_OF_ARGUMENTS_TO_FUNCTION(
|
||||
Kind.ERROR, 1015, "Incorrect number of arguments for function, {0} supplied but function takes {1}"), NO_SUCH_FUNCTION(
|
||||
Kind.ERROR, 1016, "No such function named ''{0}''"), NOT_A_FUNCTION(Kind.ERROR, 1017,
|
||||
"The name ''{0}'' did not map to a function, it mapped to a ''{1}''"), INVALID_TYPE_FOR_SELECTION(
|
||||
Kind.ERROR, 1018, "Cannot perform selection on input data of type ''{0}''"), RESULT_OF_SELECTION_CRITERIA_IS_NOT_BOOLEAN(
|
||||
Kind.ERROR, 1019, "Result of selection criteria is not boolean"), MODULUS_NOT_DEFINED(Kind.ERROR, 1020,
|
||||
"Modulus not defined between operands of type ''{0}'' and ''{1}''"), NULL_OPERAND_TO_OPERATOR(Kind.ERROR,
|
||||
1021, "Operand evaluated to null and that is not supported for this operator"), NO_SIZE_OR_INITIALIZER_FOR_ARRAY_CONSTRUCTION(
|
||||
Kind.ERROR, 1022, "No array size or initializer was supplied to construct the array"), INCORRECT_ELEMENT_TYPE_FOR_ARRAY(
|
||||
Kind.ERROR, 1023, "The array of type ''{0}'' cannot have an element of type ''{1}'' inserted"), BETWEEN_RIGHT_OPERAND_MUST_BE_TWO_ELEMENT_LIST(
|
||||
Kind.ERROR, 1024, "Right operand for the 'between' operator has to be a two-element list"), TYPE_NOT_SUPPORTED_BY_PROCESSOR(
|
||||
Kind.ERROR, 1025,
|
||||
"The collection processor ''{0}'' does not understand and input collection of elements of type {1}"), UNABLE_TO_ACCESS_FIELD(
|
||||
Kind.ERROR, 1026, "Unable to access field ''{0}'' on type ''{1}''"), UNABLE_TO_ACCESS_PROPERTY_THROUGH_GETTER(
|
||||
Kind.ERROR, 1027, "Unable to access property ''{0}'' through getter on type ''{1}''"), UNABLE_TO_ACCESS_PROPERTY_THROUGH_SETTER(
|
||||
Kind.ERROR, 1028, "Unable to access property ''{0}'' through setter on type ''{1}''"), INVALID_PATTERN(
|
||||
Kind.ERROR, 1029, "Pattern is not valid ''{0}''"), RECOGNITION_ERROR(Kind.ERROR, 1030,
|
||||
"Recognition error: {0}"), // TODO poor message when a recognition exception occurs
|
||||
PROJECTION_NOT_SUPPORTED_ON_TYPE(Kind.ERROR, 1031, "Projection is not supported on the type ''{0}''"), ARGLIST_SHOULD_NOT_BE_EVALUATED(
|
||||
Kind.ERROR, 1032, "The argument list of a lambda expression should never have getValue() called upon it"), MAPENTRY_SHOULD_NOT_BE_EVALUATED(
|
||||
Kind.ERROR, 1033, "A map entry should never have getValue() called upon it"), EXCEPTION_DURING_PROPERTY_READ(
|
||||
Kind.ERROR, 1034, "A problem occurred whilst attempting to access the property ''{0}'': ''{1}''"), EXCEPTION_DURING_CONSTRUCTOR_INVOCATION(
|
||||
Kind.ERROR, 1035, "A problem occurred whilst attempting to construct ''{0}'': ''{1}''"), DATE_CANNOT_BE_PARSED(
|
||||
Kind.ERROR, 1036, "Unable to parse date ''{0}'' using format ''{1}''"), FUNCTION_REFERENCE_CANNOT_BE_INVOKED(
|
||||
Kind.ERROR, 1037, "The function ''{0}'' mapped to an object of type ''{1}'' which cannot be invoked"), FUNCTION_NOT_DEFINED(
|
||||
Kind.ERROR, 1038, "The function ''{0}'' could not be found"), EXCEPTION_DURING_FUNCTION_CALL(Kind.ERROR,
|
||||
1039, "A problem occurred whilst attempting to invoke the function ''{0}'': ''{1}''"), ARRAY_INDEX_OUT_OF_BOUNDS(
|
||||
Kind.ERROR, 1040, "The array has ''{0}'' elements, index ''{1}'' is invalid"), COLLECTION_INDEX_OUT_OF_BOUNDS(
|
||||
Kind.ERROR, 1041, "The collection has ''{0}'' elements, index ''{1}'' is invalid"), STRING_INDEX_OUT_OF_BOUNDS(
|
||||
Kind.ERROR, 1042, "The string has ''{0}'' characters, index ''{1}'' is invalid"), INDEXING_NOT_SUPPORTED_FOR_TYPE(
|
||||
Kind.ERROR, 1043, "Indexing into type ''{0}'' is not supported"), OPERATOR_IN_CANNOT_DETERMINE_MEMBERSHIP(
|
||||
Kind.ERROR, 1044, "Operator 'in' not implemented for detecting membership of a ''{0}'' in a ''{1}''"), CANNOT_NEGATE_TYPE(
|
||||
Kind.ERROR, 1045, "Cannot determine negation of type ''{0}''"), CUT_ARGUMENTS_MUST_BE_INTS(Kind.ERROR,
|
||||
1046, "Both arguments to the cut() processor must be Integers, but they are ''{0}'' and ''{1}''"), SOUNDSLIKE_NEEDS_STRING_OPERAND(
|
||||
Kind.ERROR, 1047, "The soundslike operator needs String operands, but found a ''{0}''"), INSTANCEOF_OPERATOR_NEEDS_CLASS_OPERAND(
|
||||
Kind.ERROR, 1048, "The operator 'instanceof' needs the right operand to be a class, not a ''{0}''"), LOCAL_VARIABLE_NOT_DEFINED(
|
||||
Kind.ERROR, 1049, "Local variable named ''{0}'' could not be found"), EXCEPTION_DURING_METHOD_INVOCATION(
|
||||
Kind.ERROR, 1050,
|
||||
"A problem occurred when trying to execute method ''{0}'' on object of type ''{1}'': ''{2}''"), PLACEHOLDER_SHOULD_NEVER_BE_EVALUATED(
|
||||
Kind.ERROR, 1051, "InternalError: A placeholder node in the Ast should never be evaluated!"), OPERATOR_NOT_SUPPORTED_BETWEEN_TYPES(
|
||||
Kind.ERROR, 1052, "The operator ''{0}'' is not supported between objects of type ''{1}'' and ''{2}''"), UNEXPECTED_PROBLEM_INVOKING_OPERATOR(
|
||||
Kind.ERROR, 1054,
|
||||
"Unexpected problem invoking operator ''{0}'' between objects of type ''{1}'' and ''{2}'': {3}"), PROBLEM_LOCATING_METHOD(
|
||||
Kind.ERROR, 1055, "Problem locating method {0} cannot on type {1}"), PROBLEM_LOCATING_CONSTRUCTOR(
|
||||
Kind.ERROR, 1056,
|
||||
"A problem occurred whilst attempting to construct an object of type ''{0}'' using arguments ''{1}''"), INVALID_FIRST_OPERAND_FOR_LIKE_OPERATOR(
|
||||
Kind.ERROR, 1057, "First operand to like operator must be a string. ''{0}'' is not"), INVALID_SECOND_OPERAND_FOR_LIKE_OPERATOR(
|
||||
Kind.ERROR, 1058, "Second operand to like operator must be a string (regex). ''{0}'' is not"), SETVALUE_NOT_SUPPORTED(
|
||||
Kind.ERROR, 1059, "setValue(ExpressionState, Object) not implemented for ''{0}'' (''{1}''"), TYPE_NAME_EXPECTED_FOR_ARRAY_CONSTRUCTION(
|
||||
Kind.ERROR, 1060, "Expected the type of the new array to be specified as a String but found ''{0}''"), PROBLEM_DURING_TYPE_CONVERSION(
|
||||
Kind.ERROR, 1061, "Problem occurred during type conversion: {0}"), MULTIPLE_POSSIBLE_METHODS(Kind.ERROR,
|
||||
1062, "Method call of ''{0}'' is ambiguous, supported type conversions allow multiple variants to match"), EXCEPTION_DURING_PROPERTY_WRITE(
|
||||
Kind.ERROR, 1063, "A problem occurred whilst attempting to set the property ''{0}'': ''{1}''"), NOT_AN_INTEGER(
|
||||
Kind.ERROR, 1064, "The value ''{0}'' cannot be parsed as an int"), NOT_A_LONG(Kind.ERROR, 1065,
|
||||
"The value ''{0}'' cannot be parsed as a long"), PARSE_PROBLEM(Kind.ERROR, 1066,
|
||||
"Error occurred during expression parse: {0}"), INVALID_FIRST_OPERAND_FOR_MATCHES_OPERATOR(Kind.ERROR,
|
||||
1067, "First operand to matches operator must be a string. ''{0}'' is not"), INVALID_SECOND_OPERAND_FOR_MATCHES_OPERATOR(
|
||||
Kind.ERROR, 1068, "Second operand to matches operator must be a string. ''{0}'' is not"), FUNCTION_MUST_BE_STATIC(
|
||||
Kind.ERROR,
|
||||
1069,
|
||||
"Only static methods can be called via function references. The method ''{0}'' referred to by name ''{1}'' is not static.");
|
||||
|
||||
private Kind kind;
|
||||
private int code;
|
||||
private String message;
|
||||
|
||||
public static enum Kind {
|
||||
INFO, WARNING, ERROR
|
||||
};
|
||||
|
||||
private SpelMessages(Kind kind, int code, String message) {
|
||||
this.kind = kind;
|
||||
this.code = code;
|
||||
this.message = message;
|
||||
}
|
||||
|
||||
/**
|
||||
* Produce a complete message including the prefix, the position (if known) and with the inserts applied to the
|
||||
* message.
|
||||
*
|
||||
* @param pos the position, if less than zero it is ignored and not included in the message
|
||||
* @param inserts the inserts to put into the formatted message
|
||||
* @return a formatted message
|
||||
*/
|
||||
public String formatMessage(int pos, Object... inserts) {
|
||||
StringBuilder formattedMessage = new StringBuilder();
|
||||
formattedMessage.append("EL").append(code);
|
||||
switch (kind) {
|
||||
case WARNING:
|
||||
formattedMessage.append("W");
|
||||
break;
|
||||
case INFO:
|
||||
formattedMessage.append("I");
|
||||
break;
|
||||
case ERROR:
|
||||
formattedMessage.append("E");
|
||||
break;
|
||||
}
|
||||
formattedMessage.append(":");
|
||||
if (pos != -1) {
|
||||
formattedMessage.append("(pos ").append(pos).append("): ");
|
||||
}
|
||||
formattedMessage.append(MessageFormat.format(message, inserts));
|
||||
return formattedMessage.toString();
|
||||
}
|
||||
}
|
|
@ -1,58 +0,0 @@
|
|||
/*
|
||||
* Copyright 2004-2008 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
|
||||
*
|
||||
* 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.springframework.expression.spel;
|
||||
|
||||
import java.io.PrintStream;
|
||||
|
||||
import org.springframework.expression.spel.ast.SpelNode;
|
||||
|
||||
/**
|
||||
* Utilities for working with Spring Expressions.
|
||||
*
|
||||
* @author Andy Clement
|
||||
*
|
||||
*/
|
||||
public class SpelUtilities {
|
||||
|
||||
/**
|
||||
* Output an indented representation of the expression syntax tree to the specified output stream.
|
||||
*
|
||||
* @param printStream the output stream to print into
|
||||
* @param expression the expression to be displayed
|
||||
*/
|
||||
public static void printAbstractSyntaxTree(PrintStream printStream, SpelExpression expression) {
|
||||
printStream.println("===> Expression '" + expression.getExpressionString() + "' - AST start");
|
||||
printAST(printStream, expression.getAST(), "");
|
||||
printStream.println("===> Expression '" + expression.getExpressionString() + "' - AST end");
|
||||
}
|
||||
|
||||
/*
|
||||
* Helper method for printing the AST with indentation
|
||||
*/
|
||||
private static void printAST(PrintStream out, SpelNode t, String indent) {
|
||||
if (t != null) {
|
||||
StringBuffer sb = new StringBuffer();
|
||||
String s = (t.getType() == -1 ? "EOF" : t.getClass().getSimpleName());
|
||||
sb.append(indent).append(s);
|
||||
sb.append(" value=").append(t.getText());
|
||||
sb.append(t.getChildCount() < 2 ? "" : " children=#" + t.getChildCount());
|
||||
out.println(sb.toString());
|
||||
for (int i = 0; i < t.getChildCount(); i++) {
|
||||
printAST(out, t.getChild(i), indent + " ");
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
|
@ -1,54 +0,0 @@
|
|||
/*
|
||||
* Copyright 2004-2008 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
|
||||
*
|
||||
* 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.springframework.expression.spel.ast;
|
||||
|
||||
import org.antlr.runtime.Token;
|
||||
import org.springframework.expression.EvaluationException;
|
||||
import org.springframework.expression.spel.SpelException;
|
||||
import org.springframework.expression.spel.ExpressionState;
|
||||
|
||||
/**
|
||||
* Represents assignment. An alternative to calling setValue() for an expression is to use an assign.
|
||||
* <p>
|
||||
* Example: 'someNumberProperty=42'
|
||||
*
|
||||
* @author Andy Clement
|
||||
*
|
||||
*/
|
||||
public class Assign extends SpelNode {
|
||||
|
||||
public Assign(Token payload) {
|
||||
super(payload);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Object getValue(ExpressionState state) throws EvaluationException {
|
||||
Object newValue = getChild(1).getValue(state);
|
||||
getChild(0).setValue(state, newValue);
|
||||
return newValue;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toStringAST() {
|
||||
return new StringBuilder().append(getChild(0).toStringAST()).append("=").append(getChild(1).toStringAST())
|
||||
.toString();
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isWritable(ExpressionState expressionState) throws SpelException {
|
||||
return false;
|
||||
}
|
||||
}
|
|
@ -1,40 +0,0 @@
|
|||
/*
|
||||
* Copyright 2004-2008 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
|
||||
*
|
||||
* 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.springframework.expression.spel.ast;
|
||||
|
||||
import org.antlr.runtime.Token;
|
||||
|
||||
/**
|
||||
* Represents the literal values TRUE and FALSE.
|
||||
*
|
||||
* @author Andy Clement
|
||||
*
|
||||
*/
|
||||
public class BooleanLiteral extends Literal {
|
||||
|
||||
private final Boolean value;
|
||||
|
||||
public BooleanLiteral(Token payload, boolean value) {
|
||||
super(payload);
|
||||
this.value = value;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Boolean getLiteralValue() {
|
||||
return value;
|
||||
}
|
||||
|
||||
}
|
|
@ -1,120 +0,0 @@
|
|||
/*
|
||||
* Copyright 2004-2008 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
|
||||
*
|
||||
* 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.springframework.expression.spel.ast;
|
||||
|
||||
import org.antlr.runtime.Token;
|
||||
import org.springframework.expression.EvaluationException;
|
||||
import org.springframework.expression.spel.SpelException;
|
||||
import org.springframework.expression.spel.ExpressionState;
|
||||
|
||||
/**
|
||||
* Represents a DOT separated expression sequence, such as 'property1.property2.methodOne()'
|
||||
*
|
||||
* @author Andy Clement
|
||||
*
|
||||
*/
|
||||
public class CompoundExpression extends SpelNode {
|
||||
|
||||
public CompoundExpression(Token payload) {
|
||||
super(payload);
|
||||
}
|
||||
|
||||
/**
|
||||
* Evalutes a compound expression. This involves evaluating each piece in turn and the return value from each piece
|
||||
* is the active context object for the subsequent piece.
|
||||
*
|
||||
* @param state the state in which the expression is being evaluated
|
||||
* @return the final value from the last piece of the compound expression
|
||||
*/
|
||||
@Override
|
||||
public Object getValue(ExpressionState state) throws EvaluationException {
|
||||
Object result = null;
|
||||
SpelNode nextNode = null;
|
||||
try {
|
||||
nextNode = getChild(0);
|
||||
result = nextNode.getValue(state);
|
||||
for (int i = 1; i < getChildCount(); i++) {
|
||||
try {
|
||||
state.pushActiveContextObject(result);
|
||||
nextNode = getChild(i);
|
||||
result = nextNode.getValue(state);
|
||||
} finally {
|
||||
state.popActiveContextObject();
|
||||
}
|
||||
}
|
||||
} catch (SpelException ee) {
|
||||
// Correct the position for the error before rethrowing
|
||||
ee.setPosition(nextNode.getCharPositionInLine());
|
||||
throw ee;
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setValue(ExpressionState state, Object value) throws EvaluationException {
|
||||
if (getChildCount() == 1) {
|
||||
getChild(0).setValue(state, value);
|
||||
return;
|
||||
}
|
||||
Object ctx = getChild(0).getValue(state);
|
||||
for (int i = 1; i < getChildCount() - 1; i++) {
|
||||
try {
|
||||
state.pushActiveContextObject(ctx);
|
||||
ctx = getChild(i).getValue(state);
|
||||
} finally {
|
||||
state.popActiveContextObject();
|
||||
}
|
||||
}
|
||||
try {
|
||||
state.pushActiveContextObject(ctx);
|
||||
getChild(getChildCount() - 1).setValue(state, value);
|
||||
} finally {
|
||||
state.popActiveContextObject();
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isWritable(ExpressionState state) throws EvaluationException {
|
||||
if (getChildCount() == 1) {
|
||||
return getChild(0).isWritable(state);
|
||||
}
|
||||
Object ctx = getChild(0).getValue(state);
|
||||
for (int i = 1; i < getChildCount() - 1; i++) {
|
||||
try {
|
||||
state.pushActiveContextObject(ctx);
|
||||
ctx = getChild(i).getValue(state);
|
||||
} finally {
|
||||
state.popActiveContextObject();
|
||||
}
|
||||
}
|
||||
try {
|
||||
state.pushActiveContextObject(ctx);
|
||||
return getChild(getChildCount() - 1).isWritable(state);
|
||||
} finally {
|
||||
state.popActiveContextObject();
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toStringAST() {
|
||||
StringBuffer sb = new StringBuffer();
|
||||
for (int i = 0; i < getChildCount(); i++) {
|
||||
sb.append(getChild(i).toStringAST());
|
||||
}
|
||||
return sb.toString();
|
||||
}
|
||||
|
||||
}
|
|
@ -1,317 +0,0 @@
|
|||
/*
|
||||
* Copyright 2004-2008 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
|
||||
*
|
||||
* 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.springframework.expression.spel.ast;
|
||||
|
||||
import java.lang.reflect.Array;
|
||||
import java.util.List;
|
||||
|
||||
import org.antlr.runtime.Token;
|
||||
import org.springframework.expression.AccessException;
|
||||
import org.springframework.expression.ConstructorExecutor;
|
||||
import org.springframework.expression.ConstructorResolver;
|
||||
import org.springframework.expression.EvaluationContext;
|
||||
import org.springframework.expression.EvaluationException;
|
||||
import org.springframework.expression.spel.ExpressionState;
|
||||
import org.springframework.expression.spel.SpelException;
|
||||
import org.springframework.expression.spel.SpelMessages;
|
||||
import org.springframework.expression.spel.internal.TypeCode;
|
||||
import org.springframework.expression.spel.internal.Utils;
|
||||
|
||||
/**
|
||||
* Represents the invocation of a constructor. Either a constructor on a regular type or construction of an array. When
|
||||
* an array is constructed, an initializer can be specified.
|
||||
* <p>
|
||||
* Examples:<br>
|
||||
* new String('hello world')<br>
|
||||
* new int[]{1,2,3,4}<br>
|
||||
* new int[3] new int[3]{1,2,3}
|
||||
*
|
||||
* @author Andy Clement
|
||||
*
|
||||
*/
|
||||
public class ConstructorReference extends SpelNode {
|
||||
|
||||
/**
|
||||
* The resolver/executor model {@link ConstructorResolver} supports the caching of executor objects that can run
|
||||
* some discovered constructor repeatedly without searching for it each time. This flag controls whether caching
|
||||
* occurs and is primarily exposed for testing.
|
||||
*/
|
||||
public static boolean useCaching = true;
|
||||
|
||||
/**
|
||||
* The cached executor that may be reused on subsequent evaluations.
|
||||
*/
|
||||
private ConstructorExecutor cachedExecutor;
|
||||
|
||||
/**
|
||||
* If true then this is an array constructor, for example, 'new String[]', rather than a simple constructor 'new
|
||||
* String()'
|
||||
*/
|
||||
private final boolean isArrayConstructor;
|
||||
|
||||
public ConstructorReference(Token payload, boolean isArrayConstructor) {
|
||||
super(payload);
|
||||
this.isArrayConstructor = isArrayConstructor;
|
||||
}
|
||||
|
||||
/**
|
||||
* Implements getValue() - delegating to the code for building an array or a simple type.
|
||||
*/
|
||||
@Override
|
||||
public Object getValue(ExpressionState state) throws EvaluationException {
|
||||
if (isArrayConstructor) {
|
||||
return createArray(state);
|
||||
} else {
|
||||
return createNewInstance(state);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toStringAST() {
|
||||
StringBuilder sb = new StringBuilder();
|
||||
sb.append("new ");
|
||||
|
||||
int index = 0;
|
||||
sb.append(getChild(index++).toStringAST());
|
||||
|
||||
if (!isArrayConstructor) {
|
||||
sb.append("(");
|
||||
for (int i = index; i < getChildCount(); i++) {
|
||||
if (i > index)
|
||||
sb.append(",");
|
||||
sb.append(getChild(i).toStringAST());
|
||||
}
|
||||
sb.append(")");
|
||||
} else {
|
||||
// Next child is EXPRESSIONLIST token with children that are the
|
||||
// expressions giving array size
|
||||
sb.append("[");
|
||||
SpelNode arrayRank = getChild(index++);
|
||||
for (int i = 0; i < arrayRank.getChildCount(); i++) {
|
||||
if (i > 0)
|
||||
sb.append(",");
|
||||
sb.append(arrayRank.getChild(i).toStringAST());
|
||||
}
|
||||
sb.append("]");
|
||||
if (index < getChildCount())
|
||||
sb.append(" ").append(getChild(index).toStringAST());
|
||||
}
|
||||
return sb.toString();
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isWritable(ExpressionState expressionState) throws SpelException {
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* Create an array and return it. The children of this node indicate the type of array, the array ranks and any
|
||||
* optional initializer that might have been supplied.
|
||||
*
|
||||
* @param state the expression state within which this expression is being evaluated
|
||||
* @return the new array
|
||||
* @throws EvaluationException if there is a problem creating the array
|
||||
*/
|
||||
private Object createArray(ExpressionState state) throws EvaluationException {
|
||||
Object intendedArrayType = getChild(0).getValue(state);
|
||||
if (!(intendedArrayType instanceof String)) {
|
||||
throw new SpelException(getChild(0).getCharPositionInLine(),
|
||||
SpelMessages.TYPE_NAME_EXPECTED_FOR_ARRAY_CONSTRUCTION, Utils
|
||||
.formatClassnameForMessage(intendedArrayType.getClass()));
|
||||
}
|
||||
String type = (String) intendedArrayType;
|
||||
Class<?> componentType = null;
|
||||
TypeCode arrayTypeCode = TypeCode.forName(type);
|
||||
if (arrayTypeCode == TypeCode.OBJECT) {
|
||||
componentType = state.findType(type);
|
||||
} else {
|
||||
componentType = arrayTypeCode.getType();
|
||||
}
|
||||
|
||||
Object newArray = null;
|
||||
|
||||
if (getChild(1).getChildCount() == 0) { // are the array ranks defined?
|
||||
if (getChildCount() < 3) {
|
||||
throw new SpelException(getCharPositionInLine(),
|
||||
SpelMessages.NO_SIZE_OR_INITIALIZER_FOR_ARRAY_CONSTRUCTION);
|
||||
}
|
||||
// no array ranks so use the size of the initializer to determine array size
|
||||
int arraySize = getChild(2).getChildCount();
|
||||
newArray = Array.newInstance(componentType, arraySize);
|
||||
} else {
|
||||
// Array ranks are specified but is it a single or multiple dimension array?
|
||||
int dimensions = getChild(1).getChildCount();
|
||||
if (dimensions == 1) {
|
||||
Object o = getChild(1).getValue(state);
|
||||
int arraySize = state.toInteger(o);
|
||||
if (getChildCount() == 3) {
|
||||
// Check initializer length matches array size length
|
||||
int initializerLength = getChild(2).getChildCount();
|
||||
if (initializerLength != arraySize) {
|
||||
throw new SpelException(getChild(2).getCharPositionInLine(),
|
||||
SpelMessages.INITIALIZER_LENGTH_INCORRECT, initializerLength, arraySize);
|
||||
}
|
||||
}
|
||||
newArray = Array.newInstance(componentType, arraySize);
|
||||
} else {
|
||||
// Multi-dimensional - hold onto your hat !
|
||||
int[] dims = new int[dimensions];
|
||||
for (int d = 0; d < dimensions; d++) {
|
||||
dims[d] = state.toInteger(getChild(1).getChild(d).getValue(state));
|
||||
}
|
||||
newArray = Array.newInstance(componentType, dims);
|
||||
// TODO check any specified initializer for the multidim array matches
|
||||
}
|
||||
}
|
||||
|
||||
// Populate the array using the initializer if one is specified
|
||||
if (getChildCount() == 3) {
|
||||
SpelNode initializer = getChild(2);
|
||||
if (arrayTypeCode == TypeCode.OBJECT) {
|
||||
Object[] newObjectArray = (Object[]) newArray;
|
||||
for (int i = 0; i < newObjectArray.length; i++) {
|
||||
SpelNode elementNode = initializer.getChild(i);
|
||||
Object arrayEntry = elementNode.getValue(state);
|
||||
if (!componentType.isAssignableFrom(arrayEntry.getClass())) {
|
||||
throw new SpelException(elementNode.getCharPositionInLine(),
|
||||
SpelMessages.INCORRECT_ELEMENT_TYPE_FOR_ARRAY, componentType.getName(), arrayEntry
|
||||
.getClass().getName());
|
||||
}
|
||||
newObjectArray[i] = arrayEntry;
|
||||
}
|
||||
} else if (arrayTypeCode == TypeCode.INT) {
|
||||
int[] newIntArray = (int[]) newArray;
|
||||
for (int i = 0; i < newIntArray.length; i++) {
|
||||
newIntArray[i] = state.toInteger(initializer.getChild(i).getValue(state));
|
||||
}
|
||||
} else if (arrayTypeCode == TypeCode.BOOLEAN) {
|
||||
boolean[] newBooleanArray = (boolean[]) newArray;
|
||||
for (int i = 0; i < newBooleanArray.length; i++) {
|
||||
newBooleanArray[i] = state.toBoolean(initializer.getChild(i).getValue(state));
|
||||
}
|
||||
} else if (arrayTypeCode == TypeCode.CHAR) {
|
||||
char[] newCharArray = (char[]) newArray;
|
||||
for (int i = 0; i < newCharArray.length; i++) {
|
||||
newCharArray[i] = state.toCharacter(initializer.getChild(i).getValue(state));
|
||||
}
|
||||
} else if (arrayTypeCode == TypeCode.SHORT) {
|
||||
short[] newShortArray = (short[]) newArray;
|
||||
for (int i = 0; i < newShortArray.length; i++) {
|
||||
newShortArray[i] = state.toShort(initializer.getChild(i).getValue(state));
|
||||
}
|
||||
} else if (arrayTypeCode == TypeCode.LONG) {
|
||||
long[] newLongArray = (long[]) newArray;
|
||||
for (int i = 0; i < newLongArray.length; i++) {
|
||||
newLongArray[i] = state.toLong(initializer.getChild(i).getValue(state));
|
||||
}
|
||||
} else if (arrayTypeCode == TypeCode.FLOAT) {
|
||||
float[] newFloatArray = (float[]) newArray;
|
||||
for (int i = 0; i < newFloatArray.length; i++) {
|
||||
newFloatArray[i] = state.toFloat(initializer.getChild(i).getValue(state));
|
||||
}
|
||||
} else if (arrayTypeCode == TypeCode.DOUBLE) {
|
||||
double[] newDoubleArray = (double[]) newArray;
|
||||
for (int i = 0; i < newDoubleArray.length; i++) {
|
||||
newDoubleArray[i] = state.toDouble(initializer.getChild(i).getValue(state));
|
||||
}
|
||||
} else if (arrayTypeCode == TypeCode.BYTE) {
|
||||
byte[] newByteArray = (byte[]) newArray;
|
||||
for (int i = 0; i < newByteArray.length; i++) {
|
||||
newByteArray[i] = state.toByte(initializer.getChild(i).getValue(state));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return newArray;
|
||||
}
|
||||
|
||||
/**
|
||||
* Create a new ordinary object and return it.
|
||||
*
|
||||
* @param state the expression state within which this expression is being evaluated
|
||||
* @return the new object
|
||||
* @throws EvaluationException if there is a problem creating the object
|
||||
*/
|
||||
private Object createNewInstance(ExpressionState state) throws EvaluationException {
|
||||
Object[] arguments = new Object[getChildCount() - 1];
|
||||
Class<?>[] argumentTypes = new Class[getChildCount() - 1];
|
||||
for (int i = 0; i < arguments.length; i++) {
|
||||
Object childValue = getChild(i + 1).getValue(state);
|
||||
arguments[i] = childValue;
|
||||
argumentTypes[i] = childValue.getClass();
|
||||
}
|
||||
|
||||
if (cachedExecutor != null) {
|
||||
try {
|
||||
return cachedExecutor.execute(state.getEvaluationContext(), arguments);
|
||||
} catch (AccessException ae) {
|
||||
// this is OK - it may have gone stale due to a class change,
|
||||
// let's try to get a new one and call it before giving up
|
||||
}
|
||||
}
|
||||
|
||||
// either there was no accessor or it no longer exists
|
||||
String typename = (String) getChild(0).getValue(state);
|
||||
cachedExecutor = findExecutorForConstructor(typename, argumentTypes, state);
|
||||
try {
|
||||
return cachedExecutor.execute(state.getEvaluationContext(), arguments);
|
||||
} catch (AccessException ae) {
|
||||
throw new SpelException(ae, SpelMessages.EXCEPTION_DURING_CONSTRUCTOR_INVOCATION, typename, ae.getMessage());
|
||||
} finally {
|
||||
if (!useCaching) {
|
||||
cachedExecutor = null;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Go through the list of registered constructor resolvers and see if any can find a constructor that takes the
|
||||
* specified set of arguments.
|
||||
*
|
||||
* @param typename the type trying to be constructed
|
||||
* @param argumentTypes the types of the arguments supplied that the constructor must take
|
||||
* @param state the current state of the expression
|
||||
* @return a reusable ConstructorExecutor that can be invoked to run the constructor or null
|
||||
* @throws SpelException if there is a problem locating the constructor
|
||||
*/
|
||||
public ConstructorExecutor findExecutorForConstructor(String typename, Class<?>[] argumentTypes,
|
||||
ExpressionState state) throws SpelException {
|
||||
EvaluationContext eContext = state.getEvaluationContext();
|
||||
List<ConstructorResolver> cResolvers = eContext.getConstructorResolvers();
|
||||
if (cResolvers != null) {
|
||||
for (ConstructorResolver ctorResolver : cResolvers) {
|
||||
try {
|
||||
ConstructorExecutor cEx = ctorResolver.resolve(state.getEvaluationContext(), typename,
|
||||
argumentTypes);
|
||||
if (cEx != null) {
|
||||
return cEx;
|
||||
}
|
||||
} catch (AccessException e) {
|
||||
Throwable cause = e.getCause();
|
||||
if (cause instanceof SpelException) {
|
||||
throw (SpelException) cause;
|
||||
} else {
|
||||
throw new SpelException(cause, SpelMessages.PROBLEM_LOCATING_CONSTRUCTOR, typename, Utils
|
||||
.formatMethodForMessage("", argumentTypes));
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
throw new SpelException(SpelMessages.CONSTRUCTOR_NOT_FOUND, typename, Utils.formatMethodForMessage("",
|
||||
argumentTypes));
|
||||
}
|
||||
|
||||
}
|
|
@ -1,46 +0,0 @@
|
|||
/*
|
||||
* Copyright 2004-2008 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
|
||||
*
|
||||
* 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.springframework.expression.spel.ast;
|
||||
|
||||
import org.antlr.runtime.Token;
|
||||
import org.springframework.expression.spel.SpelException;
|
||||
import org.springframework.expression.spel.ExpressionState;
|
||||
|
||||
/**
|
||||
* This is used for preserving positional information from the input expression.
|
||||
*
|
||||
* @author Andy Clement
|
||||
*
|
||||
*/
|
||||
public class Dot extends SpelNode {
|
||||
// TODO Keep Dot for the positional information or remove it?
|
||||
|
||||
public Dot(Token payload) {
|
||||
super(payload);
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toStringAST() {
|
||||
return ".";
|
||||
}
|
||||
|
||||
@Override
|
||||
public Object getValue(ExpressionState state) throws SpelException {
|
||||
// This makes Dot a do-nothing operation, but this is not free in terms of computation
|
||||
return state.getActiveContextObject();
|
||||
}
|
||||
|
||||
}
|
|
@ -1,147 +0,0 @@
|
|||
/*
|
||||
* Copyright 2004-2008 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
|
||||
*
|
||||
* 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.springframework.expression.spel.ast;
|
||||
|
||||
import java.lang.reflect.InvocationTargetException;
|
||||
import java.lang.reflect.Method;
|
||||
import java.lang.reflect.Modifier;
|
||||
|
||||
import org.antlr.runtime.Token;
|
||||
import org.springframework.expression.EvaluationContext;
|
||||
import org.springframework.expression.EvaluationException;
|
||||
import org.springframework.expression.TypeConverter;
|
||||
import org.springframework.expression.spel.ExpressionState;
|
||||
import org.springframework.expression.spel.SpelException;
|
||||
import org.springframework.expression.spel.SpelMessages;
|
||||
import org.springframework.expression.spel.reflection.ReflectionUtils;
|
||||
|
||||
/**
|
||||
* A function reference is of the form "#someFunction(a,b,c)". Functions may be defined in the context prior to the
|
||||
* expression being evaluated or within the expression itself using a lambda function definition. For example: Lambda
|
||||
* function definition in an expression: "(#max = {|x,y|$x>$y?$x:$y};max(2,3))" Calling context defined function:
|
||||
* "#isEven(37)". Functions may also be static java methods, registered in the context prior to invocation of the
|
||||
* expression.
|
||||
*
|
||||
* Functions are very simplistic, the arguments are not part of the definition (right now), so the names must be unique.
|
||||
*
|
||||
* @author Andy Clement
|
||||
*/
|
||||
public class FunctionReference extends SpelNode {
|
||||
|
||||
private final String name;
|
||||
|
||||
public FunctionReference(Token payload) {
|
||||
super(payload);
|
||||
name = payload.getText();
|
||||
}
|
||||
|
||||
@Override
|
||||
public Object getValue(ExpressionState state) throws EvaluationException {
|
||||
Object o = state.lookupVariable(name);
|
||||
if (o == null) {
|
||||
throw new SpelException(SpelMessages.FUNCTION_NOT_DEFINED, name);
|
||||
}
|
||||
|
||||
// Two possibilities: a lambda function or a Java static method registered as a function
|
||||
if (!(o instanceof Method)) {
|
||||
throw new SpelException(SpelMessages.FUNCTION_REFERENCE_CANNOT_BE_INVOKED, name, o.getClass());
|
||||
}
|
||||
|
||||
return executeFunctionJLRMethod(state, (Method) o);
|
||||
}
|
||||
|
||||
/**
|
||||
* Execute a function represented as a java.lang.reflect.Method.
|
||||
*
|
||||
* @param state the expression evaluation state
|
||||
* @param the java method to invoke
|
||||
* @return the return value of the invoked Java method
|
||||
* @throws EvaluationException if there is any problem invoking the method
|
||||
*/
|
||||
private Object executeFunctionJLRMethod(ExpressionState state, Method m) throws EvaluationException {
|
||||
Object[] functionArgs = getArguments(state);
|
||||
|
||||
if (!m.isVarArgs() && m.getParameterTypes().length != functionArgs.length) {
|
||||
throw new SpelException(SpelMessages.INCORRECT_NUMBER_OF_ARGUMENTS_TO_FUNCTION, functionArgs.length, m
|
||||
.getParameterTypes().length);
|
||||
}
|
||||
// Only static methods can be called in this way
|
||||
if (!Modifier.isStatic(m.getModifiers())) {
|
||||
throw new SpelException(getCharPositionInLine(), SpelMessages.FUNCTION_MUST_BE_STATIC, m
|
||||
.getDeclaringClass().getName()
|
||||
+ "." + m.getName(), name);
|
||||
}
|
||||
|
||||
// Convert arguments if necessary and remap them for varargs if required
|
||||
if (functionArgs != null) {
|
||||
EvaluationContext ctx = state.getEvaluationContext();
|
||||
TypeConverter converter = null;
|
||||
if (ctx.getTypeUtils() != null) {
|
||||
converter = ctx.getTypeUtils().getTypeConverter();
|
||||
}
|
||||
ReflectionUtils.convertArguments(m.getParameterTypes(), m.isVarArgs(), converter, functionArgs);
|
||||
}
|
||||
if (m.isVarArgs()) {
|
||||
functionArgs = ReflectionUtils.setupArgumentsForVarargsInvocation(m.getParameterTypes(), functionArgs);
|
||||
}
|
||||
|
||||
try {
|
||||
return m.invoke(m.getClass(), functionArgs);
|
||||
} catch (IllegalArgumentException e) {
|
||||
throw new SpelException(getCharPositionInLine(), e, SpelMessages.EXCEPTION_DURING_FUNCTION_CALL, name, e
|
||||
.getMessage());
|
||||
} catch (IllegalAccessException e) {
|
||||
throw new SpelException(getCharPositionInLine(), e, SpelMessages.EXCEPTION_DURING_FUNCTION_CALL, name, e
|
||||
.getMessage());
|
||||
} catch (InvocationTargetException e) {
|
||||
throw new SpelException(getCharPositionInLine(), e, SpelMessages.EXCEPTION_DURING_FUNCTION_CALL, name, e
|
||||
.getMessage());
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toStringAST() {
|
||||
StringBuilder sb = new StringBuilder("#").append(name);
|
||||
sb.append("(");
|
||||
for (int i = 0; i < getChildCount(); i++) {
|
||||
if (i > 0)
|
||||
sb.append(",");
|
||||
sb.append(getChild(i).toStringAST());
|
||||
}
|
||||
sb.append(")");
|
||||
return sb.toString();
|
||||
}
|
||||
|
||||
// to 'assign' to a function don't use the () suffix and so it is just a variable reference
|
||||
@Override
|
||||
public boolean isWritable(ExpressionState expressionState) throws EvaluationException {
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* Compute the arguments to the function, they are the children of this expression node.
|
||||
* @return an array of argument values for the function call
|
||||
*/
|
||||
private Object[] getArguments(ExpressionState state) throws EvaluationException {
|
||||
// Compute arguments to the function
|
||||
Object[] arguments = new Object[getChildCount()];
|
||||
for (int i = 0; i < arguments.length; i++) {
|
||||
arguments[i] = getChild(i).getValue(state);
|
||||
}
|
||||
return arguments;
|
||||
}
|
||||
|
||||
}
|
|
@ -1,41 +0,0 @@
|
|||
/*
|
||||
* Copyright 2004-2008 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
|
||||
*
|
||||
* 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.springframework.expression.spel.ast;
|
||||
|
||||
import org.antlr.runtime.Token;
|
||||
import org.springframework.expression.spel.SpelException;
|
||||
import org.springframework.expression.spel.ExpressionState;
|
||||
|
||||
public class Identifier extends SpelNode {
|
||||
|
||||
private final String id;
|
||||
|
||||
public Identifier(Token payload) {
|
||||
super(payload);
|
||||
id = payload.getText();
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toStringAST() {
|
||||
return id;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getValue(ExpressionState state) throws SpelException {
|
||||
return id;
|
||||
}
|
||||
|
||||
}
|
|
@ -1,156 +0,0 @@
|
|||
/*
|
||||
* Copyright 2004-2008 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
|
||||
*
|
||||
* 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.springframework.expression.spel.ast;
|
||||
|
||||
import java.util.Collection;
|
||||
import java.util.Map;
|
||||
|
||||
import org.antlr.runtime.Token;
|
||||
import org.springframework.expression.EvaluationException;
|
||||
import org.springframework.expression.spel.ExpressionState;
|
||||
import org.springframework.expression.spel.SpelException;
|
||||
import org.springframework.expression.spel.SpelMessages;
|
||||
|
||||
// TODO support multidimensional arrays
|
||||
// TODO support correct syntax for multidimensional [][][] and not [,,,]
|
||||
/**
|
||||
* An Indexer can index into some proceeding structure to access a particular piece of it. Supported structures are:
|
||||
* strings/collections (lists/sets)/arrays
|
||||
*
|
||||
* @author Andy Clement
|
||||
*/
|
||||
public class Indexer extends SpelNode {
|
||||
|
||||
public Indexer(Token payload) {
|
||||
super(payload);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Object getValue(ExpressionState state) throws EvaluationException {
|
||||
Object ctx = state.getActiveContextObject();
|
||||
Object index = getChild(0).getValue(state);
|
||||
|
||||
// Indexing into a Map
|
||||
if (ctx instanceof Map) {
|
||||
return ((Map<?, ?>) ctx).get(index);
|
||||
}
|
||||
|
||||
int idx = state.toInteger(index);
|
||||
|
||||
if (ctx.getClass().isArray()) {
|
||||
return accessArrayElement(ctx, idx);
|
||||
} else if (ctx instanceof Collection) {
|
||||
Collection<?> c = (Collection<?>) ctx;
|
||||
if (idx >= c.size()) {
|
||||
throw new SpelException(SpelMessages.COLLECTION_INDEX_OUT_OF_BOUNDS, c.size(), idx);
|
||||
}
|
||||
int pos = 0;
|
||||
for (Object o : c) {
|
||||
if (pos == idx) {
|
||||
return o;
|
||||
}
|
||||
pos++;
|
||||
}
|
||||
// } else if (ctx instanceof Map) {
|
||||
// Map<?,?> c = (Map<?,?>) ctx;
|
||||
// // This code would allow a key/value pair to be pulled out by index from a map
|
||||
// if (idx >= c.size()) {
|
||||
// throw new ELException(ELMessages.COLLECTION_INDEX_OUT_OF_BOUNDS,c.size(),idx);
|
||||
// }
|
||||
// Set<?> keys = c.keySet();
|
||||
// int pos = 0;
|
||||
// for (Object k : keys) {
|
||||
// if (pos==idx) {
|
||||
// return new KeyValuePair(k,c.get(k));
|
||||
// }
|
||||
// pos++;
|
||||
// }
|
||||
} else if (ctx instanceof String) {
|
||||
String ctxString = (String) ctx;
|
||||
if (idx >= ctxString.length()) {
|
||||
throw new SpelException(SpelMessages.STRING_INDEX_OUT_OF_BOUNDS, ctxString.length(), idx);
|
||||
}
|
||||
return String.valueOf(ctxString.charAt(idx));
|
||||
}
|
||||
throw new SpelException(SpelMessages.INDEXING_NOT_SUPPORTED_FOR_TYPE, ctx.getClass().getName());
|
||||
}
|
||||
|
||||
private Object accessArrayElement(Object ctx, int idx) throws SpelException {
|
||||
Class<?> arrayComponentType = ctx.getClass().getComponentType();
|
||||
if (arrayComponentType == Integer.TYPE) {
|
||||
int[] array = (int[]) ctx;
|
||||
checkAccess(array.length, idx);
|
||||
return array[idx];
|
||||
} else if (arrayComponentType == Boolean.TYPE) {
|
||||
boolean[] array = (boolean[]) ctx;
|
||||
checkAccess(array.length, idx);
|
||||
return array[idx];
|
||||
} else if (arrayComponentType == Character.TYPE) {
|
||||
char[] array = (char[]) ctx;
|
||||
checkAccess(array.length, idx);
|
||||
return array[idx];
|
||||
} else if (arrayComponentType == Long.TYPE) {
|
||||
long[] array = (long[]) ctx;
|
||||
checkAccess(array.length, idx);
|
||||
return array[idx];
|
||||
} else if (arrayComponentType == Short.TYPE) {
|
||||
short[] array = (short[]) ctx;
|
||||
checkAccess(array.length, idx);
|
||||
return array[idx];
|
||||
} else if (arrayComponentType == Double.TYPE) {
|
||||
double[] array = (double[]) ctx;
|
||||
checkAccess(array.length, idx);
|
||||
return array[idx];
|
||||
} else if (arrayComponentType == Float.TYPE) {
|
||||
float[] array = (float[]) ctx;
|
||||
checkAccess(array.length, idx);
|
||||
return array[idx];
|
||||
} else if (arrayComponentType == Byte.TYPE) {
|
||||
byte[] array = (byte[]) ctx;
|
||||
checkAccess(array.length, idx);
|
||||
return array[idx];
|
||||
} else {
|
||||
Object[] array = (Object[]) ctx;
|
||||
checkAccess(array.length, idx);
|
||||
return array[idx];
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toStringAST() {
|
||||
StringBuilder sb = new StringBuilder();
|
||||
sb.append("[");
|
||||
for (int i = 0; i < getChildCount(); i++) {
|
||||
if (i > 0)
|
||||
sb.append(",");
|
||||
sb.append(getChild(i).toStringAST());
|
||||
}
|
||||
sb.append("]");
|
||||
return sb.toString();
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isWritable(ExpressionState expressionState) throws SpelException {
|
||||
return false;
|
||||
}
|
||||
|
||||
private void checkAccess(int arrayLength, int index) throws SpelException {
|
||||
if (index > arrayLength) {
|
||||
throw new SpelException(getCharPositionInLine(), SpelMessages.ARRAY_INDEX_OUT_OF_BOUNDS, arrayLength, index);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
|
@ -1,39 +0,0 @@
|
|||
/*
|
||||
* Copyright 2004-2008 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
|
||||
*
|
||||
* 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.springframework.expression.spel.ast;
|
||||
|
||||
import org.antlr.runtime.Token;
|
||||
|
||||
/**
|
||||
* Expression language AST node that represents an integer literal.
|
||||
*
|
||||
* @author Andy Clement
|
||||
*/
|
||||
public class IntLiteral extends Literal {
|
||||
|
||||
private final Integer value;
|
||||
|
||||
IntLiteral(Token payload, int value) {
|
||||
super(payload);
|
||||
this.value = value;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Integer getLiteralValue() {
|
||||
return value;
|
||||
}
|
||||
|
||||
}
|
|
@ -1,101 +0,0 @@
|
|||
/*
|
||||
* Copyright 2004-2008 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
|
||||
*
|
||||
* 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.springframework.expression.spel.ast;
|
||||
|
||||
import org.antlr.runtime.Token;
|
||||
import org.springframework.expression.spel.ExpressionState;
|
||||
import org.springframework.expression.spel.SpelException;
|
||||
import org.springframework.expression.spel.SpelMessages;
|
||||
import org.springframework.expression.spel.internal.InternalELException;
|
||||
|
||||
/**
|
||||
* Common superclass for nodes representing literals (boolean, string, number, etc).
|
||||
*
|
||||
* @author Andy Clement
|
||||
*
|
||||
*/
|
||||
public abstract class Literal extends SpelNode {
|
||||
|
||||
public Literal(Token payload) {
|
||||
super(payload);
|
||||
}
|
||||
|
||||
public abstract Object getLiteralValue();
|
||||
|
||||
@Override
|
||||
public final Object getValue(ExpressionState state) throws SpelException {
|
||||
return getLiteralValue();
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return getLiteralValue().toString();
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toStringAST() {
|
||||
return toString();
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isWritable(ExpressionState expressionState) throws SpelException {
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* Process the string form of a number, using the specified base if supplied and return an appropriate literal to
|
||||
* hold it. Any suffix to indicate a long will be taken into account (either 'l' or 'L' is supported).
|
||||
*
|
||||
* @param numberToken the token holding the number as its payload (eg. 1234 or 0xCAFE)
|
||||
* @param radix the base of number
|
||||
* @return a subtype of Literal that can represent it
|
||||
*/
|
||||
public static Literal getIntLiteral(Token numberToken, int radix) {
|
||||
String numberString = numberToken.getText();
|
||||
|
||||
boolean isLong = false;
|
||||
boolean isHex = (radix == 16);
|
||||
|
||||
if (numberString.length() > 0) {
|
||||
isLong = numberString.endsWith("L") || numberString.endsWith("l");
|
||||
}
|
||||
|
||||
if (isLong || isHex) { // needs to be chopped up a little
|
||||
int len = numberString.length();
|
||||
// assert: if hex then startsWith 0x or 0X
|
||||
numberString = numberString.substring((isHex ? 2 : 0), isLong ? len - 1 : len);
|
||||
}
|
||||
|
||||
if (isLong) {
|
||||
try {
|
||||
long value = Long.parseLong(numberString, radix);
|
||||
return new LongLiteral(numberToken, value);
|
||||
} catch (NumberFormatException nfe) {
|
||||
throw new InternalELException(new SpelException(numberToken.getCharPositionInLine(), nfe,
|
||||
SpelMessages.NOT_A_LONG, numberToken.getText()));
|
||||
}
|
||||
} else {
|
||||
try {
|
||||
int value = Integer.parseInt(numberString, radix);
|
||||
return new IntLiteral(numberToken, value);
|
||||
} catch (NumberFormatException nfe) {
|
||||
throw new InternalELException(new SpelException(numberToken.getCharPositionInLine(), nfe,
|
||||
SpelMessages.NOT_AN_INTEGER, numberToken.getText()));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
}
|
|
@ -1,39 +0,0 @@
|
|||
/*
|
||||
* Copyright 2004-2008 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
|
||||
*
|
||||
* 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.springframework.expression.spel.ast;
|
||||
|
||||
import org.antlr.runtime.Token;
|
||||
|
||||
/**
|
||||
* Expression language AST node that represents a long integer literal.
|
||||
*
|
||||
* @author Andy Clement
|
||||
*/
|
||||
public class LongLiteral extends Literal {
|
||||
|
||||
private final Long value;
|
||||
|
||||
LongLiteral(Token payload, long value) {
|
||||
super(payload);
|
||||
this.value = value;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Long getLiteralValue() {
|
||||
return value;
|
||||
}
|
||||
|
||||
}
|
|
@ -1,156 +0,0 @@
|
|||
/*
|
||||
* Copyright 2004-2008 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
|
||||
*
|
||||
* 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.springframework.expression.spel.ast;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
import org.antlr.runtime.Token;
|
||||
import org.springframework.expression.AccessException;
|
||||
import org.springframework.expression.EvaluationContext;
|
||||
import org.springframework.expression.EvaluationException;
|
||||
import org.springframework.expression.MethodExecutor;
|
||||
import org.springframework.expression.MethodResolver;
|
||||
import org.springframework.expression.spel.ExpressionState;
|
||||
import org.springframework.expression.spel.SpelException;
|
||||
import org.springframework.expression.spel.SpelMessages;
|
||||
import org.springframework.expression.spel.internal.Utils;
|
||||
|
||||
public class MethodReference extends SpelNode {
|
||||
|
||||
private final String name;
|
||||
private MethodExecutor fastInvocationAccessor;
|
||||
|
||||
public MethodReference(Token payload) {
|
||||
super(payload);
|
||||
name = payload.getText();
|
||||
}
|
||||
|
||||
@Override
|
||||
public Object getValue(ExpressionState state) throws EvaluationException {
|
||||
Object currentContext = state.getActiveContextObject();
|
||||
Object[] arguments = new Object[getChildCount()];
|
||||
for (int i = 0; i < arguments.length; i++) {
|
||||
arguments[i] = getChild(i).getValue(state);
|
||||
}
|
||||
if (currentContext == null) {
|
||||
throw new SpelException(getCharPositionInLine(), SpelMessages.ATTEMPTED_METHOD_CALL_ON_NULL_CONTEXT_OBJECT,
|
||||
formatMethodForMessage(name, getTypes(arguments)));
|
||||
}
|
||||
|
||||
if (fastInvocationAccessor != null) {
|
||||
try {
|
||||
return fastInvocationAccessor.execute(state.getEvaluationContext(), state.getActiveContextObject(),
|
||||
arguments);
|
||||
} catch (AccessException ae) {
|
||||
// this is OK - it may have gone stale due to a class change, let's get a new one and retry before
|
||||
// giving up
|
||||
}
|
||||
}
|
||||
// either there was no accessor or it no longer existed
|
||||
fastInvocationAccessor = findAccessorForMethod(name, getTypes(arguments), state);
|
||||
try {
|
||||
return fastInvocationAccessor.execute(state.getEvaluationContext(), state.getActiveContextObject(),
|
||||
arguments);
|
||||
} catch (AccessException ae) {
|
||||
ae.printStackTrace();
|
||||
throw new SpelException(getCharPositionInLine(), ae, SpelMessages.EXCEPTION_DURING_METHOD_INVOCATION, name,
|
||||
state.getActiveContextObject().getClass().getName(), ae.getMessage());
|
||||
}
|
||||
}
|
||||
|
||||
private Class<?>[] getTypes(Object... arguments) {
|
||||
if (arguments == null)
|
||||
return null;
|
||||
Class<?>[] argumentTypes = new Class[arguments.length];
|
||||
for (int i = 0; i < arguments.length; i++) {
|
||||
argumentTypes[i] = arguments[i].getClass();
|
||||
}
|
||||
return argumentTypes;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toStringAST() {
|
||||
StringBuilder sb = new StringBuilder();
|
||||
sb.append(name).append("(");
|
||||
for (int i = 0; i < getChildCount(); i++) {
|
||||
if (i > 0)
|
||||
sb.append(",");
|
||||
sb.append(getChild(i).toStringAST());
|
||||
}
|
||||
sb.append(")");
|
||||
return sb.toString();
|
||||
}
|
||||
|
||||
/**
|
||||
* Produce a nice string for a given method name with specified arguments.
|
||||
* @param name the name of the method
|
||||
* @param argumentTypes the types of the arguments to the method
|
||||
* @return nicely formatted string, eg. foo(String,int)
|
||||
*/
|
||||
private String formatMethodForMessage(String name, Class<?>... argumentTypes) {
|
||||
StringBuilder sb = new StringBuilder();
|
||||
sb.append(name);
|
||||
sb.append("(");
|
||||
if (argumentTypes != null) {
|
||||
for (int i = 0; i < argumentTypes.length; i++) {
|
||||
if (i > 0)
|
||||
sb.append(",");
|
||||
sb.append(argumentTypes[i].getClass());
|
||||
}
|
||||
}
|
||||
sb.append(")");
|
||||
return sb.toString();
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isWritable(ExpressionState expressionState) throws SpelException {
|
||||
return false;
|
||||
}
|
||||
|
||||
public final MethodExecutor findAccessorForMethod(String name, Class<?>[] argumentTypes, ExpressionState state)
|
||||
throws SpelException {
|
||||
Object contextObject = state.getActiveContextObject();
|
||||
EvaluationContext eContext = state.getEvaluationContext();
|
||||
if (contextObject == null) {
|
||||
throw new SpelException(SpelMessages.ATTEMPTED_METHOD_CALL_ON_NULL_CONTEXT_OBJECT, Utils
|
||||
.formatMethodForMessage(name, argumentTypes));
|
||||
}
|
||||
List<MethodResolver> mResolvers = eContext.getMethodResolvers();
|
||||
if (mResolvers != null) {
|
||||
for (MethodResolver methodResolver : mResolvers) {
|
||||
try {
|
||||
MethodExecutor cEx = methodResolver.resolve(state.getEvaluationContext(), contextObject, name,
|
||||
argumentTypes);
|
||||
if (cEx != null)
|
||||
return cEx;
|
||||
} catch (AccessException e) {
|
||||
Throwable cause = e.getCause();
|
||||
if (cause instanceof SpelException) {
|
||||
throw (SpelException) cause;
|
||||
} else {
|
||||
throw new SpelException(cause, SpelMessages.PROBLEM_LOCATING_METHOD, name, contextObject
|
||||
.getClass());
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
throw new SpelException(SpelMessages.METHOD_NOT_FOUND, Utils.formatMethodForMessage(name, argumentTypes), Utils
|
||||
.formatClassnameForMessage(contextObject instanceof Class ? ((Class<?>) contextObject) : contextObject
|
||||
.getClass()));
|
||||
// (contextObject instanceof Class ? ((Class<?>) contextObject).getName() : contextObject.getClass()
|
||||
// .getName()));
|
||||
}
|
||||
}
|
|
@ -1,36 +0,0 @@
|
|||
/*
|
||||
* Copyright 2004-2008 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
|
||||
*
|
||||
* 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.springframework.expression.spel.ast;
|
||||
|
||||
import org.antlr.runtime.Token;
|
||||
|
||||
public class NullLiteral extends Literal {
|
||||
|
||||
public NullLiteral(Token payload) {
|
||||
super(payload);
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getLiteralValue() {
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return null;
|
||||
}
|
||||
|
||||
}
|
|
@ -1,70 +0,0 @@
|
|||
/*
|
||||
* Copyright 2004-2008 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
|
||||
*
|
||||
* 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.springframework.expression.spel.ast;
|
||||
|
||||
import org.antlr.runtime.Token;
|
||||
import org.springframework.expression.spel.SpelException;
|
||||
import org.springframework.expression.spel.ExpressionState;
|
||||
|
||||
/**
|
||||
* Common supertype for operators that operate on either one or two operands. In the case of multiply or divide there
|
||||
* would be two operands, but for unary plus or minus, there is only one.
|
||||
*
|
||||
* @author Andy Clement
|
||||
*/
|
||||
public abstract class Operator extends SpelNode {
|
||||
|
||||
public Operator(Token payload) {
|
||||
super(payload);
|
||||
}
|
||||
|
||||
/**
|
||||
* Operator expressions can never be written to
|
||||
*/
|
||||
@Override
|
||||
public final boolean isWritable(ExpressionState expressionState) throws SpelException {
|
||||
return false;
|
||||
}
|
||||
|
||||
public SpelNode getLeftOperand() {
|
||||
return getChild(0);
|
||||
}
|
||||
|
||||
public SpelNode getRightOperand() {
|
||||
return getChild(1);
|
||||
}
|
||||
|
||||
public abstract String getOperatorName();
|
||||
|
||||
/**
|
||||
* String format for all operators is the same '(' [operand] [operator] [operand] ')'
|
||||
*/
|
||||
@Override
|
||||
public String toStringAST() {
|
||||
StringBuffer sb = new StringBuffer();
|
||||
if (getChildCount() > 0)
|
||||
sb.append("(");
|
||||
sb.append(getChild(0).toStringAST());
|
||||
for (int i = 1; i < getChildCount(); i++) {
|
||||
sb.append(" ").append(getOperatorName()).append(" ");
|
||||
sb.append(getChild(i).toStringAST());
|
||||
}
|
||||
if (getChildCount() > 0)
|
||||
sb.append(")");
|
||||
return sb.toString();
|
||||
}
|
||||
|
||||
}
|
|
@ -1,65 +0,0 @@
|
|||
/*
|
||||
* Copyright 2004-2008 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
|
||||
*
|
||||
* 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.springframework.expression.spel.ast;
|
||||
|
||||
import org.antlr.runtime.Token;
|
||||
import org.springframework.expression.EvaluationException;
|
||||
import org.springframework.expression.spel.SpelException;
|
||||
import org.springframework.expression.spel.ExpressionState;
|
||||
|
||||
/**
|
||||
* Represents the boolean AND operation.
|
||||
*
|
||||
* @author Andy Clement
|
||||
*/
|
||||
public class OperatorAnd extends Operator {
|
||||
|
||||
public OperatorAnd(Token payload) {
|
||||
super(payload);
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getOperatorName() {
|
||||
return "and";
|
||||
}
|
||||
|
||||
@Override
|
||||
public Object getValue(ExpressionState state) throws EvaluationException {
|
||||
boolean leftValue;
|
||||
boolean rightValue;
|
||||
|
||||
try {
|
||||
leftValue = state.toBoolean(getLeftOperand().getValue(state));
|
||||
} catch (SpelException ee) {
|
||||
ee.setPosition(getLeftOperand().getCharPositionInLine());
|
||||
throw ee;
|
||||
}
|
||||
|
||||
if (leftValue == false) {
|
||||
return false; // no need to evaluate right operand
|
||||
}
|
||||
|
||||
try {
|
||||
rightValue = state.toBoolean(getRightOperand().getValue(state));
|
||||
} catch (SpelException ee) {
|
||||
ee.setPosition(getRightOperand().getCharPositionInLine());
|
||||
throw ee;
|
||||
}
|
||||
|
||||
return /* leftValue && */rightValue;
|
||||
}
|
||||
|
||||
}
|
|
@ -1,73 +0,0 @@
|
|||
/*
|
||||
* Copyright 2004-2008 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
|
||||
*
|
||||
* 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.springframework.expression.spel.ast;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
import org.antlr.runtime.Token;
|
||||
import org.springframework.expression.EvaluationException;
|
||||
import org.springframework.expression.TypeComparator;
|
||||
import org.springframework.expression.spel.ExpressionState;
|
||||
import org.springframework.expression.spel.SpelException;
|
||||
import org.springframework.expression.spel.SpelMessages;
|
||||
|
||||
/**
|
||||
* Represents the between operator. The left operand to between must be a single value and the right operand must be a
|
||||
* list - this operator returns true if the left operand is between (using the registered comparator) the two elements
|
||||
* in the list. The definition of between being inclusive follows the SQL BETWEEN definition.
|
||||
*
|
||||
* @author Andy Clement
|
||||
*/
|
||||
public class OperatorBetween extends Operator {
|
||||
|
||||
public OperatorBetween(Token payload) {
|
||||
super(payload);
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getOperatorName() {
|
||||
return "between";
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns a boolean based on whether a value is in the range expressed. The first operand is any value whilst the
|
||||
* second is a list of two values - those two values being the bounds allowed for the first operand (inclusive).
|
||||
*
|
||||
* @param state the expression state
|
||||
* @return true if the left operand is in the range specified, false otherwise
|
||||
* @throws EvaluationException if there is a problem evaluating the expression
|
||||
*/
|
||||
@Override
|
||||
public Boolean getValue(ExpressionState state) throws EvaluationException {
|
||||
Object left = getLeftOperand().getValue(state);
|
||||
Object right = getRightOperand().getValue(state);
|
||||
if (!(right instanceof List) || ((List<?>) right).size() != 2) {
|
||||
throw new SpelException(getRightOperand().getCharPositionInLine(),
|
||||
SpelMessages.BETWEEN_RIGHT_OPERAND_MUST_BE_TWO_ELEMENT_LIST);
|
||||
}
|
||||
List<?> l = (List<?>) right;
|
||||
Object low = l.get(0);
|
||||
Object high = l.get(1);
|
||||
TypeComparator comparator = state.getTypeComparator();
|
||||
try {
|
||||
return (comparator.compare(left, low) >= 0 && comparator.compare(left, high) <= 0);
|
||||
} catch (SpelException ex) {
|
||||
ex.setPosition(getCharPositionInLine());
|
||||
throw ex;
|
||||
}
|
||||
}
|
||||
|
||||
}
|
|
@ -1,63 +0,0 @@
|
|||
/*
|
||||
* Copyright 2004-2008 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
|
||||
*
|
||||
* 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.springframework.expression.spel.ast;
|
||||
|
||||
import org.antlr.runtime.Token;
|
||||
import org.springframework.expression.EvaluationException;
|
||||
import org.springframework.expression.Operation;
|
||||
import org.springframework.expression.spel.ExpressionState;
|
||||
|
||||
/**
|
||||
* Implements division operator
|
||||
*
|
||||
* @author Andy Clement
|
||||
*/
|
||||
public class OperatorDivide extends Operator {
|
||||
|
||||
public OperatorDivide(Token payload) {
|
||||
super(payload);
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getOperatorName() {
|
||||
return "/";
|
||||
}
|
||||
|
||||
@Override
|
||||
public Object getValue(ExpressionState state) throws EvaluationException {
|
||||
Object operandOne = getLeftOperand().getValue(state);
|
||||
Object operandTwo = getRightOperand().getValue(state);
|
||||
if (operandOne instanceof Number && operandTwo instanceof Number) {
|
||||
Number op1 = (Number) operandOne;
|
||||
Number op2 = (Number) operandTwo;
|
||||
if (op1 instanceof Double || op2 instanceof Double) {
|
||||
Double result = op1.doubleValue() / op2.doubleValue();
|
||||
return result;
|
||||
} else if (op1 instanceof Float || op2 instanceof Float) {
|
||||
Float result = op1.floatValue() / op2.floatValue();
|
||||
return result;
|
||||
} else if (op1 instanceof Long || op2 instanceof Long) {
|
||||
Long result = op1.longValue() / op2.longValue();
|
||||
return result;
|
||||
} else { // TODO what about non-int result of the division?
|
||||
Integer result = op1.intValue() / op2.intValue();
|
||||
return result;
|
||||
}
|
||||
}
|
||||
return state.operate(Operation.DIVIDE, operandOne, operandTwo);
|
||||
}
|
||||
|
||||
}
|
|
@ -1,58 +0,0 @@
|
|||
/*
|
||||
* Copyright 2004-2008 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
|
||||
*
|
||||
* 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.springframework.expression.spel.ast;
|
||||
|
||||
import org.antlr.runtime.Token;
|
||||
import org.springframework.expression.EvaluationException;
|
||||
import org.springframework.expression.spel.ExpressionState;
|
||||
|
||||
/**
|
||||
* Implements equality operator.
|
||||
*
|
||||
* @author Andy Clement
|
||||
*/
|
||||
public class OperatorEquality extends Operator {
|
||||
|
||||
public OperatorEquality(Token payload) {
|
||||
super(payload);
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getOperatorName() {
|
||||
return "==";
|
||||
}
|
||||
|
||||
@Override
|
||||
public Object getValue(ExpressionState state) throws EvaluationException {
|
||||
Object left = getLeftOperand().getValue(state);
|
||||
Object right = getRightOperand().getValue(state);
|
||||
if (left instanceof Number && right instanceof Number) {
|
||||
Number op1 = (Number) left;
|
||||
Number op2 = (Number) right;
|
||||
if (op1 instanceof Double || op2 instanceof Double) {
|
||||
return op1.doubleValue() == op2.doubleValue();
|
||||
} else if (op1 instanceof Float || op2 instanceof Float) {
|
||||
return op1.floatValue() == op2.floatValue();
|
||||
} else if (op1 instanceof Long || op2 instanceof Long) {
|
||||
return op1.longValue() == op2.longValue();
|
||||
} else {
|
||||
return op1.intValue() == op2.intValue();
|
||||
}
|
||||
}
|
||||
return state.getTypeComparator().compare(left, right) == 0;
|
||||
}
|
||||
|
||||
}
|
|
@ -1,58 +0,0 @@
|
|||
/*
|
||||
* Copyright 2004-2008 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
|
||||
*
|
||||
* 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.springframework.expression.spel.ast;
|
||||
|
||||
import org.antlr.runtime.Token;
|
||||
import org.springframework.expression.EvaluationException;
|
||||
import org.springframework.expression.spel.ExpressionState;
|
||||
|
||||
/**
|
||||
* Implements greater than operator.
|
||||
*
|
||||
* @author Andy Clement
|
||||
*/
|
||||
public class OperatorGreaterThan extends Operator {
|
||||
|
||||
public OperatorGreaterThan(Token payload) {
|
||||
super(payload);
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getOperatorName() {
|
||||
return ">";
|
||||
}
|
||||
|
||||
@Override
|
||||
public Object getValue(ExpressionState state) throws EvaluationException {
|
||||
Object left = getLeftOperand().getValue(state);
|
||||
Object right = getRightOperand().getValue(state);
|
||||
if (left instanceof Number && right instanceof Number) {
|
||||
Number op1 = (Number) left;
|
||||
Number op2 = (Number) right;
|
||||
if (op1 instanceof Double || op2 instanceof Double) {
|
||||
return op1.doubleValue() > op2.doubleValue();
|
||||
} else if (op1 instanceof Float || op2 instanceof Float) {
|
||||
return op1.floatValue() > op2.floatValue();
|
||||
} else if (op1 instanceof Long || op2 instanceof Long) {
|
||||
return op1.longValue() > op2.longValue();
|
||||
} else {
|
||||
return op1.intValue() > op2.intValue();
|
||||
}
|
||||
}
|
||||
return state.getTypeComparator().compare(left, right) > 0;
|
||||
}
|
||||
|
||||
}
|
|
@ -1,58 +0,0 @@
|
|||
/*
|
||||
* Copyright 2004-2008 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
|
||||
*
|
||||
* 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.springframework.expression.spel.ast;
|
||||
|
||||
import org.antlr.runtime.Token;
|
||||
import org.springframework.expression.EvaluationException;
|
||||
import org.springframework.expression.spel.ExpressionState;
|
||||
|
||||
/**
|
||||
* Implements greater than or equal operator.
|
||||
*
|
||||
* @author Andy Clement
|
||||
*/
|
||||
public class OperatorGreaterThanOrEqual extends Operator {
|
||||
|
||||
public OperatorGreaterThanOrEqual(Token payload) {
|
||||
super(payload);
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getOperatorName() {
|
||||
return ">=";
|
||||
}
|
||||
|
||||
@Override
|
||||
public Object getValue(ExpressionState state) throws EvaluationException {
|
||||
Object left = getLeftOperand().getValue(state);
|
||||
Object right = getRightOperand().getValue(state);
|
||||
if (left instanceof Number && right instanceof Number) {
|
||||
Number op1 = (Number) left;
|
||||
Number op2 = (Number) right;
|
||||
if (op1 instanceof Double || op2 instanceof Double) {
|
||||
return op1.doubleValue() >= op2.doubleValue();
|
||||
} else if (op1 instanceof Float || op2 instanceof Float) {
|
||||
return op1.floatValue() >= op2.floatValue();
|
||||
} else if (op1 instanceof Long || op2 instanceof Long) {
|
||||
return op1.longValue() >= op2.longValue();
|
||||
} else {
|
||||
return op1.intValue() >= op2.intValue();
|
||||
}
|
||||
}
|
||||
return state.getTypeComparator().compare(left, right) >= 0;
|
||||
}
|
||||
|
||||
}
|
|
@ -1,58 +0,0 @@
|
|||
/*
|
||||
* Copyright 2004-2008 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
|
||||
*
|
||||
* 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.springframework.expression.spel.ast;
|
||||
|
||||
import org.antlr.runtime.Token;
|
||||
import org.springframework.expression.EvaluationException;
|
||||
import org.springframework.expression.spel.ExpressionState;
|
||||
|
||||
/**
|
||||
* Implements the not-equal operator
|
||||
*
|
||||
* @author Andy Clement
|
||||
*/
|
||||
public class OperatorInequality extends Operator {
|
||||
|
||||
public OperatorInequality(Token payload) {
|
||||
super(payload);
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getOperatorName() {
|
||||
return "!=";
|
||||
}
|
||||
|
||||
@Override
|
||||
public Object getValue(ExpressionState state) throws EvaluationException {
|
||||
Object left = getLeftOperand().getValue(state);
|
||||
Object right = getRightOperand().getValue(state);
|
||||
if (left instanceof Number && right instanceof Number) {
|
||||
Number op1 = (Number) left;
|
||||
Number op2 = (Number) right;
|
||||
if (op1 instanceof Double || op2 instanceof Double) {
|
||||
return op1.doubleValue() != op2.doubleValue();
|
||||
} else if (op1 instanceof Float || op2 instanceof Float) {
|
||||
return op1.floatValue() != op2.floatValue();
|
||||
} else if (op1 instanceof Long || op2 instanceof Long) {
|
||||
return op1.longValue() != op2.longValue();
|
||||
} else {
|
||||
return op1.intValue() != op2.intValue();
|
||||
}
|
||||
}
|
||||
return state.getTypeComparator().compare(left, right) != 0;
|
||||
}
|
||||
|
||||
}
|
|
@ -1,64 +0,0 @@
|
|||
/*
|
||||
* Copyright 2004-2008 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
|
||||
*
|
||||
* 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.springframework.expression.spel.ast;
|
||||
|
||||
import org.antlr.runtime.Token;
|
||||
import org.springframework.expression.EvaluationException;
|
||||
import org.springframework.expression.spel.ExpressionState;
|
||||
import org.springframework.expression.spel.SpelException;
|
||||
import org.springframework.expression.spel.SpelMessages;
|
||||
|
||||
/**
|
||||
* The operator 'instanceof' checks if an object is of the class specified in the right hand operand, in the same way
|
||||
* that instanceof does in Java.
|
||||
*
|
||||
* @author Andy Clement
|
||||
*/
|
||||
public class OperatorInstanceof extends Operator {
|
||||
|
||||
public OperatorInstanceof(Token payload) {
|
||||
super(payload);
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getOperatorName() {
|
||||
return "instanceof";
|
||||
}
|
||||
|
||||
/**
|
||||
* Compare the left operand to see it is an instance of the type specified as the right operand. The right operand
|
||||
* must be a class.
|
||||
*
|
||||
* @param state the expression state
|
||||
* @return true if the left operand is an instanceof of the right operand, otherwise false
|
||||
* @throws EvaluationException if there is a problem evaluating the expression
|
||||
*/
|
||||
@Override
|
||||
public Boolean getValue(ExpressionState state) throws EvaluationException {
|
||||
Object left = getLeftOperand().getValue(state);
|
||||
Object right = getRightOperand().getValue(state);
|
||||
if (left == null) {
|
||||
return false; // null is not an instanceof anything
|
||||
}
|
||||
if (right == null || !(right instanceof Class<?>)) {
|
||||
throw new SpelException(getRightOperand().getCharPositionInLine(),
|
||||
SpelMessages.INSTANCEOF_OPERATOR_NEEDS_CLASS_OPERAND, (right == null ? "null" : right.getClass().getName()));
|
||||
}
|
||||
Class<?> rightClass = (Class<?>) right;
|
||||
return rightClass.isAssignableFrom(left.getClass());
|
||||
}
|
||||
|
||||
}
|
|
@ -1,58 +0,0 @@
|
|||
/*
|
||||
* Copyright 2004-2008 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
|
||||
*
|
||||
* 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.springframework.expression.spel.ast;
|
||||
|
||||
import org.antlr.runtime.Token;
|
||||
import org.springframework.expression.EvaluationException;
|
||||
import org.springframework.expression.spel.ExpressionState;
|
||||
|
||||
/**
|
||||
* Implements the less than operator
|
||||
*
|
||||
* @author Andy Clement
|
||||
*/
|
||||
public class OperatorLessThan extends Operator {
|
||||
|
||||
public OperatorLessThan(Token payload) {
|
||||
super(payload);
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getOperatorName() {
|
||||
return "<";
|
||||
}
|
||||
|
||||
@Override
|
||||
public Object getValue(ExpressionState state) throws EvaluationException {
|
||||
Object left = getLeftOperand().getValue(state);
|
||||
Object right = getRightOperand().getValue(state);
|
||||
if (left instanceof Number && right instanceof Number) {
|
||||
Number op1 = (Number) left;
|
||||
Number op2 = (Number) right;
|
||||
if (op1 instanceof Double || op2 instanceof Double) {
|
||||
return op1.doubleValue() < op2.doubleValue();
|
||||
} else if (op1 instanceof Float || op2 instanceof Float) {
|
||||
return op1.floatValue() < op2.floatValue();
|
||||
} else if (op1 instanceof Long || op2 instanceof Long) {
|
||||
return op1.longValue() < op2.longValue();
|
||||
} else {
|
||||
return op1.intValue() < op2.intValue();
|
||||
}
|
||||
}
|
||||
return state.getTypeComparator().compare(left, right) < 0;
|
||||
}
|
||||
|
||||
}
|
|
@ -1,58 +0,0 @@
|
|||
/*
|
||||
* Copyright 2004-2008 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
|
||||
*
|
||||
* 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.springframework.expression.spel.ast;
|
||||
|
||||
import org.antlr.runtime.Token;
|
||||
import org.springframework.expression.EvaluationException;
|
||||
import org.springframework.expression.spel.ExpressionState;
|
||||
|
||||
/**
|
||||
* Implements the less than or equal operator
|
||||
*
|
||||
* @author Andy Clement
|
||||
*/
|
||||
public class OperatorLessThanOrEqual extends Operator {
|
||||
|
||||
public OperatorLessThanOrEqual(Token payload) {
|
||||
super(payload);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Object getValue(ExpressionState state) throws EvaluationException {
|
||||
Object left = getLeftOperand().getValue(state);
|
||||
Object right = getRightOperand().getValue(state);
|
||||
if (left instanceof Number && right instanceof Number) {
|
||||
Number op1 = (Number) left;
|
||||
Number op2 = (Number) right;
|
||||
if (op1 instanceof Double || op2 instanceof Double) {
|
||||
return op1.doubleValue() <= op2.doubleValue();
|
||||
} else if (op1 instanceof Float || op2 instanceof Float) {
|
||||
return op1.floatValue() <= op2.floatValue();
|
||||
} else if (op1 instanceof Long || op2 instanceof Long) {
|
||||
return op1.longValue() <= op2.longValue();
|
||||
} else {
|
||||
return op1.intValue() <= op2.intValue();
|
||||
}
|
||||
}
|
||||
return state.getTypeComparator().compare(left, right) <= 0;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getOperatorName() {
|
||||
return "<=";
|
||||
}
|
||||
|
||||
}
|
|
@ -1,75 +0,0 @@
|
|||
/*
|
||||
* Copyright 2004-2008 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
|
||||
*
|
||||
* 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.springframework.expression.spel.ast;
|
||||
|
||||
import java.util.regex.Matcher;
|
||||
import java.util.regex.Pattern;
|
||||
import java.util.regex.PatternSyntaxException;
|
||||
|
||||
import org.antlr.runtime.Token;
|
||||
import org.springframework.expression.EvaluationException;
|
||||
import org.springframework.expression.spel.ExpressionState;
|
||||
import org.springframework.expression.spel.SpelException;
|
||||
import org.springframework.expression.spel.SpelMessages;
|
||||
|
||||
/**
|
||||
* Implements the matches operator. Matches takes two operands. The first is a string and the second is a java regex. It
|
||||
* will return true when getValue() is called if the first operand matches the regex.
|
||||
*
|
||||
* @author Andy Clement
|
||||
*/
|
||||
public class OperatorMatches extends Operator {
|
||||
|
||||
public OperatorMatches(Token payload) {
|
||||
super(payload);
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getOperatorName() {
|
||||
return "matches";
|
||||
}
|
||||
|
||||
/**
|
||||
* Check the first operand matches the regex specified as the second operand.
|
||||
*
|
||||
* @param state the expression state
|
||||
* @return true if the first operand matches the regex specified as the second operand, otherwise false
|
||||
* @throws EvaluationException if there is a problem evaluating the expression (e.g. the regex is invalid)
|
||||
*/
|
||||
@Override
|
||||
public Boolean getValue(ExpressionState state) throws EvaluationException {
|
||||
SpelNode leftOp = getLeftOperand();
|
||||
SpelNode rightOp = getRightOperand();
|
||||
Object left = leftOp.getValue(state, String.class);
|
||||
Object right = getRightOperand().getValue(state);
|
||||
try {
|
||||
if (!(left instanceof String)) {
|
||||
throw new SpelException(leftOp.getCharPositionInLine(),
|
||||
SpelMessages.INVALID_FIRST_OPERAND_FOR_MATCHES_OPERATOR, left);
|
||||
}
|
||||
if (!(right instanceof String)) {
|
||||
throw new SpelException(rightOp.getCharPositionInLine(),
|
||||
SpelMessages.INVALID_SECOND_OPERAND_FOR_MATCHES_OPERATOR, right);
|
||||
}
|
||||
Pattern pattern = Pattern.compile((String) right);
|
||||
Matcher matcher = pattern.matcher((String) left);
|
||||
return matcher.matches();
|
||||
} catch (PatternSyntaxException pse) {
|
||||
throw new SpelException(rightOp.getCharPositionInLine(), pse, SpelMessages.INVALID_PATTERN, right);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
|
@ -1,95 +0,0 @@
|
|||
/*
|
||||
* Copyright 2004-2008 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
|
||||
*
|
||||
* 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.springframework.expression.spel.ast;
|
||||
|
||||
import org.antlr.runtime.Token;
|
||||
import org.springframework.expression.EvaluationException;
|
||||
import org.springframework.expression.Operation;
|
||||
import org.springframework.expression.spel.SpelException;
|
||||
import org.springframework.expression.spel.SpelMessages;
|
||||
import org.springframework.expression.spel.ExpressionState;
|
||||
|
||||
/**
|
||||
* Implements the minus operator. If there is only one operand it is a unary minus.
|
||||
*
|
||||
* @author Andy Clement
|
||||
*/
|
||||
public class OperatorMinus extends Operator {
|
||||
|
||||
public OperatorMinus(Token payload) {
|
||||
super(payload);
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getOperatorName() {
|
||||
return "-";
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toStringAST() {
|
||||
if (getRightOperand() == null) { // unary minus
|
||||
return new StringBuilder().append("-").append(getLeftOperand()).toString();
|
||||
}
|
||||
return super.toStringAST();
|
||||
}
|
||||
|
||||
@Override
|
||||
public Object getValue(ExpressionState state) throws EvaluationException {
|
||||
SpelNode leftOp = getLeftOperand();
|
||||
SpelNode rightOp = getRightOperand();
|
||||
if (rightOp == null) {// If only one operand, then this is unary minus
|
||||
Object left = leftOp.getValue(state);
|
||||
if (left instanceof Number) {
|
||||
Number n = (Number) left;
|
||||
if (left instanceof Double) {
|
||||
Double result = 0 - n.doubleValue();
|
||||
return result;
|
||||
} else if (left instanceof Float) {
|
||||
Float result = 0 - n.floatValue();
|
||||
return result;
|
||||
} else if (left instanceof Long) {
|
||||
Long result = 0 - n.longValue();
|
||||
return result;
|
||||
} else {
|
||||
Integer result = 0 - n.intValue();
|
||||
return result;
|
||||
}
|
||||
}
|
||||
throw new SpelException(SpelMessages.CANNOT_NEGATE_TYPE, left.getClass().getName());
|
||||
} else {
|
||||
Object left = leftOp.getValue(state);
|
||||
Object right = rightOp.getValue(state);
|
||||
if (left instanceof Number && right instanceof Number) {
|
||||
Number op1 = (Number) left;
|
||||
Number op2 = (Number) right;
|
||||
if (op1 instanceof Double || op2 instanceof Double) {
|
||||
Double result = op1.doubleValue() - op2.doubleValue();
|
||||
return result;
|
||||
} else if (op1 instanceof Float || op2 instanceof Float) {
|
||||
Float result = op1.floatValue() - op2.floatValue();
|
||||
return result;
|
||||
} else if (op1 instanceof Long || op2 instanceof Long) {
|
||||
Long result = op1.longValue() - op2.longValue();
|
||||
return result;
|
||||
} else {
|
||||
Integer result = op1.intValue() - op2.intValue();
|
||||
return result;
|
||||
}
|
||||
}
|
||||
return state.operate(Operation.SUBTRACT, left, right);
|
||||
}
|
||||
}
|
||||
}
|
|
@ -1,63 +0,0 @@
|
|||
/*
|
||||
* Copyright 2004-2008 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
|
||||
*
|
||||
* 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.springframework.expression.spel.ast;
|
||||
|
||||
import org.antlr.runtime.Token;
|
||||
import org.springframework.expression.EvaluationException;
|
||||
import org.springframework.expression.Operation;
|
||||
import org.springframework.expression.spel.ExpressionState;
|
||||
|
||||
/**
|
||||
* Implements the modulus operator.
|
||||
*
|
||||
* @author Andy Clement
|
||||
*/
|
||||
public class OperatorModulus extends Operator {
|
||||
|
||||
public OperatorModulus(Token payload) {
|
||||
super(payload);
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getOperatorName() {
|
||||
return "%";
|
||||
}
|
||||
|
||||
@Override
|
||||
public Object getValue(ExpressionState state) throws EvaluationException {
|
||||
Object operandOne = getLeftOperand().getValue(state);
|
||||
Object operandTwo = getRightOperand().getValue(state);
|
||||
if (operandOne instanceof Number && operandTwo instanceof Number) {
|
||||
Number op1 = (Number) operandOne;
|
||||
Number op2 = (Number) operandTwo;
|
||||
if (op1 instanceof Double || op2 instanceof Double) {
|
||||
Double result = op1.doubleValue() % op2.doubleValue();
|
||||
return result;
|
||||
} else if (op1 instanceof Float || op2 instanceof Float) {
|
||||
Float result = op1.floatValue() % op2.floatValue();
|
||||
return result;
|
||||
} else if (op1 instanceof Long || op2 instanceof Long) {
|
||||
Long result = op1.longValue() % op2.longValue();
|
||||
return result;
|
||||
} else {
|
||||
Integer result = op1.intValue() % op2.intValue();
|
||||
return result;
|
||||
}
|
||||
}
|
||||
return state.operate(Operation.MODULUS, operandOne, operandTwo);
|
||||
}
|
||||
|
||||
}
|
|
@ -1,86 +0,0 @@
|
|||
/*
|
||||
* Copyright 2004-2008 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
|
||||
*
|
||||
* 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.springframework.expression.spel.ast;
|
||||
|
||||
import org.antlr.runtime.Token;
|
||||
import org.springframework.expression.EvaluationException;
|
||||
import org.springframework.expression.Operation;
|
||||
import org.springframework.expression.spel.ExpressionState;
|
||||
|
||||
/**
|
||||
* Implements the multiply operator. Conversions and promotions:
|
||||
* http://java.sun.com/docs/books/jls/third_edition/html/conversions.html Section 5.6.2:
|
||||
*
|
||||
* If any of the operands is of a reference type, unboxing conversion (¤5.1.8) is performed. Then:<br>
|
||||
* If either operand is of type double, the other is converted to double.<br>
|
||||
* Otherwise, if either operand is of type float, the other is converted to float.<br>
|
||||
* Otherwise, if either operand is of type long, the other is converted to long.<br>
|
||||
* Otherwise, both operands are converted to type int.
|
||||
*
|
||||
* @author Andy Clement
|
||||
*/
|
||||
public class OperatorMultiply extends Operator {
|
||||
|
||||
public OperatorMultiply(Token payload) {
|
||||
super(payload);
|
||||
}
|
||||
|
||||
/**
|
||||
* Implements multiply directly here for some types of operand, otherwise delegates to any registered overloader for
|
||||
* types it does not recognize. Supported types here are:
|
||||
* <ul>
|
||||
* <li>integers
|
||||
* <li>doubles
|
||||
* <li>string and int ('abc' * 2 == 'abcabc')
|
||||
* </ul>
|
||||
*/
|
||||
@Override
|
||||
public Object getValue(ExpressionState state) throws EvaluationException {
|
||||
Object operandOne = getLeftOperand().getValue(state);
|
||||
Object operandTwo = getRightOperand().getValue(state);
|
||||
if (operandOne instanceof Number && operandTwo instanceof Number) {
|
||||
Number op1 = (Number) operandOne;
|
||||
Number op2 = (Number) operandTwo;
|
||||
if (op1 instanceof Double || op2 instanceof Double) {
|
||||
Double result = op1.doubleValue() * op2.doubleValue();
|
||||
return result;
|
||||
} else if (op1 instanceof Float || op2 instanceof Float) {
|
||||
Float result = op1.floatValue() * op2.floatValue();
|
||||
return result;
|
||||
} else if (op1 instanceof Long || op2 instanceof Long) {
|
||||
Long result = op1.longValue() * op2.longValue();
|
||||
return result;
|
||||
} else { // promote to int
|
||||
Integer result = op1.intValue() * op2.intValue();
|
||||
return result;
|
||||
}
|
||||
} else if (operandOne instanceof String && operandTwo instanceof Integer) {
|
||||
int repeats = ((Integer) operandTwo).intValue();
|
||||
StringBuilder result = new StringBuilder();
|
||||
for (int i = 0; i < repeats; i++) {
|
||||
result.append(operandOne);
|
||||
}
|
||||
return result.toString();
|
||||
}
|
||||
return state.operate(Operation.MULTIPLY, operandOne, operandTwo);
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getOperatorName() {
|
||||
return "*";
|
||||
}
|
||||
|
||||
}
|
|
@ -1,51 +0,0 @@
|
|||
/*
|
||||
* Copyright 2004-2008 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
|
||||
*
|
||||
* 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.springframework.expression.spel.ast;
|
||||
|
||||
import org.antlr.runtime.Token;
|
||||
import org.springframework.expression.EvaluationException;
|
||||
import org.springframework.expression.spel.SpelException;
|
||||
import org.springframework.expression.spel.ExpressionState;
|
||||
|
||||
public class OperatorNot extends SpelNode { // Not is a unary operator so do not extend BinaryOperator
|
||||
|
||||
public OperatorNot(Token payload) {
|
||||
super(payload);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Object getValue(ExpressionState state) throws EvaluationException {
|
||||
try {
|
||||
boolean value = state.toBoolean(getChild(0).getValue(state));
|
||||
return !value;
|
||||
} catch (SpelException see) {
|
||||
see.setPosition(getChild(0).getCharPositionInLine());
|
||||
throw see;
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toStringAST() {
|
||||
StringBuilder sb = new StringBuilder();
|
||||
sb.append("!").append(getChild(0).toStringAST());
|
||||
return sb.toString();
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isWritable(ExpressionState expressionState) throws SpelException {
|
||||
return false;
|
||||
}
|
||||
}
|
|
@ -1,63 +0,0 @@
|
|||
/*
|
||||
* Copyright 2004-2008 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
|
||||
*
|
||||
* 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.springframework.expression.spel.ast;
|
||||
|
||||
import org.antlr.runtime.Token;
|
||||
import org.springframework.expression.EvaluationException;
|
||||
import org.springframework.expression.spel.SpelException;
|
||||
import org.springframework.expression.spel.ExpressionState;
|
||||
|
||||
/**
|
||||
* Represents the boolean OR operation.
|
||||
*
|
||||
* @author Andy Clement
|
||||
*/
|
||||
public class OperatorOr extends Operator {
|
||||
|
||||
public OperatorOr(Token payload) {
|
||||
super(payload);
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getOperatorName() {
|
||||
return "or";
|
||||
}
|
||||
|
||||
@Override
|
||||
public Object getValue(ExpressionState state) throws EvaluationException {
|
||||
boolean leftValue;
|
||||
boolean rightValue;
|
||||
try {
|
||||
leftValue = state.toBoolean(getLeftOperand().getValue(state));
|
||||
} catch (SpelException see) {
|
||||
see.setPosition(getLeftOperand().getCharPositionInLine());
|
||||
throw see;
|
||||
}
|
||||
|
||||
if (leftValue == true)
|
||||
return true; // no need to evaluate right operand
|
||||
|
||||
try {
|
||||
rightValue = state.toBoolean(getRightOperand().getValue(state));
|
||||
} catch (SpelException see) {
|
||||
see.setPosition(getRightOperand().getCharPositionInLine());
|
||||
throw see;
|
||||
}
|
||||
|
||||
return leftValue || rightValue;
|
||||
}
|
||||
|
||||
}
|
|
@ -1,88 +0,0 @@
|
|||
/*
|
||||
* Copyright 2004-2008 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
|
||||
*
|
||||
* 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.springframework.expression.spel.ast;
|
||||
|
||||
import org.antlr.runtime.Token;
|
||||
import org.springframework.expression.EvaluationException;
|
||||
import org.springframework.expression.Operation;
|
||||
import org.springframework.expression.spel.ExpressionState;
|
||||
|
||||
public class OperatorPlus extends Operator {
|
||||
|
||||
public OperatorPlus(Token payload) {
|
||||
super(payload);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Object getValue(ExpressionState state) throws EvaluationException {
|
||||
SpelNode leftOp = getLeftOperand();
|
||||
SpelNode rightOp = getRightOperand();
|
||||
if (rightOp == null) { // If only one operand, then this is unary plus
|
||||
Object operandOne = leftOp.getValue(state);
|
||||
if (operandOne instanceof Number) {
|
||||
return new Integer(((Number) operandOne).intValue());
|
||||
}
|
||||
return state.operate(Operation.ADD, operandOne, null);
|
||||
} else {
|
||||
Object operandOne = leftOp.getValue(state);
|
||||
Object operandTwo = rightOp.getValue(state);
|
||||
if (operandOne instanceof Number && operandTwo instanceof Number) {
|
||||
Number op1 = (Number) operandOne;
|
||||
Number op2 = (Number) operandTwo;
|
||||
if (op1 instanceof Double || op2 instanceof Double) {
|
||||
Double result = op1.doubleValue() + op2.doubleValue();
|
||||
return result;
|
||||
} else if (op1 instanceof Float || op2 instanceof Float) {
|
||||
Float result = op1.floatValue() + op2.floatValue();
|
||||
return result;
|
||||
} else if (op1 instanceof Long || op2 instanceof Long) {
|
||||
Long result = op1.longValue() + op2.longValue();
|
||||
return result;
|
||||
} else { // TODO what about overflow?
|
||||
Integer result = op1.intValue() + op2.intValue();
|
||||
return result;
|
||||
}
|
||||
} else if (operandOne instanceof String && operandTwo instanceof String) {
|
||||
return new StringBuilder((String) operandOne).append((String) operandTwo).toString();
|
||||
} else if (operandOne instanceof String && operandTwo instanceof Integer) {
|
||||
String l = (String) operandOne;
|
||||
Integer i = (Integer) operandTwo;
|
||||
|
||||
// implements character + int (ie. a + 1 = b)
|
||||
if (l.length() == 1) {
|
||||
Character c = new Character((char) (new Character(l.charAt(0)) + i));
|
||||
return c.toString();
|
||||
}
|
||||
|
||||
return new StringBuilder((String) operandOne).append(((Integer) operandTwo).toString()).toString();
|
||||
}
|
||||
return state.operate(Operation.ADD, operandOne, operandTwo);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getOperatorName() {
|
||||
return "+";
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toStringAST() {
|
||||
if (getRightOperand() == null) { // unary plus
|
||||
return new StringBuilder().append("+").append(getLeftOperand()).toString();
|
||||
}
|
||||
return super.toStringAST();
|
||||
}
|
||||
}
|
|
@ -1,46 +0,0 @@
|
|||
/*
|
||||
* Copyright 2004-2008 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
|
||||
*
|
||||
* 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.springframework.expression.spel.ast;
|
||||
|
||||
import org.antlr.runtime.Token;
|
||||
import org.springframework.expression.spel.SpelException;
|
||||
import org.springframework.expression.spel.SpelMessages;
|
||||
import org.springframework.expression.spel.ExpressionState;
|
||||
|
||||
/**
|
||||
* PlaceHolder nodes are created for tokens that come through from the grammar purely to give us additional positional
|
||||
* information for messages/etc.
|
||||
*
|
||||
* @author Andy Clement
|
||||
*
|
||||
*/
|
||||
public class Placeholder extends SpelNode {
|
||||
|
||||
public Placeholder(Token payload) {
|
||||
super(payload);
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getValue(ExpressionState state) throws SpelException {
|
||||
throw new SpelException(getCharPositionInLine(), SpelMessages.PLACEHOLDER_SHOULD_NEVER_BE_EVALUATED);
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toStringAST() {
|
||||
return getText();
|
||||
}
|
||||
|
||||
}
|
|
@ -1,98 +0,0 @@
|
|||
/*
|
||||
* Copyright 2004-2008 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
|
||||
*
|
||||
* 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.springframework.expression.spel.ast;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.Collection;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
|
||||
import org.antlr.runtime.Token;
|
||||
import org.springframework.expression.EvaluationException;
|
||||
import org.springframework.expression.spel.SpelException;
|
||||
import org.springframework.expression.spel.SpelMessages;
|
||||
import org.springframework.expression.spel.ExpressionState;
|
||||
import org.springframework.expression.spel.internal.KeyValuePair;
|
||||
|
||||
/**
|
||||
* Represents projection, where a given operation is performed on all elements in some input sequence, returning
|
||||
* a new sequence of the same size. For example:
|
||||
* "{1,2,3,4,5,6,7,8,9,10}.!{#isEven(#this)}" returns "[n, y, n, y, n, y, n, y, n, y]"
|
||||
*
|
||||
* @author Andy Clement
|
||||
*
|
||||
*/
|
||||
public class Projection extends SpelNode {
|
||||
|
||||
public Projection(Token payload) {
|
||||
super(payload);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Object getValue(ExpressionState state) throws EvaluationException {
|
||||
Object operand = state.getActiveContextObject();
|
||||
|
||||
// When the input is a map, we push a special context object on the stack
|
||||
// before calling the specified operation. This special context object
|
||||
// has two fields 'key' and 'value' that refer to the map entries key
|
||||
// and value, and they can be referenced in the operation
|
||||
// eg. {'a':'y','b':'n'}.!{value=='y'?key:null}" == ['a', null]
|
||||
if (operand instanceof Map) {
|
||||
Map<?, ?> mapdata = (Map<?, ?>) operand;
|
||||
List<Object> result = new ArrayList<Object>();
|
||||
for (Object k : mapdata.keySet()) {
|
||||
try {
|
||||
state.pushActiveContextObject(new KeyValuePair(k, mapdata.get(k)));
|
||||
result.add(getChild(0).getValue(state));
|
||||
} finally {
|
||||
state.popActiveContextObject();
|
||||
}
|
||||
}
|
||||
return result;
|
||||
} else if (operand instanceof Collection) {
|
||||
List<Object> data = new ArrayList<Object>();
|
||||
data.addAll((Collection<?>) operand);
|
||||
List<Object> result = new ArrayList<Object>();
|
||||
int idx = 0;
|
||||
for (Object element : data) {
|
||||
try {
|
||||
state.pushActiveContextObject(element);
|
||||
state.enterScope("index", idx);
|
||||
result.add(getChild(0).getValue(state));
|
||||
} finally {
|
||||
state.exitScope();
|
||||
state.popActiveContextObject();
|
||||
}
|
||||
idx++;
|
||||
}
|
||||
return result;
|
||||
} else {
|
||||
throw new SpelException(SpelMessages.PROJECTION_NOT_SUPPORTED_ON_TYPE, operand.getClass().getName());
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toStringAST() {
|
||||
StringBuffer sb = new StringBuffer();
|
||||
return sb.append("!{").append(getChild(0).toStringAST()).append("}").toString();
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isWritable(ExpressionState expressionState) throws SpelException {
|
||||
return false;
|
||||
}
|
||||
|
||||
}
|
|
@ -1,245 +0,0 @@
|
|||
/*
|
||||
* Copyright 2004-2008 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
|
||||
*
|
||||
* 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.springframework.expression.spel.ast;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
import org.antlr.runtime.Token;
|
||||
import org.springframework.expression.AccessException;
|
||||
import org.springframework.expression.CacheablePropertyAccessor;
|
||||
import org.springframework.expression.EvaluationContext;
|
||||
import org.springframework.expression.PropertyAccessor;
|
||||
import org.springframework.expression.PropertyReaderExecutor;
|
||||
import org.springframework.expression.PropertyWriterExecutor;
|
||||
import org.springframework.expression.spel.ExpressionState;
|
||||
import org.springframework.expression.spel.SpelException;
|
||||
import org.springframework.expression.spel.SpelMessages;
|
||||
import org.springframework.expression.spel.internal.Utils;
|
||||
|
||||
/**
|
||||
* Represents a simple property or field reference.
|
||||
*
|
||||
* @author Andy Clement
|
||||
*/
|
||||
public class PropertyOrFieldReference extends SpelNode {
|
||||
|
||||
public static boolean useCaching = true;
|
||||
|
||||
private final Object name;
|
||||
private PropertyReaderExecutor cachedReaderExecutor;
|
||||
private PropertyWriterExecutor cachedWriterExecutor;
|
||||
|
||||
public PropertyOrFieldReference(Token payload) {
|
||||
super(payload);
|
||||
name = payload.getText();
|
||||
}
|
||||
|
||||
@Override
|
||||
public Object getValue(ExpressionState state) throws SpelException {
|
||||
return readProperty(state, name);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setValue(ExpressionState state, Object newValue) throws SpelException {
|
||||
writeProperty(state, name, newValue);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isWritable(ExpressionState state) throws SpelException {
|
||||
return isWritableProperty(name, state);
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toStringAST() {
|
||||
return name.toString();
|
||||
}
|
||||
|
||||
/**
|
||||
* Attempt to read the named property from the current context object.
|
||||
*
|
||||
* @param state the evaluation state
|
||||
* @param name the name of the property
|
||||
* @return the value of the property
|
||||
* @throws SpelException if any problem accessing the property or it cannot be found
|
||||
*/
|
||||
private Object readProperty(ExpressionState state, Object name) throws SpelException {
|
||||
Object contextObject = state.getActiveContextObject();
|
||||
EvaluationContext eContext = state.getEvaluationContext();
|
||||
|
||||
if (cachedReaderExecutor != null) {
|
||||
try {
|
||||
return cachedReaderExecutor.execute(state.getEvaluationContext(), contextObject);
|
||||
} catch (AccessException ae) {
|
||||
// this is OK - it may have gone stale due to a class change,
|
||||
// let's try to get a new one and call it before giving up
|
||||
}
|
||||
}
|
||||
|
||||
Class<?> contextObjectClass = getObjectClass(contextObject);
|
||||
|
||||
List<PropertyAccessor> accessorsToTry = getPropertyAccessorsToTry(contextObjectClass, state);
|
||||
|
||||
// Go through the accessors that may be able to resolve it. If they are a cacheable accessor then
|
||||
// get the accessor and use it. If they are not cacheable but report they can read the property
|
||||
// then ask them to read it
|
||||
if (accessorsToTry != null) {
|
||||
try {
|
||||
for (PropertyAccessor accessor : accessorsToTry) {
|
||||
if (accessor instanceof CacheablePropertyAccessor) {
|
||||
cachedReaderExecutor = ((CacheablePropertyAccessor) accessor).getReaderAccessor(eContext,
|
||||
contextObject, name);
|
||||
if (cachedReaderExecutor != null) {
|
||||
try {
|
||||
return cachedReaderExecutor.execute(state.getEvaluationContext(), contextObject);
|
||||
} catch (AccessException ae) {
|
||||
cachedReaderExecutor = null;
|
||||
throw ae;
|
||||
} finally {
|
||||
if (!useCaching) {
|
||||
cachedReaderExecutor = null;
|
||||
}
|
||||
}
|
||||
}
|
||||
} else {
|
||||
if (accessor.canRead(eContext, contextObject, name)) {
|
||||
Object value = accessor.read(eContext, contextObject, name);
|
||||
return value;
|
||||
}
|
||||
}
|
||||
}
|
||||
} catch (AccessException ae) {
|
||||
throw new SpelException(ae, SpelMessages.EXCEPTION_DURING_PROPERTY_READ, name, ae.getMessage());
|
||||
}
|
||||
}
|
||||
throw new SpelException(SpelMessages.PROPERTY_OR_FIELD_NOT_FOUND, name, Utils
|
||||
.formatClassnameForMessage(contextObjectClass));
|
||||
}
|
||||
|
||||
private void writeProperty(ExpressionState state, Object name, Object newValue) throws SpelException {
|
||||
Object contextObject = state.getActiveContextObject();
|
||||
EvaluationContext eContext = state.getEvaluationContext();
|
||||
|
||||
if (cachedWriterExecutor != null) {
|
||||
try {
|
||||
cachedWriterExecutor.execute(state.getEvaluationContext(), contextObject, newValue);
|
||||
return;
|
||||
} catch (AccessException ae) {
|
||||
// this is OK - it may have gone stale due to a class change,
|
||||
// let's try to get a new one and call it before giving up
|
||||
}
|
||||
}
|
||||
|
||||
Class<?> contextObjectClass = getObjectClass(contextObject);
|
||||
|
||||
List<PropertyAccessor> accessorsToTry = getPropertyAccessorsToTry(contextObjectClass, state);
|
||||
if (accessorsToTry != null) {
|
||||
try {
|
||||
for (PropertyAccessor accessor : accessorsToTry) {
|
||||
if (accessor instanceof CacheablePropertyAccessor) {
|
||||
cachedWriterExecutor = ((CacheablePropertyAccessor) accessor).getWriterAccessor(eContext,
|
||||
contextObject, name);
|
||||
if (cachedWriterExecutor != null) {
|
||||
try {
|
||||
cachedWriterExecutor.execute(state.getEvaluationContext(), contextObject, newValue);
|
||||
return;
|
||||
} catch (AccessException ae) {
|
||||
cachedWriterExecutor = null;
|
||||
throw ae;
|
||||
} finally {
|
||||
if (!useCaching) {
|
||||
cachedWriterExecutor = null;
|
||||
}
|
||||
}
|
||||
}
|
||||
} else {
|
||||
if (accessor.canWrite(eContext, contextObject, name)) {
|
||||
accessor.write(eContext, contextObject, name, newValue);
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
} catch (AccessException ae) {
|
||||
throw new SpelException(getCharPositionInLine(), ae, SpelMessages.EXCEPTION_DURING_PROPERTY_WRITE,
|
||||
name, ae.getMessage());
|
||||
}
|
||||
}
|
||||
throw new SpelException(SpelMessages.PROPERTY_OR_FIELD_SETTER_NOT_FOUND, name, Utils
|
||||
.formatClassnameForMessage(contextObjectClass));
|
||||
}
|
||||
|
||||
public boolean isWritableProperty(Object name, ExpressionState state) throws SpelException {
|
||||
Object contextObject = state.getActiveContextObject();
|
||||
EvaluationContext eContext = state.getEvaluationContext();
|
||||
if (contextObject == null) {
|
||||
throw new SpelException(SpelMessages.ATTEMPTED_PROPERTY_FIELD_REF_ON_NULL_CONTEXT_OBJECT, name);
|
||||
}
|
||||
List<PropertyAccessor> resolversToTry = getPropertyAccessorsToTry(
|
||||
(contextObject instanceof Class) ? ((Class<?>) contextObject) : contextObject.getClass(), state);
|
||||
if (resolversToTry != null) {
|
||||
for (PropertyAccessor pfResolver : resolversToTry) {
|
||||
try {
|
||||
if (pfResolver.canWrite(eContext, contextObject, name)) {
|
||||
return true;
|
||||
}
|
||||
} catch (AccessException ae) {
|
||||
// let others try
|
||||
}
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* Determines the set of property resolvers that should be used to try and access a property on the specified target
|
||||
* type. The resolvers are considered to be in an ordered list, however in the returned list any that are exact
|
||||
* matches for the input target type (as opposed to 'general' resolvers that could work for any type) are placed at
|
||||
* the start of the list. In addition, there are specific resolvers that exactly name the class in question and
|
||||
* resolvers that name a specific class but it is a supertype of the class we have. These are put at the end of the
|
||||
* specific resolvers set and will be tried after exactly matching accessors but before generic accessors.
|
||||
*
|
||||
* @param targetType the type upon which property access is being attempted
|
||||
* @return a list of resolvers that should be tried in order to access the property
|
||||
*/
|
||||
private List<PropertyAccessor> getPropertyAccessorsToTry(Class<?> targetType, ExpressionState state) {
|
||||
List<PropertyAccessor> specificAccessors = new ArrayList<PropertyAccessor>();
|
||||
List<PropertyAccessor> generalAccessors = new ArrayList<PropertyAccessor>();
|
||||
for (PropertyAccessor resolver : state.getPropertyAccessors()) {
|
||||
Class<?>[] targets = resolver.getSpecificTargetClasses();
|
||||
if (targets == null) { // generic resolver that says it can be used for any type
|
||||
generalAccessors.add(resolver);
|
||||
} else {
|
||||
if (targetType != null) {
|
||||
int pos = 0;
|
||||
for (int i = 0; i < targets.length; i++) {
|
||||
Class<?> clazz = targets[i];
|
||||
if (clazz == targetType) { // put exact matches on the front to be tried first?
|
||||
specificAccessors.add(pos++, resolver);
|
||||
} else if (clazz.isAssignableFrom(targetType)) { // put supertype matches at the end of the
|
||||
// specificAccessor list
|
||||
generalAccessors.add(resolver);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
List<PropertyAccessor> resolvers = new ArrayList<PropertyAccessor>();
|
||||
resolvers.addAll(specificAccessors);
|
||||
resolvers.addAll(generalAccessors);
|
||||
return resolvers;
|
||||
}
|
||||
|
||||
}
|
|
@ -1,69 +0,0 @@
|
|||
/*
|
||||
* Copyright 2004-2008 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
|
||||
*
|
||||
* 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.springframework.expression.spel.ast;
|
||||
|
||||
import org.antlr.runtime.Token;
|
||||
import org.springframework.expression.EvaluationException;
|
||||
import org.springframework.expression.spel.ExpressionState;
|
||||
|
||||
/**
|
||||
* Represents a dot separated sequence of strings that indicate a package qualified type reference.
|
||||
* <p>
|
||||
* Example: "java.lang.String" as in the expression "new java.lang.String('hello')"
|
||||
*
|
||||
* @author Andy Clement
|
||||
*
|
||||
*/
|
||||
public class QualifiedIdentifier extends SpelNode {
|
||||
|
||||
private String value;
|
||||
|
||||
public QualifiedIdentifier(Token payload) {
|
||||
super(payload);
|
||||
// value = payload.getText();
|
||||
}
|
||||
|
||||
@Override
|
||||
public Object getValue(ExpressionState state) throws EvaluationException {
|
||||
// Cache the concatenation of child identifiers
|
||||
if (value == null) {
|
||||
StringBuilder sb = new StringBuilder();
|
||||
for (int i = 0; i < getChildCount(); i++) {
|
||||
if (i > 0)
|
||||
sb.append(".");
|
||||
sb.append(getChild(i).getValue(state));
|
||||
}
|
||||
value = sb.toString();
|
||||
}
|
||||
return value;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toStringAST() {
|
||||
StringBuilder sb = new StringBuilder();
|
||||
if (value != null) {
|
||||
sb.append(value);
|
||||
} else {
|
||||
for (int i = 0; i < getChildCount(); i++) {
|
||||
if (i > 0)
|
||||
sb.append(".");
|
||||
sb.append(getChild(i).toStringAST());
|
||||
}
|
||||
}
|
||||
return sb.toString();
|
||||
}
|
||||
|
||||
}
|
|
@ -1,34 +0,0 @@
|
|||
/*
|
||||
* Copyright 2004-2008 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
|
||||
*
|
||||
* 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.springframework.expression.spel.ast;
|
||||
|
||||
import org.antlr.runtime.Token;
|
||||
|
||||
public class RealLiteral extends Literal {
|
||||
|
||||
private final Double value;
|
||||
|
||||
public RealLiteral(Token payload) {
|
||||
super(payload);
|
||||
value = Double.parseDouble(payload.getText());
|
||||
}
|
||||
|
||||
@Override
|
||||
public Double getLiteralValue() {
|
||||
return value;
|
||||
}
|
||||
|
||||
}
|
|
@ -1,146 +0,0 @@
|
|||
/*
|
||||
* Copyright 2004-2008 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
|
||||
*
|
||||
* 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.springframework.expression.spel.ast;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.Collection;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
|
||||
import org.antlr.runtime.Token;
|
||||
import org.springframework.expression.EvaluationException;
|
||||
import org.springframework.expression.spel.SpelException;
|
||||
import org.springframework.expression.spel.SpelMessages;
|
||||
import org.springframework.expression.spel.ExpressionState;
|
||||
import org.springframework.expression.spel.internal.KeyValuePair;
|
||||
|
||||
/**
|
||||
* Represents selection over a map or collection. For example: {1,2,3,4,5,6,7,8,9,10}.?{#isEven(#this) == 'y'} returns
|
||||
* [2, 4, 6, 8, 10]
|
||||
*
|
||||
* Basically a subset of the input data is returned based on the evaluation of the expression supplied as selection
|
||||
* criteria.
|
||||
*
|
||||
* @author Andy Clement
|
||||
*/
|
||||
public class Selection extends SpelNode {
|
||||
|
||||
public final static int ALL = 0; // ?{}
|
||||
public final static int FIRST = 1; // ^{}
|
||||
public final static int LAST = 2; // ${}
|
||||
|
||||
private final int variant;
|
||||
|
||||
public Selection(Token payload, int variant) {
|
||||
super(payload);
|
||||
this.variant = variant;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Object getValue(ExpressionState state) throws EvaluationException {
|
||||
Object operand = state.getActiveContextObject();
|
||||
SpelNode selectionCriteria = getChild(0);
|
||||
if (operand instanceof Map) {
|
||||
Map<?, ?> mapdata = (Map<?, ?>) operand;
|
||||
List<Object> result = new ArrayList<Object>();
|
||||
for (Object k : mapdata.keySet()) {
|
||||
try {
|
||||
Object kvpair = new KeyValuePair(k, mapdata.get(k));
|
||||
state.pushActiveContextObject(kvpair);
|
||||
Object o = selectionCriteria.getValue(state);
|
||||
if (o instanceof Boolean) {
|
||||
if (((Boolean) o).booleanValue() == true) {
|
||||
if (variant == FIRST)
|
||||
return kvpair;
|
||||
result.add(kvpair);
|
||||
}
|
||||
} else {
|
||||
throw new SpelException(selectionCriteria.getCharPositionInLine(),
|
||||
SpelMessages.RESULT_OF_SELECTION_CRITERIA_IS_NOT_BOOLEAN);// ,selectionCriteria.stringifyAST());
|
||||
}
|
||||
} finally {
|
||||
state.popActiveContextObject();
|
||||
}
|
||||
if ((variant == FIRST || variant == LAST) && result.size() == 0) {
|
||||
return null;
|
||||
}
|
||||
if (variant == LAST) {
|
||||
return result.get(result.size() - 1);
|
||||
}
|
||||
}
|
||||
return result;
|
||||
} else if (operand instanceof Collection) {
|
||||
List<Object> data = new ArrayList<Object>();
|
||||
data.addAll((Collection<?>) operand);
|
||||
List<Object> result = new ArrayList<Object>();
|
||||
int idx = 0;
|
||||
for (Object element : data) {
|
||||
try {
|
||||
state.pushActiveContextObject(element);
|
||||
state.enterScope("index", idx);
|
||||
Object o = selectionCriteria.getValue(state);
|
||||
if (o instanceof Boolean) {
|
||||
if (((Boolean) o).booleanValue() == true) {
|
||||
if (variant == FIRST)
|
||||
return element;
|
||||
result.add(element);
|
||||
}
|
||||
} else {
|
||||
throw new SpelException(selectionCriteria.getCharPositionInLine(),
|
||||
SpelMessages.RESULT_OF_SELECTION_CRITERIA_IS_NOT_BOOLEAN);// ,selectionCriteria.stringifyAST());
|
||||
}
|
||||
idx++;
|
||||
} finally {
|
||||
state.exitScope();
|
||||
state.popActiveContextObject();
|
||||
}
|
||||
}
|
||||
if ((variant == FIRST || variant == LAST) && result.size() == 0) {
|
||||
return null;
|
||||
}
|
||||
if (variant == LAST) {
|
||||
return result.get(result.size() - 1);
|
||||
}
|
||||
return result;
|
||||
} else {
|
||||
throw new SpelException(getCharPositionInLine(), SpelMessages.INVALID_TYPE_FOR_SELECTION,
|
||||
(operand == null ? "null" : operand.getClass().getName()));
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toStringAST() {
|
||||
StringBuffer sb = new StringBuffer();
|
||||
switch (variant) {
|
||||
case ALL:
|
||||
sb.append("?{");
|
||||
break;
|
||||
case FIRST:
|
||||
sb.append("^{");
|
||||
break;
|
||||
case LAST:
|
||||
sb.append("${");
|
||||
break;
|
||||
}
|
||||
return sb.append(getChild(0).toStringAST()).append("}").toString();
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isWritable(ExpressionState expressionState) throws SpelException {
|
||||
return false;
|
||||
}
|
||||
|
||||
}
|
|
@ -1,126 +0,0 @@
|
|||
/*
|
||||
* Copyright 2004-2008 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
|
||||
*
|
||||
* 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.springframework.expression.spel.ast;
|
||||
|
||||
import java.io.Serializable;
|
||||
|
||||
import org.antlr.runtime.Token;
|
||||
import org.antlr.runtime.tree.CommonTree;
|
||||
import org.springframework.expression.EvaluationException;
|
||||
import org.springframework.expression.common.ExpressionUtils;
|
||||
import org.springframework.expression.spel.ExpressionState;
|
||||
import org.springframework.expression.spel.SpelException;
|
||||
import org.springframework.expression.spel.SpelMessages;
|
||||
import org.springframework.expression.spel.generated.SpringExpressionsParser;
|
||||
|
||||
/**
|
||||
* The common supertype of all AST nodes in a parsed Spring Expression Language format expression.
|
||||
*
|
||||
* @author Andy Clement
|
||||
*
|
||||
*/
|
||||
public abstract class SpelNode extends CommonTree implements Serializable {
|
||||
|
||||
/**
|
||||
* The Antlr parser uses this constructor to build SpelNodes.
|
||||
*
|
||||
* @param payload the token for the node that has been parsed
|
||||
*/
|
||||
protected SpelNode(Token payload) {
|
||||
super(payload);
|
||||
}
|
||||
|
||||
/**
|
||||
* Evaluate the expression node in the context of the supplied expression state and return the value.
|
||||
*
|
||||
* @param expressionState the current expression state (includes the context)
|
||||
* @return the value of this node evaluated against the specified state
|
||||
*/
|
||||
public abstract Object getValue(ExpressionState expressionState) throws EvaluationException;
|
||||
|
||||
/**
|
||||
* Determine if this expression node will support a setValue() call.
|
||||
*
|
||||
* @param expressionState the current expression state (includes the context)
|
||||
* @return true if the expression node will allow setValue()
|
||||
* @throws EvaluationException if something went wrong trying to determine if the node supports writing
|
||||
*/
|
||||
public boolean isWritable(ExpressionState expressionState) throws EvaluationException {
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* Evaluate the expression to a node and then set the new value on that node. For example, if the expression
|
||||
* evaluates to a property reference then the property will be set to the new value.
|
||||
*
|
||||
* @param expressionState the current expression state (includes the context)
|
||||
* @param newValue the new value
|
||||
* @throws EvaluationException if any problem occurs evaluating the expression or setting the new value
|
||||
*/
|
||||
public void setValue(ExpressionState expressionState, Object newValue) throws EvaluationException {
|
||||
throw new SpelException(getCharPositionInLine(), SpelMessages.SETVALUE_NOT_SUPPORTED, getClass(),
|
||||
getTokenName());
|
||||
}
|
||||
|
||||
/**
|
||||
* @return return the token this node represents
|
||||
*/
|
||||
protected String getTokenName() {
|
||||
if (getToken() == null) {
|
||||
return "UNKNOWN";
|
||||
}
|
||||
return SpringExpressionsParser.tokenNames[getToken().getType()];
|
||||
}
|
||||
|
||||
/**
|
||||
* @return the string form of this AST node
|
||||
*/
|
||||
public abstract String toStringAST();
|
||||
|
||||
/**
|
||||
* Helper method that returns a SpelNode rather than an Antlr Tree node.
|
||||
*
|
||||
* @return the child node cast to a SpelNode
|
||||
*/
|
||||
@Override
|
||||
public SpelNode getChild(int index) {
|
||||
return (SpelNode) super.getChild(index);
|
||||
}
|
||||
|
||||
/**
|
||||
* Determine the class of the object passed in, unless it is already a class object.
|
||||
* @param o the object that the caller wants the class of
|
||||
* @return the class of the object if it is not already a class object, or null if the object is null
|
||||
*/
|
||||
public Class<?> getObjectClass(Object o) {
|
||||
if (o == null)
|
||||
return null;
|
||||
return (o instanceof Class) ? ((Class<?>) o) : o.getClass();
|
||||
}
|
||||
|
||||
protected final Object getValue(ExpressionState state, Class<?> desiredReturnType) throws EvaluationException {
|
||||
Object result = getValue(state);
|
||||
if (result != null && desiredReturnType != null) {
|
||||
Class<?> resultType = result.getClass();
|
||||
if (desiredReturnType.isAssignableFrom(resultType)) {
|
||||
return result;
|
||||
}
|
||||
// Attempt conversion to the requested type, may throw an exception
|
||||
return ExpressionUtils.convert(state.getEvaluationContext(), result, desiredReturnType);
|
||||
}
|
||||
return result;
|
||||
}
|
||||
}
|
|
@ -1,42 +0,0 @@
|
|||
/*
|
||||
* Copyright 2004-2008 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
|
||||
*
|
||||
* 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.springframework.expression.spel.ast;
|
||||
|
||||
import org.antlr.runtime.Token;
|
||||
|
||||
public class StringLiteral extends Literal {
|
||||
|
||||
private String value;
|
||||
|
||||
public StringLiteral(Token payload) {
|
||||
super(payload);
|
||||
value = payload.getText();
|
||||
// TODO should these have been skipped being created by the parser rules? or not?
|
||||
value = value.substring(1, value.length() - 1);
|
||||
value = value.replaceAll("''", "'");
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getLiteralValue() {
|
||||
return value;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return new StringBuilder("'").append(getLiteralValue()).append("'").toString();
|
||||
}
|
||||
|
||||
}
|
|
@ -1,66 +0,0 @@
|
|||
/*
|
||||
* Copyright 2004-2008 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
|
||||
*
|
||||
* 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.springframework.expression.spel.ast;
|
||||
|
||||
import org.antlr.runtime.Token;
|
||||
import org.springframework.expression.EvaluationException;
|
||||
import org.springframework.expression.spel.ExpressionState;
|
||||
import org.springframework.expression.spel.SpelException;
|
||||
|
||||
/**
|
||||
* Represents a ternary expression, for example: "someCheck()?true:false".
|
||||
*
|
||||
* @author Andy Clement
|
||||
*/
|
||||
public class Ternary extends SpelNode {
|
||||
|
||||
public Ternary(Token payload) {
|
||||
super(payload);
|
||||
}
|
||||
|
||||
/**
|
||||
* Evaluate the condition and if true evaluate the first alternative, otherwise evaluate the second alternative.
|
||||
*
|
||||
* @param state the expression state
|
||||
* @throws EvaluationException if the condition does not evaluate correctly to a boolean or there is a problem
|
||||
* executing the chosen alternative
|
||||
*/
|
||||
@Override
|
||||
public Object getValue(ExpressionState state) throws EvaluationException {
|
||||
Boolean b = (Boolean) getChild(0).getValue(state, Boolean.class);
|
||||
try {
|
||||
if (b) {
|
||||
return getChild(1).getValue(state);
|
||||
} else {
|
||||
return getChild(2).getValue(state);
|
||||
}
|
||||
} catch (SpelException ex) {
|
||||
ex.setPosition(getChild(0).getCharPositionInLine());
|
||||
throw ex;
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toStringAST() {
|
||||
return new StringBuilder().append(getChild(0).toStringAST()).append(" ? ").append(getChild(1).toStringAST())
|
||||
.append(" : ").append(getChild(2).toStringAST()).toString();
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isWritable(ExpressionState expressionState) throws SpelException {
|
||||
return false;
|
||||
}
|
||||
}
|
|
@ -1,64 +0,0 @@
|
|||
/*
|
||||
* Copyright 2004-2008 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
|
||||
*
|
||||
* 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.springframework.expression.spel.ast;
|
||||
|
||||
import org.antlr.runtime.Token;
|
||||
import org.springframework.expression.EvaluationException;
|
||||
import org.springframework.expression.spel.ExpressionState;
|
||||
import org.springframework.expression.spel.SpelException;
|
||||
import org.springframework.expression.spel.internal.TypeCode;
|
||||
|
||||
/**
|
||||
* Represents a reference to a type, for example "T(String)" or "T(com.somewhere.Foo)"
|
||||
*
|
||||
* @author Andy Clement
|
||||
*
|
||||
*/
|
||||
public class TypeReference extends SpelNode {
|
||||
|
||||
public TypeReference(Token payload) {
|
||||
super(payload);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Object getValue(ExpressionState state) throws EvaluationException {
|
||||
// TODO possible optimization here if we cache the discovered type reference, but can we do that?
|
||||
String typename = (String) getChild(0).getValue(state);
|
||||
if (typename.indexOf(".") == -1 && Character.isLowerCase(typename.charAt(0))) {
|
||||
TypeCode tc = TypeCode.forName(typename);
|
||||
if (tc != TypeCode.OBJECT) {
|
||||
// it is a primitive type
|
||||
return tc.getType();
|
||||
}
|
||||
}
|
||||
return state.findType(typename);
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toStringAST() {
|
||||
StringBuilder sb = new StringBuilder();
|
||||
sb.append("T(");
|
||||
sb.append(getChild(0).toStringAST());
|
||||
sb.append(")");
|
||||
return sb.toString();
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isWritable(ExpressionState expressionState) throws SpelException {
|
||||
return false;
|
||||
}
|
||||
|
||||
}
|
|
@ -1,70 +0,0 @@
|
|||
/*
|
||||
* Copyright 2004-2008 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
|
||||
*
|
||||
* 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.springframework.expression.spel.ast;
|
||||
|
||||
import org.antlr.runtime.Token;
|
||||
import org.springframework.expression.spel.SpelException;
|
||||
import org.springframework.expression.spel.SpelMessages;
|
||||
import org.springframework.expression.spel.ExpressionState;
|
||||
|
||||
/**
|
||||
* Represents a variable reference, eg. #someVar. Note this is different to a *local* variable like $someVar
|
||||
*
|
||||
* @author Andy Clement
|
||||
*
|
||||
*/
|
||||
public class VariableReference extends SpelNode {
|
||||
|
||||
// Well known variables:
|
||||
private final static String THIS = "this"; // currently active context object
|
||||
private final static String ROOT = "root"; // root context object
|
||||
|
||||
private final String name;
|
||||
|
||||
public VariableReference(Token payload) {
|
||||
super(payload);
|
||||
name = payload.getText();
|
||||
}
|
||||
|
||||
@Override
|
||||
public Object getValue(ExpressionState state) throws SpelException {
|
||||
if (name.equals(THIS))
|
||||
return state.getActiveContextObject();
|
||||
if (name.equals(ROOT))
|
||||
return state.getRootContextObject();
|
||||
Object result = state.lookupVariable(name);
|
||||
if (result == null) {
|
||||
throw new SpelException(getCharPositionInLine(), SpelMessages.VARIABLE_NOT_FOUND, name);
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setValue(ExpressionState state, Object value) throws SpelException {
|
||||
// Object oldValue = state.lookupVariable(name);
|
||||
state.setVariable(name, value);
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toStringAST() {
|
||||
return new StringBuilder("#").append(name).toString();
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isWritable(ExpressionState expressionState) throws SpelException {
|
||||
return !(name.equals(THIS) || name.equals(ROOT));
|
||||
}
|
||||
}
|
|
@ -1,268 +0,0 @@
|
|||
grammar SpringExpressions;
|
||||
|
||||
options {
|
||||
language = Java;
|
||||
output=AST;
|
||||
k=2;
|
||||
}
|
||||
|
||||
tokens {
|
||||
INTEGER_LITERAL;
|
||||
EXPRESSION;
|
||||
QUALIFIED_IDENTIFIER;
|
||||
PROPERTY_OR_FIELD;
|
||||
INDEXER;
|
||||
CONSTRUCTOR;
|
||||
HOLDER;
|
||||
NAMED_ARGUMENT;
|
||||
FUNCTIONREF;
|
||||
TYPEREF;
|
||||
VARIABLEREF;
|
||||
METHOD;
|
||||
ADD;
|
||||
SUBTRACT;
|
||||
NUMBER;
|
||||
}
|
||||
|
||||
// applies only to the parser:
|
||||
@header {package org.springframework.expression.spel.generated;}
|
||||
|
||||
// applies only to the lexer:
|
||||
@lexer::header {package org.springframework.expression.spel.generated;}
|
||||
|
||||
@members {
|
||||
// For collecting info whilst processing rules that can be used in messages
|
||||
protected Stack<String> paraphrase = new Stack<String>();
|
||||
}
|
||||
|
||||
@rulecatch {
|
||||
catch(RecognitionException e) {
|
||||
reportError(e);
|
||||
throw e;
|
||||
}
|
||||
}
|
||||
|
||||
expr: expression EOF!;
|
||||
|
||||
expression :
|
||||
logicalOrExpression
|
||||
( (ASSIGN^ logicalOrExpression)
|
||||
| (DEFAULT^ logicalOrExpression)
|
||||
| (QMARK^ expression COLON! expression))?;
|
||||
|
||||
parenExpr : LPAREN! expression RPAREN!;
|
||||
|
||||
logicalOrExpression
|
||||
: logicalAndExpression (OR^ logicalAndExpression)*;
|
||||
|
||||
logicalAndExpression
|
||||
: relationalExpression (AND^ relationalExpression)*;
|
||||
|
||||
relationalExpression : sumExpression (relationalOperator^ sumExpression)?;
|
||||
|
||||
sumExpression
|
||||
: productExpression ( (PLUS^ | MINUS^) productExpression)*;
|
||||
|
||||
productExpression
|
||||
: powerExpr ((STAR^ | DIV^| MOD^) powerExpr)* ;
|
||||
|
||||
powerExpr : unaryExpression (POWER^ unaryExpression)? ;
|
||||
|
||||
unaryExpression
|
||||
: (PLUS^ | MINUS^ | BANG^) unaryExpression
|
||||
| primaryExpression ;
|
||||
|
||||
primaryExpression
|
||||
: startNode (node)? -> ^(EXPRESSION startNode (node)?);
|
||||
|
||||
startNode
|
||||
:
|
||||
parenExpr
|
||||
| methodOrProperty
|
||||
| functionOrVar
|
||||
| indexer
|
||||
| literal
|
||||
| type
|
||||
| constructor
|
||||
| projection
|
||||
| selection
|
||||
| firstSelection
|
||||
| lastSelection
|
||||
;
|
||||
|
||||
node
|
||||
: ((DOT dottedNode) | nonDottedNode)+;
|
||||
|
||||
nonDottedNode
|
||||
: indexer;
|
||||
|
||||
dottedNode
|
||||
:
|
||||
((methodOrProperty
|
||||
| functionOrVar
|
||||
| projection
|
||||
| selection
|
||||
| firstSelection
|
||||
| lastSelection
|
||||
))
|
||||
;
|
||||
|
||||
functionOrVar
|
||||
: (POUND ID LPAREN) => function
|
||||
| var
|
||||
;
|
||||
|
||||
function : POUND id=ID methodArgs -> ^(FUNCTIONREF[$id] methodArgs);
|
||||
|
||||
var : POUND id=ID -> ^(VARIABLEREF[$id]);
|
||||
|
||||
|
||||
methodOrProperty
|
||||
: (ID LPAREN) => id=ID methodArgs -> ^(METHOD[$id] methodArgs)
|
||||
| property
|
||||
;
|
||||
|
||||
// may have to preserve these commas to make it easier to offer suggestions in the right place
|
||||
// mod at 9th feb 19:13 - added the second 'COMMA?' to allow for code completion "foo(A,"
|
||||
// TODO need to preserve commas and then check for badly formed call later (optimizing tree walk) to disallow "foo(a,b,c,)"
|
||||
methodArgs : LPAREN! (argument (COMMA! argument)* (COMMA!)?)? RPAREN!;
|
||||
|
||||
// If we match ID then create a node called PROPERTY_OR_FIELD and copy the id info into it.
|
||||
// this means the propertyOrField.text is what id.text would have been, rather than having to
|
||||
// access id as a child of the new node.
|
||||
property: id=ID -> ^(PROPERTY_OR_FIELD[$id]);
|
||||
|
||||
|
||||
indexer: LBRACKET r1=argument (COMMA r2=argument)* RBRACKET -> ^(INDEXER $r1 ($r2)*);
|
||||
|
||||
// argument;
|
||||
// TODO make expression conditional with ? if want completion for when the RCURLY is missing
|
||||
projection: PROJECT^ expression RCURLY!;
|
||||
|
||||
selection: SELECT^ expression RCURLY!;
|
||||
|
||||
firstSelection: SELECT_FIRST^ expression RCURLY!;
|
||||
|
||||
lastSelection: SELECT_LAST^ expression RCURLY!;
|
||||
|
||||
// TODO cope with array types
|
||||
type: TYPE qualifiedId RPAREN -> ^(TYPEREF qualifiedId);
|
||||
//type: TYPE tn=qualifiedId (LBRACKET RBRACKET)? (COMMA qid=qualifiedId)? RPAREN
|
||||
|
||||
|
||||
constructor
|
||||
: ('new' qualifiedId LPAREN) => 'new' qualifiedId ctorArgs -> ^(CONSTRUCTOR qualifiedId ctorArgs)
|
||||
;
|
||||
|
||||
ctorArgs
|
||||
: LPAREN! (namedArgument (COMMA! namedArgument)*)? RPAREN!;
|
||||
|
||||
argument : expression;
|
||||
|
||||
namedArgument
|
||||
: (ID ASSIGN) => id=ID ASSIGN expression
|
||||
-> ^(NAMED_ARGUMENT[$id] expression)
|
||||
| argument ;
|
||||
|
||||
qualifiedId : ID (DOT ID)* -> ^(QUALIFIED_IDENTIFIER ID*);
|
||||
|
||||
contextName : ID (DIV ID)* -> ^(QUALIFIED_IDENTIFIER ID*);
|
||||
|
||||
literal
|
||||
: INTEGER_LITERAL
|
||||
| STRING_LITERAL
|
||||
| DQ_STRING_LITERAL
|
||||
| boolLiteral
|
||||
| NULL_LITERAL
|
||||
| HEXADECIMAL_INTEGER_LITERAL
|
||||
| REAL_LITERAL
|
||||
;
|
||||
|
||||
boolLiteral: TRUE | FALSE;
|
||||
|
||||
INTEGER_LITERAL
|
||||
: (DECIMAL_DIGIT)+ (INTEGER_TYPE_SUFFIX)?;
|
||||
|
||||
HEXADECIMAL_INTEGER_LITERAL : ('0x' | '0X') (HEX_DIGIT)+ (INTEGER_TYPE_SUFFIX)?;
|
||||
|
||||
relationalOperator
|
||||
: EQUAL
|
||||
| NOT_EQUAL
|
||||
| LESS_THAN
|
||||
| LESS_THAN_OR_EQUAL
|
||||
| GREATER_THAN
|
||||
| GREATER_THAN_OR_EQUAL
|
||||
| INSTANCEOF
|
||||
| BETWEEN
|
||||
| MATCHES
|
||||
;
|
||||
|
||||
ASSIGN: '=';
|
||||
EQUAL: '==';
|
||||
NOT_EQUAL: '!=';
|
||||
LESS_THAN: '<';
|
||||
LESS_THAN_OR_EQUAL: '<=';
|
||||
GREATER_THAN: '>';
|
||||
GREATER_THAN_OR_EQUAL: '>=';
|
||||
INSTANCEOF: 'instanceof';
|
||||
BETWEEN:'between';
|
||||
MATCHES:'matches';
|
||||
NULL_LITERAL: 'null';
|
||||
|
||||
SEMI: ';';
|
||||
DOT: '.';
|
||||
COMMA: ',';
|
||||
LPAREN: '(';
|
||||
RPAREN: ')';
|
||||
LCURLY: '{';
|
||||
RCURLY: '}';
|
||||
LBRACKET: '[';
|
||||
RBRACKET: ']';
|
||||
PIPE: '|';
|
||||
|
||||
AND: 'and';
|
||||
OR: 'or';
|
||||
FALSE: 'false';
|
||||
TRUE: 'true';
|
||||
|
||||
PLUS: '+';
|
||||
MINUS: '-';
|
||||
DIV: '/';
|
||||
STAR: '*';
|
||||
MOD: '%';
|
||||
POWER: '^';
|
||||
BANG: '!';
|
||||
POUND: '#';
|
||||
QMARK: '?';
|
||||
DEFAULT: '??';
|
||||
PROJECT: '!{';
|
||||
SELECT: '?{';
|
||||
SELECT_FIRST: '^{';
|
||||
SELECT_LAST: '${';
|
||||
TYPE: 'T(';
|
||||
|
||||
STRING_LITERAL: '\''! (APOS|~'\'')* '\''!;
|
||||
DQ_STRING_LITERAL: '"'! (~'"')* '"'!;
|
||||
ID: ('a'..'z'|'A'..'Z'|'_') ('a'..'z'|'A'..'Z'|'_'|'0'..'9'|DOT_ESCAPED)*;
|
||||
DOT_ESCAPED: '\\.';
|
||||
WS: ( ' ' | '\t' | '\n' |'\r')+ { $channel=HIDDEN; } ;
|
||||
DOLLAR: '$';
|
||||
AT: '@';
|
||||
UPTO: '..';
|
||||
COLON: ':';
|
||||
|
||||
|
||||
REAL_LITERAL :
|
||||
('.' (DECIMAL_DIGIT)+ (EXPONENT_PART)? (REAL_TYPE_SUFFIX)?) |
|
||||
((DECIMAL_DIGIT)+ '.' (DECIMAL_DIGIT)+ (EXPONENT_PART)? (REAL_TYPE_SUFFIX)?) |
|
||||
((DECIMAL_DIGIT)+ (EXPONENT_PART) (REAL_TYPE_SUFFIX)?) |
|
||||
((DECIMAL_DIGIT)+ (REAL_TYPE_SUFFIX));
|
||||
|
||||
fragment APOS : '\''! '\'';
|
||||
fragment DECIMAL_DIGIT : '0'..'9' ;
|
||||
fragment INTEGER_TYPE_SUFFIX : ( 'L' | 'l' );
|
||||
fragment HEX_DIGIT : '0'|'1'|'2'|'3'|'4'|'5'|'6'|'7'|'8'|'9'|'A'|'B'|'C'|'D'|'E'|'F'|'a'|'b'|'c'|'d'|'e'|'f';
|
||||
|
||||
fragment EXPONENT_PART : 'e' (SIGN)* (DECIMAL_DIGIT)+ | 'E' (SIGN)* (DECIMAL_DIGIT)+ ;
|
||||
fragment SIGN : '+' | '-' ;
|
||||
fragment REAL_TYPE_SUFFIX : 'F' | 'f' | 'D' | 'd';
|
|
@ -1,74 +0,0 @@
|
|||
GREATER_THAN_OR_EQUAL=61
|
||||
HOLDER=10
|
||||
COMMA=37
|
||||
SELECT_FIRST=43
|
||||
GREATER_THAN=60
|
||||
TYPE=45
|
||||
MINUS=28
|
||||
SELECT_LAST=44
|
||||
NUMBER=18
|
||||
LESS_THAN=58
|
||||
BANG=33
|
||||
FALSE=52
|
||||
METHOD=15
|
||||
PROPERTY_OR_FIELD=7
|
||||
LBRACKET=38
|
||||
INDEXER=8
|
||||
MOD=31
|
||||
FUNCTIONREF=12
|
||||
NULL_LITERAL=48
|
||||
NAMED_ARGUMENT=11
|
||||
OR=25
|
||||
PIPE=67
|
||||
DOT=34
|
||||
RCURLY=41
|
||||
EXPRESSION=5
|
||||
AND=26
|
||||
LCURLY=66
|
||||
REAL_TYPE_SUFFIX=75
|
||||
STRING_LITERAL=46
|
||||
QUALIFIED_IDENTIFIER=6
|
||||
SELECT=42
|
||||
ASSIGN=19
|
||||
SUBTRACT=17
|
||||
RBRACKET=39
|
||||
INSTANCEOF=62
|
||||
BETWEEN=63
|
||||
RPAREN=24
|
||||
SIGN=76
|
||||
LPAREN=23
|
||||
HEX_DIGIT=55
|
||||
PLUS=27
|
||||
APOS=68
|
||||
INTEGER_LITERAL=4
|
||||
AT=72
|
||||
ID=36
|
||||
NOT_EQUAL=57
|
||||
POWER=32
|
||||
TYPEREF=13
|
||||
DECIMAL_DIGIT=53
|
||||
WS=70
|
||||
DOLLAR=71
|
||||
LESS_THAN_OR_EQUAL=59
|
||||
DQ_STRING_LITERAL=47
|
||||
HEXADECIMAL_INTEGER_LITERAL=49
|
||||
SEMI=65
|
||||
CONSTRUCTOR=9
|
||||
INTEGER_TYPE_SUFFIX=54
|
||||
EQUAL=56
|
||||
MATCHES=64
|
||||
DOT_ESCAPED=69
|
||||
UPTO=73
|
||||
QMARK=21
|
||||
DEFAULT=20
|
||||
COLON=22
|
||||
PROJECT=40
|
||||
DIV=30
|
||||
STAR=29
|
||||
REAL_LITERAL=50
|
||||
VARIABLEREF=14
|
||||
EXPONENT_PART=74
|
||||
TRUE=51
|
||||
ADD=16
|
||||
POUND=35
|
||||
'new'=77
|
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
|
@ -1,142 +0,0 @@
|
|||
lexer grammar SpringExpressions;
|
||||
options {
|
||||
language=Java;
|
||||
|
||||
}
|
||||
@header {package org.springframework.expression.spel.generated;}
|
||||
|
||||
T77 : 'new' ;
|
||||
|
||||
// $ANTLR src "/Users/aclement/el2/spring-framework/trunk/org.springframework.expression/src/main/java/org/springframework/expression/spel/generated/SpringExpressions.g" 183
|
||||
INTEGER_LITERAL
|
||||
: (DECIMAL_DIGIT)+ (INTEGER_TYPE_SUFFIX)?;
|
||||
|
||||
// $ANTLR src "/Users/aclement/el2/spring-framework/trunk/org.springframework.expression/src/main/java/org/springframework/expression/spel/generated/SpringExpressions.g" 186
|
||||
HEXADECIMAL_INTEGER_LITERAL : ('0x' | '0X') (HEX_DIGIT)+ (INTEGER_TYPE_SUFFIX)?;
|
||||
|
||||
// $ANTLR src "/Users/aclement/el2/spring-framework/trunk/org.springframework.expression/src/main/java/org/springframework/expression/spel/generated/SpringExpressions.g" 200
|
||||
ASSIGN: '=';
|
||||
// $ANTLR src "/Users/aclement/el2/spring-framework/trunk/org.springframework.expression/src/main/java/org/springframework/expression/spel/generated/SpringExpressions.g" 201
|
||||
EQUAL: '==';
|
||||
// $ANTLR src "/Users/aclement/el2/spring-framework/trunk/org.springframework.expression/src/main/java/org/springframework/expression/spel/generated/SpringExpressions.g" 202
|
||||
NOT_EQUAL: '!=';
|
||||
// $ANTLR src "/Users/aclement/el2/spring-framework/trunk/org.springframework.expression/src/main/java/org/springframework/expression/spel/generated/SpringExpressions.g" 203
|
||||
LESS_THAN: '<';
|
||||
// $ANTLR src "/Users/aclement/el2/spring-framework/trunk/org.springframework.expression/src/main/java/org/springframework/expression/spel/generated/SpringExpressions.g" 204
|
||||
LESS_THAN_OR_EQUAL: '<=';
|
||||
// $ANTLR src "/Users/aclement/el2/spring-framework/trunk/org.springframework.expression/src/main/java/org/springframework/expression/spel/generated/SpringExpressions.g" 205
|
||||
GREATER_THAN: '>';
|
||||
// $ANTLR src "/Users/aclement/el2/spring-framework/trunk/org.springframework.expression/src/main/java/org/springframework/expression/spel/generated/SpringExpressions.g" 206
|
||||
GREATER_THAN_OR_EQUAL: '>=';
|
||||
// $ANTLR src "/Users/aclement/el2/spring-framework/trunk/org.springframework.expression/src/main/java/org/springframework/expression/spel/generated/SpringExpressions.g" 207
|
||||
INSTANCEOF: 'instanceof';
|
||||
// $ANTLR src "/Users/aclement/el2/spring-framework/trunk/org.springframework.expression/src/main/java/org/springframework/expression/spel/generated/SpringExpressions.g" 208
|
||||
BETWEEN:'between';
|
||||
// $ANTLR src "/Users/aclement/el2/spring-framework/trunk/org.springframework.expression/src/main/java/org/springframework/expression/spel/generated/SpringExpressions.g" 209
|
||||
MATCHES:'matches';
|
||||
// $ANTLR src "/Users/aclement/el2/spring-framework/trunk/org.springframework.expression/src/main/java/org/springframework/expression/spel/generated/SpringExpressions.g" 210
|
||||
NULL_LITERAL: 'null';
|
||||
|
||||
// $ANTLR src "/Users/aclement/el2/spring-framework/trunk/org.springframework.expression/src/main/java/org/springframework/expression/spel/generated/SpringExpressions.g" 212
|
||||
SEMI: ';';
|
||||
// $ANTLR src "/Users/aclement/el2/spring-framework/trunk/org.springframework.expression/src/main/java/org/springframework/expression/spel/generated/SpringExpressions.g" 213
|
||||
DOT: '.';
|
||||
// $ANTLR src "/Users/aclement/el2/spring-framework/trunk/org.springframework.expression/src/main/java/org/springframework/expression/spel/generated/SpringExpressions.g" 214
|
||||
COMMA: ',';
|
||||
// $ANTLR src "/Users/aclement/el2/spring-framework/trunk/org.springframework.expression/src/main/java/org/springframework/expression/spel/generated/SpringExpressions.g" 215
|
||||
LPAREN: '(';
|
||||
// $ANTLR src "/Users/aclement/el2/spring-framework/trunk/org.springframework.expression/src/main/java/org/springframework/expression/spel/generated/SpringExpressions.g" 216
|
||||
RPAREN: ')';
|
||||
// $ANTLR src "/Users/aclement/el2/spring-framework/trunk/org.springframework.expression/src/main/java/org/springframework/expression/spel/generated/SpringExpressions.g" 217
|
||||
LCURLY: '{';
|
||||
// $ANTLR src "/Users/aclement/el2/spring-framework/trunk/org.springframework.expression/src/main/java/org/springframework/expression/spel/generated/SpringExpressions.g" 218
|
||||
RCURLY: '}';
|
||||
// $ANTLR src "/Users/aclement/el2/spring-framework/trunk/org.springframework.expression/src/main/java/org/springframework/expression/spel/generated/SpringExpressions.g" 219
|
||||
LBRACKET: '[';
|
||||
// $ANTLR src "/Users/aclement/el2/spring-framework/trunk/org.springframework.expression/src/main/java/org/springframework/expression/spel/generated/SpringExpressions.g" 220
|
||||
RBRACKET: ']';
|
||||
// $ANTLR src "/Users/aclement/el2/spring-framework/trunk/org.springframework.expression/src/main/java/org/springframework/expression/spel/generated/SpringExpressions.g" 221
|
||||
PIPE: '|';
|
||||
|
||||
// $ANTLR src "/Users/aclement/el2/spring-framework/trunk/org.springframework.expression/src/main/java/org/springframework/expression/spel/generated/SpringExpressions.g" 223
|
||||
AND: 'and';
|
||||
// $ANTLR src "/Users/aclement/el2/spring-framework/trunk/org.springframework.expression/src/main/java/org/springframework/expression/spel/generated/SpringExpressions.g" 224
|
||||
OR: 'or';
|
||||
// $ANTLR src "/Users/aclement/el2/spring-framework/trunk/org.springframework.expression/src/main/java/org/springframework/expression/spel/generated/SpringExpressions.g" 225
|
||||
FALSE: 'false';
|
||||
// $ANTLR src "/Users/aclement/el2/spring-framework/trunk/org.springframework.expression/src/main/java/org/springframework/expression/spel/generated/SpringExpressions.g" 226
|
||||
TRUE: 'true';
|
||||
|
||||
// $ANTLR src "/Users/aclement/el2/spring-framework/trunk/org.springframework.expression/src/main/java/org/springframework/expression/spel/generated/SpringExpressions.g" 228
|
||||
PLUS: '+';
|
||||
// $ANTLR src "/Users/aclement/el2/spring-framework/trunk/org.springframework.expression/src/main/java/org/springframework/expression/spel/generated/SpringExpressions.g" 229
|
||||
MINUS: '-';
|
||||
// $ANTLR src "/Users/aclement/el2/spring-framework/trunk/org.springframework.expression/src/main/java/org/springframework/expression/spel/generated/SpringExpressions.g" 230
|
||||
DIV: '/';
|
||||
// $ANTLR src "/Users/aclement/el2/spring-framework/trunk/org.springframework.expression/src/main/java/org/springframework/expression/spel/generated/SpringExpressions.g" 231
|
||||
STAR: '*';
|
||||
// $ANTLR src "/Users/aclement/el2/spring-framework/trunk/org.springframework.expression/src/main/java/org/springframework/expression/spel/generated/SpringExpressions.g" 232
|
||||
MOD: '%';
|
||||
// $ANTLR src "/Users/aclement/el2/spring-framework/trunk/org.springframework.expression/src/main/java/org/springframework/expression/spel/generated/SpringExpressions.g" 233
|
||||
POWER: '^';
|
||||
// $ANTLR src "/Users/aclement/el2/spring-framework/trunk/org.springframework.expression/src/main/java/org/springframework/expression/spel/generated/SpringExpressions.g" 234
|
||||
BANG: '!';
|
||||
// $ANTLR src "/Users/aclement/el2/spring-framework/trunk/org.springframework.expression/src/main/java/org/springframework/expression/spel/generated/SpringExpressions.g" 235
|
||||
POUND: '#';
|
||||
// $ANTLR src "/Users/aclement/el2/spring-framework/trunk/org.springframework.expression/src/main/java/org/springframework/expression/spel/generated/SpringExpressions.g" 236
|
||||
QMARK: '?';
|
||||
// $ANTLR src "/Users/aclement/el2/spring-framework/trunk/org.springframework.expression/src/main/java/org/springframework/expression/spel/generated/SpringExpressions.g" 237
|
||||
DEFAULT: '??';
|
||||
// $ANTLR src "/Users/aclement/el2/spring-framework/trunk/org.springframework.expression/src/main/java/org/springframework/expression/spel/generated/SpringExpressions.g" 238
|
||||
PROJECT: '!{';
|
||||
// $ANTLR src "/Users/aclement/el2/spring-framework/trunk/org.springframework.expression/src/main/java/org/springframework/expression/spel/generated/SpringExpressions.g" 239
|
||||
SELECT: '?{';
|
||||
// $ANTLR src "/Users/aclement/el2/spring-framework/trunk/org.springframework.expression/src/main/java/org/springframework/expression/spel/generated/SpringExpressions.g" 240
|
||||
SELECT_FIRST: '^{';
|
||||
// $ANTLR src "/Users/aclement/el2/spring-framework/trunk/org.springframework.expression/src/main/java/org/springframework/expression/spel/generated/SpringExpressions.g" 241
|
||||
SELECT_LAST: '${';
|
||||
// $ANTLR src "/Users/aclement/el2/spring-framework/trunk/org.springframework.expression/src/main/java/org/springframework/expression/spel/generated/SpringExpressions.g" 242
|
||||
TYPE: 'T(';
|
||||
|
||||
// $ANTLR src "/Users/aclement/el2/spring-framework/trunk/org.springframework.expression/src/main/java/org/springframework/expression/spel/generated/SpringExpressions.g" 244
|
||||
STRING_LITERAL: '\''! (APOS|~'\'')* '\''!;
|
||||
// $ANTLR src "/Users/aclement/el2/spring-framework/trunk/org.springframework.expression/src/main/java/org/springframework/expression/spel/generated/SpringExpressions.g" 245
|
||||
DQ_STRING_LITERAL: '"'! (~'"')* '"'!;
|
||||
// $ANTLR src "/Users/aclement/el2/spring-framework/trunk/org.springframework.expression/src/main/java/org/springframework/expression/spel/generated/SpringExpressions.g" 246
|
||||
ID: ('a'..'z'|'A'..'Z'|'_') ('a'..'z'|'A'..'Z'|'_'|'0'..'9'|DOT_ESCAPED)*;
|
||||
// $ANTLR src "/Users/aclement/el2/spring-framework/trunk/org.springframework.expression/src/main/java/org/springframework/expression/spel/generated/SpringExpressions.g" 247
|
||||
DOT_ESCAPED: '\\.';
|
||||
// $ANTLR src "/Users/aclement/el2/spring-framework/trunk/org.springframework.expression/src/main/java/org/springframework/expression/spel/generated/SpringExpressions.g" 248
|
||||
WS: ( ' ' | '\t' | '\n' |'\r')+ { $channel=HIDDEN; } ;
|
||||
// $ANTLR src "/Users/aclement/el2/spring-framework/trunk/org.springframework.expression/src/main/java/org/springframework/expression/spel/generated/SpringExpressions.g" 249
|
||||
DOLLAR: '$';
|
||||
// $ANTLR src "/Users/aclement/el2/spring-framework/trunk/org.springframework.expression/src/main/java/org/springframework/expression/spel/generated/SpringExpressions.g" 250
|
||||
AT: '@';
|
||||
// $ANTLR src "/Users/aclement/el2/spring-framework/trunk/org.springframework.expression/src/main/java/org/springframework/expression/spel/generated/SpringExpressions.g" 251
|
||||
UPTO: '..';
|
||||
// $ANTLR src "/Users/aclement/el2/spring-framework/trunk/org.springframework.expression/src/main/java/org/springframework/expression/spel/generated/SpringExpressions.g" 252
|
||||
COLON: ':';
|
||||
|
||||
|
||||
// $ANTLR src "/Users/aclement/el2/spring-framework/trunk/org.springframework.expression/src/main/java/org/springframework/expression/spel/generated/SpringExpressions.g" 255
|
||||
REAL_LITERAL :
|
||||
('.' (DECIMAL_DIGIT)+ (EXPONENT_PART)? (REAL_TYPE_SUFFIX)?) |
|
||||
((DECIMAL_DIGIT)+ '.' (DECIMAL_DIGIT)+ (EXPONENT_PART)? (REAL_TYPE_SUFFIX)?) |
|
||||
((DECIMAL_DIGIT)+ (EXPONENT_PART) (REAL_TYPE_SUFFIX)?) |
|
||||
((DECIMAL_DIGIT)+ (REAL_TYPE_SUFFIX));
|
||||
|
||||
// $ANTLR src "/Users/aclement/el2/spring-framework/trunk/org.springframework.expression/src/main/java/org/springframework/expression/spel/generated/SpringExpressions.g" 261
|
||||
fragment APOS : '\''! '\'';
|
||||
// $ANTLR src "/Users/aclement/el2/spring-framework/trunk/org.springframework.expression/src/main/java/org/springframework/expression/spel/generated/SpringExpressions.g" 262
|
||||
fragment DECIMAL_DIGIT : '0'..'9' ;
|
||||
// $ANTLR src "/Users/aclement/el2/spring-framework/trunk/org.springframework.expression/src/main/java/org/springframework/expression/spel/generated/SpringExpressions.g" 263
|
||||
fragment INTEGER_TYPE_SUFFIX : ( 'L' | 'l' );
|
||||
// $ANTLR src "/Users/aclement/el2/spring-framework/trunk/org.springframework.expression/src/main/java/org/springframework/expression/spel/generated/SpringExpressions.g" 264
|
||||
fragment HEX_DIGIT : '0'|'1'|'2'|'3'|'4'|'5'|'6'|'7'|'8'|'9'|'A'|'B'|'C'|'D'|'E'|'F'|'a'|'b'|'c'|'d'|'e'|'f';
|
||||
|
||||
// $ANTLR src "/Users/aclement/el2/spring-framework/trunk/org.springframework.expression/src/main/java/org/springframework/expression/spel/generated/SpringExpressions.g" 266
|
||||
fragment EXPONENT_PART : 'e' (SIGN)* (DECIMAL_DIGIT)+ | 'E' (SIGN)* (DECIMAL_DIGIT)+ ;
|
||||
// $ANTLR src "/Users/aclement/el2/spring-framework/trunk/org.springframework.expression/src/main/java/org/springframework/expression/spel/generated/SpringExpressions.g" 267
|
||||
fragment SIGN : '+' | '-' ;
|
||||
// $ANTLR src "/Users/aclement/el2/spring-framework/trunk/org.springframework.expression/src/main/java/org/springframework/expression/spel/generated/SpringExpressions.g" 268
|
||||
fragment REAL_TYPE_SUFFIX : 'F' | 'f' | 'D' | 'd';
|
|
@ -1,39 +0,0 @@
|
|||
/*
|
||||
* Copyright 2004-2008 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
|
||||
*
|
||||
* 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.springframework.expression.spel.internal;
|
||||
|
||||
import org.antlr.runtime.Token;
|
||||
import org.springframework.expression.spel.SpelException;
|
||||
import org.springframework.expression.spel.ExpressionState;
|
||||
import org.springframework.expression.spel.ast.SpelNode;
|
||||
|
||||
public class EmptySpelNode extends SpelNode {
|
||||
|
||||
public EmptySpelNode(Token payload) {
|
||||
super(payload);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Object getValue(ExpressionState state) throws SpelException {
|
||||
throw new RuntimeException("?");
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toStringAST() {
|
||||
return "<no string form node '" + getTokenName() + "'>";
|
||||
}
|
||||
|
||||
}
|
|
@ -1,35 +0,0 @@
|
|||
/*
|
||||
* Copyright 2004-2008 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
|
||||
*
|
||||
* 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.springframework.expression.spel.internal;
|
||||
|
||||
import org.springframework.expression.spel.SpelException;
|
||||
|
||||
/**
|
||||
* Wraps an ELException and can pass up through Antlr since it is unchecked, where it can then be unwrapped.
|
||||
*
|
||||
* @author Andy Clement
|
||||
*/
|
||||
public class InternalELException extends RuntimeException {
|
||||
|
||||
public InternalELException(SpelException e) {
|
||||
super(e);
|
||||
}
|
||||
|
||||
@Override
|
||||
public SpelException getCause() {
|
||||
return (SpelException) super.getCause();
|
||||
}
|
||||
}
|
|
@ -1,33 +0,0 @@
|
|||
/*
|
||||
* Copyright 2004-2008 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
|
||||
*
|
||||
* 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.springframework.expression.spel.internal;
|
||||
|
||||
/**
|
||||
* Special object that is used to wrap a map entry/value when iterating over a map. Providing a direct way for the
|
||||
* expression to refer to either the key or value.
|
||||
*
|
||||
* @author Andy Clement
|
||||
*/
|
||||
public class KeyValuePair {
|
||||
public Object key;
|
||||
public Object value;
|
||||
|
||||
public KeyValuePair(Object k, Object v) {
|
||||
this.key = k;
|
||||
this.value = v;
|
||||
}
|
||||
|
||||
}
|
|
@ -1,172 +0,0 @@
|
|||
/*
|
||||
* Copyright 2004-2008 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
|
||||
*
|
||||
* 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.springframework.expression.spel.internal;
|
||||
|
||||
import org.antlr.runtime.Token;
|
||||
import org.antlr.runtime.tree.CommonTreeAdaptor;
|
||||
import org.springframework.expression.spel.ast.Assign;
|
||||
import org.springframework.expression.spel.ast.BooleanLiteral;
|
||||
import org.springframework.expression.spel.ast.CompoundExpression;
|
||||
import org.springframework.expression.spel.ast.ConstructorReference;
|
||||
import org.springframework.expression.spel.ast.Dot;
|
||||
import org.springframework.expression.spel.ast.FunctionReference;
|
||||
import org.springframework.expression.spel.ast.Identifier;
|
||||
import org.springframework.expression.spel.ast.Indexer;
|
||||
import org.springframework.expression.spel.ast.Literal;
|
||||
import org.springframework.expression.spel.ast.MethodReference;
|
||||
import org.springframework.expression.spel.ast.NullLiteral;
|
||||
import org.springframework.expression.spel.ast.OperatorAnd;
|
||||
import org.springframework.expression.spel.ast.OperatorBetween;
|
||||
import org.springframework.expression.spel.ast.OperatorDivide;
|
||||
import org.springframework.expression.spel.ast.OperatorEquality;
|
||||
import org.springframework.expression.spel.ast.OperatorGreaterThan;
|
||||
import org.springframework.expression.spel.ast.OperatorGreaterThanOrEqual;
|
||||
import org.springframework.expression.spel.ast.OperatorInequality;
|
||||
import org.springframework.expression.spel.ast.OperatorInstanceof;
|
||||
import org.springframework.expression.spel.ast.OperatorLessThan;
|
||||
import org.springframework.expression.spel.ast.OperatorLessThanOrEqual;
|
||||
import org.springframework.expression.spel.ast.OperatorMatches;
|
||||
import org.springframework.expression.spel.ast.OperatorMinus;
|
||||
import org.springframework.expression.spel.ast.OperatorModulus;
|
||||
import org.springframework.expression.spel.ast.OperatorMultiply;
|
||||
import org.springframework.expression.spel.ast.OperatorNot;
|
||||
import org.springframework.expression.spel.ast.OperatorOr;
|
||||
import org.springframework.expression.spel.ast.OperatorPlus;
|
||||
import org.springframework.expression.spel.ast.Placeholder;
|
||||
import org.springframework.expression.spel.ast.Projection;
|
||||
import org.springframework.expression.spel.ast.PropertyOrFieldReference;
|
||||
import org.springframework.expression.spel.ast.QualifiedIdentifier;
|
||||
import org.springframework.expression.spel.ast.RealLiteral;
|
||||
import org.springframework.expression.spel.ast.Selection;
|
||||
import org.springframework.expression.spel.ast.StringLiteral;
|
||||
import org.springframework.expression.spel.ast.Ternary;
|
||||
import org.springframework.expression.spel.ast.TypeReference;
|
||||
import org.springframework.expression.spel.ast.VariableReference;
|
||||
import org.springframework.expression.spel.generated.SpringExpressionsLexer;
|
||||
|
||||
public class SpelTreeAdaptor extends CommonTreeAdaptor {
|
||||
@Override
|
||||
public Object create(Token payload) {
|
||||
if (payload != null) {
|
||||
switch (payload.getType()) {
|
||||
|
||||
case SpringExpressionsLexer.TRUE:
|
||||
return new BooleanLiteral(payload, true);
|
||||
case SpringExpressionsLexer.FALSE:
|
||||
return new BooleanLiteral(payload, false);
|
||||
|
||||
case SpringExpressionsLexer.OR:
|
||||
return new OperatorOr(payload);
|
||||
case SpringExpressionsLexer.AND:
|
||||
return new OperatorAnd(payload);
|
||||
case SpringExpressionsLexer.BANG:
|
||||
return new OperatorNot(payload);
|
||||
|
||||
case SpringExpressionsLexer.REAL_LITERAL:
|
||||
return new RealLiteral(payload);
|
||||
case SpringExpressionsLexer.INTEGER_LITERAL:
|
||||
return Literal.getIntLiteral(payload, 10);
|
||||
case SpringExpressionsLexer.HEXADECIMAL_INTEGER_LITERAL:
|
||||
return Literal.getIntLiteral(payload, 16);
|
||||
|
||||
case SpringExpressionsLexer.NOT_EQUAL:
|
||||
return new OperatorInequality(payload);
|
||||
case SpringExpressionsLexer.EQUAL:
|
||||
return new OperatorEquality(payload);
|
||||
case SpringExpressionsLexer.GREATER_THAN:
|
||||
return new OperatorGreaterThan(payload);
|
||||
case SpringExpressionsLexer.LESS_THAN:
|
||||
return new OperatorLessThan(payload);
|
||||
case SpringExpressionsLexer.LESS_THAN_OR_EQUAL:
|
||||
return new OperatorLessThanOrEqual(payload);
|
||||
case SpringExpressionsLexer.GREATER_THAN_OR_EQUAL:
|
||||
return new OperatorGreaterThanOrEqual(payload);
|
||||
case SpringExpressionsLexer.PLUS:
|
||||
return new OperatorPlus(payload);
|
||||
case SpringExpressionsLexer.MINUS:
|
||||
return new OperatorMinus(payload);
|
||||
case SpringExpressionsLexer.STAR/* MULTIPLY */:
|
||||
return new OperatorMultiply(payload);
|
||||
case SpringExpressionsLexer.DIV/* DIVIDE */:
|
||||
return new OperatorDivide(payload);
|
||||
case SpringExpressionsLexer.MOD:
|
||||
return new OperatorModulus(payload);
|
||||
|
||||
case SpringExpressionsLexer.STRING_LITERAL:
|
||||
case SpringExpressionsLexer.DQ_STRING_LITERAL:
|
||||
return new StringLiteral(payload);
|
||||
case SpringExpressionsLexer.NULL_LITERAL:
|
||||
return new NullLiteral(payload);
|
||||
|
||||
case SpringExpressionsLexer.ID:
|
||||
return new Identifier(payload);
|
||||
case SpringExpressionsLexer.PROPERTY_OR_FIELD:
|
||||
return new PropertyOrFieldReference(payload);
|
||||
case SpringExpressionsLexer.METHOD:
|
||||
return new MethodReference(payload);
|
||||
case SpringExpressionsLexer.QUALIFIED_IDENTIFIER:
|
||||
return new QualifiedIdentifier(payload);
|
||||
case SpringExpressionsLexer.TYPEREF:
|
||||
return new TypeReference(payload);
|
||||
|
||||
case SpringExpressionsLexer.EXPRESSION:
|
||||
return new CompoundExpression(payload);
|
||||
|
||||
case SpringExpressionsLexer.CONSTRUCTOR:
|
||||
return new ConstructorReference(payload, false);
|
||||
case SpringExpressionsLexer.VARIABLEREF:
|
||||
return new VariableReference(payload);
|
||||
case SpringExpressionsLexer.FUNCTIONREF:
|
||||
return new FunctionReference(payload);
|
||||
case SpringExpressionsLexer.PROJECT:
|
||||
return new Projection(payload);
|
||||
case SpringExpressionsLexer.SELECT:
|
||||
return new Selection(payload, Selection.ALL);
|
||||
case SpringExpressionsLexer.SELECT_FIRST:
|
||||
return new Selection(payload, Selection.FIRST);
|
||||
case SpringExpressionsLexer.SELECT_LAST:
|
||||
return new Selection(payload, Selection.LAST);
|
||||
|
||||
case SpringExpressionsLexer.ASSIGN:
|
||||
return new Assign(payload);
|
||||
case SpringExpressionsLexer.QMARK:
|
||||
return new Ternary(payload);
|
||||
case SpringExpressionsLexer.INDEXER:
|
||||
return new Indexer(payload);
|
||||
|
||||
case SpringExpressionsLexer.BETWEEN:
|
||||
return new OperatorBetween(payload);
|
||||
case SpringExpressionsLexer.MATCHES:
|
||||
return new OperatorMatches(payload);
|
||||
case SpringExpressionsLexer.INSTANCEOF:
|
||||
return new OperatorInstanceof(payload);
|
||||
|
||||
case SpringExpressionsLexer.RPAREN:
|
||||
return new Placeholder(payload);
|
||||
case SpringExpressionsLexer.COLON:
|
||||
return new Placeholder(payload);
|
||||
|
||||
case SpringExpressionsLexer.DOT:
|
||||
return new Dot(payload);
|
||||
|
||||
default:
|
||||
throw new RuntimeException("Not implemented for '" + payload + "' " + getToken(payload) + "' "
|
||||
+ payload.getType());
|
||||
}
|
||||
}
|
||||
return new EmptySpelNode(payload);
|
||||
}
|
||||
}
|
|
@ -1,81 +0,0 @@
|
|||
/*
|
||||
* Copyright 2004-2008 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
|
||||
*
|
||||
* 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.springframework.expression.spel.internal;
|
||||
|
||||
import org.antlr.runtime.RecognitionException;
|
||||
import org.springframework.expression.spel.SpelException;
|
||||
import org.springframework.expression.spel.SpelMessages;
|
||||
import org.springframework.expression.spel.generated.SpringExpressionsLexer;
|
||||
|
||||
public class SpringExpressionsLexerExtender extends SpringExpressionsLexer {
|
||||
|
||||
public SpringExpressionsLexerExtender() {
|
||||
super();
|
||||
}
|
||||
|
||||
/**
|
||||
* recover() attempts to provide better error messages once something has gone wrong. It then throws a
|
||||
* InternalELException (has to be this unchecked exception as the exception must flow through Antlr lexer methods
|
||||
* that do not have declared exceptions). The InternalELException will be caught at the top level and altered to
|
||||
* include context (line,column) information before being rethrown.<br>
|
||||
*
|
||||
* This error analysis code is in recover() rather than reportError() because reportError() isn't always called by
|
||||
* the lexer and there is no way to add the calls to it by editing the .g file.
|
||||
*/
|
||||
@Override
|
||||
public void recover(RecognitionException re) {
|
||||
// TODO recovery needs an overhaul once the expression language syntax is agreed
|
||||
|
||||
// List<?> rules = getRuleInvocationStack(re, SpringExpressionsLexer.class.getName());
|
||||
// String failedRule = (String) rules.get(rules.size() - 1);
|
||||
// System.out.println("DBG: lexer rule " + failedRule);
|
||||
// need a concrete example of error recovery in here please! then i can delete the below
|
||||
// if (re instanceof NoViableAltException) {
|
||||
// NoViableAltException nvae = (NoViableAltException) re;
|
||||
// // example error data: { "abc": def }
|
||||
// if (failedRule.equals("mTokens") && Character.isLetter((char) (nvae.getUnexpectedType()))) {
|
||||
// logger.error(ParserMessage.ERROR_STRINGS_MUST_BE_QUOTED, re.line, re.charPositionInLine);
|
||||
// }
|
||||
//
|
||||
// } else if (re instanceof MismatchedRangeException) {
|
||||
// // MismatchedRangeException mre = (MismatchedRangeException) re;
|
||||
// // example error data: [ 123e ]
|
||||
// if (failedRule.equals("mDIGIT") && rules.size() > 3 && ((String) rules.get(rules.size() -
|
||||
// 3)).equals("mExponent")) {
|
||||
// logger.error(ParserMessage.ERROR_INVALID_EXPONENT, re.line, re.charPositionInLine);
|
||||
// }
|
||||
// } else if (re instanceof MismatchedTokenException) {
|
||||
// MismatchedTokenException mte = (MismatchedTokenException) re;
|
||||
// logger.error(ParserMessage.ERROR_MISMATCHED_CHARACTER, mte.charPositionInLine, mte.charPositionInLine,
|
||||
// getCharErrorDisplay(mte.expecting), getCharErrorDisplay(mte.c));
|
||||
// }
|
||||
SpelException realException = new SpelException(re, SpelMessages.RECOGNITION_ERROR, re.toString());
|
||||
throw new InternalELException(realException);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void reportError(RecognitionException re) {
|
||||
// Do not report anything. If better messages could be reported they will have been reported
|
||||
// by the recover() method above.
|
||||
}
|
||||
|
||||
// private String getTokenForId(int id) {
|
||||
// if (id == -1)
|
||||
// return "EOF";
|
||||
// return getTokenNames()[id];
|
||||
// }
|
||||
|
||||
}
|
|
@ -1,87 +0,0 @@
|
|||
/*
|
||||
* Copyright 2004-2008 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
|
||||
*
|
||||
* 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.springframework.expression.spel.internal;
|
||||
|
||||
import org.antlr.runtime.BitSet;
|
||||
import org.antlr.runtime.IntStream;
|
||||
import org.antlr.runtime.RecognitionException;
|
||||
import org.antlr.runtime.Token;
|
||||
import org.antlr.runtime.TokenStream;
|
||||
import org.springframework.expression.spel.SpelException;
|
||||
import org.springframework.expression.spel.SpelMessages;
|
||||
import org.springframework.expression.spel.generated.SpringExpressionsParser;
|
||||
|
||||
public class SpringExpressionsParserExtender extends SpringExpressionsParser {
|
||||
|
||||
public SpringExpressionsParserExtender(TokenStream input) {
|
||||
super(input);
|
||||
}
|
||||
|
||||
/**
|
||||
* Override super type implementation and just include the character position rather than the line number since the
|
||||
* expressions are nearly all going to be just one line.
|
||||
*/
|
||||
@Override
|
||||
public String getErrorHeader(RecognitionException e) {
|
||||
StringBuilder retval = new StringBuilder();
|
||||
retval.append("(pos ").append(e.charPositionInLine).append("): ");
|
||||
return retval.toString();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void displayRecognitionError(String[] tokenNames, RecognitionException e) {
|
||||
String message = getErrorMessage(e, tokenNames);
|
||||
// TODO would something like this be worthwhile to improve messages?
|
||||
// if (message.equals("no viable alternative at input '<EOF>'") && !paraphrase.isEmpty()) {
|
||||
// // This means we ran out of input building something, that something is named in paraphrase
|
||||
// message = "no more input data to process whilst constructing " + paraphrase.peek();
|
||||
// }
|
||||
SpelException parsingProblem = new SpelException(e.charPositionInLine, e, SpelMessages.PARSE_PROBLEM, message);
|
||||
throw new InternalELException(parsingProblem);
|
||||
}
|
||||
|
||||
/**
|
||||
* Overridden purely because the base implementation does a System.err.println()
|
||||
*/
|
||||
@Override
|
||||
public void recoverFromMismatchedToken(IntStream input, RecognitionException e, int ttype, BitSet follow)
|
||||
throws RecognitionException {
|
||||
// if next token is what we are looking for then "delete" this token
|
||||
if (input.LA(2) == ttype) {
|
||||
reportError(e);
|
||||
/*
|
||||
* System.err.println("recoverFromMismatchedToken deleting "+input.LT(1)+ " since "+input.LT(2)+" is what we
|
||||
* want");
|
||||
*/
|
||||
beginResync();
|
||||
input.consume(); // simply delete extra token
|
||||
endResync();
|
||||
input.consume(); // move past ttype token as if all were ok
|
||||
return;
|
||||
}
|
||||
if (!recoverFromMismatchedElement(input, e, follow)) {
|
||||
throw e;
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getTokenErrorDisplay(Token t) {
|
||||
if (t == null) {
|
||||
return "<unknown>";
|
||||
}
|
||||
return super.getTokenErrorDisplay(t);
|
||||
}
|
||||
}
|
|
@ -1,103 +0,0 @@
|
|||
/*
|
||||
* Copyright 2004-2008 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
|
||||
*
|
||||
* 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.springframework.expression.spel.internal;
|
||||
|
||||
public enum TypeCode {
|
||||
|
||||
OBJECT(0, Object.class), BOOLEAN(1, Boolean.TYPE), BYTE(1, Byte.TYPE), CHAR(1, Character.TYPE), SHORT(2, Short.TYPE), INT(
|
||||
3, Integer.TYPE), LONG(4, Long.TYPE), FLOAT(5, Float.TYPE), DOUBLE(6, Double.TYPE);
|
||||
|
||||
private int code;
|
||||
private Class<?> type;
|
||||
|
||||
TypeCode(int code, Class<?> type) {
|
||||
this.code = code;
|
||||
this.type = type;
|
||||
}
|
||||
|
||||
public Class<?> getType() {
|
||||
return type;
|
||||
}
|
||||
|
||||
public static TypeCode forClass(Class<?> c) {
|
||||
TypeCode[] allValues = TypeCode.values();
|
||||
for (int i = 0; i < allValues.length; i++) {
|
||||
TypeCode typeCode = allValues[i];
|
||||
if (c == typeCode.getType()) {
|
||||
return typeCode;
|
||||
}
|
||||
}
|
||||
return OBJECT;
|
||||
}
|
||||
|
||||
/**
|
||||
* For a primitive name this will determine the typecode value - supports
|
||||
* int,byte,char,short,long,double,float,boolean
|
||||
*/
|
||||
public static TypeCode forName(String name) {
|
||||
if (name.equals("int"))
|
||||
return TypeCode.INT;
|
||||
else if (name.equals("boolean"))
|
||||
return TypeCode.BOOLEAN;
|
||||
else if (name.equals("char"))
|
||||
return TypeCode.CHAR;
|
||||
else if (name.equals("long"))
|
||||
return TypeCode.LONG;
|
||||
else if (name.equals("float"))
|
||||
return TypeCode.FLOAT;
|
||||
else if (name.equals("double"))
|
||||
return TypeCode.DOUBLE;
|
||||
else if (name.equals("short"))
|
||||
return TypeCode.SHORT;
|
||||
else if (name.equals("byte"))
|
||||
return TypeCode.BYTE;
|
||||
return TypeCode.OBJECT;
|
||||
}
|
||||
|
||||
public int getCode() {
|
||||
return code;
|
||||
}
|
||||
|
||||
public Object coerce(TypeCode fromTypeCode, Object fromObject) {
|
||||
if (this == TypeCode.INT) {
|
||||
switch (fromTypeCode) {
|
||||
case BOOLEAN:
|
||||
return ((Boolean) fromObject).booleanValue() ? 1 : 0;
|
||||
}
|
||||
}
|
||||
//
|
||||
// return Integer.valueOf
|
||||
// } else if (this==TypeCode.BOOLEAN) {
|
||||
// return new Boolean(left).intValue();
|
||||
return null;
|
||||
}
|
||||
|
||||
public static TypeCode forValue(Number op1) {
|
||||
return forClass(op1.getClass());
|
||||
}
|
||||
|
||||
public boolean isDouble() {
|
||||
return this == DOUBLE;
|
||||
}
|
||||
|
||||
public boolean isFloat() {
|
||||
return this == FLOAT;
|
||||
}
|
||||
|
||||
public boolean isLong() {
|
||||
return this == LONG;
|
||||
}
|
||||
}
|
|
@ -1,76 +0,0 @@
|
|||
/*
|
||||
* Copyright 2004-2008 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
|
||||
*
|
||||
* 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.springframework.expression.spel.internal;
|
||||
|
||||
/**
|
||||
* Utility methods (formatters, etc) used during parsing and evaluation.
|
||||
*
|
||||
* @author Andy Clement
|
||||
*/
|
||||
public class Utils {
|
||||
|
||||
/**
|
||||
* Produce a nice string for a given method name with specified arguments.
|
||||
*
|
||||
* @param name the name of the method
|
||||
* @param argumentTypes the types of the arguments to the method
|
||||
* @return nicely formatted string, eg. foo(String,int)
|
||||
*/
|
||||
public static String formatMethodForMessage(String name, Class<?>... argumentTypes) {
|
||||
StringBuilder sb = new StringBuilder();
|
||||
sb.append(name);
|
||||
sb.append("(");
|
||||
if (argumentTypes != null) {
|
||||
for (int i = 0; i < argumentTypes.length; i++) {
|
||||
if (i > 0)
|
||||
sb.append(",");
|
||||
sb.append(argumentTypes[i].getName());
|
||||
}
|
||||
}
|
||||
sb.append(")");
|
||||
return sb.toString();
|
||||
}
|
||||
|
||||
/**
|
||||
* Produce a nice string for a given class object. For example a string array will have the formatted name
|
||||
* "java.lang.String[]".
|
||||
*
|
||||
* @param clazz The class whose name is to be formatted
|
||||
* @return a formatted string suitable for message inclusion
|
||||
*/
|
||||
public static String formatClassnameForMessage(Class<?> clazz) {
|
||||
if (clazz==null) {
|
||||
return "null";
|
||||
}
|
||||
StringBuilder fmtd = new StringBuilder();
|
||||
if (clazz.isArray()) {
|
||||
int dims = 1;
|
||||
Class baseClass = clazz.getComponentType();
|
||||
while (baseClass.isArray()) {
|
||||
baseClass = baseClass.getComponentType();
|
||||
dims++;
|
||||
}
|
||||
fmtd.append(baseClass.getName());
|
||||
for (int i = 0; i < dims; i++) {
|
||||
fmtd.append("[]");
|
||||
}
|
||||
} else {
|
||||
fmtd.append(clazz.getName());
|
||||
}
|
||||
return fmtd.toString();
|
||||
}
|
||||
|
||||
}
|
|
@ -1,57 +0,0 @@
|
|||
/*
|
||||
* Copyright 2004-2008 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
|
||||
*
|
||||
* 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.springframework.expression.spel.internal;
|
||||
|
||||
import java.util.HashMap;
|
||||
import java.util.Map;
|
||||
|
||||
/**
|
||||
* A new scope is entered when a function is called and it is used to hold the parameters to the function call. If the names
|
||||
* of the parameters clash with those in a higher level scope, those in the higher level scope will not be accessible whilst
|
||||
* the function is executing. When the function returns the scope is exited.
|
||||
*
|
||||
* @author Andy Clement
|
||||
*
|
||||
*/
|
||||
public class VariableScope {
|
||||
|
||||
private final Map<String, Object> vars = new HashMap<String, Object>();
|
||||
|
||||
public VariableScope() { }
|
||||
|
||||
public VariableScope(Map<String, Object> arguments) {
|
||||
if (arguments!=null) {
|
||||
vars.putAll(arguments);
|
||||
}
|
||||
}
|
||||
|
||||
public VariableScope(String name,Object value) {
|
||||
vars.put(name,value);
|
||||
}
|
||||
|
||||
public Object lookupVariable(String name) {
|
||||
return vars.get(name);
|
||||
}
|
||||
|
||||
public void setVariable(String name, Object value) {
|
||||
vars.put(name,value);
|
||||
}
|
||||
|
||||
public boolean definesVariable(String name) {
|
||||
return vars.containsKey(name);
|
||||
}
|
||||
|
||||
}
|
|
@ -1,35 +0,0 @@
|
|||
/*
|
||||
* Copyright 2004-2008 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
|
||||
*
|
||||
* 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.springframework.expression.spel.internal;
|
||||
|
||||
import org.springframework.expression.spel.SpelException;
|
||||
|
||||
/**
|
||||
* Wraps an ELException and can pass up through Antlr since it is unchecked, where it can then be unwrapped.
|
||||
*
|
||||
* @author Andy Clement
|
||||
*/
|
||||
public class WrappedExpressionException extends RuntimeException {
|
||||
|
||||
WrappedExpressionException(SpelException e) {
|
||||
super(e);
|
||||
}
|
||||
|
||||
@Override
|
||||
public SpelException getCause() {
|
||||
return (SpelException) super.getCause();
|
||||
}
|
||||
}
|
|
@ -1,74 +0,0 @@
|
|||
/*
|
||||
* Copyright 2004-2008 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
|
||||
*
|
||||
* 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.springframework.expression.spel.reflection;
|
||||
|
||||
import java.lang.reflect.Constructor;
|
||||
import java.lang.reflect.InvocationTargetException;
|
||||
|
||||
import org.springframework.expression.AccessException;
|
||||
import org.springframework.expression.ConstructorExecutor;
|
||||
import org.springframework.expression.EvaluationContext;
|
||||
import org.springframework.expression.EvaluationException;
|
||||
|
||||
/**
|
||||
* A simple CommandExecutor implementation that runs a constructor using reflective invocation.
|
||||
*
|
||||
* @author Andy Clement
|
||||
*/
|
||||
public class ReflectionConstructorExecutor implements ConstructorExecutor {
|
||||
|
||||
private final Constructor<?> c;
|
||||
|
||||
// When the constructor was found, we will have determined if arguments need to be converted for it
|
||||
// to be invoked. Conversion won't be cheap so let's only do it if necessary.
|
||||
private final Integer[] argsRequiringConversion;
|
||||
|
||||
public ReflectionConstructorExecutor(Constructor<?> constructor, Integer[] argsRequiringConversion) {
|
||||
c = constructor;
|
||||
this.argsRequiringConversion = argsRequiringConversion;
|
||||
}
|
||||
|
||||
/**
|
||||
* Invoke a constructor via reflection.
|
||||
*/
|
||||
public Object execute(EvaluationContext context, Object... arguments) throws AccessException {
|
||||
if (argsRequiringConversion != null && arguments != null) {
|
||||
try {
|
||||
ReflectionUtils.convertArguments(c.getParameterTypes(), c.isVarArgs(), context.getTypeUtils()
|
||||
.getTypeConverter(), argsRequiringConversion, arguments);
|
||||
} catch (EvaluationException ex) {
|
||||
throw new AccessException("Problem invoking constructor on '" + c + "': " + ex.getMessage(), ex);
|
||||
}
|
||||
}
|
||||
if (c.isVarArgs()) {
|
||||
arguments = ReflectionUtils.setupArgumentsForVarargsInvocation(c.getParameterTypes(), arguments);
|
||||
}
|
||||
try {
|
||||
if (!c.isAccessible()) {
|
||||
c.setAccessible(true);
|
||||
}
|
||||
return c.newInstance(arguments);
|
||||
} catch (IllegalArgumentException e) {
|
||||
throw new AccessException("Problem invoking constructor on '" + c + "' : " + e.getMessage(), e);
|
||||
} catch (InstantiationException e) {
|
||||
throw new AccessException("Problem invoking constructor on '" + c + "' : " + e.getMessage(), e);
|
||||
} catch (IllegalAccessException e) {
|
||||
throw new AccessException("Problem invoking constructor on '" + c + "' : " + e.getMessage(), e);
|
||||
} catch (InvocationTargetException e) {
|
||||
throw new AccessException("Problem invoking constructor on '" + c + "' : " + e.getMessage(), e);
|
||||
}
|
||||
}
|
||||
}
|
|
@ -1,66 +0,0 @@
|
|||
/*
|
||||
* Copyright 2004-2008 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
|
||||
*
|
||||
* 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.springframework.expression.spel.reflection;
|
||||
|
||||
import org.springframework.expression.AccessException;
|
||||
import org.springframework.expression.ConstructorExecutor;
|
||||
import org.springframework.expression.ConstructorResolver;
|
||||
import org.springframework.expression.EvaluationContext;
|
||||
import org.springframework.expression.EvaluationException;
|
||||
import org.springframework.expression.spel.reflection.ReflectionUtils.DiscoveredConstructor;
|
||||
|
||||
/**
|
||||
* A constructor resolver that uses reflection to locate the constructor that should be invoked
|
||||
*
|
||||
* @author Andy Clement
|
||||
*/
|
||||
public class ReflectionConstructorResolver implements ConstructorResolver {
|
||||
|
||||
/*
|
||||
* Indicates if this resolve will allow matches to be found that require some of the input arguments to be
|
||||
* transformed by the conversion service.
|
||||
*/
|
||||
private boolean allowMatchesRequiringArgumentConversion = true;
|
||||
|
||||
public ReflectionConstructorResolver() {
|
||||
}
|
||||
|
||||
public ReflectionConstructorResolver(boolean allowMatchesRequiringArgumentConversion) {
|
||||
this.allowMatchesRequiringArgumentConversion = allowMatchesRequiringArgumentConversion;
|
||||
}
|
||||
|
||||
public void setAllowMatchRequiringArgumentConversion(boolean allow) {
|
||||
this.allowMatchesRequiringArgumentConversion = allow;
|
||||
}
|
||||
|
||||
/**
|
||||
* Locate a matching constructor or return null if non can be found.
|
||||
*/
|
||||
public ConstructorExecutor resolve(EvaluationContext context, String typename, Class<?>[] argumentTypes)
|
||||
throws AccessException {
|
||||
try {
|
||||
Class<?> c = context.getTypeUtils().getTypeLocator().findType(typename);
|
||||
DiscoveredConstructor dCtor = ReflectionUtils.findConstructor(context.getTypeUtils().getTypeConverter(), c,
|
||||
argumentTypes, allowMatchesRequiringArgumentConversion);
|
||||
if (dCtor == null) {
|
||||
return null;
|
||||
}
|
||||
return new ReflectionConstructorExecutor(dCtor.theConstructor, dCtor.argumentsRequiringConversion);
|
||||
} catch (EvaluationException e) {
|
||||
throw new AccessException(null,e);
|
||||
}
|
||||
}
|
||||
}
|
|
@ -1,70 +0,0 @@
|
|||
/*
|
||||
* Copyright 2004-2008 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
|
||||
*
|
||||
* 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.springframework.expression.spel.reflection;
|
||||
|
||||
import java.lang.reflect.InvocationTargetException;
|
||||
import java.lang.reflect.Method;
|
||||
|
||||
import org.springframework.expression.AccessException;
|
||||
import org.springframework.expression.EvaluationContext;
|
||||
import org.springframework.expression.EvaluationException;
|
||||
import org.springframework.expression.MethodExecutor;
|
||||
|
||||
public class ReflectionMethodExecutor implements MethodExecutor {
|
||||
|
||||
private final Method m;
|
||||
|
||||
// When the method was found, we will have determined if arguments need to be converted for it
|
||||
// to be invoked. Conversion won't be cheap so let's only do it if necessary.
|
||||
private final Integer[] argsRequiringConversion;
|
||||
|
||||
public ReflectionMethodExecutor(Method theMethod, Integer[] argumentsRequiringConversion) {
|
||||
m = theMethod;
|
||||
argsRequiringConversion = argumentsRequiringConversion;
|
||||
}
|
||||
|
||||
public Object execute(EvaluationContext context, Object target, Object... arguments) throws AccessException {
|
||||
if (argsRequiringConversion != null && arguments != null) {
|
||||
try {
|
||||
ReflectionUtils.convertArguments(m.getParameterTypes(), m.isVarArgs(), context.getTypeUtils()
|
||||
.getTypeConverter(), argsRequiringConversion, arguments);
|
||||
} catch (EvaluationException ex) {
|
||||
throw new AccessException("Problem invoking method '" + m.getName() + "' on '" + target.getClass()
|
||||
+ "': " + ex.getMessage(), ex);
|
||||
}
|
||||
}
|
||||
if (m.isVarArgs()) {
|
||||
arguments = ReflectionUtils.setupArgumentsForVarargsInvocation(m.getParameterTypes(), arguments);
|
||||
}
|
||||
try {
|
||||
if (!m.isAccessible()) {
|
||||
m.setAccessible(true);
|
||||
}
|
||||
return m.invoke(target, arguments);
|
||||
} catch (IllegalArgumentException e) {
|
||||
throw new AccessException("Problem invoking method '" + m.getName() + "' on '" + target.getClass() + "': "
|
||||
+ e.getMessage(), e);
|
||||
} catch (IllegalAccessException e) {
|
||||
throw new AccessException("Problem invoking method '" + m.getName() + "' on '" + target.getClass() + "': "
|
||||
+ e.getMessage(), e);
|
||||
} catch (InvocationTargetException e) {
|
||||
e.getCause().printStackTrace();
|
||||
throw new AccessException("Problem invoking method '" + m.getName() + "' on '" + target.getClass() + "': "
|
||||
+ e.getMessage(), e);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
|
@ -1,63 +0,0 @@
|
|||
/*
|
||||
* Copyright 2004-2008 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
|
||||
*
|
||||
* 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.springframework.expression.spel.reflection;
|
||||
|
||||
import org.springframework.expression.AccessException;
|
||||
import org.springframework.expression.EvaluationContext;
|
||||
import org.springframework.expression.EvaluationException;
|
||||
import org.springframework.expression.MethodExecutor;
|
||||
import org.springframework.expression.MethodResolver;
|
||||
import org.springframework.expression.spel.reflection.ReflectionUtils.DiscoveredMethod;
|
||||
|
||||
/**
|
||||
* A method resolver that uses reflection to locate the method that should be invoked
|
||||
*
|
||||
* @author Andy Clement
|
||||
*/
|
||||
public class ReflectionMethodResolver implements MethodResolver {
|
||||
|
||||
/*
|
||||
* Indicates if this resolve will allow matches to be found that require some of the input arguments to be
|
||||
* transformed by the conversion service.
|
||||
*/
|
||||
private boolean allowMatchesRequiringArgumentConversion = true;
|
||||
|
||||
public ReflectionMethodResolver() {
|
||||
}
|
||||
|
||||
public ReflectionMethodResolver(boolean allowMatchesRequiringArgumentConversion) {
|
||||
this.allowMatchesRequiringArgumentConversion = allowMatchesRequiringArgumentConversion;
|
||||
}
|
||||
|
||||
public void setAllowMatchRequiringArgumentConversion(boolean allow) {
|
||||
this.allowMatchesRequiringArgumentConversion = allow;
|
||||
}
|
||||
|
||||
public MethodExecutor resolve(EvaluationContext context, Object targetObject, String name, Class<?>[] argumentTypes) throws AccessException {
|
||||
try {
|
||||
Class<?> relevantClass = (targetObject instanceof Class ? (Class<?>) targetObject : targetObject.getClass());
|
||||
DiscoveredMethod dMethod = ReflectionUtils.findMethod(context.getTypeUtils().getTypeConverter(), name,
|
||||
argumentTypes, relevantClass, allowMatchesRequiringArgumentConversion);
|
||||
if (dMethod == null) {
|
||||
return null;
|
||||
}
|
||||
return new ReflectionMethodExecutor(dMethod.theMethod, dMethod.argumentsRequiringConversion);
|
||||
} catch (EvaluationException e) {
|
||||
throw new AccessException(null,e);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
|
@ -1,57 +0,0 @@
|
|||
package org.springframework.expression.spel.reflection;
|
||||
|
||||
import java.lang.reflect.Field;
|
||||
import java.lang.reflect.InvocationTargetException;
|
||||
import java.lang.reflect.Method;
|
||||
|
||||
import org.springframework.expression.AccessException;
|
||||
import org.springframework.expression.EvaluationContext;
|
||||
import org.springframework.expression.PropertyReaderExecutor;
|
||||
|
||||
public class ReflectionPropertyReaderExecutor implements PropertyReaderExecutor {
|
||||
|
||||
private Method methodToAccessProperty;
|
||||
private Field fieldToAccessProperty;
|
||||
private final String propertyName;
|
||||
|
||||
public ReflectionPropertyReaderExecutor(String propertyName, Method method) {
|
||||
this.propertyName = propertyName;
|
||||
methodToAccessProperty = method;
|
||||
}
|
||||
|
||||
public ReflectionPropertyReaderExecutor(String propertyName, Field field) {
|
||||
this.propertyName = propertyName;
|
||||
fieldToAccessProperty = field;
|
||||
}
|
||||
|
||||
public Object execute(EvaluationContext context, Object target) throws AccessException {
|
||||
if (methodToAccessProperty != null) {
|
||||
try {
|
||||
if (!methodToAccessProperty.isAccessible()) {
|
||||
methodToAccessProperty.setAccessible(true);
|
||||
}
|
||||
return methodToAccessProperty.invoke(target);
|
||||
} catch (IllegalArgumentException e) {
|
||||
throw new AccessException("Unable to access property '" + propertyName + "' through getter", e);
|
||||
} catch (IllegalAccessException e) {
|
||||
throw new AccessException("Unable to access property '" + propertyName + "' through getter", e);
|
||||
} catch (InvocationTargetException e) {
|
||||
throw new AccessException("Unable to access property '" + propertyName + "' through getter", e);
|
||||
}
|
||||
}
|
||||
if (fieldToAccessProperty != null) {
|
||||
try {
|
||||
if (!fieldToAccessProperty.isAccessible()) {
|
||||
fieldToAccessProperty.setAccessible(true);
|
||||
}
|
||||
return fieldToAccessProperty.get(target);
|
||||
} catch (IllegalArgumentException e) {
|
||||
throw new AccessException("Unable to access field: " + propertyName, e);
|
||||
} catch (IllegalAccessException e) {
|
||||
throw new AccessException("Unable to access field: " + propertyName, e);
|
||||
}
|
||||
}
|
||||
throw new AccessException("No method or field accessor found for property '" + propertyName + "'");
|
||||
}
|
||||
|
||||
}
|
|
@ -1,21 +0,0 @@
|
|||
package org.springframework.expression.spel.reflection;
|
||||
|
||||
import java.lang.reflect.Array;
|
||||
|
||||
import org.springframework.expression.AccessException;
|
||||
import org.springframework.expression.EvaluationContext;
|
||||
import org.springframework.expression.PropertyReaderExecutor;
|
||||
|
||||
public class ReflectionPropertyReaderExecutorForArrayLength implements PropertyReaderExecutor {
|
||||
|
||||
public ReflectionPropertyReaderExecutorForArrayLength() {
|
||||
}
|
||||
|
||||
public Object execute(EvaluationContext context, Object target) throws AccessException {
|
||||
if (target.getClass().isArray()) {
|
||||
return Array.getLength(target);
|
||||
}
|
||||
throw new AccessException("Cannot determine length of a non-array type '" + target.getClass() + "'");
|
||||
}
|
||||
|
||||
}
|
|
@ -1,223 +0,0 @@
|
|||
/*
|
||||
* Copyright 2004-2008 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
|
||||
*
|
||||
* 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.springframework.expression.spel.reflection;
|
||||
|
||||
import java.lang.reflect.Field;
|
||||
import java.lang.reflect.Method;
|
||||
|
||||
import org.springframework.expression.CacheablePropertyAccessor;
|
||||
import org.springframework.expression.EvaluationContext;
|
||||
import org.springframework.expression.PropertyReaderExecutor;
|
||||
import org.springframework.expression.PropertyWriterExecutor;
|
||||
|
||||
/**
|
||||
* Simple PropertyResolver that uses reflection to access properties for reading and writing. A property can be accessed
|
||||
* if it is accessible as a field on the object or through a getter (if being read) or a setter (if being written). This
|
||||
* implementation currently follows the Resolver/Executor model (it extends CacheablePropertyAccessor) - the code that
|
||||
* would be used if it were a simple property accessor is shown at the end.
|
||||
*
|
||||
* @author Andy Clement
|
||||
*/
|
||||
public class ReflectionPropertyResolver extends CacheablePropertyAccessor {
|
||||
|
||||
/**
|
||||
* @return null which means this is a general purpose accessor
|
||||
*/
|
||||
public Class<?>[] getSpecificTargetClasses() {
|
||||
return null;
|
||||
}
|
||||
|
||||
/**
|
||||
* Use reflection to discover if a named property is accessible on an target type and if it is return an executor
|
||||
* object that can be called repeatedly to retrieve that property. A property is accessible either as a field or
|
||||
* through a getter.
|
||||
*
|
||||
* @param context the context in which the access is being attempted
|
||||
* @param target the target object on which the property is being accessed
|
||||
* @param name the name of the property
|
||||
*/
|
||||
@Override
|
||||
public PropertyReaderExecutor getReaderAccessor(EvaluationContext context, Object target, Object name) {
|
||||
if (target == null) {
|
||||
return null;
|
||||
}
|
||||
Class<?> relevantClass = (target instanceof Class ? (Class<?>) target : target.getClass());
|
||||
if (!(name instanceof String)) {
|
||||
// A property not found exception will occur if the reflection finder was supposed to find it
|
||||
return null;
|
||||
}
|
||||
String propertyName = (String) name;
|
||||
if (relevantClass.isArray() && propertyName.equals("length")) {
|
||||
return new ReflectionPropertyReaderExecutorForArrayLength();
|
||||
}
|
||||
Method m = ReflectionUtils.findGetterForProperty(propertyName, relevantClass, target instanceof Class);
|
||||
if (m != null) {
|
||||
return new ReflectionPropertyReaderExecutor(propertyName, m);
|
||||
}
|
||||
Field field = ReflectionUtils.findField(propertyName, relevantClass, target instanceof Class);
|
||||
if (field != null) {
|
||||
return new ReflectionPropertyReaderExecutor(propertyName, field);
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
/**
|
||||
* Use reflection to discover if a named property is accessible on an target type and if it is return an executor
|
||||
* object that can be called repeatedly to set that property. A property is writable either as a field or through a
|
||||
* setter.
|
||||
*
|
||||
* @param context the context in which the set is being attempted
|
||||
* @param target the target object on which the property is being set
|
||||
* @param name the name of the property
|
||||
*/
|
||||
@Override
|
||||
public PropertyWriterExecutor getWriterAccessor(EvaluationContext context, Object target, Object name) {
|
||||
if (target == null) {
|
||||
return null;
|
||||
}
|
||||
Class<?> relevantClass = (target instanceof Class ? (Class<?>) target : target.getClass());
|
||||
if (!(name instanceof String)) {
|
||||
// A property not found exception will occur if the reflection finder was supposed to find it
|
||||
return null;
|
||||
}
|
||||
Method m = ReflectionUtils.findSetterForProperty((String) name, relevantClass, target instanceof Class);
|
||||
if (m != null) {
|
||||
return new ReflectionPropertyWriterExecutor((String) name, m);
|
||||
}
|
||||
Field field = ReflectionUtils.findField((String) name, relevantClass, target instanceof Class);
|
||||
if (field != null) {
|
||||
return new ReflectionPropertyWriterExecutor((String) name, field);
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
// /**
|
||||
// * Return true if the resolver is able to read the specified property from the specified target.
|
||||
// */
|
||||
// public boolean canRead(EvaluationContext relatedContext, Object target, Object name) throws AccessException {
|
||||
// if (target==null) {
|
||||
// return false;
|
||||
// }
|
||||
// Class<?> relevantClass = (target instanceof Class ? (Class<?>) target : target.getClass());
|
||||
// if (!(name instanceof String)) {
|
||||
// return false;
|
||||
// }
|
||||
// String propertyName = (String) name;
|
||||
// Field field = ReflectionUtils.findField(propertyName, relevantClass);
|
||||
// if (field != null) {
|
||||
// return true;
|
||||
// }
|
||||
// Method m = ReflectionUtils.findGetterForProperty(propertyName, relevantClass);
|
||||
// if (m != null) {
|
||||
// return true;
|
||||
// }
|
||||
// return false;
|
||||
// }
|
||||
//
|
||||
// /**
|
||||
// * Read the specified property from the specified target. //
|
||||
// */
|
||||
// public Object read(EvaluationContext context, Object target, Object name) throws AccessException {
|
||||
// if (target==null) {
|
||||
// return null;
|
||||
// }
|
||||
// Class<?> relevantClass = (target instanceof Class ? (Class<?>) target : target.getClass());
|
||||
// if (!(name instanceof String)) {
|
||||
// return null;
|
||||
// }
|
||||
// String propertyName = (String) name;
|
||||
// Field field = ReflectionUtils.findField(propertyName, relevantClass);
|
||||
// if (field != null) {
|
||||
// try {
|
||||
// if (!field.isAccessible()) {
|
||||
// field.setAccessible(true);
|
||||
// }
|
||||
// return field.get(target);
|
||||
// } catch (IllegalArgumentException e) {
|
||||
// throw new AccessException("Unable to access field: " + name, e);
|
||||
// } catch (IllegalAccessException e) {
|
||||
// throw new AccessException("Unable to access field: " + name, e);
|
||||
// }
|
||||
// }
|
||||
// Method m = ReflectionUtils.findGetterForProperty(propertyName, relevantClass);
|
||||
// if (m != null) {
|
||||
// try {
|
||||
// if (!m.isAccessible())
|
||||
// m.setAccessible(true);
|
||||
// return m.invoke(target);
|
||||
// } catch (IllegalArgumentException e) {
|
||||
// throw new AccessException("Unable to access property '" + name + "' through getter", e);
|
||||
// } catch (IllegalAccessException e) {
|
||||
// throw new AccessException("Unable to access property '" + name + "' through getter", e);
|
||||
// } catch (InvocationTargetException e) {
|
||||
// throw new AccessException("Unable to access property '" + name + "' through getter", e);
|
||||
// }
|
||||
// }
|
||||
// return null;
|
||||
// }
|
||||
// public void write(EvaluationContext context, Object target, Object name, Object newValue) throws AccessException
|
||||
// {
|
||||
// if (target==null) {
|
||||
// return;
|
||||
// }
|
||||
// Class<?> relevantClass = (target instanceof Class ? (Class<?>) target : target.getClass());
|
||||
// if (!(name instanceof String))
|
||||
// return;
|
||||
// Field field = ReflectionUtils.findField((String) name, relevantClass);
|
||||
// if (field != null) {
|
||||
// try {
|
||||
// if (!field.isAccessible())
|
||||
// field.setAccessible(true);
|
||||
// field.set(target, newValue);
|
||||
// } catch (IllegalArgumentException e) {
|
||||
// throw new AccessException("Unable to write to property '" + name + "'", e);
|
||||
// } catch (IllegalAccessException e) {
|
||||
// throw new AccessException("Unable to write to property '" + name + "'", e);
|
||||
// }
|
||||
// }
|
||||
// Method m = ReflectionUtils.findSetterForProperty((String) name, relevantClass);
|
||||
// if (m != null) {
|
||||
// try {
|
||||
// if (!m.isAccessible())
|
||||
// m.setAccessible(true);
|
||||
// m.invoke(target, newValue);
|
||||
// } catch (IllegalArgumentException e) {
|
||||
// throw new AccessException("Unable to access property '" + name + "' through setter", e);
|
||||
// } catch (IllegalAccessException e) {
|
||||
// throw new AccessException("Unable to access property '" + name + "' through setter", e);
|
||||
// } catch (InvocationTargetException e) {
|
||||
// throw new AccessException("Unable to access property '" + name + "' through setter", e);
|
||||
// }
|
||||
// }
|
||||
// }
|
||||
//
|
||||
//
|
||||
// public boolean canWrite(EvaluationContext context, Object target, Object name) throws AccessException {
|
||||
// if (target==null) {
|
||||
// return false;
|
||||
// }
|
||||
// Class<?> relevantClass = (target instanceof Class ? (Class<?>) target : target.getClass());
|
||||
// if (!(name instanceof String))
|
||||
// return false;
|
||||
// Field field = ReflectionUtils.findField((String) name, relevantClass);
|
||||
// if (field != null)
|
||||
// return true;
|
||||
// Method m = ReflectionUtils.findSetterForProperty((String) name, relevantClass);
|
||||
// if (m != null)
|
||||
// return true;
|
||||
// return false;
|
||||
// }
|
||||
}
|
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in New Issue