├── src ├── main │ ├── resources │ │ └── META-INF │ │ │ └── services │ │ │ └── jakarta.el.ExpressionFactory │ └── java │ │ ├── org │ │ └── glassfish │ │ │ └── expressly │ │ │ ├── stream │ │ │ ├── Operator.java │ │ │ ├── Optional.java │ │ │ └── StreamELResolver.java │ │ │ ├── parser │ │ │ ├── AstMapEntry.java │ │ │ ├── NodeVisitor.java │ │ │ ├── AstAssign.java │ │ │ ├── AstConcat.java │ │ │ ├── AstTrue.java │ │ │ ├── AstFalse.java │ │ │ ├── AstDotSuffix.java │ │ │ ├── AstLambdaParameters.java │ │ │ ├── AstBracketSuffix.java │ │ │ ├── AstListData.java │ │ │ ├── BooleanNode.java │ │ │ ├── ArithmeticNode.java │ │ │ ├── AstEqual.java │ │ │ ├── AstNotEqual.java │ │ │ ├── AstDiv.java │ │ │ ├── AstNull.java │ │ │ ├── AstMod.java │ │ │ ├── AstMinus.java │ │ │ ├── AstMult.java │ │ │ ├── AstSemiColon.java │ │ │ ├── AstAnd.java │ │ │ ├── AstPlus.java │ │ │ ├── AstOr.java │ │ │ ├── AstNot.java │ │ │ ├── AstLessThan.java │ │ │ ├── AstGreaterThan.java │ │ │ ├── AstLessThanEqual.java │ │ │ ├── AstGreaterThanEqual.java │ │ │ ├── AstMethodArguments.java │ │ │ ├── AstDynamicExpression.java │ │ │ ├── AstDeferredExpression.java │ │ │ ├── AstInteger.java │ │ │ ├── AstFloatingPoint.java │ │ │ ├── AstCompositeExpression.java │ │ │ ├── AstMapData.java │ │ │ ├── AstEmpty.java │ │ │ ├── AstLiteralExpression.java │ │ │ ├── AstLambdaExpression.java │ │ │ ├── AstString.java │ │ │ ├── AstChoice.java │ │ │ ├── AstNegative.java │ │ │ ├── Node.java │ │ │ ├── ELParserTreeConstants.java │ │ │ ├── Token.java │ │ │ ├── JJTELParserState.java │ │ │ ├── TokenMgrError.java │ │ │ ├── ELParserConstants.java │ │ │ ├── SimpleNode.java │ │ │ └── AstFunction.java │ │ │ ├── lang │ │ │ ├── FunctionMapperFactory.java │ │ │ ├── VariableMapperImpl.java │ │ │ ├── VariableMapperFactory.java │ │ │ ├── EvaluationContext.java │ │ │ └── FunctionMapperImpl.java │ │ │ ├── util │ │ │ └── MessageFactory.java │ │ │ ├── Messages.properties │ │ │ ├── MethodExpressionLiteral.java │ │ │ ├── ValueExpressionLiteral.java │ │ │ └── ExpressionFactoryImpl.java │ │ └── com │ │ └── sun │ │ └── el │ │ └── ExpressionFactoryImpl.java └── test │ └── java │ ├── jakarta │ └── el │ │ ├── package-info.java │ │ └── DefaultMethodTest.java │ └── org │ └── glassfish │ └── el │ └── test │ ├── Date.java │ ├── Order.java │ ├── Product.java │ ├── Customer.java │ ├── StaticRefTest.java │ ├── EscapingTest.java │ ├── DataBase.java │ ├── EvalListenerTest.java │ ├── ConvertTest.java │ ├── LambdaTest.java │ ├── ElasticityTest.java.sav │ ├── OperatorTest.java │ └── ELProcessorTest.java ├── .gitignore ├── README.md ├── exclude.xml ├── NOTICE.md └── CONTRIBUTING.md /src/main/resources/META-INF/services/jakarta.el.ExpressionFactory: -------------------------------------------------------------------------------- 1 | org.glassfish.expressly.ExpressionFactoryImpl -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | *.class 2 | .classpath 3 | .project 4 | 5 | # Mobile Tools for Java (J2ME) 6 | .mtj.tmp/ 7 | 8 | # Package Files # 9 | *.jar 10 | *.war 11 | *.ear 12 | 13 | # virtual machine crash logs, see http://www.java.com/en/download/help/error_hotspot.xml 14 | hs_err_pid* 15 | 16 | .idea 17 | *.iml 18 | target 19 | 20 | # emacs 21 | *~ 22 | 23 | *.class 24 | *.jar 25 | target/ 26 | /bin/ 27 | /dist/ 28 | .settings/ 29 | /**/.classpath 30 | /**/.project 31 | 32 | /.project 33 | nb-configuration.xml 34 | 35 | # mac 36 | .DS_Store 37 | 38 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # Eclipse Expressly 2 | 3 | 4 | Eclipse Expressly implements [Jakarta Expression Language](https://jakarta.ee/specifications/expression-language/6.0/), an expression language for Java applications. 5 | 6 | This project contains the Eclipse implementation. For the API see https://github.com/jakartaee/expression-language 7 | 8 | 9 | Building 10 | -------- 11 | 12 | Expressly can be built by executing the following from the project root: 13 | 14 | ``mvn clean package`` 15 | 16 | Expressly requires JDK 17 and Maven 3.6.0 to be build. 17 | 18 | 19 | ## Making Changes 20 | 21 | To make changes, fork this repository, make your changes, and submit a pull request. 22 | -------------------------------------------------------------------------------- /src/main/java/org/glassfish/expressly/stream/Operator.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2012, 2018 Oracle and/or its affiliates. All rights reserved. 3 | * 4 | * This program and the accompanying materials are made available under the 5 | * terms of the Eclipse Public License v. 2.0, which is available at 6 | * http://www.eclipse.org/legal/epl-2.0. 7 | * 8 | * This Source Code may also be made available under the following Secondary 9 | * Licenses when the conditions for such availability set forth in the 10 | * Eclipse Public License v. 2.0 are satisfied: GNU General Public License, 11 | * version 2 with the GNU Classpath Exception, which is available at 12 | * https://www.gnu.org/software/classpath/license.html. 13 | * 14 | * SPDX-License-Identifier: EPL-2.0 OR GPL-2.0 WITH Classpath-exception-2.0 15 | */ 16 | 17 | package org.glassfish.expressly.stream; 18 | 19 | import java.util.Iterator; 20 | 21 | interface Operator { 22 | 23 | Iterator iterator(Iterator upstream); 24 | } 25 | -------------------------------------------------------------------------------- /src/main/java/org/glassfish/expressly/parser/AstMapEntry.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2012, 2018 Oracle and/or its affiliates. All rights reserved. 3 | * 4 | * This program and the accompanying materials are made available under the 5 | * terms of the Eclipse Public License v. 2.0, which is available at 6 | * http://www.eclipse.org/legal/epl-2.0. 7 | * 8 | * This Source Code may also be made available under the following Secondary 9 | * Licenses when the conditions for such availability set forth in the 10 | * Eclipse Public License v. 2.0 are satisfied: GNU General Public License, 11 | * version 2 with the GNU Classpath Exception, which is available at 12 | * https://www.gnu.org/software/classpath/license.html. 13 | * 14 | * SPDX-License-Identifier: EPL-2.0 OR GPL-2.0 WITH Classpath-exception-2.0 15 | */ 16 | 17 | package org.glassfish.expressly.parser; 18 | 19 | /** 20 | * @author Kin-man Chung 21 | */ 22 | public class AstMapEntry extends SimpleNode { 23 | public AstMapEntry(int id) { 24 | super(id); 25 | } 26 | } 27 | -------------------------------------------------------------------------------- /src/main/java/org/glassfish/expressly/parser/NodeVisitor.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 1997, 2018 Oracle and/or its affiliates. All rights reserved. 3 | * 4 | * This program and the accompanying materials are made available under the 5 | * terms of the Eclipse Public License v. 2.0, which is available at 6 | * http://www.eclipse.org/legal/epl-2.0. 7 | * 8 | * This Source Code may also be made available under the following Secondary 9 | * Licenses when the conditions for such availability set forth in the 10 | * Eclipse Public License v. 2.0 are satisfied: GNU General Public License, 11 | * version 2 with the GNU Classpath Exception, which is available at 12 | * https://www.gnu.org/software/classpath/license.html. 13 | * 14 | * SPDX-License-Identifier: EPL-2.0 OR GPL-2.0 WITH Classpath-exception-2.0 15 | */ 16 | 17 | package org.glassfish.expressly.parser; 18 | 19 | import jakarta.el.ELException; 20 | 21 | /** 22 | * @author Jacob Hookom [jacob@hookom.net] 23 | * @version $Change: 181177 $$DateTime: 2001/06/26 08:45:09 $$Author: kchung $ 24 | */ 25 | public interface NodeVisitor { 26 | void visit(Node node) throws ELException; 27 | } 28 | -------------------------------------------------------------------------------- /src/test/java/jakarta/el/package-info.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2021 Contributors to the Eclipse Foundation. 3 | * 4 | * This program and the accompanying materials are made available under the 5 | * terms of the Eclipse Public License v. 2.0, which is available at 6 | * http://www.eclipse.org/legal/epl-2.0. 7 | * 8 | * This Source Code may also be made available under the following Secondary 9 | * Licenses when the conditions for such availability set forth in the 10 | * Eclipse Public License v. 2.0 are satisfied: GNU General Public License, 11 | * version 2 with the GNU Classpath Exception, which is available at 12 | * https://www.gnu.org/software/classpath/license.html. 13 | * 14 | * SPDX-License-Identifier: EPL-2.0 OR GPL-2.0 WITH Classpath-exception-2.0 15 | */ 16 | 17 | /** 18 | * This package provides tests targeted primarily at the API but that need the 19 | * plumbing provided by the implementation. While these tests could be placed in 20 | * a separate module that depends on the API and the implementation they are 21 | * currently located here as they do provide a degree of testing the the 22 | * implementation as well. 23 | */ 24 | package jakarta.el; -------------------------------------------------------------------------------- /src/main/java/com/sun/el/ExpressionFactoryImpl.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 1997, 2021 Oracle and/or its affiliates and others. 3 | * All rights reserved. 4 | * 5 | * This program and the accompanying materials are made available under the 6 | * terms of the Eclipse Public License v. 2.0, which is available at 7 | * http://www.eclipse.org/legal/epl-2.0. 8 | * 9 | * This Source Code may also be made available under the following Secondary 10 | * Licenses when the conditions for such availability set forth in the 11 | * Eclipse Public License v. 2.0 are satisfied: GNU General Public License, 12 | * version 2 with the GNU Classpath Exception, which is available at 13 | * https://www.gnu.org/software/classpath/license.html. 14 | * 15 | * SPDX-License-Identifier: EPL-2.0 OR GPL-2.0 WITH Classpath-exception-2.0 16 | */ 17 | package com.sun.el; 18 | 19 | import java.util.Properties; 20 | 21 | public class ExpressionFactoryImpl extends org.glassfish.expressly.ExpressionFactoryImpl { 22 | 23 | public ExpressionFactoryImpl() { 24 | super(); 25 | } 26 | 27 | public ExpressionFactoryImpl(Properties properties) { 28 | super(properties); 29 | } 30 | } 31 | -------------------------------------------------------------------------------- /src/test/java/org/glassfish/el/test/Date.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2018 Oracle and/or its affiliates. All rights reserved. 3 | * 4 | * This program and the accompanying materials are made available under the 5 | * terms of the Eclipse Public License v. 2.0, which is available at 6 | * http://www.eclipse.org/legal/epl-2.0. 7 | * 8 | * This Source Code may also be made available under the following Secondary 9 | * Licenses when the conditions for such availability set forth in the 10 | * Eclipse Public License v. 2.0 are satisfied: GNU General Public License, 11 | * version 2 with the GNU Classpath Exception, which is available at 12 | * https://www.gnu.org/software/classpath/license.html. 13 | * 14 | * SPDX-License-Identifier: EPL-2.0 OR GPL-2.0 WITH Classpath-exception-2.0 15 | */ 16 | 17 | package org.glassfish.el.test; 18 | 19 | public class Date { 20 | int year, month, date; 21 | 22 | public Date(int year, int month, int date) { 23 | this.year = year; 24 | this.month = month; 25 | this.date = date; 26 | } 27 | 28 | public int getYear() { return year; } 29 | public int getMonth() { return month; } 30 | public int getDate() { return date; } 31 | 32 | @Override 33 | public String toString() { 34 | return "" + month + "/" + date + "/" + year; 35 | } 36 | } 37 | -------------------------------------------------------------------------------- /src/main/java/org/glassfish/expressly/parser/AstAssign.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 1997, 2018 Oracle and/or its affiliates. All rights reserved. 3 | * 4 | * This program and the accompanying materials are made available under the 5 | * terms of the Eclipse Public License v. 2.0, which is available at 6 | * http://www.eclipse.org/legal/epl-2.0. 7 | * 8 | * This Source Code may also be made available under the following Secondary 9 | * Licenses when the conditions for such availability set forth in the 10 | * Eclipse Public License v. 2.0 are satisfied: GNU General Public License, 11 | * version 2 with the GNU Classpath Exception, which is available at 12 | * https://www.gnu.org/software/classpath/license.html. 13 | * 14 | * SPDX-License-Identifier: EPL-2.0 OR GPL-2.0 WITH Classpath-exception-2.0 15 | */ 16 | 17 | package org.glassfish.expressly.parser; 18 | 19 | import org.glassfish.expressly.lang.EvaluationContext; 20 | 21 | import jakarta.el.ELException; 22 | 23 | public class AstAssign extends SimpleNode { 24 | public AstAssign(int id) { 25 | super(id); 26 | } 27 | 28 | @Override 29 | public Object getValue(EvaluationContext ctx) throws ELException { 30 | 31 | Object value = children[1].getValue(ctx); 32 | children[0].setValue(ctx, value); 33 | return value; 34 | } 35 | } 36 | -------------------------------------------------------------------------------- /src/main/java/org/glassfish/expressly/parser/AstConcat.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2012, 2018 Oracle and/or its affiliates. All rights reserved. 3 | * 4 | * This program and the accompanying materials are made available under the 5 | * terms of the Eclipse Public License v. 2.0, which is available at 6 | * http://www.eclipse.org/legal/epl-2.0. 7 | * 8 | * This Source Code may also be made available under the following Secondary 9 | * Licenses when the conditions for such availability set forth in the 10 | * Eclipse Public License v. 2.0 are satisfied: GNU General Public License, 11 | * version 2 with the GNU Classpath Exception, which is available at 12 | * https://www.gnu.org/software/classpath/license.html. 13 | * 14 | * SPDX-License-Identifier: EPL-2.0 OR GPL-2.0 WITH Classpath-exception-2.0 15 | */ 16 | 17 | package org.glassfish.expressly.parser; 18 | 19 | import org.glassfish.expressly.lang.EvaluationContext; 20 | 21 | import jakarta.el.ELException; 22 | 23 | /** 24 | * @author Kin-man Chung 25 | */ 26 | public final class AstConcat extends SimpleNode { 27 | public AstConcat(int id) { 28 | super(id); 29 | } 30 | 31 | @Override 32 | public Object getValue(EvaluationContext ctx) throws ELException { 33 | return children[0].getValue(ctx).toString() + children[1].getValue(ctx).toString(); 34 | } 35 | } 36 | -------------------------------------------------------------------------------- /exclude.xml: -------------------------------------------------------------------------------- 1 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | 30 | 31 | 32 | 33 | 34 | 35 | 36 | -------------------------------------------------------------------------------- /src/main/java/org/glassfish/expressly/parser/AstTrue.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 1997, 2018 Oracle and/or its affiliates. All rights reserved. 3 | * 4 | * This program and the accompanying materials are made available under the 5 | * terms of the Eclipse Public License v. 2.0, which is available at 6 | * http://www.eclipse.org/legal/epl-2.0. 7 | * 8 | * This Source Code may also be made available under the following Secondary 9 | * Licenses when the conditions for such availability set forth in the 10 | * Eclipse Public License v. 2.0 are satisfied: GNU General Public License, 11 | * version 2 with the GNU Classpath Exception, which is available at 12 | * https://www.gnu.org/software/classpath/license.html. 13 | * 14 | * SPDX-License-Identifier: EPL-2.0 OR GPL-2.0 WITH Classpath-exception-2.0 15 | */ 16 | 17 | package org.glassfish.expressly.parser; 18 | 19 | import org.glassfish.expressly.lang.EvaluationContext; 20 | 21 | import jakarta.el.ELException; 22 | 23 | /** 24 | * @author Jacob Hookom [jacob@hookom.net] 25 | * @version $Change: 181177 $$DateTime: 2001/06/26 08:45:09 $$Author: kchung $ 26 | */ 27 | public final class AstTrue extends BooleanNode { 28 | public AstTrue(int id) { 29 | super(id); 30 | } 31 | 32 | @Override 33 | public Object getValue(EvaluationContext ctx) throws ELException { 34 | return Boolean.TRUE; 35 | } 36 | } 37 | -------------------------------------------------------------------------------- /src/main/java/org/glassfish/expressly/parser/AstFalse.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 1997, 2018 Oracle and/or its affiliates. All rights reserved. 3 | * 4 | * This program and the accompanying materials are made available under the 5 | * terms of the Eclipse Public License v. 2.0, which is available at 6 | * http://www.eclipse.org/legal/epl-2.0. 7 | * 8 | * This Source Code may also be made available under the following Secondary 9 | * Licenses when the conditions for such availability set forth in the 10 | * Eclipse Public License v. 2.0 are satisfied: GNU General Public License, 11 | * version 2 with the GNU Classpath Exception, which is available at 12 | * https://www.gnu.org/software/classpath/license.html. 13 | * 14 | * SPDX-License-Identifier: EPL-2.0 OR GPL-2.0 WITH Classpath-exception-2.0 15 | */ 16 | 17 | package org.glassfish.expressly.parser; 18 | 19 | import org.glassfish.expressly.lang.EvaluationContext; 20 | 21 | import jakarta.el.ELException; 22 | 23 | /** 24 | * @author Jacob Hookom [jacob@hookom.net] 25 | * @version $Change: 181177 $$DateTime: 2001/06/26 08:45:09 $$Author: kchung $ 26 | */ 27 | public final class AstFalse extends BooleanNode { 28 | public AstFalse(int id) { 29 | super(id); 30 | } 31 | 32 | @Override 33 | public Object getValue(EvaluationContext ctx) throws ELException { 34 | return Boolean.FALSE; 35 | } 36 | } 37 | -------------------------------------------------------------------------------- /src/main/java/org/glassfish/expressly/parser/AstDotSuffix.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 1997, 2018 Oracle and/or its affiliates. All rights reserved. 3 | * 4 | * This program and the accompanying materials are made available under the 5 | * terms of the Eclipse Public License v. 2.0, which is available at 6 | * http://www.eclipse.org/legal/epl-2.0. 7 | * 8 | * This Source Code may also be made available under the following Secondary 9 | * Licenses when the conditions for such availability set forth in the 10 | * Eclipse Public License v. 2.0 are satisfied: GNU General Public License, 11 | * version 2 with the GNU Classpath Exception, which is available at 12 | * https://www.gnu.org/software/classpath/license.html. 13 | * 14 | * SPDX-License-Identifier: EPL-2.0 OR GPL-2.0 WITH Classpath-exception-2.0 15 | */ 16 | 17 | package org.glassfish.expressly.parser; 18 | 19 | import org.glassfish.expressly.lang.EvaluationContext; 20 | 21 | import jakarta.el.ELException; 22 | 23 | /** 24 | * @author Jacob Hookom [jacob@hookom.net] 25 | * @version $Change: 181177 $$DateTime: 2001/06/26 08:45:09 $$Author: kchung $ 26 | */ 27 | public final class AstDotSuffix extends SimpleNode { 28 | public AstDotSuffix(int id) { 29 | super(id); 30 | } 31 | 32 | @Override 33 | public Object getValue(EvaluationContext ctx) throws ELException { 34 | return this.image; 35 | } 36 | } 37 | -------------------------------------------------------------------------------- /src/main/java/org/glassfish/expressly/parser/AstLambdaParameters.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2012, 2018 Oracle and/or its affiliates. All rights reserved. 3 | * 4 | * This program and the accompanying materials are made available under the 5 | * terms of the Eclipse Public License v. 2.0, which is available at 6 | * http://www.eclipse.org/legal/epl-2.0. 7 | * 8 | * This Source Code may also be made available under the following Secondary 9 | * Licenses when the conditions for such availability set forth in the 10 | * Eclipse Public License v. 2.0 are satisfied: GNU General Public License, 11 | * version 2 with the GNU Classpath Exception, which is available at 12 | * https://www.gnu.org/software/classpath/license.html. 13 | * 14 | * SPDX-License-Identifier: EPL-2.0 OR GPL-2.0 WITH Classpath-exception-2.0 15 | */ 16 | 17 | package org.glassfish.expressly.parser; 18 | 19 | import java.util.ArrayList; 20 | import java.util.List; 21 | 22 | /** 23 | * @author Kin-man Chung 24 | */ 25 | 26 | public class AstLambdaParameters extends SimpleNode { 27 | public AstLambdaParameters(int id) { 28 | super(id); 29 | } 30 | 31 | List getParameters() { 32 | List parameters = new ArrayList(); 33 | if (children != null) { 34 | for (Node child : children) { 35 | parameters.add(child.getImage()); 36 | } 37 | } 38 | return parameters; 39 | } 40 | } 41 | -------------------------------------------------------------------------------- /src/main/java/org/glassfish/expressly/parser/AstBracketSuffix.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 1997, 2018 Oracle and/or its affiliates. All rights reserved. 3 | * 4 | * This program and the accompanying materials are made available under the 5 | * terms of the Eclipse Public License v. 2.0, which is available at 6 | * http://www.eclipse.org/legal/epl-2.0. 7 | * 8 | * This Source Code may also be made available under the following Secondary 9 | * Licenses when the conditions for such availability set forth in the 10 | * Eclipse Public License v. 2.0 are satisfied: GNU General Public License, 11 | * version 2 with the GNU Classpath Exception, which is available at 12 | * https://www.gnu.org/software/classpath/license.html. 13 | * 14 | * SPDX-License-Identifier: EPL-2.0 OR GPL-2.0 WITH Classpath-exception-2.0 15 | */ 16 | 17 | package org.glassfish.expressly.parser; 18 | 19 | import org.glassfish.expressly.lang.EvaluationContext; 20 | 21 | import jakarta.el.ELException; 22 | 23 | /** 24 | * @author Jacob Hookom [jacob@hookom.net] 25 | * @author Kin-man Chung 26 | * @version $Change: 181177 $$DateTime: 2001/06/26 08:45:09 $$Author: kchung $ 27 | */ 28 | public final class AstBracketSuffix extends SimpleNode { 29 | public AstBracketSuffix(int id) { 30 | super(id); 31 | } 32 | 33 | @Override 34 | public Object getValue(EvaluationContext ctx) throws ELException { 35 | return this.children[0].getValue(ctx); 36 | } 37 | } 38 | -------------------------------------------------------------------------------- /src/main/java/org/glassfish/expressly/parser/AstListData.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2012, 2018 Oracle and/or its affiliates. All rights reserved. 3 | * 4 | * This program and the accompanying materials are made available under the 5 | * terms of the Eclipse Public License v. 2.0, which is available at 6 | * http://www.eclipse.org/legal/epl-2.0. 7 | * 8 | * This Source Code may also be made available under the following Secondary 9 | * Licenses when the conditions for such availability set forth in the 10 | * Eclipse Public License v. 2.0 are satisfied: GNU General Public License, 11 | * version 2 with the GNU Classpath Exception, which is available at 12 | * https://www.gnu.org/software/classpath/license.html. 13 | * 14 | * SPDX-License-Identifier: EPL-2.0 OR GPL-2.0 WITH Classpath-exception-2.0 15 | */ 16 | 17 | package org.glassfish.expressly.parser; 18 | 19 | import java.util.ArrayList; 20 | 21 | import org.glassfish.expressly.lang.EvaluationContext; 22 | 23 | /** 24 | * @author Kin-man Chung 25 | */ 26 | public class AstListData extends SimpleNode { 27 | public AstListData(int id) { 28 | super(id); 29 | } 30 | 31 | @Override 32 | public Object getValue(EvaluationContext ctx) { 33 | ArrayList list = new ArrayList(); 34 | int paramCount = this.jjtGetNumChildren(); 35 | for (int i = 0; i < paramCount; i++) { 36 | list.add(this.children[i].getValue(ctx)); 37 | } 38 | return list; 39 | } 40 | } 41 | -------------------------------------------------------------------------------- /src/main/java/org/glassfish/expressly/parser/BooleanNode.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2022, 2022 Contributors to the Eclipse Foundation. 3 | * Copyright (c) 1997, 2018 Oracle and/or its affiliates. All rights reserved. 4 | * 5 | * This program and the accompanying materials are made available under the 6 | * terms of the Eclipse Public License v. 2.0, which is available at 7 | * http://www.eclipse.org/legal/epl-2.0. 8 | * 9 | * This Source Code may also be made available under the following Secondary 10 | * Licenses when the conditions for such availability set forth in the 11 | * Eclipse Public License v. 2.0 are satisfied: GNU General Public License, 12 | * version 2 with the GNU Classpath Exception, which is available at 13 | * https://www.gnu.org/software/classpath/license.html. 14 | * 15 | * SPDX-License-Identifier: EPL-2.0 OR GPL-2.0 WITH Classpath-exception-2.0 16 | */ 17 | 18 | package org.glassfish.expressly.parser; 19 | 20 | import org.glassfish.expressly.lang.EvaluationContext; 21 | 22 | import jakarta.el.ELException; 23 | 24 | /** 25 | * @author Jacob Hookom [jacob@hookom.net] 26 | * @version $Change: 181177 $$DateTime: 2001/06/26 08:45:09 $$Author: kchung $ 27 | */ 28 | public class BooleanNode extends SimpleNode { 29 | /** 30 | * @param i 31 | */ 32 | public BooleanNode(int i) { 33 | super(i); 34 | } 35 | 36 | @Override 37 | public Class getType(EvaluationContext ctx) throws ELException { 38 | return Boolean.class; 39 | } 40 | } 41 | -------------------------------------------------------------------------------- /src/main/java/org/glassfish/expressly/parser/ArithmeticNode.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2022, 2022 Contributors to the Eclipse Foundation. 3 | * Copyright (c) 1997, 2018 Oracle and/or its affiliates. All rights reserved. 4 | * 5 | * This program and the accompanying materials are made available under the 6 | * terms of the Eclipse Public License v. 2.0, which is available at 7 | * http://www.eclipse.org/legal/epl-2.0. 8 | * 9 | * This Source Code may also be made available under the following Secondary 10 | * Licenses when the conditions for such availability set forth in the 11 | * Eclipse Public License v. 2.0 are satisfied: GNU General Public License, 12 | * version 2 with the GNU Classpath Exception, which is available at 13 | * https://www.gnu.org/software/classpath/license.html. 14 | * 15 | * SPDX-License-Identifier: EPL-2.0 OR GPL-2.0 WITH Classpath-exception-2.0 16 | */ 17 | 18 | package org.glassfish.expressly.parser; 19 | 20 | import org.glassfish.expressly.lang.EvaluationContext; 21 | 22 | import jakarta.el.ELException; 23 | 24 | /** 25 | * @author Jacob Hookom [jacob@hookom.net] 26 | * @version $Change: 181177 $$DateTime: 2001/06/26 08:45:09 $$Author: kchung $ 27 | */ 28 | public class ArithmeticNode extends SimpleNode { 29 | 30 | /** 31 | * @param i 32 | */ 33 | public ArithmeticNode(int i) { 34 | super(i); 35 | } 36 | 37 | @Override 38 | public Class getType(EvaluationContext ctx) throws ELException { 39 | return Number.class; 40 | } 41 | } 42 | -------------------------------------------------------------------------------- /src/main/java/org/glassfish/expressly/parser/AstEqual.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 1997, 2018 Oracle and/or its affiliates. All rights reserved. 3 | * 4 | * This program and the accompanying materials are made available under the 5 | * terms of the Eclipse Public License v. 2.0, which is available at 6 | * http://www.eclipse.org/legal/epl-2.0. 7 | * 8 | * This Source Code may also be made available under the following Secondary 9 | * Licenses when the conditions for such availability set forth in the 10 | * Eclipse Public License v. 2.0 are satisfied: GNU General Public License, 11 | * version 2 with the GNU Classpath Exception, which is available at 12 | * https://www.gnu.org/software/classpath/license.html. 13 | * 14 | * SPDX-License-Identifier: EPL-2.0 OR GPL-2.0 WITH Classpath-exception-2.0 15 | */ 16 | 17 | package org.glassfish.expressly.parser; 18 | 19 | import org.glassfish.expressly.lang.EvaluationContext; 20 | 21 | import jakarta.el.ELException; 22 | 23 | /** 24 | * @author Jacob Hookom [jacob@hookom.net] 25 | * @version $Change: 181177 $$DateTime: 2001/06/26 08:45:09 $$Author: kchung $ 26 | */ 27 | public final class AstEqual extends BooleanNode { 28 | public AstEqual(int id) { 29 | super(id); 30 | } 31 | 32 | @Override 33 | public Object getValue(EvaluationContext ctx) throws ELException { 34 | Object obj0 = this.children[0].getValue(ctx); 35 | Object obj1 = this.children[1].getValue(ctx); 36 | return Boolean.valueOf(equals(obj0, obj1)); 37 | } 38 | } 39 | -------------------------------------------------------------------------------- /src/main/java/org/glassfish/expressly/parser/AstNotEqual.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2022, 2022 Contributors to the Eclipse Foundation. 3 | * Copyright (c) 1997, 2018 Oracle and/or its affiliates. All rights reserved. 4 | * 5 | * This program and the accompanying materials are made available under the 6 | * terms of the Eclipse Public License v. 2.0, which is available at 7 | * http://www.eclipse.org/legal/epl-2.0. 8 | * 9 | * This Source Code may also be made available under the following Secondary 10 | * Licenses when the conditions for such availability set forth in the 11 | * Eclipse Public License v. 2.0 are satisfied: GNU General Public License, 12 | * version 2 with the GNU Classpath Exception, which is available at 13 | * https://www.gnu.org/software/classpath/license.html. 14 | * 15 | * SPDX-License-Identifier: EPL-2.0 OR GPL-2.0 WITH Classpath-exception-2.0 16 | */ 17 | 18 | package org.glassfish.expressly.parser; 19 | 20 | import org.glassfish.expressly.lang.EvaluationContext; 21 | 22 | import jakarta.el.ELException; 23 | 24 | /** 25 | * @author Jacob Hookom [jacob@hookom.net] 26 | * @version $Change: 181177 $$DateTime: 2001/06/26 08:45:09 $$Author: kchung $ 27 | */ 28 | public final class AstNotEqual extends BooleanNode { 29 | public AstNotEqual(int id) { 30 | super(id); 31 | } 32 | 33 | @Override 34 | public Object getValue(EvaluationContext ctx) throws ELException { 35 | return Boolean.valueOf(!equals( 36 | children[0].getValue(ctx), 37 | children[1].getValue(ctx))); 38 | } 39 | } 40 | -------------------------------------------------------------------------------- /src/main/java/org/glassfish/expressly/parser/AstDiv.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 1997, 2018 Oracle and/or its affiliates. All rights reserved. 3 | * 4 | * This program and the accompanying materials are made available under the 5 | * terms of the Eclipse Public License v. 2.0, which is available at 6 | * http://www.eclipse.org/legal/epl-2.0. 7 | * 8 | * This Source Code may also be made available under the following Secondary 9 | * Licenses when the conditions for such availability set forth in the 10 | * Eclipse Public License v. 2.0 are satisfied: GNU General Public License, 11 | * version 2 with the GNU Classpath Exception, which is available at 12 | * https://www.gnu.org/software/classpath/license.html. 13 | * 14 | * SPDX-License-Identifier: EPL-2.0 OR GPL-2.0 WITH Classpath-exception-2.0 15 | */ 16 | 17 | package org.glassfish.expressly.parser; 18 | 19 | import org.glassfish.expressly.lang.ELArithmetic; 20 | import org.glassfish.expressly.lang.EvaluationContext; 21 | 22 | import jakarta.el.ELException; 23 | 24 | /** 25 | * @author Jacob Hookom [jacob@hookom.net] 26 | * @version $Change: 181177 $$DateTime: 2001/06/26 08:45:09 $$Author: kchung $ 27 | */ 28 | public final class AstDiv extends ArithmeticNode { 29 | public AstDiv(int id) { 30 | super(id); 31 | } 32 | 33 | @Override 34 | public Object getValue(EvaluationContext ctx) throws ELException { 35 | Object obj0 = this.children[0].getValue(ctx); 36 | Object obj1 = this.children[1].getValue(ctx); 37 | return ELArithmetic.divide(obj0, obj1); 38 | } 39 | } 40 | -------------------------------------------------------------------------------- /src/main/java/org/glassfish/expressly/parser/AstNull.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2022, 2022 Contributors to the Eclipse Foundation. 3 | * Copyright (c) 1997, 2018 Oracle and/or its affiliates. All rights reserved. 4 | * 5 | * This program and the accompanying materials are made available under the 6 | * terms of the Eclipse Public License v. 2.0, which is available at 7 | * http://www.eclipse.org/legal/epl-2.0. 8 | * 9 | * This Source Code may also be made available under the following Secondary 10 | * Licenses when the conditions for such availability set forth in the 11 | * Eclipse Public License v. 2.0 are satisfied: GNU General Public License, 12 | * version 2 with the GNU Classpath Exception, which is available at 13 | * https://www.gnu.org/software/classpath/license.html. 14 | * 15 | * SPDX-License-Identifier: EPL-2.0 OR GPL-2.0 WITH Classpath-exception-2.0 16 | */ 17 | 18 | package org.glassfish.expressly.parser; 19 | 20 | import org.glassfish.expressly.lang.EvaluationContext; 21 | 22 | import jakarta.el.ELException; 23 | 24 | /** 25 | * @author Jacob Hookom [jacob@hookom.net] 26 | * @version $Change: 181177 $$DateTime: 2001/06/26 08:45:09 $$Author: kchung $ 27 | */ 28 | public final class AstNull extends SimpleNode { 29 | public AstNull(int id) { 30 | super(id); 31 | } 32 | 33 | @Override 34 | public Class getType(EvaluationContext ctx) throws ELException { 35 | return null; 36 | } 37 | 38 | @Override 39 | public Object getValue(EvaluationContext ctx) throws ELException { 40 | return null; 41 | } 42 | } 43 | -------------------------------------------------------------------------------- /src/main/java/org/glassfish/expressly/parser/AstMod.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2022, 2022 Contributors to the Eclipse Foundation. 3 | * Copyright (c) 1997, 2018 Oracle and/or its affiliates. All rights reserved. 4 | * 5 | * This program and the accompanying materials are made available under the 6 | * terms of the Eclipse Public License v. 2.0, which is available at 7 | * http://www.eclipse.org/legal/epl-2.0. 8 | * 9 | * This Source Code may also be made available under the following Secondary 10 | * Licenses when the conditions for such availability set forth in the 11 | * Eclipse Public License v. 2.0 are satisfied: GNU General Public License, 12 | * version 2 with the GNU Classpath Exception, which is available at 13 | * https://www.gnu.org/software/classpath/license.html. 14 | * 15 | * SPDX-License-Identifier: EPL-2.0 OR GPL-2.0 WITH Classpath-exception-2.0 16 | */ 17 | 18 | package org.glassfish.expressly.parser; 19 | 20 | import org.glassfish.expressly.lang.ELArithmetic; 21 | import org.glassfish.expressly.lang.EvaluationContext; 22 | 23 | import jakarta.el.ELException; 24 | 25 | /** 26 | * @author Jacob Hookom [jacob@hookom.net] 27 | * @version $Change: 181177 $$DateTime: 2001/06/26 08:45:09 $$Author: kchung $ 28 | */ 29 | public final class AstMod extends ArithmeticNode { 30 | public AstMod(int id) { 31 | super(id); 32 | } 33 | 34 | @Override 35 | public Object getValue(EvaluationContext ctx) throws ELException { 36 | return ELArithmetic.mod( 37 | children[0].getValue(ctx), 38 | children[1].getValue(ctx)); 39 | } 40 | } 41 | -------------------------------------------------------------------------------- /src/main/java/org/glassfish/expressly/parser/AstMinus.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2022, 2022 Contributors to the Eclipse Foundation. 3 | * Copyright (c) 1997, 2018 Oracle and/or its affiliates. All rights reserved. 4 | * 5 | * This program and the accompanying materials are made available under the 6 | * terms of the Eclipse Public License v. 2.0, which is available at 7 | * http://www.eclipse.org/legal/epl-2.0. 8 | * 9 | * This Source Code may also be made available under the following Secondary 10 | * Licenses when the conditions for such availability set forth in the 11 | * Eclipse Public License v. 2.0 are satisfied: GNU General Public License, 12 | * version 2 with the GNU Classpath Exception, which is available at 13 | * https://www.gnu.org/software/classpath/license.html. 14 | * 15 | * SPDX-License-Identifier: EPL-2.0 OR GPL-2.0 WITH Classpath-exception-2.0 16 | */ 17 | 18 | package org.glassfish.expressly.parser; 19 | 20 | import org.glassfish.expressly.lang.ELArithmetic; 21 | import org.glassfish.expressly.lang.EvaluationContext; 22 | 23 | import jakarta.el.ELException; 24 | 25 | /** 26 | * @author Jacob Hookom [jacob@hookom.net] 27 | * @version $Change: 181177 $$DateTime: 2001/06/26 08:45:09 $$Author: kchung $ 28 | */ 29 | public final class AstMinus extends ArithmeticNode { 30 | public AstMinus(int id) { 31 | super(id); 32 | } 33 | 34 | @Override 35 | public Object getValue(EvaluationContext ctx) throws ELException { 36 | return ELArithmetic.subtract( 37 | children[0].getValue(ctx), 38 | children[1].getValue(ctx)); 39 | } 40 | } 41 | -------------------------------------------------------------------------------- /src/main/java/org/glassfish/expressly/parser/AstMult.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2022, 2022 Contributors to the Eclipse Foundation. 3 | * Copyright (c) 1997, 2018 Oracle and/or its affiliates. All rights reserved. 4 | * 5 | * This program and the accompanying materials are made available under the 6 | * terms of the Eclipse Public License v. 2.0, which is available at 7 | * http://www.eclipse.org/legal/epl-2.0. 8 | * 9 | * This Source Code may also be made available under the following Secondary 10 | * Licenses when the conditions for such availability set forth in the 11 | * Eclipse Public License v. 2.0 are satisfied: GNU General Public License, 12 | * version 2 with the GNU Classpath Exception, which is available at 13 | * https://www.gnu.org/software/classpath/license.html. 14 | * 15 | * SPDX-License-Identifier: EPL-2.0 OR GPL-2.0 WITH Classpath-exception-2.0 16 | */ 17 | 18 | package org.glassfish.expressly.parser; 19 | 20 | import org.glassfish.expressly.lang.ELArithmetic; 21 | import org.glassfish.expressly.lang.EvaluationContext; 22 | 23 | import jakarta.el.ELException; 24 | 25 | /** 26 | * @author Jacob Hookom [jacob@hookom.net] 27 | * @version $Change: 181177 $$DateTime: 2001/06/26 08:45:09 $$Author: kchung $ 28 | */ 29 | public final class AstMult extends ArithmeticNode { 30 | public AstMult(int id) { 31 | super(id); 32 | } 33 | 34 | @Override 35 | public Object getValue(EvaluationContext ctx) throws ELException { 36 | return ELArithmetic.multiply( 37 | children[0].getValue(ctx), 38 | children[1].getValue(ctx)); 39 | } 40 | } 41 | -------------------------------------------------------------------------------- /src/main/java/org/glassfish/expressly/parser/AstSemiColon.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2022, 2022 Contributors to the Eclipse Foundation. 3 | * Copyright (c) 2012, 2018 Oracle and/or its affiliates. All rights reserved. 4 | * 5 | * This program and the accompanying materials are made available under the 6 | * terms of the Eclipse Public License v. 2.0, which is available at 7 | * http://www.eclipse.org/legal/epl-2.0. 8 | * 9 | * This Source Code may also be made available under the following Secondary 10 | * Licenses when the conditions for such availability set forth in the 11 | * Eclipse Public License v. 2.0 are satisfied: GNU General Public License, 12 | * version 2 with the GNU Classpath Exception, which is available at 13 | * https://www.gnu.org/software/classpath/license.html. 14 | * 15 | * SPDX-License-Identifier: EPL-2.0 OR GPL-2.0 WITH Classpath-exception-2.0 16 | */ 17 | 18 | package org.glassfish.expressly.parser; 19 | 20 | import org.glassfish.expressly.lang.EvaluationContext; 21 | 22 | import jakarta.el.ELException; 23 | 24 | /** 25 | * @author Kin-man Chung 26 | */ 27 | public class AstSemiColon extends SimpleNode { 28 | public AstSemiColon(int id) { 29 | super(id); 30 | } 31 | 32 | @Override 33 | public Object getValue(EvaluationContext ctx) throws ELException { 34 | children[0].getValue(ctx); 35 | return children[1].getValue(ctx); 36 | } 37 | 38 | @Override 39 | public void setValue(EvaluationContext ctx, Object value) throws ELException { 40 | children[0].getValue(ctx); 41 | children[1].setValue(ctx, value); 42 | } 43 | } 44 | -------------------------------------------------------------------------------- /src/main/java/org/glassfish/expressly/parser/AstAnd.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 1997, 2018 Oracle and/or its affiliates. All rights reserved. 3 | * 4 | * This program and the accompanying materials are made available under the 5 | * terms of the Eclipse Public License v. 2.0, which is available at 6 | * http://www.eclipse.org/legal/epl-2.0. 7 | * 8 | * This Source Code may also be made available under the following Secondary 9 | * Licenses when the conditions for such availability set forth in the 10 | * Eclipse Public License v. 2.0 are satisfied: GNU General Public License, 11 | * version 2 with the GNU Classpath Exception, which is available at 12 | * https://www.gnu.org/software/classpath/license.html. 13 | * 14 | * SPDX-License-Identifier: EPL-2.0 OR GPL-2.0 WITH Classpath-exception-2.0 15 | */ 16 | 17 | package org.glassfish.expressly.parser; 18 | 19 | import org.glassfish.expressly.lang.EvaluationContext; 20 | 21 | import jakarta.el.ELException; 22 | 23 | /** 24 | * @author Jacob Hookom [jacob@hookom.net] 25 | * @version $Change: 181177 $$DateTime: 2001/06/26 08:45:09 $$Author: kchung $ 26 | */ 27 | public final class AstAnd extends BooleanNode { 28 | public AstAnd(int id) { 29 | super(id); 30 | } 31 | 32 | @Override 33 | public Object getValue(EvaluationContext ctx) throws ELException { 34 | Object obj = children[0].getValue(ctx); 35 | Boolean b = coerceToBoolean(obj); 36 | if (!b.booleanValue()) { 37 | return b; 38 | } 39 | obj = children[1].getValue(ctx); 40 | b = coerceToBoolean(obj); 41 | return b; 42 | } 43 | } 44 | -------------------------------------------------------------------------------- /src/test/java/org/glassfish/el/test/Order.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2018 Oracle and/or its affiliates. All rights reserved. 3 | * 4 | * This program and the accompanying materials are made available under the 5 | * terms of the Eclipse Public License v. 2.0, which is available at 6 | * http://www.eclipse.org/legal/epl-2.0. 7 | * 8 | * This Source Code may also be made available under the following Secondary 9 | * Licenses when the conditions for such availability set forth in the 10 | * Eclipse Public License v. 2.0 are satisfied: GNU General Public License, 11 | * version 2 with the GNU Classpath Exception, which is available at 12 | * https://www.gnu.org/software/classpath/license.html. 13 | * 14 | * SPDX-License-Identifier: EPL-2.0 OR GPL-2.0 WITH Classpath-exception-2.0 15 | */ 16 | 17 | package org.glassfish.el.test; 18 | 19 | public class Order { 20 | 21 | int orderID; 22 | int customerID; 23 | Date orderDate; 24 | double total; 25 | 26 | public Order(int orderID, int customerID, Date orderDate, double total) { 27 | this.orderID = orderID; 28 | this.customerID = customerID; 29 | this.orderDate = orderDate; 30 | this.total = total; 31 | } 32 | 33 | @Override 34 | public String toString() { 35 | return "Order: " + orderID + ", " + customerID + 36 | ", " + orderDate.toString() + ", " + total; 37 | } 38 | 39 | public int getOrderID() { return orderID; } 40 | public int getCustomerID() { return customerID; } 41 | public Date getOrderDate() { return orderDate; } 42 | public double getTotal() { return total; } 43 | } 44 | -------------------------------------------------------------------------------- /src/main/java/org/glassfish/expressly/parser/AstPlus.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2022, 2022 Contributors to the Eclipse Foundation. 3 | * Copyright (c) 1997, 2018 Oracle and/or its affiliates. All rights reserved. 4 | * 5 | * This program and the accompanying materials are made available under the 6 | * terms of the Eclipse Public License v. 2.0, which is available at 7 | * http://www.eclipse.org/legal/epl-2.0. 8 | * 9 | * This Source Code may also be made available under the following Secondary 10 | * Licenses when the conditions for such availability set forth in the 11 | * Eclipse Public License v. 2.0 are satisfied: GNU General Public License, 12 | * version 2 with the GNU Classpath Exception, which is available at 13 | * https://www.gnu.org/software/classpath/license.html. 14 | * 15 | * SPDX-License-Identifier: EPL-2.0 OR GPL-2.0 WITH Classpath-exception-2.0 16 | */ 17 | 18 | package org.glassfish.expressly.parser; 19 | 20 | import org.glassfish.expressly.lang.ELArithmetic; 21 | import org.glassfish.expressly.lang.EvaluationContext; 22 | 23 | import jakarta.el.ELException; 24 | 25 | /** 26 | * @author Jacob Hookom [jacob@hookom.net] 27 | * @author Kin-man Chung 28 | * @version $Change: 181177 $$DateTime: 2001/06/26 08:45:09 $$Author: kchung $ 29 | */ 30 | public final class AstPlus extends ArithmeticNode { 31 | public AstPlus(int id) { 32 | super(id); 33 | } 34 | 35 | @Override 36 | public Object getValue(EvaluationContext ctx) throws ELException { 37 | return ELArithmetic.add( 38 | children[0].getValue(ctx), 39 | children[1].getValue(ctx)); 40 | } 41 | } 42 | -------------------------------------------------------------------------------- /src/main/java/org/glassfish/expressly/parser/AstOr.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2022, 2022 Contributors to the Eclipse Foundation. 3 | * Copyright (c) 1997, 2018 Oracle and/or its affiliates. All rights reserved. 4 | * 5 | * This program and the accompanying materials are made available under the 6 | * terms of the Eclipse Public License v. 2.0, which is available at 7 | * http://www.eclipse.org/legal/epl-2.0. 8 | * 9 | * This Source Code may also be made available under the following Secondary 10 | * Licenses when the conditions for such availability set forth in the 11 | * Eclipse Public License v. 2.0 are satisfied: GNU General Public License, 12 | * version 2 with the GNU Classpath Exception, which is available at 13 | * https://www.gnu.org/software/classpath/license.html. 14 | * 15 | * SPDX-License-Identifier: EPL-2.0 OR GPL-2.0 WITH Classpath-exception-2.0 16 | */ 17 | 18 | package org.glassfish.expressly.parser; 19 | 20 | import org.glassfish.expressly.lang.EvaluationContext; 21 | 22 | import jakarta.el.ELException; 23 | 24 | /** 25 | * @author Jacob Hookom [jacob@hookom.net] 26 | * @version $Change: 181177 $$DateTime: 2001/06/26 08:45:09 $$Author: kchung $ 27 | */ 28 | public final class AstOr extends BooleanNode { 29 | public AstOr(int id) { 30 | super(id); 31 | } 32 | 33 | @Override 34 | public Object getValue(EvaluationContext ctx) throws ELException { 35 | Boolean value = coerceToBoolean(children[0].getValue(ctx)); 36 | if (value.booleanValue()) { 37 | return value; 38 | } 39 | 40 | return coerceToBoolean(children[1].getValue(ctx)); 41 | } 42 | } 43 | -------------------------------------------------------------------------------- /src/main/java/org/glassfish/expressly/parser/AstNot.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2022, 2022 Contributors to the Eclipse Foundation. 3 | * Copyright (c) 1997, 2018 Oracle and/or its affiliates. All rights reserved. 4 | * 5 | * This program and the accompanying materials are made available under the 6 | * terms of the Eclipse Public License v. 2.0, which is available at 7 | * http://www.eclipse.org/legal/epl-2.0. 8 | * 9 | * This Source Code may also be made available under the following Secondary 10 | * Licenses when the conditions for such availability set forth in the 11 | * Eclipse Public License v. 2.0 are satisfied: GNU General Public License, 12 | * version 2 with the GNU Classpath Exception, which is available at 13 | * https://www.gnu.org/software/classpath/license.html. 14 | * 15 | * SPDX-License-Identifier: EPL-2.0 OR GPL-2.0 WITH Classpath-exception-2.0 16 | */ 17 | 18 | package org.glassfish.expressly.parser; 19 | 20 | import org.glassfish.expressly.lang.EvaluationContext; 21 | 22 | import jakarta.el.ELException; 23 | 24 | /** 25 | * @author Jacob Hookom [jacob@hookom.net] 26 | * @version $Change: 181177 $$DateTime: 2001/06/26 08:45:09 $$Author: kchung $ 27 | */ 28 | public final class AstNot extends SimpleNode { 29 | public AstNot(int id) { 30 | super(id); 31 | } 32 | 33 | @Override 34 | public Class getType(EvaluationContext ctx) throws ELException { 35 | return Boolean.class; 36 | } 37 | 38 | @Override 39 | public Object getValue(EvaluationContext ctx) throws ELException { 40 | return Boolean.valueOf(!coerceToBoolean( 41 | children[0].getValue(ctx)).booleanValue()); 42 | } 43 | } 44 | -------------------------------------------------------------------------------- /src/main/java/org/glassfish/expressly/parser/AstLessThan.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 1997, 2018 Oracle and/or its affiliates. All rights reserved. 3 | * 4 | * This program and the accompanying materials are made available under the 5 | * terms of the Eclipse Public License v. 2.0, which is available at 6 | * http://www.eclipse.org/legal/epl-2.0. 7 | * 8 | * This Source Code may also be made available under the following Secondary 9 | * Licenses when the conditions for such availability set forth in the 10 | * Eclipse Public License v. 2.0 are satisfied: GNU General Public License, 11 | * version 2 with the GNU Classpath Exception, which is available at 12 | * https://www.gnu.org/software/classpath/license.html. 13 | * 14 | * SPDX-License-Identifier: EPL-2.0 OR GPL-2.0 WITH Classpath-exception-2.0 15 | */ 16 | 17 | package org.glassfish.expressly.parser; 18 | 19 | import org.glassfish.expressly.lang.EvaluationContext; 20 | 21 | import jakarta.el.ELException; 22 | 23 | /** 24 | * @author Jacob Hookom [jacob@hookom.net] 25 | * @version $Change: 181177 $$DateTime: 2001/06/26 08:45:09 $$Author: kchung $ 26 | */ 27 | public final class AstLessThan extends BooleanNode { 28 | public AstLessThan(int id) { 29 | super(id); 30 | } 31 | 32 | @Override 33 | public Object getValue(EvaluationContext ctx) throws ELException { 34 | Object obj0 = this.children[0].getValue(ctx); 35 | if (obj0 == null) { 36 | return Boolean.FALSE; 37 | } 38 | Object obj1 = this.children[1].getValue(ctx); 39 | if (obj1 == null) { 40 | return Boolean.FALSE; 41 | } 42 | return (compare(obj0, obj1) < 0) ? Boolean.TRUE : Boolean.FALSE; 43 | } 44 | } 45 | -------------------------------------------------------------------------------- /src/main/java/org/glassfish/expressly/parser/AstGreaterThan.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 1997, 2018 Oracle and/or its affiliates. All rights reserved. 3 | * 4 | * This program and the accompanying materials are made available under the 5 | * terms of the Eclipse Public License v. 2.0, which is available at 6 | * http://www.eclipse.org/legal/epl-2.0. 7 | * 8 | * This Source Code may also be made available under the following Secondary 9 | * Licenses when the conditions for such availability set forth in the 10 | * Eclipse Public License v. 2.0 are satisfied: GNU General Public License, 11 | * version 2 with the GNU Classpath Exception, which is available at 12 | * https://www.gnu.org/software/classpath/license.html. 13 | * 14 | * SPDX-License-Identifier: EPL-2.0 OR GPL-2.0 WITH Classpath-exception-2.0 15 | */ 16 | 17 | package org.glassfish.expressly.parser; 18 | 19 | import org.glassfish.expressly.lang.EvaluationContext; 20 | 21 | import jakarta.el.ELException; 22 | 23 | /** 24 | * @author Jacob Hookom [jacob@hookom.net] 25 | * @version $Change: 181177 $$DateTime: 2001/06/26 08:45:09 $$Author: kchung $ 26 | */ 27 | public final class AstGreaterThan extends BooleanNode { 28 | public AstGreaterThan(int id) { 29 | super(id); 30 | } 31 | 32 | @Override 33 | public Object getValue(EvaluationContext ctx) throws ELException { 34 | Object obj0 = this.children[0].getValue(ctx); 35 | if (obj0 == null) { 36 | return Boolean.FALSE; 37 | } 38 | Object obj1 = this.children[1].getValue(ctx); 39 | if (obj1 == null) { 40 | return Boolean.FALSE; 41 | } 42 | return (compare(obj0, obj1) > 0) ? Boolean.TRUE : Boolean.FALSE; 43 | } 44 | } 45 | -------------------------------------------------------------------------------- /src/main/java/org/glassfish/expressly/parser/AstLessThanEqual.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 1997, 2018 Oracle and/or its affiliates. All rights reserved. 3 | * 4 | * This program and the accompanying materials are made available under the 5 | * terms of the Eclipse Public License v. 2.0, which is available at 6 | * http://www.eclipse.org/legal/epl-2.0. 7 | * 8 | * This Source Code may also be made available under the following Secondary 9 | * Licenses when the conditions for such availability set forth in the 10 | * Eclipse Public License v. 2.0 are satisfied: GNU General Public License, 11 | * version 2 with the GNU Classpath Exception, which is available at 12 | * https://www.gnu.org/software/classpath/license.html. 13 | * 14 | * SPDX-License-Identifier: EPL-2.0 OR GPL-2.0 WITH Classpath-exception-2.0 15 | */ 16 | 17 | package org.glassfish.expressly.parser; 18 | 19 | import org.glassfish.expressly.lang.EvaluationContext; 20 | 21 | import jakarta.el.ELException; 22 | 23 | /** 24 | * @author Jacob Hookom [jacob@hookom.net] 25 | * @version $Change: 181177 $$DateTime: 2001/06/26 08:45:09 $$Author: kchung $ 26 | */ 27 | public final class AstLessThanEqual extends BooleanNode { 28 | public AstLessThanEqual(int id) { 29 | super(id); 30 | } 31 | 32 | @Override 33 | public Object getValue(EvaluationContext ctx) throws ELException { 34 | Object obj0 = this.children[0].getValue(ctx); 35 | Object obj1 = this.children[1].getValue(ctx); 36 | if (obj0 == obj1) { 37 | return Boolean.TRUE; 38 | } 39 | if (obj0 == null || obj1 == null) { 40 | return Boolean.FALSE; 41 | } 42 | return (compare(obj0, obj1) <= 0) ? Boolean.TRUE : Boolean.FALSE; 43 | } 44 | } 45 | -------------------------------------------------------------------------------- /src/main/java/org/glassfish/expressly/parser/AstGreaterThanEqual.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 1997, 2018 Oracle and/or its affiliates. All rights reserved. 3 | * 4 | * This program and the accompanying materials are made available under the 5 | * terms of the Eclipse Public License v. 2.0, which is available at 6 | * http://www.eclipse.org/legal/epl-2.0. 7 | * 8 | * This Source Code may also be made available under the following Secondary 9 | * Licenses when the conditions for such availability set forth in the 10 | * Eclipse Public License v. 2.0 are satisfied: GNU General Public License, 11 | * version 2 with the GNU Classpath Exception, which is available at 12 | * https://www.gnu.org/software/classpath/license.html. 13 | * 14 | * SPDX-License-Identifier: EPL-2.0 OR GPL-2.0 WITH Classpath-exception-2.0 15 | */ 16 | 17 | package org.glassfish.expressly.parser; 18 | 19 | import org.glassfish.expressly.lang.EvaluationContext; 20 | 21 | import jakarta.el.ELException; 22 | 23 | /** 24 | * @author Jacob Hookom [jacob@hookom.net] 25 | * @version $Change: 181177 $$DateTime: 2001/06/26 08:45:09 $$Author: kchung $ 26 | */ 27 | public final class AstGreaterThanEqual extends BooleanNode { 28 | public AstGreaterThanEqual(int id) { 29 | super(id); 30 | } 31 | 32 | @Override 33 | public Object getValue(EvaluationContext ctx) throws ELException { 34 | Object obj0 = this.children[0].getValue(ctx); 35 | Object obj1 = this.children[1].getValue(ctx); 36 | if (obj0 == obj1) { 37 | return Boolean.TRUE; 38 | } 39 | if (obj0 == null || obj1 == null) { 40 | return Boolean.FALSE; 41 | } 42 | return (compare(obj0, obj1) >= 0) ? Boolean.TRUE : Boolean.FALSE; 43 | } 44 | } 45 | -------------------------------------------------------------------------------- /NOTICE.md: -------------------------------------------------------------------------------- 1 | # Notices for Expressly 2 | 3 | This content is produced and maintained by the Eclipse Expressly project. 4 | 5 | * Project home: https://projects.eclipse.org/projects/ee4j.expressly 6 | 7 | ## Trademarks 8 | 9 | Expressly and Jakarta Expression Language are trademark of the Eclipse 10 | Foundations. 11 | 12 | ## Copyright 13 | 14 | All content is the property of the respective authors or their employers. For 15 | more information regarding authorship of content, please consult the listed 16 | source code repository logs. 17 | 18 | ## Declared Project Licenses 19 | 20 | This program and the accompanying materials are made available under the terms 21 | of the Eclipse Public License v. 2.0 which is available at 22 | http://www.eclipse.org/legal/epl-2.0. This Source Code may also be made 23 | available under the following Secondary Licenses when the conditions for such 24 | availability set forth in the Eclipse Public License v. 2.0 are satisfied: GNU 25 | General Public License, version 2 with the GNU Classpath Exception which is 26 | available at https://www.gnu.org/software/classpath/license.html. 27 | 28 | SPDX-License-Identifier: EPL-2.0 OR GPL-2.0 WITH Classpath-exception-2.0 29 | 30 | ## Source Code 31 | 32 | The project maintains the following source code repositories: 33 | 34 | * https://github.com/eclipse-ee4j/expressly 35 | 36 | ## Third-party Content 37 | 38 | ## Cryptography 39 | 40 | Content may contain encryption software. The country in which you are currently 41 | may have restrictions on the import, possession, and use, and/or re-export to 42 | another country, of encryption software. BEFORE using any encryption software, 43 | please check the country's laws, regulations and policies concerning the import, 44 | possession, or use, and re-export of encryption software, to see if this is 45 | permitted. 46 | -------------------------------------------------------------------------------- /src/test/java/org/glassfish/el/test/Product.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2018 Oracle and/or its affiliates. All rights reserved. 3 | * 4 | * This program and the accompanying materials are made available under the 5 | * terms of the Eclipse Public License v. 2.0, which is available at 6 | * http://www.eclipse.org/legal/epl-2.0. 7 | * 8 | * This Source Code may also be made available under the following Secondary 9 | * Licenses when the conditions for such availability set forth in the 10 | * Eclipse Public License v. 2.0 are satisfied: GNU General Public License, 11 | * version 2 with the GNU Classpath Exception, which is available at 12 | * https://www.gnu.org/software/classpath/license.html. 13 | * 14 | * SPDX-License-Identifier: EPL-2.0 OR GPL-2.0 WITH Classpath-exception-2.0 15 | */ 16 | 17 | package org.glassfish.el.test; 18 | 19 | public class Product { 20 | 21 | public int productID; 22 | public String name; 23 | public String category; 24 | public double unitPrice; 25 | public int unitsInStock; 26 | 27 | Product (int productID, String name, String category, 28 | double unitPrice, int unitsInStock) { 29 | 30 | this.productID = productID; 31 | this.name = name; 32 | this.category = category; 33 | this.unitPrice = unitPrice; 34 | this.unitsInStock = unitsInStock; 35 | } 36 | 37 | @Override 38 | public String toString() { 39 | return "Product: " + productID + ", " + name + ", " + 40 | category + ", " + unitPrice + ", " + unitsInStock; 41 | } 42 | 43 | public int getProductID() { return productID; } 44 | public String getName() { return name; } 45 | public String getCategory() { return category; } 46 | public double getUnitPrice() { return unitPrice; } 47 | public int getUnitsInStock() { return unitsInStock; } 48 | 49 | } 50 | -------------------------------------------------------------------------------- /CONTRIBUTING.md: -------------------------------------------------------------------------------- 1 | # Contributing to Eclipse Expressly 2 | 3 | Thanks for your interest in this project. 4 | 5 | ## Project description 6 | 7 | Expressly implements Jakarta Expression Language, which provides an important mechanism 8 | for enabling the presentation layer (web pages) to communicate with the 9 | application logic (managed beans). Jakarta Expression Language is used by several Jakarta EE 10 | technologies, such as Jakarta Faces, Jakarta Server Pages, Jakarta Security and Contexts and 11 | Dependency Injection for Jakarta EE (CDI). 12 | 13 | Jakarta Expression Language can also be used in stand-alone environments. 14 | 15 | * https://projects.eclipse.org/projects/ee4j.expressly 16 | * https://projects.eclipse.org/projects/ee4j.el 17 | 18 | ## Developer resources 19 | 20 | Information regarding source code management, builds, coding standards, and 21 | more. 22 | 23 | * https://projects.eclipse.org/projects/ee4j.expressly/developer 24 | 25 | The project maintains the following source code repositories 26 | 27 | * https://github.com/eclipse-ee4j/expressly 28 | 29 | ## Eclipse Contributor Agreement 30 | 31 | Before your contribution can be accepted by the project team contributors must 32 | electronically sign the Eclipse Contributor Agreement (ECA). 33 | 34 | * http://www.eclipse.org/legal/ECA.php 35 | 36 | Commits that are provided by non-committers must have a Signed-off-by field in 37 | the footer indicating that the author is aware of the terms by which the 38 | contribution has been provided to the project. The non-committer must 39 | additionally have an Eclipse Foundation account and must have a signed Eclipse 40 | Contributor Agreement (ECA) on file. 41 | 42 | For more information, please see the Eclipse Committer Handbook: 43 | https://www.eclipse.org/projects/handbook/#resources-commit 44 | 45 | ## Contact 46 | 47 | Contact the project developers via the project's "dev" list. 48 | 49 | -------------------------------------------------------------------------------- /src/main/java/org/glassfish/expressly/parser/AstMethodArguments.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2022, 2022 Contributors to the Eclipse Foundation. 3 | * Copyright (c) 2012, 2018 Oracle and/or its affiliates. All rights reserved. 4 | * 5 | * This program and the accompanying materials are made available under the 6 | * terms of the Eclipse Public License v. 2.0, which is available at 7 | * http://www.eclipse.org/legal/epl-2.0. 8 | * 9 | * This Source Code may also be made available under the following Secondary 10 | * Licenses when the conditions for such availability set forth in the 11 | * Eclipse Public License v. 2.0 are satisfied: GNU General Public License, 12 | * version 2 with the GNU Classpath Exception, which is available at 13 | * https://www.gnu.org/software/classpath/license.html. 14 | * 15 | * SPDX-License-Identifier: EPL-2.0 OR GPL-2.0 WITH Classpath-exception-2.0 16 | */ 17 | 18 | package org.glassfish.expressly.parser; 19 | 20 | import org.glassfish.expressly.lang.EvaluationContext; 21 | 22 | import jakarta.el.ELException; 23 | 24 | /** 25 | * @author Kin-man Chung 26 | */ 27 | public class AstMethodArguments extends SimpleNode { 28 | public AstMethodArguments(int id) { 29 | super(id); 30 | } 31 | 32 | Class[] getParamTypes() { 33 | return null; 34 | } 35 | 36 | public Object[] getParameters(EvaluationContext ctx) throws ELException { 37 | if (children == null) { 38 | return new Object[] {}; 39 | } 40 | 41 | Object[] obj = new Object[children.length]; 42 | for (int i = 0; i < obj.length; i++) { 43 | obj[i] = children[i].getValue(ctx); 44 | } 45 | return obj; 46 | } 47 | 48 | public int getParameterCount() { 49 | return children == null ? 0 : children.length; 50 | } 51 | 52 | @Override 53 | public boolean isParametersProvided() { 54 | return true; 55 | } 56 | 57 | } 58 | -------------------------------------------------------------------------------- /src/main/java/org/glassfish/expressly/parser/AstDynamicExpression.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2022, 2022 Contributors to the Eclipse Foundation. 3 | * Copyright (c) 1997, 2018 Oracle and/or its affiliates. All rights reserved. 4 | * 5 | * This program and the accompanying materials are made available under the 6 | * terms of the Eclipse Public License v. 2.0, which is available at 7 | * http://www.eclipse.org/legal/epl-2.0. 8 | * 9 | * This Source Code may also be made available under the following Secondary 10 | * Licenses when the conditions for such availability set forth in the 11 | * Eclipse Public License v. 2.0 are satisfied: GNU General Public License, 12 | * version 2 with the GNU Classpath Exception, which is available at 13 | * https://www.gnu.org/software/classpath/license.html. 14 | * 15 | * SPDX-License-Identifier: EPL-2.0 OR GPL-2.0 WITH Classpath-exception-2.0 16 | */ 17 | 18 | package org.glassfish.expressly.parser; 19 | 20 | import org.glassfish.expressly.lang.EvaluationContext; 21 | 22 | import jakarta.el.ELException; 23 | 24 | /** 25 | * @author Jacob Hookom [jacob@hookom.net] 26 | * @version $Change: 181177 $$DateTime: 2001/06/26 08:45:09 $$Author: kchung $ 27 | */ 28 | public final class AstDynamicExpression extends SimpleNode { 29 | public AstDynamicExpression(int id) { 30 | super(id); 31 | } 32 | 33 | @Override 34 | public Class getType(EvaluationContext ctx) throws ELException { 35 | return children[0].getType(ctx); 36 | } 37 | 38 | @Override 39 | public Object getValue(EvaluationContext ctx) throws ELException { 40 | return children[0].getValue(ctx); 41 | } 42 | 43 | @Override 44 | public boolean isReadOnly(EvaluationContext ctx) throws ELException { 45 | return children[0].isReadOnly(ctx); 46 | } 47 | 48 | @Override 49 | public void setValue(EvaluationContext ctx, Object value) throws ELException { 50 | children[0].setValue(ctx, value); 51 | } 52 | } 53 | -------------------------------------------------------------------------------- /src/main/java/org/glassfish/expressly/parser/AstDeferredExpression.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2022, 2022 Contributors to the Eclipse Foundation. 3 | * Copyright (c) 1997, 2018 Oracle and/or its affiliates. All rights reserved. 4 | * 5 | * This program and the accompanying materials are made available under the 6 | * terms of the Eclipse Public License v. 2.0, which is available at 7 | * http://www.eclipse.org/legal/epl-2.0. 8 | * 9 | * This Source Code may also be made available under the following Secondary 10 | * Licenses when the conditions for such availability set forth in the 11 | * Eclipse Public License v. 2.0 are satisfied: GNU General Public License, 12 | * version 2 with the GNU Classpath Exception, which is available at 13 | * https://www.gnu.org/software/classpath/license.html. 14 | * 15 | * SPDX-License-Identifier: EPL-2.0 OR GPL-2.0 WITH Classpath-exception-2.0 16 | */ 17 | 18 | package org.glassfish.expressly.parser; 19 | 20 | import org.glassfish.expressly.lang.EvaluationContext; 21 | 22 | import jakarta.el.ELException; 23 | 24 | /** 25 | * @author Jacob Hookom [jacob@hookom.net] 26 | * @version $Change: 181177 $$DateTime: 2001/06/26 08:45:09 $$Author: kchung $ 27 | */ 28 | public final class AstDeferredExpression extends SimpleNode { 29 | public AstDeferredExpression(int id) { 30 | super(id); 31 | } 32 | 33 | @Override 34 | public Class getType(EvaluationContext ctx) throws ELException { 35 | return children[0].getType(ctx); 36 | } 37 | 38 | @Override 39 | public Object getValue(EvaluationContext ctx) throws ELException { 40 | return children[0].getValue(ctx); 41 | } 42 | 43 | @Override 44 | public boolean isReadOnly(EvaluationContext ctx) throws ELException { 45 | return children[0].isReadOnly(ctx); 46 | } 47 | 48 | @Override 49 | public void setValue(EvaluationContext ctx, Object value) throws ELException { 50 | children[0].setValue(ctx, value); 51 | } 52 | } 53 | -------------------------------------------------------------------------------- /src/main/java/org/glassfish/expressly/parser/AstInteger.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2022, 2022 Contributors to the Eclipse Foundation. 3 | * Copyright (c) 1997, 2018 Oracle and/or its affiliates. All rights reserved. 4 | * 5 | * This program and the accompanying materials are made available under the 6 | * terms of the Eclipse Public License v. 2.0, which is available at 7 | * http://www.eclipse.org/legal/epl-2.0. 8 | * 9 | * This Source Code may also be made available under the following Secondary 10 | * Licenses when the conditions for such availability set forth in the 11 | * Eclipse Public License v. 2.0 are satisfied: GNU General Public License, 12 | * version 2 with the GNU Classpath Exception, which is available at 13 | * https://www.gnu.org/software/classpath/license.html. 14 | * 15 | * SPDX-License-Identifier: EPL-2.0 OR GPL-2.0 WITH Classpath-exception-2.0 16 | */ 17 | 18 | package org.glassfish.expressly.parser; 19 | 20 | import java.math.BigInteger; 21 | 22 | import org.glassfish.expressly.lang.EvaluationContext; 23 | 24 | import jakarta.el.ELException; 25 | 26 | /** 27 | * @author Jacob Hookom [jacob@hookom.net] 28 | * @version $Change: 181177 $$DateTime: 2001/06/26 08:45:09 $$Author: kchung $ 29 | */ 30 | public final class AstInteger extends SimpleNode { 31 | public AstInteger(int id) { 32 | super(id); 33 | } 34 | 35 | private Number number; 36 | 37 | @Override 38 | public Class getType(EvaluationContext ctx) throws ELException { 39 | return getInteger().getClass(); 40 | } 41 | 42 | @Override 43 | public Object getValue(EvaluationContext ctx) throws ELException { 44 | return getInteger(); 45 | } 46 | 47 | protected Number getInteger() { 48 | if (number == null) { 49 | try { 50 | number = Long.valueOf(image); 51 | } catch (ArithmeticException e1) { 52 | this.number = new BigInteger(image); 53 | } 54 | } 55 | 56 | return number; 57 | } 58 | } 59 | -------------------------------------------------------------------------------- /src/main/java/org/glassfish/expressly/stream/Optional.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2022, 2022 Contributors to the Eclipse Foundation. 3 | * Copyright (c) 2012, 2018 Oracle and/or its affiliates. All rights reserved. 4 | * 5 | * This program and the accompanying materials are made available under the 6 | * terms of the Eclipse Public License v. 2.0, which is available at 7 | * http://www.eclipse.org/legal/epl-2.0. 8 | * 9 | * This Source Code may also be made available under the following Secondary 10 | * Licenses when the conditions for such availability set forth in the 11 | * Eclipse Public License v. 2.0 are satisfied: GNU General Public License, 12 | * version 2 with the GNU Classpath Exception, which is available at 13 | * https://www.gnu.org/software/classpath/license.html. 14 | * 15 | * SPDX-License-Identifier: EPL-2.0 OR GPL-2.0 WITH Classpath-exception-2.0 16 | */ 17 | 18 | package org.glassfish.expressly.stream; 19 | 20 | import java.util.NoSuchElementException; 21 | 22 | import jakarta.el.LambdaExpression; 23 | 24 | public class Optional { 25 | 26 | private final Object value; 27 | 28 | Optional(Object value) { 29 | if (value == null) { 30 | throw new NullPointerException(); 31 | } 32 | 33 | this.value = value; 34 | } 35 | 36 | Optional() { 37 | this.value = null; 38 | } 39 | 40 | public boolean isPresent() { 41 | return value != null; 42 | } 43 | 44 | public void ifPresent(LambdaExpression lambda) { 45 | if (value != null) { 46 | lambda.invoke(value); 47 | } 48 | } 49 | 50 | public Object get() { 51 | if (value == null) { 52 | throw new NoSuchElementException("No value present"); 53 | } 54 | 55 | return value; 56 | } 57 | 58 | public Object orElse(Object other) { 59 | return value != null ? value : other; 60 | } 61 | 62 | public Object orElseGet(LambdaExpression other) { 63 | return value != null ? value : other.invoke(); 64 | } 65 | } 66 | -------------------------------------------------------------------------------- /src/main/java/org/glassfish/expressly/parser/AstFloatingPoint.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2022, 2022 Contributors to the Eclipse Foundation. 3 | * Copyright (c) 1997, 2018 Oracle and/or its affiliates. All rights reserved. 4 | * 5 | * This program and the accompanying materials are made available under the 6 | * terms of the Eclipse Public License v. 2.0, which is available at 7 | * http://www.eclipse.org/legal/epl-2.0. 8 | * 9 | * This Source Code may also be made available under the following Secondary 10 | * Licenses when the conditions for such availability set forth in the 11 | * Eclipse Public License v. 2.0 are satisfied: GNU General Public License, 12 | * version 2 with the GNU Classpath Exception, which is available at 13 | * https://www.gnu.org/software/classpath/license.html. 14 | * 15 | * SPDX-License-Identifier: EPL-2.0 OR GPL-2.0 WITH Classpath-exception-2.0 16 | */ 17 | 18 | package org.glassfish.expressly.parser; 19 | 20 | import java.math.BigDecimal; 21 | 22 | import org.glassfish.expressly.lang.EvaluationContext; 23 | 24 | import jakarta.el.ELException; 25 | 26 | /** 27 | * @author Jacob Hookom [jacob@hookom.net] 28 | * @version $Change: 181177 $$DateTime: 2001/06/26 08:45:09 $$Author: kchung $ 29 | */ 30 | public final class AstFloatingPoint extends SimpleNode { 31 | public AstFloatingPoint(int id) { 32 | super(id); 33 | } 34 | 35 | private Number number; 36 | 37 | @Override 38 | public Class getType(EvaluationContext ctx) throws ELException { 39 | return getFloatingPoint().getClass(); 40 | } 41 | 42 | @Override 43 | public Object getValue(EvaluationContext ctx) throws ELException { 44 | return getFloatingPoint(); 45 | } 46 | 47 | public Number getFloatingPoint() { 48 | if (number == null) { 49 | try { 50 | number = Double.valueOf(image); 51 | } catch (ArithmeticException e0) { 52 | number = new BigDecimal(image); 53 | } 54 | } 55 | 56 | return number; 57 | } 58 | 59 | } 60 | -------------------------------------------------------------------------------- /src/test/java/org/glassfish/el/test/Customer.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2018 Oracle and/or its affiliates. All rights reserved. 3 | * 4 | * This program and the accompanying materials are made available under the 5 | * terms of the Eclipse Public License v. 2.0, which is available at 6 | * http://www.eclipse.org/legal/epl-2.0. 7 | * 8 | * This Source Code may also be made available under the following Secondary 9 | * Licenses when the conditions for such availability set forth in the 10 | * Eclipse Public License v. 2.0 are satisfied: GNU General Public License, 11 | * version 2 with the GNU Classpath Exception, which is available at 12 | * https://www.gnu.org/software/classpath/license.html. 13 | * 14 | * SPDX-License-Identifier: EPL-2.0 OR GPL-2.0 WITH Classpath-exception-2.0 15 | */ 16 | 17 | package org.glassfish.el.test; 18 | 19 | import java.util.List; 20 | import java.util.ArrayList; 21 | 22 | public class Customer { 23 | int customerID; 24 | String name; 25 | String address; 26 | String city; 27 | String country; 28 | String phone; 29 | List orders; 30 | 31 | public Customer(int customerID, String name, String address, String city, 32 | String country, String phone) { 33 | this.customerID = customerID; 34 | this.name = name; 35 | this.address = address; 36 | this.city = city; 37 | this.country = country; 38 | this.phone = phone; 39 | this.orders = new ArrayList<>(); 40 | } 41 | 42 | @Override 43 | public String toString() { 44 | return "Customer: " + customerID + ", " + name + ", " + city + ", " + 45 | country; 46 | } 47 | 48 | public int getCustomerID() { return customerID;} 49 | public String getName() { return name;} 50 | public String getAddress() { return address; } 51 | public String getCity() { return city; } 52 | public String getCountry() { return country; } 53 | public String getPhone() { return phone; } 54 | public List getOrders() { return orders; } 55 | } 56 | -------------------------------------------------------------------------------- /src/main/java/org/glassfish/expressly/lang/FunctionMapperFactory.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2022, 2022 Contributors to the Eclipse Foundation. 3 | * Copyright (c) 1997, 2018 Oracle and/or its affiliates. All rights reserved. 4 | * 5 | * This program and the accompanying materials are made available under the 6 | * terms of the Eclipse Public License v. 2.0, which is available at 7 | * http://www.eclipse.org/legal/epl-2.0. 8 | * 9 | * This Source Code may also be made available under the following Secondary 10 | * Licenses when the conditions for such availability set forth in the 11 | * Eclipse Public License v. 2.0 are satisfied: GNU General Public License, 12 | * version 2 with the GNU Classpath Exception, which is available at 13 | * https://www.gnu.org/software/classpath/license.html. 14 | * 15 | * SPDX-License-Identifier: EPL-2.0 OR GPL-2.0 WITH Classpath-exception-2.0 16 | */ 17 | 18 | package org.glassfish.expressly.lang; 19 | 20 | import java.lang.reflect.Method; 21 | 22 | import jakarta.el.FunctionMapper; 23 | 24 | /** 25 | * @author Jacob Hookom [jacob@hookom.net] 26 | * @author kchung 27 | */ 28 | public class FunctionMapperFactory extends FunctionMapper { 29 | 30 | protected FunctionMapperImpl memento; 31 | protected FunctionMapper target; 32 | 33 | public FunctionMapperFactory(FunctionMapper mapper) { 34 | if (mapper == null) { 35 | throw new NullPointerException("FunctionMapper target cannot be null"); 36 | } 37 | this.target = mapper; 38 | } 39 | 40 | @Override 41 | public Method resolveFunction(String prefix, String localName) { 42 | if (memento == null) { 43 | memento = new FunctionMapperImpl(); 44 | } 45 | Method functionMethod = target.resolveFunction(prefix, localName); 46 | if (functionMethod != null) { 47 | memento.addFunction(prefix, localName, functionMethod); 48 | } 49 | 50 | return functionMethod; 51 | } 52 | 53 | public FunctionMapper create() { 54 | return memento; 55 | } 56 | 57 | } 58 | -------------------------------------------------------------------------------- /src/main/java/org/glassfish/expressly/parser/AstCompositeExpression.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2022, 2022 Contributors to the Eclipse Foundation. 3 | * Copyright (c) 2021 Payara Services Ltd. 4 | * Copyright (c) 1997, 2018 Oracle and/or its affiliates. All rights reserved. 5 | * 6 | * This program and the accompanying materials are made available under the 7 | * terms of the Eclipse Public License v. 2.0, which is available at 8 | * http://www.eclipse.org/legal/epl-2.0. 9 | * 10 | * This Source Code may also be made available under the following Secondary 11 | * Licenses when the conditions for such availability set forth in the 12 | * Eclipse Public License v. 2.0 are satisfied: GNU General Public License, 13 | * version 2 with the GNU Classpath Exception, which is available at 14 | * https://www.gnu.org/software/classpath/license.html. 15 | * 16 | * SPDX-License-Identifier: EPL-2.0 OR GPL-2.0 WITH Classpath-exception-2.0 17 | */ 18 | 19 | package org.glassfish.expressly.parser; 20 | 21 | import org.glassfish.expressly.lang.EvaluationContext; 22 | 23 | import jakarta.el.ELException; 24 | 25 | /** 26 | * @author Jacob Hookom [jacob@hookom.net] 27 | * @version $Change: 181177 $$DateTime: 2001/06/26 08:45:09 $$Author: kchung $ 28 | */ 29 | public final class AstCompositeExpression extends SimpleNode { 30 | 31 | public AstCompositeExpression(int id) { 32 | super(id); 33 | } 34 | 35 | @Override 36 | public Class getType(EvaluationContext ctx) throws ELException { 37 | return String.class; 38 | } 39 | 40 | @Override 41 | public Object getValue(EvaluationContext ctx) throws ELException { 42 | StringBuilder valueBuilder = new StringBuilder(16); 43 | 44 | if (children != null) { 45 | for (int i = 0; i < children.length; i++) { 46 | Object value = children[i].getValue(ctx); 47 | if (value != null) { 48 | valueBuilder.append(value); 49 | } 50 | } 51 | } 52 | 53 | return valueBuilder.toString(); 54 | } 55 | } 56 | -------------------------------------------------------------------------------- /src/main/java/org/glassfish/expressly/parser/AstMapData.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2012, 2018 Oracle and/or its affiliates. All rights reserved. 3 | * 4 | * This program and the accompanying materials are made available under the 5 | * terms of the Eclipse Public License v. 2.0, which is available at 6 | * http://www.eclipse.org/legal/epl-2.0. 7 | * 8 | * This Source Code may also be made available under the following Secondary 9 | * Licenses when the conditions for such availability set forth in the 10 | * Eclipse Public License v. 2.0 are satisfied: GNU General Public License, 11 | * version 2 with the GNU Classpath Exception, which is available at 12 | * https://www.gnu.org/software/classpath/license.html. 13 | * 14 | * SPDX-License-Identifier: EPL-2.0 OR GPL-2.0 WITH Classpath-exception-2.0 15 | */ 16 | 17 | package org.glassfish.expressly.parser; 18 | 19 | import java.util.HashMap; 20 | import java.util.HashSet; 21 | 22 | import org.glassfish.expressly.lang.EvaluationContext; 23 | 24 | import jakarta.el.ELException; 25 | 26 | /** 27 | * @author Kin-man Chung 28 | */ 29 | public class AstMapData extends SimpleNode { 30 | public AstMapData(int id) { 31 | super(id); 32 | } 33 | 34 | @Override 35 | public Object getValue(EvaluationContext ctx) { 36 | HashSet set = new HashSet(); 37 | HashMap map = new HashMap(); 38 | 39 | int paramCount = this.jjtGetNumChildren(); 40 | for (int i = 0; i < paramCount; i++) { 41 | Node entry = this.children[i]; 42 | Object v1 = entry.jjtGetChild(0).getValue(ctx); 43 | if (entry.jjtGetNumChildren() > 1) { 44 | // expr: expr 45 | map.put(v1, entry.jjtGetChild(1).getValue(ctx)); 46 | } else { 47 | set.add(v1); 48 | } 49 | } 50 | // It is error to have mixed set/map entries 51 | if (set.size() > 0 && map.size() > 0) { 52 | throw new ELException("Cannot mix set entry with map entry."); 53 | } 54 | if (map.size() > 0) { 55 | return map; 56 | } 57 | return set; 58 | } 59 | } 60 | -------------------------------------------------------------------------------- /src/main/java/org/glassfish/expressly/lang/VariableMapperImpl.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2022, 2022 Contributors to the Eclipse Foundation. 3 | * Copyright (c) 1997, 2018 Oracle and/or its affiliates. All rights reserved. 4 | * 5 | * This program and the accompanying materials are made available under the 6 | * terms of the Eclipse Public License v. 2.0, which is available at 7 | * http://www.eclipse.org/legal/epl-2.0. 8 | * 9 | * This Source Code may also be made available under the following Secondary 10 | * Licenses when the conditions for such availability set forth in the 11 | * Eclipse Public License v. 2.0 are satisfied: GNU General Public License, 12 | * version 2 with the GNU Classpath Exception, which is available at 13 | * https://www.gnu.org/software/classpath/license.html. 14 | * 15 | * SPDX-License-Identifier: EPL-2.0 OR GPL-2.0 WITH Classpath-exception-2.0 16 | */ 17 | 18 | package org.glassfish.expressly.lang; 19 | 20 | import java.io.Externalizable; 21 | import java.io.IOException; 22 | import java.io.ObjectInput; 23 | import java.io.ObjectOutput; 24 | import java.util.HashMap; 25 | import java.util.Map; 26 | 27 | import jakarta.el.ValueExpression; 28 | import jakarta.el.VariableMapper; 29 | 30 | public class VariableMapperImpl extends VariableMapper implements Externalizable { 31 | 32 | private static final long serialVersionUID = 1L; 33 | 34 | private Map vars = new HashMap<>(); 35 | 36 | public VariableMapperImpl() { 37 | super(); 38 | } 39 | 40 | @Override 41 | public ValueExpression resolveVariable(String variable) { 42 | return vars.get(variable); 43 | } 44 | 45 | @Override 46 | public ValueExpression setVariable(String variable, ValueExpression expression) { 47 | return vars.put(variable, expression); 48 | } 49 | 50 | // Safe cast. 51 | @Override 52 | @SuppressWarnings("unchecked") 53 | public void readExternal(ObjectInput in) throws IOException, ClassNotFoundException { 54 | vars = (Map) in.readObject(); 55 | } 56 | 57 | @Override 58 | public void writeExternal(ObjectOutput out) throws IOException { 59 | out.writeObject(vars); 60 | } 61 | } 62 | -------------------------------------------------------------------------------- /src/main/java/org/glassfish/expressly/lang/VariableMapperFactory.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2022, 2022 Contributors to the Eclipse Foundation. 3 | * Copyright (c) 1997, 2018 Oracle and/or its affiliates. All rights reserved. 4 | * 5 | * This program and the accompanying materials are made available under the 6 | * terms of the Eclipse Public License v. 2.0, which is available at 7 | * http://www.eclipse.org/legal/epl-2.0. 8 | * 9 | * This Source Code may also be made available under the following Secondary 10 | * Licenses when the conditions for such availability set forth in the 11 | * Eclipse Public License v. 2.0 are satisfied: GNU General Public License, 12 | * version 2 with the GNU Classpath Exception, which is available at 13 | * https://www.gnu.org/software/classpath/license.html. 14 | * 15 | * SPDX-License-Identifier: EPL-2.0 OR GPL-2.0 WITH Classpath-exception-2.0 16 | */ 17 | 18 | package org.glassfish.expressly.lang; 19 | 20 | import jakarta.el.ValueExpression; 21 | import jakarta.el.VariableMapper; 22 | 23 | /** 24 | * Creates a VariableMapper for the variables used in the expression. 25 | */ 26 | public class VariableMapperFactory extends VariableMapper { 27 | 28 | private final VariableMapper target; 29 | private VariableMapper momento; 30 | 31 | public VariableMapperFactory(VariableMapper target) { 32 | if (target == null) { 33 | throw new NullPointerException("Target VariableMapper cannot be null"); 34 | } 35 | this.target = target; 36 | } 37 | 38 | public VariableMapper create() { 39 | return momento; 40 | } 41 | 42 | @Override 43 | public ValueExpression resolveVariable(String variable) { 44 | ValueExpression valueExpression = target.resolveVariable(variable); 45 | if (valueExpression != null) { 46 | if (momento == null) { 47 | momento = new VariableMapperImpl(); 48 | } 49 | momento.setVariable(variable, valueExpression); 50 | } 51 | 52 | return valueExpression; 53 | } 54 | 55 | @Override 56 | public ValueExpression setVariable(String variable, ValueExpression expression) { 57 | throw new UnsupportedOperationException("Cannot Set Variables on Factory"); 58 | } 59 | } 60 | -------------------------------------------------------------------------------- /src/main/java/org/glassfish/expressly/parser/AstEmpty.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2022, 2022 Contributors to the Eclipse Foundation. 3 | * Copyright (c) 1997, 2018 Oracle and/or its affiliates. All rights reserved. 4 | * 5 | * This program and the accompanying materials are made available under the 6 | * terms of the Eclipse Public License v. 2.0, which is available at 7 | * http://www.eclipse.org/legal/epl-2.0. 8 | * 9 | * This Source Code may also be made available under the following Secondary 10 | * Licenses when the conditions for such availability set forth in the 11 | * Eclipse Public License v. 2.0 are satisfied: GNU General Public License, 12 | * version 2 with the GNU Classpath Exception, which is available at 13 | * https://www.gnu.org/software/classpath/license.html. 14 | * 15 | * SPDX-License-Identifier: EPL-2.0 OR GPL-2.0 WITH Classpath-exception-2.0 16 | */ 17 | 18 | package org.glassfish.expressly.parser; 19 | 20 | import java.util.Collection; 21 | import java.util.Map; 22 | 23 | import org.glassfish.expressly.lang.EvaluationContext; 24 | 25 | import jakarta.el.ELException; 26 | 27 | /** 28 | * @author Jacob Hookom [jacob@hookom.net] 29 | * @version $Change: 181177 $$DateTime: 2001/06/26 08:45:09 $$Author: kchung $ 30 | */ 31 | public final class AstEmpty extends SimpleNode { 32 | public AstEmpty(int id) { 33 | super(id); 34 | } 35 | 36 | @Override 37 | public Class getType(EvaluationContext ctx) throws ELException { 38 | return Boolean.class; 39 | } 40 | 41 | @SuppressWarnings("rawtypes") 42 | @Override 43 | public Object getValue(EvaluationContext ctx) throws ELException { 44 | Object obj = this.children[0].getValue(ctx); 45 | if (obj == null) { 46 | return Boolean.TRUE; 47 | } 48 | 49 | if (obj instanceof String) { 50 | return Boolean.valueOf(((String) obj).length() == 0); 51 | } 52 | 53 | if (obj instanceof Object[]) { 54 | return Boolean.valueOf(((Object[]) obj).length == 0); 55 | } 56 | 57 | if (obj instanceof Collection) { 58 | return Boolean.valueOf(((Collection) obj).isEmpty()); 59 | } 60 | 61 | if (obj instanceof Map) { 62 | return Boolean.valueOf(((Map) obj).isEmpty()); 63 | } 64 | 65 | return Boolean.FALSE; 66 | } 67 | } 68 | -------------------------------------------------------------------------------- /src/test/java/org/glassfish/el/test/StaticRefTest.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2018, 2021 Oracle and/or its affiliates and others. 3 | * All rights reserved. 4 | * 5 | * This program and the accompanying materials are made available under the 6 | * terms of the Eclipse Public License v. 2.0, which is available at 7 | * http://www.eclipse.org/legal/epl-2.0. 8 | * 9 | * This Source Code may also be made available under the following Secondary 10 | * Licenses when the conditions for such availability set forth in the 11 | * Eclipse Public License v. 2.0 are satisfied: GNU General Public License, 12 | * version 2 with the GNU Classpath Exception, which is available at 13 | * https://www.gnu.org/software/classpath/license.html. 14 | * 15 | * SPDX-License-Identifier: EPL-2.0 OR GPL-2.0 WITH Classpath-exception-2.0 16 | */ 17 | 18 | package org.glassfish.el.test; 19 | 20 | import jakarta.el.ELProcessor; 21 | import org.junit.After; 22 | import org.junit.AfterClass; 23 | import org.junit.Before; 24 | import org.junit.BeforeClass; 25 | import org.junit.Test; 26 | import static org.junit.Assert.*; 27 | 28 | /** 29 | * 30 | * @author kichung 31 | */ 32 | public class StaticRefTest { 33 | 34 | ELProcessor elp; 35 | 36 | public StaticRefTest() { 37 | } 38 | 39 | @BeforeClass 40 | public static void setUpClass() throws Exception { 41 | System.setProperty("jakarta.el.ExpressionFactory", "org.glassfish.expressly.ExpressionFactoryImpl"); 42 | } 43 | 44 | @AfterClass 45 | public static void tearDownClass() throws Exception { 46 | } 47 | 48 | @Before 49 | public void setUp() { 50 | elp = new ELProcessor(); 51 | } 52 | 53 | @After 54 | public void tearDown() { 55 | } 56 | 57 | @Test 58 | public void testStaticRef() { 59 | // Pre imported java.lang classes 60 | Boolean ret = elp.eval("Boolean.TRUE"); 61 | assertTrue(ret.booleanValue()); 62 | ret = elp.eval("Boolean.TRUE"); 63 | assertTrue(ret.booleanValue()); // test caching Boolean 64 | } 65 | 66 | @Test 67 | public void testConstructor() { 68 | assertEquals(Integer.valueOf(1001), elp.eval("Integer(1001)")); 69 | } 70 | 71 | @Test 72 | public void testStaticMethod() { 73 | assertEquals(Integer.valueOf(4), elp.eval("Integer.numberOfTrailingZeros(16)")); 74 | } 75 | } 76 | -------------------------------------------------------------------------------- /src/main/java/org/glassfish/expressly/parser/AstLiteralExpression.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2022, 2022 Contributors to the Eclipse Foundation. 3 | * Copyright (c) 2021 Payara Services Ltd. 4 | * Copyright (c) 1997, 2018 Oracle and/or its affiliates. All rights reserved. 5 | * 6 | * This program and the accompanying materials are made available under the 7 | * terms of the Eclipse Public License v. 2.0, which is available at 8 | * http://www.eclipse.org/legal/epl-2.0. 9 | * 10 | * This Source Code may also be made available under the following Secondary 11 | * Licenses when the conditions for such availability set forth in the 12 | * Eclipse Public License v. 2.0 are satisfied: GNU General Public License, 13 | * version 2 with the GNU Classpath Exception, which is available at 14 | * https://www.gnu.org/software/classpath/license.html. 15 | * 16 | * SPDX-License-Identifier: EPL-2.0 OR GPL-2.0 WITH Classpath-exception-2.0 17 | */ 18 | 19 | package org.glassfish.expressly.parser; 20 | 21 | import org.glassfish.expressly.lang.EvaluationContext; 22 | 23 | import jakarta.el.ELException; 24 | 25 | /** 26 | * @author Jacob Hookom [jacob@hookom.net] 27 | * @version $Change: 181177 $$DateTime: 2001/06/26 08:45:09 $$Author: kchung $ 28 | */ 29 | public final class AstLiteralExpression extends SimpleNode { 30 | public AstLiteralExpression(int id) { 31 | super(id); 32 | } 33 | 34 | @Override 35 | public Class getType(EvaluationContext ctx) throws ELException { 36 | return String.class; 37 | } 38 | 39 | @Override 40 | public Object getValue(EvaluationContext ctx) throws ELException { 41 | return this.image; 42 | } 43 | 44 | @Override 45 | public void setImage(String image) { 46 | if (image.indexOf('\\') == -1) { 47 | this.image = image; 48 | return; 49 | } 50 | int size = image.length(); 51 | StringBuilder buf = new StringBuilder(size); 52 | for (int i = 0; i < size; i++) { 53 | char c = image.charAt(i); 54 | if (c == '\\' && i + 1 < size) { 55 | char c1 = image.charAt(i + 1); 56 | if (c1 == '\\' || c1 == '"' || c1 == '\'' || c1 == '#' || c1 == '$') { 57 | c = c1; 58 | i++; 59 | } 60 | } 61 | buf.append(c); 62 | } 63 | this.image = buf.toString(); 64 | } 65 | } 66 | -------------------------------------------------------------------------------- /src/test/java/org/glassfish/el/test/EscapingTest.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2021 Oracle and/or its affiliates. All rights reserved. 3 | * 4 | * This program and the accompanying materials are made available under the 5 | * terms of the Eclipse Public License v. 2.0, which is available at 6 | * http://www.eclipse.org/legal/epl-2.0. 7 | * 8 | * This Source Code may also be made available under the following Secondary 9 | * Licenses when the conditions for such availability set forth in the 10 | * Eclipse Public License v. 2.0 are satisfied: GNU General Public License, 11 | * version 2 with the GNU Classpath Exception, which is available at 12 | * https://www.gnu.org/software/classpath/license.html. 13 | * 14 | * SPDX-License-Identifier: EPL-2.0 OR GPL-2.0 WITH Classpath-exception-2.0 15 | */ 16 | 17 | package org.glassfish.el.test; 18 | 19 | import jakarta.el.ELManager; 20 | import jakarta.el.ELProcessor; 21 | import jakarta.el.ValueExpression; 22 | import org.junit.BeforeClass; 23 | import org.junit.Test; 24 | 25 | import static org.junit.Assert.assertEquals; 26 | 27 | public class EscapingTest { 28 | 29 | static ELProcessor elp; 30 | static ELManager elm; 31 | 32 | public EscapingTest() { 33 | } 34 | 35 | @BeforeClass 36 | public static void setUpClass() throws Exception { 37 | System.setProperty("jakarta.el.ExpressionFactory", "org.glassfish.expressly.ExpressionFactoryImpl"); 38 | elp = new ELProcessor(); 39 | elm = elp.getELManager(); 40 | } 41 | 42 | @Test 43 | public void testEscape01() { 44 | assertEquals("$2", evaluateExpression("$${1+1}")); 45 | assertEquals("$${1+1}", evaluateExpression("$\\${1+1}")); 46 | } 47 | 48 | @Test 49 | public void testEscape02() { 50 | assertEquals("$2", evaluateExpression("$#{1+1}")); 51 | assertEquals("$#{1+1}", evaluateExpression("$\\#{1+1}")); 52 | } 53 | 54 | @Test 55 | public void testEscape03() { 56 | assertEquals("#2", evaluateExpression("##{1+1}")); 57 | assertEquals("##{1+1}", evaluateExpression("#\\#{1+1}")); 58 | } 59 | 60 | @Test 61 | public void testEscape04() { 62 | assertEquals("#2", evaluateExpression("#${1+1}")); 63 | assertEquals("#${1+1}", evaluateExpression("#\\${1+1}")); 64 | } 65 | 66 | private String evaluateExpression(String expr) { 67 | ValueExpression v = ELManager.getExpressionFactory().createValueExpression( 68 | elm.getELContext(), expr, String.class); 69 | return (String) v.getValue(elm.getELContext()); 70 | } 71 | } 72 | -------------------------------------------------------------------------------- /src/main/java/org/glassfish/expressly/parser/AstLambdaExpression.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2012, 2018 Oracle and/or its affiliates. All rights reserved. 3 | * 4 | * This program and the accompanying materials are made available under the 5 | * terms of the Eclipse Public License v. 2.0, which is available at 6 | * http://www.eclipse.org/legal/epl-2.0. 7 | * 8 | * This Source Code may also be made available under the following Secondary 9 | * Licenses when the conditions for such availability set forth in the 10 | * Eclipse Public License v. 2.0 are satisfied: GNU General Public License, 11 | * version 2 with the GNU Classpath Exception, which is available at 12 | * https://www.gnu.org/software/classpath/license.html. 13 | * 14 | * SPDX-License-Identifier: EPL-2.0 OR GPL-2.0 WITH Classpath-exception-2.0 15 | */ 16 | 17 | package org.glassfish.expressly.parser; 18 | 19 | import java.util.List; 20 | 21 | import org.glassfish.expressly.ValueExpressionImpl; 22 | import org.glassfish.expressly.lang.EvaluationContext; 23 | import org.glassfish.expressly.util.MessageFactory; 24 | 25 | import jakarta.el.ELException; 26 | import jakarta.el.LambdaExpression; 27 | import jakarta.el.ValueExpression; 28 | 29 | /** 30 | * @author Kin-man Chung 31 | */ 32 | public class AstLambdaExpression extends SimpleNode { 33 | 34 | public AstLambdaExpression(int id) { 35 | super(id); 36 | } 37 | 38 | @Override 39 | public Object getValue(EvaluationContext ctx) throws ELException { 40 | // Create a lambda expression 41 | ValueExpression expr = new ValueExpressionImpl("#{Lambda Expression}", this.children[1], ctx.getFunctionMapper(), ctx.getVariableMapper(), null); 42 | List parameters = ((AstLambdaParameters) this.children[0]).getParameters(); 43 | LambdaExpression lambda = new LambdaExpression(parameters, expr); 44 | if (this.children.length <= 2) { 45 | return lambda; 46 | } 47 | 48 | // There are arguments following the lambda exprn, invoke it now. 49 | Object ret = null; 50 | for (int i = 2; i < this.children.length; i++) { 51 | if (ret != null) { 52 | if (!(ret instanceof LambdaExpression)) { 53 | throw new ELException(MessageFactory.get("error.lambda.call")); 54 | } 55 | lambda = (LambdaExpression) ret; 56 | } 57 | AstMethodArguments args = (AstMethodArguments) this.children[i]; 58 | ret = lambda.invoke(ctx, args.getParameters(ctx)); 59 | } 60 | return ret; 61 | } 62 | } 63 | -------------------------------------------------------------------------------- /src/main/java/org/glassfish/expressly/util/MessageFactory.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2022, 2022 Contributors to the Eclipse Foundation. 3 | * Copyright (c) 1997, 2018 Oracle and/or its affiliates. All rights reserved. 4 | * 5 | * This program and the accompanying materials are made available under the 6 | * terms of the Eclipse Public License v. 2.0, which is available at 7 | * http://www.eclipse.org/legal/epl-2.0. 8 | * 9 | * This Source Code may also be made available under the following Secondary 10 | * Licenses when the conditions for such availability set forth in the 11 | * Eclipse Public License v. 2.0 are satisfied: GNU General Public License, 12 | * version 2 with the GNU Classpath Exception, which is available at 13 | * https://www.gnu.org/software/classpath/license.html. 14 | * 15 | * SPDX-License-Identifier: EPL-2.0 OR GPL-2.0 WITH Classpath-exception-2.0 16 | */ 17 | 18 | package org.glassfish.expressly.util; 19 | 20 | import java.text.MessageFormat; 21 | import java.util.ResourceBundle; 22 | 23 | /** 24 | * @author Jacob Hookom [jacob@hookom.net] 25 | * @version $Change: 181177 $$DateTime: 2001/06/26 08:45:09 $$Author: kchung $ 26 | */ 27 | public final class MessageFactory { 28 | 29 | protected final static ResourceBundle bundle = ResourceBundle.getBundle("org.glassfish.expressly.Messages"); 30 | 31 | public MessageFactory() { 32 | super(); 33 | } 34 | 35 | public static String get(final String key) { 36 | return bundle.getString(key); 37 | } 38 | 39 | public static String get(final String key, final Object obj0) { 40 | return getArray(key, new Object[] { obj0 }); 41 | } 42 | 43 | public static String get(final String key, final Object obj0, final Object obj1) { 44 | return getArray(key, new Object[] { obj0, obj1 }); 45 | } 46 | 47 | public static String get(final String key, final Object obj0, final Object obj1, final Object obj2) { 48 | return getArray(key, new Object[] { obj0, obj1, obj2 }); 49 | } 50 | 51 | public static String get(final String key, final Object obj0, final Object obj1, final Object obj2, final Object obj3) { 52 | return getArray(key, new Object[] { obj0, obj1, obj2, obj3 }); 53 | } 54 | 55 | public static String get(final String key, final Object obj0, final Object obj1, final Object obj2, final Object obj3, final Object obj4) { 56 | return getArray(key, new Object[] { obj0, obj1, obj2, obj3, obj4 }); 57 | } 58 | 59 | public static String getArray(final String key, final Object[] objA) { 60 | return MessageFormat.format(bundle.getString(key), objA); 61 | } 62 | 63 | } 64 | -------------------------------------------------------------------------------- /src/main/java/org/glassfish/expressly/parser/AstString.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2022, 2022 Contributors to the Eclipse Foundation. 3 | * Copyright (c) 2021 Payara Services Ltd. 4 | * Copyright (c) 1997, 2018 Oracle and/or its affiliates. All rights reserved. 5 | * 6 | * This program and the accompanying materials are made available under the 7 | * terms of the Eclipse Public License v. 2.0, which is available at 8 | * http://www.eclipse.org/legal/epl-2.0. 9 | * 10 | * This Source Code may also be made available under the following Secondary 11 | * Licenses when the conditions for such availability set forth in the 12 | * Eclipse Public License v. 2.0 are satisfied: GNU General Public License, 13 | * version 2 with the GNU Classpath Exception, which is available at 14 | * https://www.gnu.org/software/classpath/license.html. 15 | * 16 | * SPDX-License-Identifier: EPL-2.0 OR GPL-2.0 WITH Classpath-exception-2.0 17 | */ 18 | 19 | package org.glassfish.expressly.parser; 20 | 21 | import org.glassfish.expressly.lang.EvaluationContext; 22 | 23 | import jakarta.el.ELException; 24 | 25 | /** 26 | * @author Jacob Hookom [jacob@hookom.net] 27 | * @version $Change: 181177 $$DateTime: 2001/06/26 08:45:09 $$Author: kchung $ 28 | */ 29 | public final class AstString extends SimpleNode { 30 | 31 | public AstString(int id) { 32 | super(id); 33 | } 34 | 35 | private String string; 36 | 37 | public String getString() { 38 | if (string == null) { 39 | string = image.substring(1, image.length() - 1); 40 | } 41 | 42 | return string; 43 | } 44 | 45 | @Override 46 | public Class getType(EvaluationContext ctx) throws ELException { 47 | return String.class; 48 | } 49 | 50 | @Override 51 | public Object getValue(EvaluationContext ctx) throws ELException { 52 | return getString(); 53 | } 54 | 55 | @Override 56 | public void setImage(String image) { 57 | if (image.indexOf('\\') == -1) { 58 | this.image = image; 59 | return; 60 | } 61 | 62 | int size = image.length(); 63 | StringBuilder buf = new StringBuilder(size); 64 | for (int i = 0; i < size; i++) { 65 | char c = image.charAt(i); 66 | if (c == '\\' && i + 1 < size) { 67 | char c1 = image.charAt(i + 1); 68 | if (c1 == '\\' || c1 == '"' || c1 == '\'' || c1 == '#' || c1 == '$') { 69 | c = c1; 70 | i++; 71 | } 72 | } 73 | buf.append(c); 74 | } 75 | 76 | this.image = buf.toString(); 77 | } 78 | } 79 | -------------------------------------------------------------------------------- /src/test/java/jakarta/el/DefaultMethodTest.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2021 Contributors to the Eclipse Foundation. 3 | * 4 | * This program and the accompanying materials are made available under the 5 | * terms of the Eclipse Public License v. 2.0, which is available at 6 | * http://www.eclipse.org/legal/epl-2.0. 7 | * 8 | * This Source Code may also be made available under the following Secondary 9 | * Licenses when the conditions for such availability set forth in the 10 | * Eclipse Public License v. 2.0 are satisfied: GNU General Public License, 11 | * version 2 with the GNU Classpath Exception, which is available at 12 | * https://www.gnu.org/software/classpath/license.html. 13 | * 14 | * SPDX-License-Identifier: EPL-2.0 OR GPL-2.0 WITH Classpath-exception-2.0 15 | */ 16 | package jakarta.el; 17 | 18 | import org.junit.Assert; 19 | import org.junit.Test; 20 | 21 | /** 22 | * Tests the behaviour of the BeanELResolver with default methods. 23 | */ 24 | public class DefaultMethodTest { 25 | 26 | public interface MyInterface { 27 | default public String getValueB() { 28 | return "defaultB"; 29 | } 30 | default public String getValueC() { 31 | return "defaultC"; 32 | } 33 | } 34 | 35 | public class MyBean implements MyInterface { 36 | public String getValueA() { 37 | return "valueA"; 38 | } 39 | 40 | @Override 41 | public String getValueC() { 42 | return "valueC"; 43 | } 44 | 45 | } 46 | 47 | @Test 48 | public void testGetValue() { 49 | 50 | MyBean bean = new MyBean(); 51 | 52 | BeanELResolver resolver = new BeanELResolver(); 53 | ELContext context = new StandardELContext(ELManager.getExpressionFactory()); 54 | 55 | Object result = resolver.getValue(context, bean, "valueA"); 56 | Assert.assertEquals(bean.getValueA(), result); 57 | } 58 | 59 | @Test 60 | public void testGetDefaultValue() { 61 | 62 | MyBean bean = new MyBean(); 63 | 64 | BeanELResolver resolver = new BeanELResolver(); 65 | ELContext context = new StandardELContext(ELManager.getExpressionFactory()); 66 | 67 | Object result = resolver.getValue(context, bean, "valueB"); 68 | Assert.assertEquals(bean.getValueB(), result); 69 | } 70 | 71 | @Test 72 | public void testGetDefaultOverriddenValue() { 73 | 74 | MyBean bean = new MyBean(); 75 | 76 | BeanELResolver resolver = new BeanELResolver(); 77 | ELContext context = new StandardELContext(ELManager.getExpressionFactory()); 78 | 79 | Object result = resolver.getValue(context, bean, "valueC"); 80 | Assert.assertEquals(bean.getValueC(), result); 81 | } 82 | } 83 | -------------------------------------------------------------------------------- /src/main/java/org/glassfish/expressly/parser/AstChoice.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2022, 2022 Contributors to the Eclipse Foundation. 3 | * Copyright (c) 1997, 2018 Oracle and/or its affiliates. All rights reserved. 4 | * 5 | * This program and the accompanying materials are made available under the 6 | * terms of the Eclipse Public License v. 2.0, which is available at 7 | * http://www.eclipse.org/legal/epl-2.0. 8 | * 9 | * This Source Code may also be made available under the following Secondary 10 | * Licenses when the conditions for such availability set forth in the 11 | * Eclipse Public License v. 2.0 are satisfied: GNU General Public License, 12 | * version 2 with the GNU Classpath Exception, which is available at 13 | * https://www.gnu.org/software/classpath/license.html. 14 | * 15 | * SPDX-License-Identifier: EPL-2.0 OR GPL-2.0 WITH Classpath-exception-2.0 16 | */ 17 | 18 | package org.glassfish.expressly.parser; 19 | 20 | import org.glassfish.expressly.lang.EvaluationContext; 21 | 22 | import jakarta.el.ELException; 23 | 24 | /** 25 | * @author Jacob Hookom [jacob@hookom.net] 26 | * @version $Change: 181177 $$DateTime: 2001/06/26 08:45:09 $$Author: kchung $ 27 | */ 28 | public final class AstChoice extends SimpleNode { 29 | public AstChoice(int id) { 30 | super(id); 31 | } 32 | 33 | @Override 34 | public Class getType(EvaluationContext ctx) throws ELException { 35 | Object obj0 = this.children[0].getValue(ctx); 36 | Boolean b0 = coerceToBoolean(obj0); 37 | return this.children[((b0.booleanValue() ? 1 : 2))].getType(ctx); 38 | } 39 | 40 | @Override 41 | public Object getValue(EvaluationContext ctx) throws ELException { 42 | Object obj0 = this.children[0].getValue(ctx); 43 | Boolean b0 = coerceToBoolean(obj0); 44 | return this.children[((b0.booleanValue() ? 1 : 2))].getValue(ctx); 45 | } 46 | 47 | @Override 48 | public boolean isReadOnly(EvaluationContext ctx) throws ELException { 49 | Object obj0 = this.children[0].getValue(ctx); 50 | Boolean b0 = coerceToBoolean(obj0); 51 | return this.children[((b0.booleanValue() ? 1 : 2))].isReadOnly(ctx); 52 | } 53 | 54 | @Override 55 | public void setValue(EvaluationContext ctx, Object value) throws ELException { 56 | Object obj0 = this.children[0].getValue(ctx); 57 | Boolean b0 = coerceToBoolean(obj0); 58 | this.children[((b0.booleanValue() ? 1 : 2))].setValue(ctx, value); 59 | } 60 | 61 | @Override 62 | public Object invoke(EvaluationContext ctx, Class[] paramTypes, Object[] paramValues) throws ELException { 63 | Object obj0 = this.children[0].getValue(ctx); 64 | Boolean b0 = coerceToBoolean(obj0); 65 | return this.children[((b0.booleanValue() ? 1 : 2))].invoke(ctx, paramTypes, paramValues); 66 | } 67 | 68 | } 69 | -------------------------------------------------------------------------------- /src/main/java/org/glassfish/expressly/parser/AstNegative.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2022, 2022 Contributors to the Eclipse Foundation. 3 | * Copyright (c) 1997, 2018 Oracle and/or its affiliates. All rights reserved. 4 | * 5 | * This program and the accompanying materials are made available under the 6 | * terms of the Eclipse Public License v. 2.0, which is available at 7 | * http://www.eclipse.org/legal/epl-2.0. 8 | * 9 | * This Source Code may also be made available under the following Secondary 10 | * Licenses when the conditions for such availability set forth in the 11 | * Eclipse Public License v. 2.0 are satisfied: GNU General Public License, 12 | * version 2 with the GNU Classpath Exception, which is available at 13 | * https://www.gnu.org/software/classpath/license.html. 14 | * 15 | * SPDX-License-Identifier: EPL-2.0 OR GPL-2.0 WITH Classpath-exception-2.0 16 | */ 17 | 18 | package org.glassfish.expressly.parser; 19 | 20 | import java.math.BigDecimal; 21 | import java.math.BigInteger; 22 | 23 | import org.glassfish.expressly.lang.EvaluationContext; 24 | 25 | import jakarta.el.ELException; 26 | 27 | /** 28 | * @author Jacob Hookom [jacob@hookom.net] 29 | * @version $Change: 181177 $$DateTime: 2001/06/26 08:45:09 $$Author: kchung $ 30 | */ 31 | public final class AstNegative extends SimpleNode { 32 | public AstNegative(int id) { 33 | super(id); 34 | } 35 | 36 | @Override 37 | public Class getType(EvaluationContext ctx) throws ELException { 38 | return Number.class; 39 | } 40 | 41 | @Override 42 | public Object getValue(EvaluationContext ctx) throws ELException { 43 | Object obj = children[0].getValue(ctx); 44 | 45 | if (obj == null) { 46 | return Long.valueOf(0); 47 | } 48 | if (obj instanceof BigDecimal) { 49 | return ((BigDecimal) obj).negate(); 50 | } 51 | if (obj instanceof BigInteger) { 52 | return ((BigInteger) obj).negate(); 53 | } 54 | if (obj instanceof String) { 55 | if (isStringFloat((String) obj)) { 56 | return Double.valueOf(-Double.parseDouble((String) obj)); 57 | } 58 | return Long.valueOf(-Long.parseLong((String) obj)); 59 | } 60 | 61 | Class type = obj.getClass(); 62 | if (obj instanceof Long || Long.TYPE == type) { 63 | return Long.valueOf(-((Long) obj).longValue()); 64 | } 65 | if (obj instanceof Double || Double.TYPE == type) { 66 | return Double.valueOf(-((Double) obj).doubleValue()); 67 | } 68 | if (obj instanceof Integer || Integer.TYPE == type) { 69 | return Integer.valueOf(-((Integer) obj).intValue()); 70 | } 71 | if (obj instanceof Float || Float.TYPE == type) { 72 | return Float.valueOf(-((Float) obj).floatValue()); 73 | } 74 | if (obj instanceof Short || Short.TYPE == type) { 75 | return Short.valueOf((short) -((Short) obj).shortValue()); 76 | } 77 | if (obj instanceof Byte || Byte.TYPE == type) { 78 | return Byte.valueOf((byte) -((Byte) obj).byteValue()); 79 | } 80 | Long num = (Long) coerceToNumber(obj, Long.class); 81 | return Long.valueOf(-num.longValue()); 82 | } 83 | } 84 | -------------------------------------------------------------------------------- /src/main/java/org/glassfish/expressly/parser/Node.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2022, 2022 Contributors to the Eclipse Foundation. 3 | * Copyright (c) 1997, 2018 Oracle and/or its affiliates. All rights reserved. 4 | * 5 | * This program and the accompanying materials are made available under the 6 | * terms of the Eclipse Public License v. 2.0, which is available at 7 | * http://www.eclipse.org/legal/epl-2.0. 8 | * 9 | * This Source Code may also be made available under the following Secondary 10 | * Licenses when the conditions for such availability set forth in the 11 | * Eclipse Public License v. 2.0 are satisfied: GNU General Public License, 12 | * version 2 with the GNU Classpath Exception, which is available at 13 | * https://www.gnu.org/software/classpath/license.html. 14 | * 15 | * SPDX-License-Identifier: EPL-2.0 OR GPL-2.0 WITH Classpath-exception-2.0 16 | */ 17 | 18 | package org.glassfish.expressly.parser; 19 | 20 | import org.glassfish.expressly.lang.EvaluationContext; 21 | 22 | import jakarta.el.ELException; 23 | import jakarta.el.MethodInfo; 24 | import jakarta.el.MethodReference; 25 | import jakarta.el.ValueReference; 26 | 27 | /* All AST nodes must implement this interface. It provides basic 28 | machinery for constructing the parent and child relationships 29 | between nodes. */ 30 | 31 | /** 32 | * @author Jacob Hookom [jacob@hookom.net] 33 | * @version $Change: 181177 $$DateTime: 2001/06/26 08:45:09 $$Author: kchung $ 34 | */ 35 | public interface Node { 36 | 37 | /** 38 | * This method is called after the node has been made the current node. It indicates that child nodes can now be added 39 | * to it. 40 | */ 41 | void jjtOpen(); 42 | 43 | /** 44 | * This method is called after all the child nodes have been added. 45 | */ 46 | void jjtClose(); 47 | 48 | /** 49 | * This pair of methods are used to inform the node of its parent. 50 | */ 51 | void jjtSetParent(Node n); 52 | 53 | Node jjtGetParent(); 54 | 55 | /** 56 | * This method tells the node to add its argument to the node's list of children. 57 | */ 58 | void jjtAddChild(Node n, int i); 59 | 60 | /** 61 | * This method returns a child node. The children are numbered from zero, left to right. 62 | */ 63 | Node jjtGetChild(int i); 64 | 65 | /** Return the number of children the node has. */ 66 | int jjtGetNumChildren(); 67 | 68 | String getImage(); 69 | 70 | Object getValue(EvaluationContext ctx) throws ELException; 71 | 72 | void setValue(EvaluationContext ctx, Object value) throws ELException; 73 | 74 | Class getType(EvaluationContext ctx) throws ELException; 75 | 76 | ValueReference getValueReference(EvaluationContext ctx) throws ELException; 77 | 78 | boolean isReadOnly(EvaluationContext ctx) throws ELException; 79 | 80 | void accept(NodeVisitor visitor) throws ELException; 81 | 82 | MethodInfo getMethodInfo(EvaluationContext ctx, Class[] paramTypes) throws ELException; 83 | 84 | MethodReference getMethodReference(EvaluationContext ctx); 85 | 86 | Object invoke(EvaluationContext ctx, Class[] paramTypes, Object[] paramValues) throws ELException; 87 | 88 | @Override 89 | boolean equals(Object n); 90 | 91 | @Override 92 | int hashCode(); 93 | 94 | boolean isParametersProvided(); 95 | } 96 | -------------------------------------------------------------------------------- /src/main/java/org/glassfish/expressly/Messages.properties: -------------------------------------------------------------------------------- 1 | # 2 | # Copyright (c) 1997, 2018 Oracle and/or its affiliates. All rights reserved. 3 | # 4 | # This program and the accompanying materials are made available under the 5 | # terms of the Eclipse Public License v. 2.0, which is available at 6 | # http://www.eclipse.org/legal/epl-2.0. 7 | # 8 | # This Source Code may also be made available under the following Secondary 9 | # Licenses when the conditions for such availability set forth in the 10 | # Eclipse Public License v. 2.0 are satisfied: GNU General Public License, 11 | # version 2 with the GNU Classpath Exception, which is available at 12 | # https://www.gnu.org/software/classpath/license.html. 13 | # 14 | # SPDX-License-Identifier: EPL-2.0 OR GPL-2.0 WITH Classpath-exception-2.0 15 | # 16 | 17 | # General Errors 18 | error.convert=Cannot convert {0} of type {1} to {2} 19 | error.compare=Cannot compare {0} to {1} 20 | error.function=Problems calling function ''{0}'' 21 | error.function.syntax=Syntax error in calling function ''{0}'' 22 | error.unreachable.base=Target Unreachable, identifier ''{0}'' resolved to null 23 | error.unreachable.property=Target Unreachable, ''{0}'' returned null 24 | error.resolver.unhandled=ELResolver did not handle type: {0} with property of ''{1}'' 25 | error.resolver.unhandled.null=ELResolver cannot handle a null base Object with identifier ''{0}'' 26 | 27 | # ValueExpressionLiteral 28 | error.value.literal.write=ValueExpression is a literal and not writable: {0} 29 | 30 | # ExpressionFactoryImpl 31 | error.null=Expression cannot be null 32 | error.mixed=Expression cannot contain both '#{..}' and '${..}' : {0} 33 | error.method=Not a valid MethodExpression : {0} 34 | error.method.nullParms=Parameter types cannot be null 35 | error.value.expectedType=Expected type cannot be null 36 | 37 | # ExpressionMediator 38 | error.eval=Error Evaluating {0} : {1} 39 | 40 | # ValueSetVisitor 41 | error.syntax.set=Illegal Syntax for Set Operation 42 | 43 | error.syntax.assign=Illegal Syntax for Assign Operation 44 | 45 | # ReflectionUtil 46 | error.method.notfound=Method not found: {0}.{1}({2}) 47 | error.method.ambiguous=Unable to find unambiguous method: {0}.{1}({2}) 48 | error.property.notfound=Property ''{1}'' not found on {0} 49 | 50 | # ValidatingVisitor 51 | error.fnMapper.null=Expression uses functions, but no FunctionMapper was provided 52 | error.fnMapper.method=Function ''{0}'' not found 53 | error.fnMapper.paramcount=Function ''{0}'' specifies {1} params, but {2} were supplied 54 | 55 | # **ExpressionImpl 56 | error.context.null=ELContext was null 57 | 58 | # ArrayELResolver 59 | error.array.outofbounds=Index {0} is out of bounds for array of size {1} 60 | 61 | # ListELResolver 62 | error.list.outofbounds=Index {0} is out of bounds for list of size {1} 63 | 64 | # BeanELResolver 65 | error.property.notfound=Property ''{1}'' not found on type: {0} 66 | error.property.invocation=Property ''{1}'' threw an exception from type: {0} 67 | error.property.notreadable=Property ''{1}'' doesn't have a 'get' specified on type: {0} 68 | error.property.notwritable=Property ''{1}'' doesn't have a 'set' specified on type: {0} 69 | 70 | # AstValue 71 | error.method.name=An instance of {0} is specified as the static method name, it 72 | must be a String 73 | 74 | # AstType 75 | error.class.notfound=The specified class ''{0}'' not found 76 | 77 | # AstLambdaExpression 78 | error.lambda.call=A Lambda expression must return another Lambda expression in this syntax 79 | error.lambda.parameter.readonly=The Lambda parameter ''{0}'' is not writable 80 | -------------------------------------------------------------------------------- /src/main/java/org/glassfish/expressly/parser/ELParserTreeConstants.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2018 Oracle and/or its affiliates. All rights reserved. 3 | * 4 | * This program and the accompanying materials are made available under the 5 | * terms of the Eclipse Public License v. 2.0, which is available at 6 | * http://www.eclipse.org/legal/epl-2.0. 7 | * 8 | * This Source Code may also be made available under the following Secondary 9 | * Licenses when the conditions for such availability set forth in the 10 | * Eclipse Public License v. 2.0 are satisfied: GNU General Public License, 11 | * version 2 with the GNU Classpath Exception, which is available at 12 | * https://www.gnu.org/software/classpath/license.html. 13 | * 14 | * SPDX-License-Identifier: EPL-2.0 OR GPL-2.0 WITH Classpath-exception-2.0 15 | */ 16 | 17 | /* Generated By:JavaCC: Do not edit this line. ELParserTreeConstants.java Version 5.0 */ 18 | package org.glassfish.expressly.parser; 19 | 20 | public interface ELParserTreeConstants 21 | { 22 | public int JJTCOMPOSITEEXPRESSION = 0; 23 | public int JJTLITERALEXPRESSION = 1; 24 | public int JJTDEFERREDEXPRESSION = 2; 25 | public int JJTDYNAMICEXPRESSION = 3; 26 | public int JJTVOID = 4; 27 | public int JJTSEMICOLON = 5; 28 | public int JJTASSIGN = 6; 29 | public int JJTLAMBDAEXPRESSION = 7; 30 | public int JJTLAMBDAPARAMETERS = 8; 31 | public int JJTCHOICE = 9; 32 | public int JJTOR = 10; 33 | public int JJTAND = 11; 34 | public int JJTEQUAL = 12; 35 | public int JJTNOTEQUAL = 13; 36 | public int JJTLESSTHAN = 14; 37 | public int JJTGREATERTHAN = 15; 38 | public int JJTLESSTHANEQUAL = 16; 39 | public int JJTGREATERTHANEQUAL = 17; 40 | public int JJTCONCAT = 18; 41 | public int JJTPLUS = 19; 42 | public int JJTMINUS = 20; 43 | public int JJTMULT = 21; 44 | public int JJTDIV = 22; 45 | public int JJTMOD = 23; 46 | public int JJTNEGATIVE = 24; 47 | public int JJTNOT = 25; 48 | public int JJTEMPTY = 26; 49 | public int JJTVALUE = 27; 50 | public int JJTDOTSUFFIX = 28; 51 | public int JJTBRACKETSUFFIX = 29; 52 | public int JJTMETHODARGUMENTS = 30; 53 | public int JJTMAPDATA = 31; 54 | public int JJTMAPENTRY = 32; 55 | public int JJTLISTDATA = 33; 56 | public int JJTIDENTIFIER = 34; 57 | public int JJTFUNCTION = 35; 58 | public int JJTTRUE = 36; 59 | public int JJTFALSE = 37; 60 | public int JJTFLOATINGPOINT = 38; 61 | public int JJTINTEGER = 39; 62 | public int JJTSTRING = 40; 63 | public int JJTNULL = 41; 64 | 65 | 66 | public String[] jjtNodeName = { 67 | "CompositeExpression", 68 | "LiteralExpression", 69 | "DeferredExpression", 70 | "DynamicExpression", 71 | "void", 72 | "SemiColon", 73 | "Assign", 74 | "LambdaExpression", 75 | "LambdaParameters", 76 | "Choice", 77 | "Or", 78 | "And", 79 | "Equal", 80 | "NotEqual", 81 | "LessThan", 82 | "GreaterThan", 83 | "LessThanEqual", 84 | "GreaterThanEqual", 85 | "Concat", 86 | "Plus", 87 | "Minus", 88 | "Mult", 89 | "Div", 90 | "Mod", 91 | "Negative", 92 | "Not", 93 | "Empty", 94 | "Value", 95 | "DotSuffix", 96 | "BracketSuffix", 97 | "MethodArguments", 98 | "MapData", 99 | "MapEntry", 100 | "ListData", 101 | "Identifier", 102 | "Function", 103 | "True", 104 | "False", 105 | "FloatingPoint", 106 | "Integer", 107 | "String", 108 | "Null", 109 | }; 110 | } 111 | /* JavaCC - OriginalChecksum=295bae338407e43a1d349f1ce802614a (do not edit this line) */ 112 | -------------------------------------------------------------------------------- /src/main/java/org/glassfish/expressly/MethodExpressionLiteral.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2022, 2022 Contributors to the Eclipse Foundation. 3 | * Copyright (c) 1997, 2018 Oracle and/or its affiliates. All rights reserved. 4 | * 5 | * This program and the accompanying materials are made available under the 6 | * terms of the Eclipse Public License v. 2.0, which is available at 7 | * http://www.eclipse.org/legal/epl-2.0. 8 | * 9 | * This Source Code may also be made available under the following Secondary 10 | * Licenses when the conditions for such availability set forth in the 11 | * Eclipse Public License v. 2.0 are satisfied: GNU General Public License, 12 | * version 2 with the GNU Classpath Exception, which is available at 13 | * https://www.gnu.org/software/classpath/license.html. 14 | * 15 | * SPDX-License-Identifier: EPL-2.0 OR GPL-2.0 WITH Classpath-exception-2.0 16 | */ 17 | 18 | package org.glassfish.expressly; 19 | 20 | import static org.glassfish.expressly.util.ReflectionUtil.toTypeArray; 21 | import static org.glassfish.expressly.util.ReflectionUtil.toTypeNameArray; 22 | 23 | import java.io.Externalizable; 24 | import java.io.IOException; 25 | import java.io.ObjectInput; 26 | import java.io.ObjectOutput; 27 | 28 | import org.glassfish.expressly.util.ReflectionUtil; 29 | 30 | import jakarta.el.ELContext; 31 | import jakarta.el.ELException; 32 | import jakarta.el.MethodExpression; 33 | import jakarta.el.MethodInfo; 34 | 35 | public class MethodExpressionLiteral extends MethodExpression implements Externalizable { 36 | 37 | private Class expectedType; 38 | private String expression; 39 | private Class[] paramTypes; 40 | 41 | public MethodExpressionLiteral() { 42 | // do nothing 43 | } 44 | 45 | public MethodExpressionLiteral(String expression, Class expectedType, Class[] paramTypes) { 46 | this.expression = expression; 47 | this.expectedType = expectedType; 48 | this.paramTypes = paramTypes; 49 | } 50 | 51 | @Override 52 | public MethodInfo getMethodInfo(ELContext context) throws ELException { 53 | return new MethodInfo(expression, expectedType, paramTypes); 54 | } 55 | 56 | @Override 57 | public Object invoke(ELContext context, Object[] params) throws ELException { 58 | if (expectedType == null) { 59 | return expression; 60 | } 61 | 62 | try { 63 | return context.convertToType(expression, expectedType); 64 | } catch (Exception ex) { 65 | throw new ELException(ex); 66 | } 67 | } 68 | 69 | @Override 70 | public String getExpressionString() { 71 | return expression; 72 | } 73 | 74 | @Override 75 | public boolean equals(Object obj) { 76 | return obj instanceof MethodExpressionLiteral && this.hashCode() == obj.hashCode(); 77 | } 78 | 79 | @Override 80 | public int hashCode() { 81 | return expression.hashCode(); 82 | } 83 | 84 | @Override 85 | public boolean isLiteralText() { 86 | return true; 87 | } 88 | 89 | @Override 90 | public void readExternal(ObjectInput in) throws IOException, ClassNotFoundException { 91 | expression = in.readUTF(); 92 | String type = in.readUTF(); 93 | 94 | if (!"".equals(type)) { 95 | expectedType = ReflectionUtil.forName(type); 96 | } 97 | 98 | paramTypes = toTypeArray(((String[]) in.readObject())); 99 | } 100 | 101 | @Override 102 | public void writeExternal(ObjectOutput out) throws IOException { 103 | out.writeUTF(expression); 104 | out.writeUTF(expectedType != null ? expectedType.getName() : ""); 105 | out.writeObject(toTypeNameArray(paramTypes)); 106 | } 107 | } 108 | -------------------------------------------------------------------------------- /src/main/java/org/glassfish/expressly/parser/Token.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2022, 2022 Contributors to the Eclipse Foundation. 3 | * Copyright (c) 1997, 2018 Oracle and/or its affiliates. All rights reserved. 4 | * 5 | * This program and the accompanying materials are made available under the 6 | * terms of the Eclipse Public License v. 2.0, which is available at 7 | * http://www.eclipse.org/legal/epl-2.0. 8 | * 9 | * This Source Code may also be made available under the following Secondary 10 | * Licenses when the conditions for such availability set forth in the 11 | * Eclipse Public License v. 2.0 are satisfied: GNU General Public License, 12 | * version 2 with the GNU Classpath Exception, which is available at 13 | * https://www.gnu.org/software/classpath/license.html. 14 | * 15 | * SPDX-License-Identifier: EPL-2.0 OR GPL-2.0 WITH Classpath-exception-2.0 16 | */ 17 | 18 | package org.glassfish.expressly.parser; 19 | 20 | import java.io.Serializable; 21 | 22 | /** 23 | * Describes the input token stream. 24 | */ 25 | 26 | public class Token implements Serializable { 27 | 28 | private static final long serialVersionUID = 1L; 29 | 30 | /** 31 | * An integer that describes the kind of this token. This numbering system is determined by JavaCCParser, and a table of 32 | * these numbers is stored in the file ...Constants.java. 33 | */ 34 | public int kind; 35 | 36 | /** 37 | * beginLine and beginColumn describe the position of the first character of this token; endLine and endColumn describe 38 | * the position of the last character of this token. 39 | */ 40 | public int beginLine, beginColumn, endLine, endColumn; 41 | 42 | /** 43 | * The string image of the token. 44 | */ 45 | public String image; 46 | 47 | /** 48 | * A reference to the next regular (non-special) token from the input stream. If this is the last token from the input 49 | * stream, or if the token manager has not read tokens beyond this one, this field is set to null. This is true only if 50 | * this token is also a regular token. Otherwise, see below for a description of the contents of this field. 51 | */ 52 | public Token next; 53 | 54 | /** 55 | * This field is used to access special tokens that occur prior to this token, but after the immediately preceding 56 | * regular (non-special) token. If there are no such special tokens, this field is set to null. When there are more than 57 | * one such special token, this field refers to the last of these special tokens, which in turn refers to the next 58 | * previous special token through its specialToken field, and so on until the first special token (whose specialToken 59 | * field is null). The next fields of special tokens refer to other special tokens that immediately follow it (without 60 | * an intervening regular token). If there is no such token, this field is null. 61 | */ 62 | public Token specialToken; 63 | 64 | /** 65 | * Returns the image. 66 | */ 67 | @Override 68 | public String toString() { 69 | return image; 70 | } 71 | 72 | /** 73 | * Returns a new Token object, by default. However, if you want, you can create and return subclass objects based on the 74 | * value of ofKind. Simply add the cases to the switch for all those special cases. For example, if you have a subclass 75 | * of Token called IDToken that you want to create if ofKind is ID, simlpy add something like : 76 | * 77 | * case MyParserConstants.ID : return new IDToken(); 78 | * 79 | * to the following switch statement. Then you can cast matchedToken variable to the appropriate type and use it in your 80 | * lexical actions. 81 | */ 82 | public static final Token newToken(int ofKind) { 83 | switch (ofKind) { 84 | default: 85 | return new Token(); 86 | } 87 | } 88 | 89 | } 90 | -------------------------------------------------------------------------------- /src/test/java/org/glassfish/el/test/DataBase.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2018 Oracle and/or its affiliates. All rights reserved. 3 | * 4 | * This program and the accompanying materials are made available under the 5 | * terms of the Eclipse Public License v. 2.0, which is available at 6 | * http://www.eclipse.org/legal/epl-2.0. 7 | * 8 | * This Source Code may also be made available under the following Secondary 9 | * Licenses when the conditions for such availability set forth in the 10 | * Eclipse Public License v. 2.0 are satisfied: GNU General Public License, 11 | * version 2 with the GNU Classpath Exception, which is available at 12 | * https://www.gnu.org/software/classpath/license.html. 13 | * 14 | * SPDX-License-Identifier: EPL-2.0 OR GPL-2.0 WITH Classpath-exception-2.0 15 | */ 16 | 17 | package org.glassfish.el.test; 18 | 19 | import java.util.List; 20 | import java.util.ArrayList; 21 | 22 | public class DataBase { 23 | 24 | private int curCustomer = 100; 25 | private int curProduct = 200; 26 | private int curOrder = 10; 27 | private boolean inited; 28 | 29 | private List customers; 30 | private List products; 31 | private List orders; 32 | 33 | public List getCustomers() { return this.customers; } 34 | public List getProducts() { return this.products; } 35 | public List getOrders() { return this.orders; } 36 | 37 | public void init() { 38 | if (inited) { 39 | return; 40 | } 41 | 42 | inited = true; 43 | customers = new ArrayList<>(); 44 | orders = new ArrayList<>(); 45 | products = new ArrayList<>(); 46 | initCustomer(); 47 | initProduct(); 48 | initOrder(); 49 | } 50 | 51 | void initCustomer() { 52 | c("John Doe", "123 Willow Road", "Menlo Park", "USA", 53 | "650-734-2187"); 54 | c("Mary Lane", "75 State Street", "Atlanta", "USA", "302-145-8765"); 55 | c("Charlie Yeh", "5 Nathan Road", "Kowlon", "Hong Kong", "11-7565-2323"); 56 | } 57 | 58 | void initProduct() { 59 | p("Eagle", "book", 12.50, 100); // id: 200 60 | p("Coming Home", "dvd", 8.00, 50); // id: 201 61 | p("Greatest Hits", "cd", 6.5, 200); // id: 202 62 | p("History of Golf", "book", 11.0, 30); // id: 203 63 | p("Toy Story", "dvd", 10.00, 1000); // id: 204 64 | p("iSee", "book", 12.50, 150); // 205 65 | } 66 | 67 | void initOrder() { 68 | o(100, new Date(2010, 2, 18), 20.80); 69 | o(100, new Date(2011, 5, 3), 34.50); 70 | o(100, new Date(2011, 8, 2), 210.75); 71 | o(101, new Date(2011, 1, 15), 50.23); 72 | o(101, new Date(2012, 1, 3), 126.77); 73 | o(102, new Date(2011, 4, 15), 101.20); 74 | } 75 | 76 | void c(String name, String address, String city, 77 | String country, String phone) { 78 | customers.add(new Customer(curCustomer++, name, address, 79 | city, country, phone)); 80 | } 81 | 82 | void o(int customerID, Date orderDate, double total) { 83 | Order order = new Order(curOrder++, customerID, orderDate, total); 84 | this.orders.add(order); 85 | findCustomer(customerID).getOrders().add(order); 86 | } 87 | 88 | void p(String name, String category, double unitPrice, int unitsInStock) { 89 | products.add(new Product(curProduct++, name, category, unitPrice, 90 | unitsInStock)); 91 | } 92 | 93 | private Customer findCustomer(int id) { 94 | for(Customer customer: customers) { 95 | if (customer.customerID == id) { 96 | return customer; 97 | } 98 | } 99 | return null; 100 | } 101 | } 102 | 103 | -------------------------------------------------------------------------------- /src/main/java/org/glassfish/expressly/stream/StreamELResolver.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2022, 2022 Contributors to the Eclipse Foundation. 3 | * Copyright (c) 2012, 2018 Oracle and/or its affiliates. All rights reserved. 4 | * 5 | * This program and the accompanying materials are made available under the 6 | * terms of the Eclipse Public License v. 2.0, which is available at 7 | * http://www.eclipse.org/legal/epl-2.0. 8 | * 9 | * This Source Code may also be made available under the following Secondary 10 | * Licenses when the conditions for such availability set forth in the 11 | * Eclipse Public License v. 2.0 are satisfied: GNU General Public License, 12 | * version 2 with the GNU Classpath Exception, which is available at 13 | * https://www.gnu.org/software/classpath/license.html. 14 | * 15 | * SPDX-License-Identifier: EPL-2.0 OR GPL-2.0 WITH Classpath-exception-2.0 16 | */ 17 | 18 | package org.glassfish.expressly.stream; 19 | 20 | import jakarta.el.ELContext; 21 | import jakarta.el.ELResolver; 22 | import java.lang.reflect.Array; 23 | import java.util.Collection; 24 | import java.util.Iterator; 25 | 26 | /* 27 | * This ELResolver intercepts method calls to a Collections, to provide 28 | * support for collection operations. 29 | */ 30 | 31 | public class StreamELResolver extends ELResolver { 32 | 33 | @Override 34 | public Object invoke(final ELContext context, final Object base, final Object method, final Class[] paramTypes, final Object[] params) { 35 | if (context == null) { 36 | throw new NullPointerException(); 37 | } 38 | 39 | if (base instanceof Collection) { 40 | @SuppressWarnings("unchecked") 41 | Collection collection = (Collection) base; 42 | if ("stream".equals(method) && params.length == 0) { 43 | context.setPropertyResolved(true); 44 | return new Stream(collection.iterator()); 45 | } 46 | } 47 | 48 | if (base.getClass().isArray()) { 49 | if ("stream".equals(method) && params.length == 0) { 50 | context.setPropertyResolved(true); 51 | return new Stream(arrayIterator(base)); 52 | } 53 | } 54 | 55 | return null; 56 | } 57 | 58 | private static Iterator arrayIterator(final Object base) { 59 | final int size = Array.getLength(base); 60 | return new Iterator() { 61 | int index = 0; 62 | boolean yielded; 63 | Object current; 64 | 65 | @Override 66 | public boolean hasNext() { 67 | if ((!yielded) && index < size) { 68 | current = Array.get(base, index++); 69 | yielded = true; 70 | } 71 | return yielded; 72 | } 73 | 74 | @Override 75 | public Object next() { 76 | yielded = false; 77 | return current; 78 | } 79 | 80 | @Override 81 | public void remove() { 82 | throw new UnsupportedOperationException(); 83 | } 84 | }; 85 | } 86 | 87 | @Override 88 | public Object getValue(ELContext context, Object base, Object property) { 89 | return null; 90 | } 91 | 92 | @Override 93 | public Class getType(ELContext context, Object base, Object property) { 94 | return null; 95 | } 96 | 97 | @Override 98 | public void setValue(ELContext context, Object base, Object property, Object value) { 99 | } 100 | 101 | @Override 102 | public boolean isReadOnly(ELContext context, Object base, Object property) { 103 | return false; 104 | } 105 | 106 | @Override 107 | public Class getCommonPropertyType(ELContext context, Object base) { 108 | return String.class; 109 | } 110 | } 111 | -------------------------------------------------------------------------------- /src/test/java/org/glassfish/el/test/EvalListenerTest.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2018 Oracle and/or its affiliates. All rights reserved. 3 | * 4 | * This program and the accompanying materials are made available under the 5 | * terms of the Eclipse Public License v. 2.0, which is available at 6 | * http://www.eclipse.org/legal/epl-2.0. 7 | * 8 | * This Source Code may also be made available under the following Secondary 9 | * Licenses when the conditions for such availability set forth in the 10 | * Eclipse Public License v. 2.0 are satisfied: GNU General Public License, 11 | * version 2 with the GNU Classpath Exception, which is available at 12 | * https://www.gnu.org/software/classpath/license.html. 13 | * 14 | * SPDX-License-Identifier: EPL-2.0 OR GPL-2.0 WITH Classpath-exception-2.0 15 | */ 16 | 17 | package org.glassfish.el.test; 18 | 19 | import java.util.ArrayList; 20 | import jakarta.el.ELManager; 21 | import jakarta.el.ELContext; 22 | import jakarta.el.ELProcessor; 23 | import jakarta.el.EvaluationListener; 24 | import org.junit.After; 25 | import org.junit.AfterClass; 26 | import org.junit.Before; 27 | import org.junit.BeforeClass; 28 | import org.junit.Test; 29 | import static org.junit.Assert.*; 30 | 31 | /** 32 | * 33 | * @author kichung 34 | */ 35 | public class EvalListenerTest { 36 | 37 | public EvalListenerTest() { 38 | } 39 | 40 | @BeforeClass 41 | public static void setUpClass() throws Exception { 42 | System.setProperty("jakarta.el.ExpressionFactory", "org.glassfish.expressly.ExpressionFactoryImpl"); 43 | } 44 | 45 | @AfterClass 46 | public static void tearDownClass() throws Exception { 47 | } 48 | 49 | @Before 50 | public void setUp() { 51 | } 52 | 53 | @After 54 | public void tearDown() { 55 | } 56 | 57 | @Test 58 | public void testEvalListener() { 59 | ELProcessor elp = new ELProcessor(); 60 | ELManager elm = elp.getELManager(); 61 | final ArrayList msgs = new ArrayList<>(); 62 | elm.addEvaluationListener(new EvaluationListener() { 63 | @Override 64 | public void beforeEvaluation(ELContext ctxt, String expr) { 65 | System.out.println("Before: " + expr); 66 | msgs.add("Before: " + expr); 67 | } 68 | @Override 69 | public void afterEvaluation(ELContext ctxt, String expr) { 70 | System.out.println("After: " + expr); 71 | msgs.add("After: " + expr); 72 | } 73 | }); 74 | elp.eval("100 + 10"); 75 | elp.eval("x = 5; x*101"); 76 | String[] expected = {"Before: ${100 + 10}", 77 | "After: ${100 + 10}", 78 | "Before: ${x = 5; x*101}", 79 | "After: ${x = 5; x*101}" }; 80 | for (int i = 0; i < expected.length; i++) { 81 | assertEquals(expected[i], msgs.get(i)); 82 | } 83 | } 84 | 85 | @Test 86 | public void testResListener() { 87 | ELProcessor elp = new ELProcessor(); 88 | ELManager elm = elp.getELManager(); 89 | final ArrayList msgs = new ArrayList<>(); 90 | elm.addEvaluationListener(new EvaluationListener() { 91 | @Override 92 | public void propertyResolved(ELContext ctxt, Object b, Object p) { 93 | System.out.println("Resolved: " + b + " " + p); 94 | msgs.add("Resolved: " + b + " " + p); 95 | } 96 | }); 97 | elp.eval("x = 10"); 98 | elp.eval("[1,2,3][2]"); 99 | elp.eval("'abcd'.length()"); 100 | elp.eval("'xyz'.class"); 101 | String[] expected = { 102 | "Resolved: null x", 103 | "Resolved: [1, 2, 3] 2", 104 | "Resolved: abcd length", 105 | "Resolved: xyz class" 106 | }; 107 | for (int i = 0; i < expected.length; i++) { 108 | assertEquals(expected[i], msgs.get(i)); 109 | } 110 | } 111 | } 112 | -------------------------------------------------------------------------------- /src/main/java/org/glassfish/expressly/ValueExpressionLiteral.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2022, 2022 Contributors to the Eclipse Foundation. 3 | * Copyright (c) 1997, 2018 Oracle and/or its affiliates. All rights reserved. 4 | * 5 | * This program and the accompanying materials are made available under the 6 | * terms of the Eclipse Public License v. 2.0, which is available at 7 | * http://www.eclipse.org/legal/epl-2.0. 8 | * 9 | * This Source Code may also be made available under the following Secondary 10 | * Licenses when the conditions for such availability set forth in the 11 | * Eclipse Public License v. 2.0 are satisfied: GNU General Public License, 12 | * version 2 with the GNU Classpath Exception, which is available at 13 | * https://www.gnu.org/software/classpath/license.html. 14 | * 15 | * SPDX-License-Identifier: EPL-2.0 OR GPL-2.0 WITH Classpath-exception-2.0 16 | */ 17 | 18 | package org.glassfish.expressly; 19 | 20 | import static org.glassfish.expressly.util.ReflectionUtil.forName; 21 | 22 | import java.io.Externalizable; 23 | import java.io.IOException; 24 | import java.io.ObjectInput; 25 | import java.io.ObjectOutput; 26 | 27 | import org.glassfish.expressly.util.MessageFactory; 28 | 29 | import jakarta.el.ELContext; 30 | import jakarta.el.ELException; 31 | import jakarta.el.PropertyNotWritableException; 32 | import jakarta.el.ValueExpression; 33 | 34 | public final class ValueExpressionLiteral extends ValueExpression implements Externalizable { 35 | 36 | private static final long serialVersionUID = 1L; 37 | 38 | private Object value; 39 | private Class expectedType; 40 | 41 | public ValueExpressionLiteral() { 42 | super(); 43 | } 44 | 45 | public ValueExpressionLiteral(Object value, Class expectedType) { 46 | this.value = value; 47 | this.expectedType = expectedType; 48 | } 49 | 50 | @SuppressWarnings("unchecked") 51 | @Override 52 | public T getValue(ELContext context) { 53 | if (expectedType != null) { 54 | try { 55 | return (T) context.convertToType(value, expectedType); 56 | } catch (IllegalArgumentException ex) { 57 | throw new ELException(ex); 58 | } 59 | } 60 | 61 | return (T) value; 62 | } 63 | 64 | @Override 65 | public void setValue(ELContext context, Object value) { 66 | throw new PropertyNotWritableException(MessageFactory.get("error.value.literal.write", value)); 67 | } 68 | 69 | @Override 70 | public boolean isReadOnly(ELContext context) { 71 | return true; 72 | } 73 | 74 | @Override 75 | public Class getType(ELContext context) { 76 | return value != null ? value.getClass() : null; 77 | } 78 | 79 | @Override 80 | public Class getExpectedType() { 81 | return expectedType; 82 | } 83 | 84 | @Override 85 | public String getExpressionString() { 86 | return value != null ? value.toString() : null; 87 | } 88 | 89 | @Override 90 | public boolean equals(Object obj) { 91 | return obj instanceof ValueExpressionLiteral && this.equals((ValueExpressionLiteral) obj); 92 | } 93 | 94 | public boolean equals(ValueExpressionLiteral ve) { 95 | return (ve != null && (this.value != null && ve.value != null && (this.value == ve.value || this.value.equals(ve.value)))); 96 | } 97 | 98 | @Override 99 | public int hashCode() { 100 | return value != null ? value.hashCode() : 0; 101 | } 102 | 103 | @Override 104 | public boolean isLiteralText() { 105 | return true; 106 | } 107 | 108 | @Override 109 | public void writeExternal(ObjectOutput out) throws IOException { 110 | out.writeObject(value); 111 | out.writeUTF(expectedType != null ? expectedType.getName() : ""); 112 | } 113 | 114 | @Override 115 | public void readExternal(ObjectInput in) throws IOException, ClassNotFoundException { 116 | value = in.readObject(); 117 | String type = in.readUTF(); 118 | if (!"".equals(type)) { 119 | expectedType = forName(type); 120 | } 121 | } 122 | } 123 | -------------------------------------------------------------------------------- /src/test/java/org/glassfish/el/test/ConvertTest.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2018, 2021 Oracle and/or its affiliates and others. 3 | * All rights reserved. 4 | * 5 | * This program and the accompanying materials are made available under the 6 | * terms of the Eclipse Public License v. 2.0, which is available at 7 | * http://www.eclipse.org/legal/epl-2.0. 8 | * 9 | * This Source Code may also be made available under the following Secondary 10 | * Licenses when the conditions for such availability set forth in the 11 | * Eclipse Public License v. 2.0 are satisfied: GNU General Public License, 12 | * version 2 with the GNU Classpath Exception, which is available at 13 | * https://www.gnu.org/software/classpath/license.html. 14 | * 15 | * SPDX-License-Identifier: EPL-2.0 OR GPL-2.0 WITH Classpath-exception-2.0 16 | */ 17 | 18 | package org.glassfish.el.test; 19 | 20 | import jakarta.el.ELContext; 21 | import jakarta.el.ELProcessor; 22 | import jakarta.el.TypeConverter; 23 | import org.junit.After; 24 | import org.junit.AfterClass; 25 | import org.junit.Before; 26 | import org.junit.BeforeClass; 27 | import org.junit.Test; 28 | import static org.junit.Assert.*; 29 | 30 | import java.lang.reflect.InvocationTargetException; 31 | 32 | /** 33 | * 34 | * @author kichung 35 | */ 36 | public class ConvertTest { 37 | ELProcessor elp; 38 | 39 | public ConvertTest() { 40 | } 41 | 42 | @BeforeClass 43 | public static void setUpClass() throws Exception { 44 | System.setProperty("jakarta.el.ExpressionFactory", "org.glassfish.expressly.ExpressionFactoryImpl"); 45 | } 46 | 47 | @AfterClass 48 | public static void tearDownClass() throws Exception { 49 | } 50 | 51 | @Before 52 | public void setUp() { 53 | elp = new ELProcessor(); 54 | } 55 | 56 | @After 57 | public void tearDown() { 58 | } 59 | 60 | static public class MyBean { 61 | String name; 62 | int pint; 63 | Integer integer; 64 | 65 | public MyBean() { 66 | 67 | } 68 | public MyBean(String name) { 69 | this.name = name; 70 | } 71 | public String getName() { 72 | return this.name; 73 | } 74 | public void setPint(int v) { 75 | this.pint = v; 76 | } 77 | public int getPint() { 78 | return this.pint; 79 | } 80 | 81 | public void setInteger(Integer i){ 82 | this.integer = i; 83 | } 84 | 85 | public Integer getInteger() { 86 | return this.integer; 87 | } 88 | } 89 | @Test 90 | public void testVoid() { 91 | MyBean bean = new MyBean(); 92 | elp.defineBean("bean", bean); 93 | // Assig null to int is 0; 94 | Object obj = elp.eval("bean.pint = null"); 95 | assertEquals(obj, null); 96 | assertEquals(bean.getPint(), 0); 97 | 98 | // Assig null to Integer is null 99 | elp.setValue("bean.integer", null); 100 | assertEquals(bean.getInteger(), null); 101 | } 102 | 103 | @Test 104 | public void testCustom() { 105 | elp.getELManager().addELResolver(new TypeConverter() { 106 | @Override 107 | public T convertToType(ELContext context, Object obj, Class type) { 108 | if (obj instanceof String && type == MyBean.class) { 109 | try { 110 | T result = type.getConstructor(String.class).newInstance(obj); 111 | context.setPropertyResolved(true); 112 | return result; 113 | } catch (InstantiationException | IllegalAccessException | IllegalArgumentException | 114 | InvocationTargetException | NoSuchMethodException | SecurityException e) { 115 | e.printStackTrace(); 116 | // Can't happen as MyBean has a suitable constructor 117 | } 118 | } 119 | return null; 120 | } 121 | }); 122 | 123 | Object val = elp.getValue("'John Doe'", MyBean.class); 124 | assertTrue(val instanceof MyBean); 125 | assertEquals(((MyBean)val).getName(), "John Doe"); 126 | } 127 | } 128 | -------------------------------------------------------------------------------- /src/test/java/org/glassfish/el/test/LambdaTest.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2018, 2021 Oracle and/or its affiliates and others. 3 | * All rights reserved. 4 | * 5 | * This program and the accompanying materials are made available under the 6 | * terms of the Eclipse Public License v. 2.0, which is available at 7 | * http://www.eclipse.org/legal/epl-2.0. 8 | * 9 | * This Source Code may also be made available under the following Secondary 10 | * Licenses when the conditions for such availability set forth in the 11 | * Eclipse Public License v. 2.0 are satisfied: GNU General Public License, 12 | * version 2 with the GNU Classpath Exception, which is available at 13 | * https://www.gnu.org/software/classpath/license.html. 14 | * 15 | * SPDX-License-Identifier: EPL-2.0 OR GPL-2.0 WITH Classpath-exception-2.0 16 | */ 17 | 18 | package org.glassfish.el.test; 19 | 20 | import org.junit.Test; 21 | import org.junit.Before; 22 | import org.junit.BeforeClass; 23 | import static org.junit.Assert.assertEquals; 24 | 25 | import jakarta.el.ELProcessor; 26 | 27 | public class LambdaTest { 28 | 29 | @BeforeClass 30 | public static void setUpClass() throws Exception { 31 | System.setProperty("jakarta.el.ExpressionFactory", "org.glassfish.expressly.ExpressionFactoryImpl"); 32 | } 33 | 34 | @Before 35 | public void setUp() { 36 | } 37 | 38 | void testExpr(ELProcessor elp, String testname, String expr, Long expected) { 39 | System.out.println("=== Test Lambda Expression:" + testname + " ==="); 40 | System.out.println(" ** " + expr); 41 | Object result = elp.eval(expr); 42 | System.out.println(" returns " + result); 43 | assertEquals(expected, result); 44 | } 45 | 46 | @Test 47 | public void testImmediate() { 48 | ELProcessor elp = new ELProcessor(); 49 | testExpr(elp, "immediate", "(x->x+1)(10)", Long.valueOf(11)); 50 | testExpr(elp, "immediate0", "(()->1001)()", Long.valueOf(1001)); 51 | testExpr(elp, "immediate1", "((x,y)->x+y)(null, null)", Long.valueOf(0)); 52 | testExpr(elp, "immediate 2", "(((x,y)->x+y)(3,4))", Long.valueOf(7)); 53 | testExpr(elp, "immediate 3", "(x->(y=x)+1)(10) + y", Long.valueOf(21)); 54 | } 55 | 56 | @Test 57 | public void testAssignInvoke() { 58 | ELProcessor elp = new ELProcessor(); 59 | testExpr(elp, "assign", "func = x->x+1; func(10)", Long.valueOf(11)); 60 | testExpr(elp, "assign 2", "func = (x,y)->x+y; func(3,4)", Long.valueOf(7)); 61 | } 62 | 63 | @Test 64 | public void testConditional() { 65 | ELProcessor elp = new ELProcessor(); 66 | elp.eval("cond = true"); 67 | testExpr(elp, "conditional", "(x->cond? x+1: x+2)(10)", Long.valueOf(11)); 68 | elp.eval("cond = false"); 69 | testExpr(elp, "conditional 2", 70 | "func = cond? (x->x+1): (x->x+2); func(10)", Long.valueOf(12)); 71 | } 72 | 73 | @Test 74 | public void testFact() { 75 | ELProcessor elp = new ELProcessor(); 76 | testExpr(elp, "factorial", "fact = n->n==0? 1: n*fact(n-1); fact(5)", Long.valueOf(120)); 77 | testExpr(elp, "fibonacci", "f = n->n==0? 0: n==1? 1: f(n-1)+f(n-2); f(10)", Long.valueOf(55)); 78 | } 79 | 80 | @Test 81 | public void testVar() { 82 | ELProcessor elp = new ELProcessor(); 83 | elp.setVariable("v", "x->x+1"); 84 | testExpr(elp, "assignment to variable", "v(10)", Long.valueOf(11)); 85 | } 86 | 87 | @Test 88 | public void testLambda() { 89 | ELProcessor elp = new ELProcessor(); 90 | testExpr(elp, "Lambda Lambda 1", "f = ()->y->y+1; f()(100)", Long.valueOf(101)); 91 | testExpr(elp, "Lambda Lambda 2", "f = (x)->(tem=x; y->tem+y); f(1)(100)", Long.valueOf(101)); 92 | testExpr(elp, "Lambda Lambda 3", "(()->y->y+1)()(100)", Long.valueOf(101)); 93 | testExpr(elp, "Lambda Lambda 4", "(x->(y->x+y)(1))(100)", Long.valueOf(101)); 94 | testExpr(elp, "Lambda Lambda 5", "((x)->(y->x+y))(1)(100)", Long.valueOf(101)); 95 | testExpr(elp, "Lambda Lambda 6" 96 | , "(x->y->x(0)+y)(x->x+1)(100)", Long.valueOf(101)); 97 | testExpr(elp, "Lambda Lambda 7", "f = ()->((1)); f()", Long.valueOf(1)); 98 | testExpr(elp, "Lambda Lambda 8", "f = ()->(y)->y+1; f()(100)", Long.valueOf(101)); 99 | } 100 | } 101 | -------------------------------------------------------------------------------- /src/test/java/org/glassfish/el/test/ElasticityTest.java.sav: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2018 Oracle and/or its affiliates. All rights reserved. 3 | * 4 | * This program and the accompanying materials are made available under the 5 | * terms of the Eclipse Public License v. 2.0, which is available at 6 | * http://www.eclipse.org/legal/epl-2.0. 7 | * 8 | * This Source Code may also be made available under the following Secondary 9 | * Licenses when the conditions for such availability set forth in the 10 | * Eclipse Public License v. 2.0 are satisfied: GNU General Public License, 11 | * version 2 with the GNU Classpath Exception, which is available at 12 | * https://www.gnu.org/software/classpath/license.html. 13 | * 14 | * SPDX-License-Identifier: EPL-2.0 OR GPL-2.0 WITH Classpath-exception-2.0 15 | */ 16 | 17 | package org.glassfish.el.test; 18 | 19 | import java.util.*; 20 | import jakarta.el.*; 21 | import org.junit.After; 22 | import org.junit.AfterClass; 23 | import org.junit.Before; 24 | import org.junit.BeforeClass; 25 | import org.junit.Test; 26 | import static org.junit.Assert.*; 27 | 28 | /** 29 | * 30 | * @author kichung 31 | */ 32 | public class ElasticityTest { 33 | 34 | ELProcessor elp; 35 | 36 | public ElasticityTest() { 37 | } 38 | 39 | @BeforeClass 40 | public static void setUpClass() throws Exception { 41 | } 42 | 43 | @AfterClass 44 | public static void tearDownClass() throws Exception { 45 | } 46 | 47 | @Before 48 | public void setUp() { 49 | elp = new ELProcessor(); 50 | } 51 | 52 | @After 53 | public void tearDown() { 54 | } 55 | 56 | static public class Data { 57 | int s; 58 | int d; 59 | 60 | public Data(int s, int d) { 61 | this.s = s; 62 | this.d = d; 63 | } 64 | 65 | public int getS() { 66 | return this.s; 67 | } 68 | 69 | public int getD() { 70 | return this.d; 71 | } 72 | } 73 | 74 | static public class Metric { 75 | int limit; 76 | List list = new ArrayList(); 77 | 78 | public Metric(int limit) { 79 | this.limit = limit; 80 | } 81 | 82 | public int getLimit() { 83 | return limit; 84 | } 85 | 86 | public List getList() { 87 | return list; 88 | } 89 | } 90 | Map clusters = new HashMap(); 91 | 92 | private void init() { 93 | Metric m1 = new Metric(10); 94 | m1.getList().add(new Data(1, 80)); 95 | m1.getList().add(new Data(3, 90)); 96 | m1.getList().add(new Data(4, 100)); 97 | m1.getList().add(new Data(5, 50)); 98 | m1.getList().add(new Data(6, 60)); 99 | 100 | Metric m2 = new Metric(10); 101 | m2.getList().add(new Data(1, 80)); 102 | m2.getList().add(new Data(3, 82)); 103 | m2.getList().add(new Data(7, 90)); 104 | m2.getList().add(new Data(9, 140)); 105 | m2.getList().add(new Data(15, 80)); 106 | 107 | Metric m3 = new Metric(10); 108 | m3.getList().add(new Data(4, 100)); 109 | m3.getList().add(new Data(5, 81)); 110 | m3.getList().add(new Data(6, 200)); 111 | m3.getList().add(new Data(20, 80)); 112 | 113 | clusters.put("c1", m1); 114 | clusters.put("c2", m2); 115 | clusters.put("c3", m3); 116 | 117 | elp.defineBean("c", clusters); 118 | } 119 | @Test 120 | public void testElaticity() { 121 | init(); 122 | Object obj; 123 | 124 | obj = elp.eval( 125 | "c.values().select(" + 126 | "v->v.list.where(d->d.s>1 && d.s<10)." + 127 | "average(d->d.d)).toList()"); 128 | 129 | System.out.println(obj); 130 | obj = elp.eval( 131 | "c.values().select(v->v.list." + 132 | "where(d->d.s>1 && d.s<10)." + 133 | "average(d->d.d) > 100).toList()"); 134 | System.out.println(obj); 135 | obj = elp.eval( 136 | "c.values().select(v->v.list." + 137 | "where(d->d.s>1 && d.s<10)." + 138 | "average(d->d.d) > 100).any()"); 139 | System.out.println(obj); 140 | obj = elp.eval( 141 | "c.entrySet().select(s->[s.key, s.value.list." + 142 | "where(d->d.s>1 && d.s<10)." + 143 | "average(d->d.d)]).toList()"); 144 | System.out.println(obj); 145 | } 146 | } 147 | -------------------------------------------------------------------------------- /src/main/java/org/glassfish/expressly/ExpressionFactoryImpl.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2022, 2022 Contributors to the Eclipse Foundation. 3 | * Copyright (c) 1997, 2021 Oracle and/or its affiliates and others. 4 | * All rights reserved. 5 | * 6 | * This program and the accompanying materials are made available under the 7 | * terms of the Eclipse Public License v. 2.0, which is available at 8 | * http://www.eclipse.org/legal/epl-2.0. 9 | * 10 | * This Source Code may also be made available under the following Secondary 11 | * Licenses when the conditions for such availability set forth in the 12 | * Eclipse Public License v. 2.0 are satisfied: GNU General Public License, 13 | * version 2 with the GNU Classpath Exception, which is available at 14 | * https://www.gnu.org/software/classpath/license.html. 15 | * 16 | * SPDX-License-Identifier: EPL-2.0 OR GPL-2.0 WITH Classpath-exception-2.0 17 | */ 18 | 19 | package org.glassfish.expressly; 20 | 21 | import java.lang.reflect.Method; 22 | import java.util.HashMap; 23 | import java.util.Map; 24 | import java.util.Properties; 25 | 26 | import org.glassfish.expressly.lang.ELSupport; 27 | import org.glassfish.expressly.lang.ExpressionBuilder; 28 | import org.glassfish.expressly.stream.StreamELResolver; 29 | import org.glassfish.expressly.util.MessageFactory; 30 | 31 | import jakarta.el.ELContext; 32 | import jakarta.el.ELException; 33 | import jakarta.el.ELResolver; 34 | import jakarta.el.ExpressionFactory; 35 | import jakarta.el.MethodExpression; 36 | import jakarta.el.ValueExpression; 37 | 38 | /** 39 | * @see ExpressionFactory 40 | * 41 | * @author Jacob Hookom [jacob@hookom.net] 42 | * @author Kin-man Chung 43 | * @version $Change: 181177 $$DateTime: 2001/06/26 08:45:09 $$Author: kchung $ 44 | */ 45 | public class ExpressionFactoryImpl extends ExpressionFactory { 46 | 47 | private Properties properties; 48 | private boolean isBackwardCompatible22; 49 | 50 | public ExpressionFactoryImpl() { 51 | super(); 52 | } 53 | 54 | public ExpressionFactoryImpl(Properties properties) { 55 | super(); 56 | this.properties = properties; 57 | this.isBackwardCompatible22 = "true".equals(getProperty("jakarta.el.bc2.2")); 58 | } 59 | 60 | /** 61 | * Coerces an object to a specific type according to the Jakarta Expression Language type conversion rules. The custom 62 | * type conversions in the ELResolvers are not considered. 63 | * 64 | * Jakarta Expression Language version 2.2 backward compatibility conversion rules apply if ExpressionFactoryImpl was created with property 65 | * "jakarta.el.bc2.2" set to true. 66 | */ 67 | @Override 68 | public T coerceToType(Object obj, Class type) { 69 | try { 70 | return ELSupport.coerceToType(null, obj, type, isBackwardCompatible22); 71 | } catch (IllegalArgumentException ex) { 72 | throw new ELException(ex); 73 | } 74 | } 75 | 76 | @Override 77 | public MethodExpression createMethodExpression(ELContext context, String expression, Class expectedReturnType, Class[] expectedParamTypes) { 78 | MethodExpression methodExpression = 79 | new ExpressionBuilder(expression, context) 80 | .createMethodExpression(expectedReturnType, expectedParamTypes); 81 | 82 | if (expectedParamTypes == null && !methodExpression.isParametersProvided()) { 83 | throw new NullPointerException(MessageFactory.get("error.method.nullParms")); 84 | } 85 | 86 | return methodExpression; 87 | } 88 | 89 | @Override 90 | public ValueExpression createValueExpression(ELContext context, String expression, Class expectedType) { 91 | if (expectedType == null) { 92 | throw new NullPointerException(MessageFactory.get("error.value.expectedType")); 93 | } 94 | 95 | return new ExpressionBuilder(expression, context).createValueExpression(expectedType); 96 | } 97 | 98 | @Override 99 | public ValueExpression createValueExpression(Object instance, Class expectedType) { 100 | if (expectedType == null) { 101 | throw new NullPointerException(MessageFactory.get("error.value.expectedType")); 102 | } 103 | 104 | return new ValueExpressionLiteral(instance, expectedType); 105 | } 106 | 107 | public String getProperty(String key) { 108 | if (properties == null) { 109 | return null; 110 | } 111 | 112 | return properties.getProperty(key); 113 | } 114 | 115 | @Override 116 | public ELResolver getStreamELResolver() { 117 | return new StreamELResolver(); 118 | } 119 | 120 | @Override 121 | public Map getInitFunctionMap() { 122 | return new HashMap(); 123 | } 124 | } 125 | -------------------------------------------------------------------------------- /src/main/java/org/glassfish/expressly/parser/JJTELParserState.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2022, 2022 Contributors to the Eclipse Foundation. 3 | * Copyright (c) 2018 Oracle and/or its affiliates. All rights reserved. 4 | * 5 | * This program and the accompanying materials are made available under the 6 | * terms of the Eclipse Public License v. 2.0, which is available at 7 | * http://www.eclipse.org/legal/epl-2.0. 8 | * 9 | * This Source Code may also be made available under the following Secondary 10 | * Licenses when the conditions for such availability set forth in the 11 | * Eclipse Public License v. 2.0 are satisfied: GNU General Public License, 12 | * version 2 with the GNU Classpath Exception, which is available at 13 | * https://www.gnu.org/software/classpath/license.html. 14 | * 15 | * SPDX-License-Identifier: EPL-2.0 OR GPL-2.0 WITH Classpath-exception-2.0 16 | */ 17 | 18 | /* Generated By:JavaCC: Do not edit this line. JJTELParserState.java Version 5.0 */ 19 | package org.glassfish.expressly.parser; 20 | 21 | public class JJTELParserState { 22 | private java.util.List nodes; 23 | private java.util.List marks; 24 | 25 | private int sp; // number of nodes on stack 26 | private int mk; // current mark 27 | private boolean node_created; 28 | 29 | public JJTELParserState() { 30 | nodes = new java.util.ArrayList(); 31 | marks = new java.util.ArrayList(); 32 | sp = 0; 33 | mk = 0; 34 | } 35 | 36 | /* 37 | * Determines whether the current node was actually closed and pushed. This should only be called in the final user 38 | * action of a node scope. 39 | */ 40 | public boolean nodeCreated() { 41 | return node_created; 42 | } 43 | 44 | /* 45 | * Call this to reinitialize the node stack. It is called automatically by the parser's ReInit() method. 46 | */ 47 | public void reset() { 48 | nodes.clear(); 49 | marks.clear(); 50 | sp = 0; 51 | mk = 0; 52 | } 53 | 54 | /* 55 | * Returns the root node of the AST. It only makes sense to call this after a successful parse. 56 | */ 57 | public Node rootNode() { 58 | return nodes.get(0); 59 | } 60 | 61 | /* Pushes a node on to the stack. */ 62 | public void pushNode(Node n) { 63 | nodes.add(n); 64 | ++sp; 65 | } 66 | 67 | /* 68 | * Returns the node on the top of the stack, and remove it from the stack. 69 | */ 70 | public Node popNode() { 71 | if (--sp < mk) { 72 | mk = marks.remove(marks.size() - 1); 73 | } 74 | return nodes.remove(nodes.size() - 1); 75 | } 76 | 77 | /* Returns the node currently on the top of the stack. */ 78 | public Node peekNode() { 79 | return nodes.get(nodes.size() - 1); 80 | } 81 | 82 | /* 83 | * Returns the number of children on the stack in the current node scope. 84 | */ 85 | public int nodeArity() { 86 | return sp - mk; 87 | } 88 | 89 | public void clearNodeScope(Node n) { 90 | while (sp > mk) { 91 | popNode(); 92 | } 93 | mk = marks.remove(marks.size() - 1); 94 | } 95 | 96 | public void openNodeScope(Node n) { 97 | marks.add(mk); 98 | mk = sp; 99 | n.jjtOpen(); 100 | } 101 | 102 | /* 103 | * A definite node is constructed from a specified number of children. That number of nodes are popped from the stack 104 | * and made the children of the definite node. Then the definite node is pushed on to the stack. 105 | */ 106 | public void closeNodeScope(Node n, int num) { 107 | mk = marks.remove(marks.size() - 1); 108 | while (num-- > 0) { 109 | Node c = popNode(); 110 | c.jjtSetParent(n); 111 | n.jjtAddChild(c, num); 112 | } 113 | n.jjtClose(); 114 | pushNode(n); 115 | node_created = true; 116 | } 117 | 118 | /* 119 | * A conditional node is constructed if its condition is true. All the nodes that have been pushed since the node was 120 | * opened are made children of the conditional node, which is then pushed on to the stack. If the condition is false the 121 | * node is not constructed and they are left on the stack. 122 | */ 123 | public void closeNodeScope(Node n, boolean condition) { 124 | if (condition) { 125 | int a = nodeArity(); 126 | mk = marks.remove(marks.size() - 1); 127 | while (a-- > 0) { 128 | Node c = popNode(); 129 | c.jjtSetParent(n); 130 | n.jjtAddChild(c, a); 131 | } 132 | n.jjtClose(); 133 | pushNode(n); 134 | node_created = true; 135 | } else { 136 | mk = marks.remove(marks.size() - 1); 137 | node_created = false; 138 | } 139 | } 140 | } 141 | /* JavaCC - OriginalChecksum=a169ec9bf66edaa6db0c5550b112beee (do not edit this line) */ 142 | -------------------------------------------------------------------------------- /src/main/java/org/glassfish/expressly/lang/EvaluationContext.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2022, 2022 Contributors to the Eclipse Foundation. 3 | * Copyright (c) 1997, 2021 Oracle and/or its affiliates and others. 4 | * All rights reserved. 5 | * 6 | * This program and the accompanying materials are made available under the 7 | * terms of the Eclipse Public License v. 2.0, which is available at 8 | * http://www.eclipse.org/legal/epl-2.0. 9 | * 10 | * This Source Code may also be made available under the following Secondary 11 | * Licenses when the conditions for such availability set forth in the 12 | * Eclipse Public License v. 2.0 are satisfied: GNU General Public License, 13 | * version 2 with the GNU Classpath Exception, which is available at 14 | * https://www.gnu.org/software/classpath/license.html. 15 | * 16 | * SPDX-License-Identifier: EPL-2.0 OR GPL-2.0 WITH Classpath-exception-2.0 17 | */ 18 | 19 | package org.glassfish.expressly.lang; 20 | 21 | import java.util.List; 22 | import java.util.Map; 23 | import java.util.function.BiConsumer; 24 | 25 | import jakarta.el.ELContext; 26 | import jakarta.el.ELResolver; 27 | import jakarta.el.EvaluationListener; 28 | import jakarta.el.FunctionMapper; 29 | import jakarta.el.ImportHandler; 30 | import jakarta.el.VariableMapper; 31 | 32 | /** 33 | * The context for Jakarta Expression expression evaluation. This wrapper ELContext captures the function mapper and the 34 | * variable mapper at the point when the expression is parsed, and only for those functions and variable used in the 35 | * expression. 36 | */ 37 | public final class EvaluationContext extends ELContext { 38 | 39 | private final ELContext elContext; 40 | private final FunctionMapper fnMapper; 41 | private final VariableMapper varMapper; 42 | 43 | public EvaluationContext(ELContext elContext, FunctionMapper fnMapper, VariableMapper varMapper) { 44 | this.elContext = elContext; 45 | this.fnMapper = fnMapper; 46 | this.varMapper = varMapper; 47 | } 48 | 49 | public ELContext getELContext() { 50 | return elContext; 51 | } 52 | 53 | @Override 54 | public FunctionMapper getFunctionMapper() { 55 | return fnMapper; 56 | } 57 | 58 | @Override 59 | public VariableMapper getVariableMapper() { 60 | return varMapper; 61 | } 62 | 63 | @Override 64 | public Object getContext(Class key) { 65 | return elContext.getContext(key); 66 | } 67 | 68 | @Override 69 | public ELResolver getELResolver() { 70 | return elContext.getELResolver(); 71 | } 72 | 73 | @Override 74 | public boolean isPropertyResolved() { 75 | return elContext.isPropertyResolved(); 76 | } 77 | 78 | @Override 79 | public void putContext(Class key, Object contextObject) { 80 | elContext.putContext(key, contextObject); 81 | } 82 | 83 | @Override 84 | public void setPropertyResolved(boolean resolved) { 85 | elContext.setPropertyResolved(resolved); 86 | } 87 | 88 | @Override 89 | public void setPropertyResolved(Object base, Object property) { 90 | elContext.setPropertyResolved(base, property); 91 | } 92 | 93 | @Override 94 | public void addEvaluationListener(EvaluationListener listener) { 95 | elContext.addEvaluationListener(listener); 96 | } 97 | 98 | @Override 99 | public List getEvaluationListeners() { 100 | return elContext.getEvaluationListeners(); 101 | } 102 | 103 | @Override 104 | public void notifyBeforeEvaluation(String expr) { 105 | elContext.notifyBeforeEvaluation(expr); 106 | } 107 | 108 | @Override 109 | public void notifyAfterEvaluation(String expr) { 110 | elContext.notifyAfterEvaluation(expr); 111 | } 112 | 113 | @Override 114 | public void notifyPropertyResolved(Object base, Object property) { 115 | elContext.notifyPropertyResolved(base, property); 116 | } 117 | 118 | @Override 119 | public boolean isLambdaArgument(String arg) { 120 | return elContext.isLambdaArgument(arg); 121 | } 122 | 123 | @Override 124 | public Object getLambdaArgument(String arg) { 125 | return elContext.getLambdaArgument(arg); 126 | } 127 | 128 | @Override 129 | public void enterLambdaScope(Map args) { 130 | elContext.enterLambdaScope(args); 131 | } 132 | 133 | @Override 134 | public void exitLambdaScope() { 135 | elContext.exitLambdaScope(); 136 | } 137 | 138 | @SuppressWarnings({ "unchecked", "rawtypes" }) 139 | @Override 140 | public T convertToType(Object obj, Class targetType) { 141 | T convertedType = elContext.convertToType(obj, targetType); 142 | if (convertedType instanceof BiConsumer) { 143 | ((BiConsumer) convertedType).accept("org.glassfish.expressly.setElContext", this); 144 | } 145 | 146 | return convertedType; 147 | } 148 | 149 | @Override 150 | public ImportHandler getImportHandler() { 151 | return elContext.getImportHandler(); 152 | } 153 | } 154 | -------------------------------------------------------------------------------- /src/test/java/org/glassfish/el/test/OperatorTest.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2018, 2021 Oracle and/or its affiliates and others. 3 | * All rights reserved. 4 | * 5 | * This program and the accompanying materials are made available under the 6 | * terms of the Eclipse Public License v. 2.0, which is available at 7 | * http://www.eclipse.org/legal/epl-2.0. 8 | * 9 | * This Source Code may also be made available under the following Secondary 10 | * Licenses when the conditions for such availability set forth in the 11 | * Eclipse Public License v. 2.0 are satisfied: GNU General Public License, 12 | * version 2 with the GNU Classpath Exception, which is available at 13 | * https://www.gnu.org/software/classpath/license.html. 14 | * 15 | * SPDX-License-Identifier: EPL-2.0 OR GPL-2.0 WITH Classpath-exception-2.0 16 | */ 17 | 18 | package org.glassfish.el.test; 19 | 20 | import org.junit.AfterClass; 21 | import org.junit.Before; 22 | import org.junit.BeforeClass; 23 | import org.junit.Test; 24 | import static org.junit.Assert.*; 25 | import jakarta.el.ELProcessor; 26 | import jakarta.el.ELManager; 27 | import jakarta.el.ValueExpression; 28 | 29 | /** 30 | * 31 | * @author Kin-man 32 | */ 33 | public class OperatorTest { 34 | 35 | static ELProcessor elp; 36 | 37 | public OperatorTest() { 38 | } 39 | 40 | @BeforeClass 41 | public static void setUpClass() throws Exception { 42 | System.setProperty("jakarta.el.ExpressionFactory", "org.glassfish.expressly.ExpressionFactoryImpl"); 43 | elp = new ELProcessor(); 44 | } 45 | 46 | @AfterClass 47 | public static void tearDownClass() throws Exception { 48 | } 49 | 50 | @Before 51 | public void setUp() { 52 | } 53 | 54 | void testExpr(String testname, String expr, Object expected) { 55 | System.out.println("=== Test " + testname + " ==="); 56 | System.out.println(" ** " + expr); 57 | Object result = elp.eval(expr); 58 | System.out.println(" returns " + result); 59 | assertEquals(expected, result); 60 | } 61 | 62 | @Test 63 | public void testConcat() { 64 | testExpr("concat", "a = null; b = null; a + b", Long.valueOf(0)); 65 | testExpr("add", "10 + 11", Long.valueOf(21)); 66 | testExpr("add 2", "((1)) + 1", Long.valueOf(2)); 67 | testExpr("concat", "'10' + 11", Long.valueOf(21)); 68 | testExpr("concat 2", "11 + '10'", Long.valueOf(21)); 69 | testExpr("concat 3", "100 += 10 ", "10010"); 70 | testExpr("concat 4", "'100' += 10", "10010"); 71 | testExpr("concat 5", "'100' + 10 + 1", Long.valueOf(111)); 72 | testExpr("concat 6", "'100' += 10 + 1", "10011"); 73 | } 74 | 75 | @Test 76 | public void testAssign() { 77 | elp.eval("vv = 10"); 78 | testExpr("assign", "vv+1", Long.valueOf(11)); 79 | elp.eval("vv = 100"); 80 | testExpr("assign 2", "vv", Long.valueOf(100)); 81 | testExpr("assign 3", "x = vv = vv+1; x + vv", Long.valueOf(202)); 82 | elp.eval("map = {'one':100, 'two':200}"); 83 | testExpr("assign 4", "map.two = 201; map.two", Long.valueOf(201)); 84 | testExpr("assign string", "x='string'; x += 1", "string1"); 85 | } 86 | 87 | @Test 88 | public void testSemi() { 89 | testExpr("semi", "10; 20", Long.valueOf(20)); 90 | testExpr("semi0", "10; 20; 30", Long.valueOf(30)); 91 | elp.eval("x = 10; 20"); 92 | testExpr("semi 2", "x", Long.valueOf(10)); 93 | testExpr("semi 3", "(x = 10; 20) + (x ; x+1)", Long.valueOf(31)); 94 | testExpr("semi 4", "(x = 10; y) = 11; x + y", Long.valueOf(21)); 95 | } 96 | @Test 97 | public void testMisc() { 98 | testExpr("quote", "\"'\"", "'"); 99 | testExpr("quote", "'\"'", "\""); 100 | ELManager elm = elp.getELManager(); 101 | ValueExpression v = ELManager.getExpressionFactory().createValueExpression( 102 | elm.getELContext(), "#${1+1}", Object.class); 103 | Object ret = v.getValue(elm.getELContext()); 104 | assertEquals(ret, "#2"); 105 | 106 | elp.setVariable("debug", "true"); 107 | ret = elp.eval("debug == true"); 108 | // elp.eval("[1,2][true]"); // throws IllegalArgumentExpression 109 | /* 110 | elp.defineBean("date", new Date(2013, 1,2)); 111 | elp.eval("date.getYear()"); 112 | 113 | elp.defineBean("href", null); 114 | testExpr("space", "(empty href)?'#':href", "#"); 115 | MethodExpression m = elm.getExpressionFactory().createMethodExpression( 116 | elm.getELContext(), "${name}", Object.class, new Class[] {}); 117 | m.invoke(elm.getELContext(), null); 118 | */ 119 | } 120 | 121 | @Test 122 | public void testEquals() { 123 | testExpr("string", "'xx' == 'xx'", Boolean.TRUE); 124 | testExpr("number", "'a'.length() == 1", Boolean.TRUE); 125 | testExpr("coerce '01'", "'01' == 1", Boolean.TRUE); 126 | testExpr("coerce '01'", "1 == '01'", Boolean.TRUE); 127 | testExpr("coerce '01.10'", "'01.10' == 1.10", Boolean.TRUE); 128 | } 129 | } 130 | -------------------------------------------------------------------------------- /src/main/java/org/glassfish/expressly/lang/FunctionMapperImpl.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2022, 2022 Contributors to the Eclipse Foundation. 3 | * Copyright (c) 1997, 2018 Oracle and/or its affiliates. All rights reserved. 4 | * 5 | * This program and the accompanying materials are made available under the 6 | * terms of the Eclipse Public License v. 2.0, which is available at 7 | * http://www.eclipse.org/legal/epl-2.0. 8 | * 9 | * This Source Code may also be made available under the following Secondary 10 | * Licenses when the conditions for such availability set forth in the 11 | * Eclipse Public License v. 2.0 are satisfied: GNU General Public License, 12 | * version 2 with the GNU Classpath Exception, which is available at 13 | * https://www.gnu.org/software/classpath/license.html. 14 | * 15 | * SPDX-License-Identifier: EPL-2.0 OR GPL-2.0 WITH Classpath-exception-2.0 16 | */ 17 | 18 | package org.glassfish.expressly.lang; 19 | 20 | import static org.glassfish.expressly.util.ReflectionUtil.toTypeArray; 21 | import static org.glassfish.expressly.util.ReflectionUtil.toTypeNameArray; 22 | 23 | import java.io.Externalizable; 24 | import java.io.IOException; 25 | import java.io.ObjectInput; 26 | import java.io.ObjectOutput; 27 | import java.lang.reflect.Method; 28 | import java.util.HashMap; 29 | import java.util.Map; 30 | 31 | import jakarta.el.FunctionMapper; 32 | 33 | /** 34 | * @author Jacob Hookom [jacob@hookom.net] 35 | * @author kchung 36 | */ 37 | public class FunctionMapperImpl extends FunctionMapper implements Externalizable { 38 | 39 | private static final long serialVersionUID = 1L; 40 | 41 | protected Map functions; 42 | 43 | @Override 44 | public Method resolveFunction(String prefix, String localName) { 45 | if (functions == null) { 46 | return null; 47 | } 48 | 49 | return functions.get(prefix + ":" + localName).getMethod(); 50 | } 51 | 52 | public void addFunction(String prefix, String localName, Method method) { 53 | if (functions == null) { 54 | functions = new HashMap<>(); 55 | } 56 | 57 | Function function = new Function(prefix, localName, method); 58 | synchronized (this) { 59 | functions.put(prefix + ":" + localName, function); 60 | } 61 | } 62 | 63 | @Override 64 | public void writeExternal(ObjectOutput out) throws IOException { 65 | out.writeObject(functions); 66 | } 67 | 68 | @Override 69 | @SuppressWarnings("unchecked") 70 | public void readExternal(ObjectInput in) throws IOException, ClassNotFoundException { 71 | functions = (Map) in.readObject(); 72 | } 73 | 74 | public static class Function implements Externalizable { 75 | 76 | protected transient Method method; 77 | protected String owner; 78 | protected String name; 79 | protected String[] types; 80 | protected String prefix; 81 | protected String localName; 82 | 83 | public Function(String prefix, String localName, Method method) { 84 | if (localName == null) { 85 | throw new NullPointerException("LocalName cannot be null"); 86 | } 87 | 88 | if (method == null) { 89 | throw new NullPointerException("Method cannot be null"); 90 | } 91 | this.prefix = prefix; 92 | this.localName = localName; 93 | this.method = method; 94 | } 95 | 96 | public Function() { 97 | // for serialization 98 | } 99 | 100 | @Override 101 | public void writeExternal(ObjectOutput out) throws IOException { 102 | out.writeUTF((prefix != null) ? prefix : ""); 103 | out.writeUTF(localName); 104 | 105 | if (owner != null) { 106 | out.writeUTF(owner); 107 | } else { 108 | out.writeUTF(method.getDeclaringClass().getName()); 109 | } 110 | if (name != null) { 111 | out.writeUTF(name); 112 | } else { 113 | out.writeUTF(method.getName()); 114 | } 115 | if (types != null) { 116 | out.writeObject(types); 117 | } else { 118 | out.writeObject(toTypeNameArray(method.getParameterTypes())); 119 | } 120 | } 121 | 122 | @Override 123 | public void readExternal(ObjectInput in) throws IOException, ClassNotFoundException { 124 | prefix = in.readUTF(); 125 | if ("".equals(prefix)) { 126 | prefix = null; 127 | } 128 | localName = in.readUTF(); 129 | owner = in.readUTF(); 130 | name = in.readUTF(); 131 | types = (String[]) in.readObject(); 132 | } 133 | 134 | public Method getMethod() { 135 | if (method == null) { 136 | try { 137 | this.method = Class.forName(owner, false, Thread.currentThread().getContextClassLoader()) 138 | .getMethod(name, toTypeArray(types)); 139 | } catch (Exception e) { 140 | e.printStackTrace(); 141 | } 142 | } 143 | 144 | return method; 145 | } 146 | 147 | @Override 148 | public boolean equals(Object obj) { 149 | if (obj instanceof Function) { 150 | return this.hashCode() == obj.hashCode(); 151 | } 152 | 153 | return false; 154 | } 155 | 156 | @Override 157 | public int hashCode() { 158 | return (prefix + localName).hashCode(); 159 | } 160 | } 161 | 162 | } 163 | -------------------------------------------------------------------------------- /src/main/java/org/glassfish/expressly/parser/TokenMgrError.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2022, 2022 Contributors to the Eclipse Foundation. 3 | * Copyright (c) 2021 Payara Services Ltd. 4 | * Copyright (c) 1997, 2018 Oracle and/or its affiliates. All rights reserved. 5 | * 6 | * This program and the accompanying materials are made available under the 7 | * terms of the Eclipse Public License v. 2.0, which is available at 8 | * http://www.eclipse.org/legal/epl-2.0. 9 | * 10 | * This Source Code may also be made available under the following Secondary 11 | * Licenses when the conditions for such availability set forth in the 12 | * Eclipse Public License v. 2.0 are satisfied: GNU General Public License, 13 | * version 2 with the GNU Classpath Exception, which is available at 14 | * https://www.gnu.org/software/classpath/license.html. 15 | * 16 | * SPDX-License-Identifier: EPL-2.0 OR GPL-2.0 WITH Classpath-exception-2.0 17 | */ 18 | 19 | package org.glassfish.expressly.parser; 20 | 21 | public class TokenMgrError extends Error { 22 | 23 | private static final long serialVersionUID = 1L; 24 | 25 | // Ordinals for various reasons why an Error of this type can be thrown. 26 | 27 | /** 28 | * Lexical error occured. 29 | */ 30 | static final int LEXICAL_ERROR = 0; 31 | 32 | /** 33 | * An attempt wass made to create a second instance of a static token manager. 34 | */ 35 | static final int STATIC_LEXER_ERROR = 1; 36 | 37 | /** 38 | * Tried to change to an invalid lexical state. 39 | */ 40 | static final int INVALID_LEXICAL_STATE = 2; 41 | 42 | /** 43 | * Detected (and bailed out of) an infinite loop in the token manager. 44 | */ 45 | static final int LOOP_DETECTED = 3; 46 | 47 | /** 48 | * Indicates the reason why the exception is thrown. It will have one of the above 4 values. 49 | */ 50 | int errorCode; 51 | 52 | /** 53 | * Replaces unprintable characters by their espaced (or unicode escaped) equivalents in the given string 54 | */ 55 | protected static final String addEscapes(String unescapedString) { 56 | StringBuilder escapedString = new StringBuilder(); 57 | 58 | char ch; 59 | for (int i = 0; i < unescapedString.length(); i++) { 60 | switch (unescapedString.charAt(i)) { 61 | case 0: 62 | continue; 63 | case '\b': 64 | escapedString.append("\\b"); 65 | continue; 66 | case '\t': 67 | escapedString.append("\\t"); 68 | continue; 69 | case '\n': 70 | escapedString.append("\\n"); 71 | continue; 72 | case '\f': 73 | escapedString.append("\\f"); 74 | continue; 75 | case '\r': 76 | escapedString.append("\\r"); 77 | continue; 78 | case '\"': 79 | escapedString.append("\\\""); 80 | continue; 81 | case '\'': 82 | escapedString.append("\\\'"); 83 | continue; 84 | case '\\': 85 | escapedString.append("\\\\"); 86 | continue; 87 | default: 88 | if ((ch = unescapedString.charAt(i)) < 0x20 || ch > 0x7e) { 89 | String s = "0000" + Integer.toString(ch, 16); 90 | escapedString.append("\\u" + s.substring(s.length() - 4, s.length())); 91 | } else { 92 | escapedString.append(ch); 93 | } 94 | continue; 95 | } 96 | } 97 | 98 | return escapedString.toString(); 99 | } 100 | 101 | /** 102 | * Returns a detailed message for the Error when it is thrown by the token manager to indicate a lexical error. 103 | * Parameters : EOFSeen : indicates if EOF caused the lexicl error curLexState : lexical state in which this error 104 | * occured errorLine : line number when the error occured errorColumn : column number when the error occured errorAfter 105 | * : prefix that was seen before this error occured curchar : the offending character Note: You can customize the 106 | * lexical error message by modifying this method. 107 | */ 108 | protected static String LexicalError(boolean EOFSeen, int lexState, int errorLine, int errorColumn, String errorAfter, char curChar) { 109 | return 110 | "Lexical error at line " + errorLine + 111 | ", column " + errorColumn + 112 | ". Encountered: " + 113 | (EOFSeen ? " " : ("\"" + addEscapes(String.valueOf(curChar)) + "\"") + 114 | " (" + (int) curChar + "), ") + 115 | "after : \"" + addEscapes(errorAfter) + "\""; 116 | } 117 | 118 | /* 119 | * Constructors of various flavors follow. 120 | */ 121 | 122 | public TokenMgrError() { 123 | } 124 | 125 | public TokenMgrError(String message, int reason) { 126 | super(message); 127 | errorCode = reason; 128 | } 129 | 130 | public TokenMgrError(boolean EOFSeen, int lexState, int errorLine, int errorColumn, String errorAfter, char curChar, int reason) { 131 | this(LexicalError(EOFSeen, lexState, errorLine, errorColumn, errorAfter, curChar), reason); 132 | } 133 | 134 | /** 135 | * You can also modify the body of this method to customize your error messages. For example, cases like LOOP_DETECTED 136 | * and INVALID_LEXICAL_STATE are not of end-users concern, so you can return something like : 137 | * 138 | * "Internal Error : Please file a bug report .... " 139 | * 140 | * from this method for such cases in the release version of your parser. 141 | */ 142 | @Override 143 | public String getMessage() { 144 | return super.getMessage(); 145 | } 146 | } 147 | -------------------------------------------------------------------------------- /src/main/java/org/glassfish/expressly/parser/ELParserConstants.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2018 Oracle and/or its affiliates. All rights reserved. 3 | * 4 | * This program and the accompanying materials are made available under the 5 | * terms of the Eclipse Public License v. 2.0, which is available at 6 | * http://www.eclipse.org/legal/epl-2.0. 7 | * 8 | * This Source Code may also be made available under the following Secondary 9 | * Licenses when the conditions for such availability set forth in the 10 | * Eclipse Public License v. 2.0 are satisfied: GNU General Public License, 11 | * version 2 with the GNU Classpath Exception, which is available at 12 | * https://www.gnu.org/software/classpath/license.html. 13 | * 14 | * SPDX-License-Identifier: EPL-2.0 OR GPL-2.0 WITH Classpath-exception-2.0 15 | */ 16 | 17 | /* Generated By:JJTree&JavaCC: Do not edit this line. ELParserConstants.java */ 18 | package org.glassfish.expressly.parser; 19 | 20 | 21 | /** 22 | * Token literal values and constants. 23 | * Generated by org.javacc.parser.OtherFilesGen#start() 24 | */ 25 | public interface ELParserConstants { 26 | 27 | /** End of File. */ 28 | int EOF = 0; 29 | /** RegularExpression Id. */ 30 | int LITERAL_EXPRESSION = 1; 31 | /** RegularExpression Id. */ 32 | int START_DYNAMIC_EXPRESSION = 2; 33 | /** RegularExpression Id. */ 34 | int START_DEFERRED_EXPRESSION = 3; 35 | /** RegularExpression Id. */ 36 | int START_MAP = 9; 37 | /** RegularExpression Id. */ 38 | int RCURL = 10; 39 | /** RegularExpression Id. */ 40 | int INTEGER_LITERAL = 11; 41 | /** RegularExpression Id. */ 42 | int FLOATING_POINT_LITERAL = 12; 43 | /** RegularExpression Id. */ 44 | int EXPONENT = 13; 45 | /** RegularExpression Id. */ 46 | int STRING_LITERAL = 14; 47 | /** RegularExpression Id. */ 48 | int BADLY_ESCAPED_STRING_LITERAL = 15; 49 | /** RegularExpression Id. */ 50 | int TRUE = 16; 51 | /** RegularExpression Id. */ 52 | int FALSE = 17; 53 | /** RegularExpression Id. */ 54 | int NULL = 18; 55 | /** RegularExpression Id. */ 56 | int DOT = 19; 57 | /** RegularExpression Id. */ 58 | int LPAREN = 20; 59 | /** RegularExpression Id. */ 60 | int RPAREN = 21; 61 | /** RegularExpression Id. */ 62 | int LBRACK = 22; 63 | /** RegularExpression Id. */ 64 | int RBRACK = 23; 65 | /** RegularExpression Id. */ 66 | int COLON = 24; 67 | /** RegularExpression Id. */ 68 | int COMMA = 25; 69 | /** RegularExpression Id. */ 70 | int SEMICOLON = 26; 71 | /** RegularExpression Id. */ 72 | int GT0 = 27; 73 | /** RegularExpression Id. */ 74 | int GT1 = 28; 75 | /** RegularExpression Id. */ 76 | int LT0 = 29; 77 | /** RegularExpression Id. */ 78 | int LT1 = 30; 79 | /** RegularExpression Id. */ 80 | int GE0 = 31; 81 | /** RegularExpression Id. */ 82 | int GE1 = 32; 83 | /** RegularExpression Id. */ 84 | int LE0 = 33; 85 | /** RegularExpression Id. */ 86 | int LE1 = 34; 87 | /** RegularExpression Id. */ 88 | int EQ0 = 35; 89 | /** RegularExpression Id. */ 90 | int EQ1 = 36; 91 | /** RegularExpression Id. */ 92 | int NE0 = 37; 93 | /** RegularExpression Id. */ 94 | int NE1 = 38; 95 | /** RegularExpression Id. */ 96 | int NOT0 = 39; 97 | /** RegularExpression Id. */ 98 | int NOT1 = 40; 99 | /** RegularExpression Id. */ 100 | int AND0 = 41; 101 | /** RegularExpression Id. */ 102 | int AND1 = 42; 103 | /** RegularExpression Id. */ 104 | int OR0 = 43; 105 | /** RegularExpression Id. */ 106 | int OR1 = 44; 107 | /** RegularExpression Id. */ 108 | int EMPTY = 45; 109 | /** RegularExpression Id. */ 110 | int INSTANCEOF = 46; 111 | /** RegularExpression Id. */ 112 | int MULT = 47; 113 | /** RegularExpression Id. */ 114 | int PLUS = 48; 115 | /** RegularExpression Id. */ 116 | int MINUS = 49; 117 | /** RegularExpression Id. */ 118 | int QUESTIONMARK = 50; 119 | /** RegularExpression Id. */ 120 | int DIV0 = 51; 121 | /** RegularExpression Id. */ 122 | int DIV1 = 52; 123 | /** RegularExpression Id. */ 124 | int MOD0 = 53; 125 | /** RegularExpression Id. */ 126 | int MOD1 = 54; 127 | /** RegularExpression Id. */ 128 | int CONCAT = 55; 129 | /** RegularExpression Id. */ 130 | int ASSIGN = 56; 131 | /** RegularExpression Id. */ 132 | int ARROW = 57; 133 | /** RegularExpression Id. */ 134 | int IDENTIFIER = 58; 135 | /** RegularExpression Id. */ 136 | int IMPL_OBJ_START = 59; 137 | /** RegularExpression Id. */ 138 | int LETTER = 60; 139 | /** RegularExpression Id. */ 140 | int DIGIT = 61; 141 | /** RegularExpression Id. */ 142 | int ILLEGAL_CHARACTER = 62; 143 | 144 | /** Lexical state. */ 145 | int DEFAULT = 0; 146 | /** Lexical state. */ 147 | int IN_EXPRESSION = 1; 148 | /** Lexical state. */ 149 | int IN_MAP = 2; 150 | 151 | /** Literal token values. */ 152 | String[] tokenImage = { 153 | "", 154 | "", 155 | "\"${\"", 156 | "\"#{\"", 157 | "\"\\\\\"", 158 | "\" \"", 159 | "\"\\t\"", 160 | "\"\\n\"", 161 | "\"\\r\"", 162 | "\"{\"", 163 | "\"}\"", 164 | "", 165 | "", 166 | "", 167 | "", 168 | "", 169 | "\"true\"", 170 | "\"false\"", 171 | "\"null\"", 172 | "\".\"", 173 | "\"(\"", 174 | "\")\"", 175 | "\"[\"", 176 | "\"]\"", 177 | "\":\"", 178 | "\",\"", 179 | "\";\"", 180 | "\">\"", 181 | "\"gt\"", 182 | "\"<\"", 183 | "\"lt\"", 184 | "\">=\"", 185 | "\"ge\"", 186 | "\"<=\"", 187 | "\"le\"", 188 | "\"==\"", 189 | "\"eq\"", 190 | "\"!=\"", 191 | "\"ne\"", 192 | "\"!\"", 193 | "\"not\"", 194 | "\"&&\"", 195 | "\"and\"", 196 | "\"||\"", 197 | "\"or\"", 198 | "\"empty\"", 199 | "\"instanceof\"", 200 | "\"*\"", 201 | "\"+\"", 202 | "\"-\"", 203 | "\"?\"", 204 | "\"/\"", 205 | "\"div\"", 206 | "\"%\"", 207 | "\"mod\"", 208 | "\"+=\"", 209 | "\"=\"", 210 | "\"->\"", 211 | "", 212 | "\"#\"", 213 | "", 214 | "", 215 | "", 216 | }; 217 | 218 | } 219 | -------------------------------------------------------------------------------- /src/test/java/org/glassfish/el/test/ELProcessorTest.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2018, 2021 Oracle and/or its affiliates and others. 3 | * All rights reserved. 4 | * 5 | * This program and the accompanying materials are made available under the 6 | * terms of the Eclipse Public License v. 2.0, which is available at 7 | * http://www.eclipse.org/legal/epl-2.0. 8 | * 9 | * This Source Code may also be made available under the following Secondary 10 | * Licenses when the conditions for such availability set forth in the 11 | * Eclipse Public License v. 2.0 are satisfied: GNU General Public License, 12 | * version 2 with the GNU Classpath Exception, which is available at 13 | * https://www.gnu.org/software/classpath/license.html. 14 | * 15 | * SPDX-License-Identifier: EPL-2.0 OR GPL-2.0 WITH Classpath-exception-2.0 16 | */ 17 | 18 | package org.glassfish.el.test; 19 | 20 | import org.junit.Test; 21 | import org.junit.Before; 22 | import org.junit.BeforeClass; 23 | import static org.junit.Assert.assertEquals; 24 | import static org.junit.Assert.assertNull; 25 | import static org.junit.Assert.assertTrue; 26 | 27 | import jakarta.el.ELProcessor; 28 | import jakarta.el.ELManager; 29 | import jakarta.el.ExpressionFactory; 30 | import jakarta.el.MethodExpression; 31 | import jakarta.el.ELContext; 32 | import java.lang.reflect.Method; 33 | 34 | public class ELProcessorTest { 35 | 36 | static ELProcessor elp; 37 | static ELManager elm; 38 | static ExpressionFactory factory; 39 | 40 | @BeforeClass 41 | public static void setUpClass() throws Exception { 42 | System.setProperty("jakarta.el.ExpressionFactory", "org.glassfish.expressly.ExpressionFactoryImpl"); 43 | 44 | elp = new ELProcessor(); 45 | elm = elp.getELManager(); 46 | factory = ELManager.getExpressionFactory(); 47 | } 48 | 49 | @Before 50 | public void setUp() { 51 | } 52 | 53 | @Test 54 | public void testMethExpr() { 55 | MethodExpression meth = null; 56 | ELContext ctxt = elm.getELContext(); 57 | try { 58 | meth = factory.createMethodExpression( 59 | ctxt, "#{str.length}", Object.class, null); 60 | } catch (NullPointerException ex){ 61 | // Do nothing 62 | } 63 | assertTrue(meth == null); 64 | meth = factory.createMethodExpression( 65 | ctxt, "#{'abc'.length()}", Object.class, null); 66 | Object result = meth.invoke(ctxt, new Object[] {"abcde"}); 67 | System.out.println("'abc'.length() called, equals " + result); 68 | assertEquals(result, Integer.valueOf(3)); 69 | } 70 | 71 | @Test 72 | public void testGetValue() { 73 | Object result = elp.eval("10 + 1"); 74 | assertEquals(result.toString(), "11"); 75 | result = elp.getValue("10 + 2", String.class); 76 | assertEquals(result, "12"); 77 | } 78 | 79 | @Test 80 | public void testSetVariable () { 81 | elp.setVariable("xx", "100"); 82 | Object result = elp.getValue("xx + 11", String.class); 83 | assertEquals(result, "111"); 84 | elp.setVariable("xx", null); 85 | assertNull(elp.eval("xx")); 86 | elp.setVariable("yy", "abc"); 87 | assertEquals(elp.eval("yy = 123; abc"), Long.valueOf(123)); 88 | assertEquals(elp.eval("abc = 456; yy"), Long.valueOf(456)); 89 | } 90 | 91 | @Test 92 | public void testConcat() { 93 | Object result = elp.eval("'10' + 1"); 94 | assertEquals(result, Long.valueOf(11)); 95 | result = elp.eval("10 += '1'"); 96 | assertEquals(result.toString(), "101"); 97 | } 98 | 99 | @Test 100 | public void testParenthesis() { 101 | elp.setVariable("xx", "1"); 102 | Object result = elp.eval("((xx)) + 1"); 103 | assertEquals(result, Long.valueOf(2)); 104 | } 105 | 106 | @Test 107 | public void defineFuncTest() { 108 | Class c = MyBean.class; 109 | Method meth = null; 110 | Method meth2 = null; 111 | try { 112 | meth = c.getMethod("getBar", new Class[] {}); 113 | meth2 = c.getMethod("getFoo", new Class[] {}); 114 | } catch (Exception e) { 115 | System.out.printf("Exception: ", e); 116 | } 117 | try { 118 | elp.defineFunction("xx", "", meth); 119 | Boolean ret = elp.eval("xx:getBar() == 64"); 120 | assertTrue(ret.booleanValue()); 121 | } catch (NoSuchMethodException ex) { 122 | 123 | } 124 | 125 | boolean caught = false; 126 | try { 127 | elp.defineFunction("", "", meth2); 128 | Boolean ret = elp.eval("getFoo() == 100"); 129 | assertTrue(ret.booleanValue()); 130 | } catch (NoSuchMethodException ex) { 131 | caught = true; 132 | } 133 | assertTrue(caught); 134 | 135 | try { 136 | elp.defineFunction("yy", "", "org.glassfish.el.test.ELProcessorTest$MyBean", "getBar"); 137 | Boolean ret = elp.eval("yy:getBar() == 64"); 138 | assertTrue(ret.booleanValue()); 139 | } catch (ClassNotFoundException | NoSuchMethodException ex) { 140 | 141 | } 142 | 143 | caught = false; 144 | try { 145 | elp.defineFunction("yy", "", "org.glassfish.el.test.ELProcessorTest$MyBean", "getFooBar"); 146 | Boolean ret = elp.eval("yy:getBar() == 100"); 147 | assertTrue(ret.booleanValue()); 148 | } catch (ClassNotFoundException | NoSuchMethodException ex) { 149 | caught = true; 150 | } 151 | assertTrue(caught); 152 | 153 | caught = false; 154 | try { 155 | elp.defineFunction("yy", "", "testBean", "getFoo"); 156 | Boolean ret = elp.eval("yy:getBar() == 100"); 157 | assertTrue(ret.booleanValue()); 158 | } catch (ClassNotFoundException | NoSuchMethodException ex) { 159 | caught = true; 160 | } 161 | assertTrue(caught); 162 | } 163 | /* 164 | @Test 165 | public void testBean() { 166 | elp.defineBean("xyz", new MyBean()); 167 | Object result = elp.eval("xyz.foo"); 168 | assertEquals(result.toString(), "100"); 169 | } 170 | */ 171 | 172 | @Test 173 | public void testImport() { 174 | elm.importClass("org.glassfish.el.test.ELProcessorTest$MyBean"); 175 | Boolean ret = elp.eval("ELProcessorTest$MyBean.aaaa == 101"); 176 | assertTrue(ret.booleanValue()); 177 | ret = elp.eval("ELProcessorTest$MyBean.getBar() == 64"); 178 | assertTrue(ret.booleanValue()); 179 | elm.importStatic("org.glassfish.el.test.ELProcessorTest$MyBean.aaaa"); 180 | assertEquals(Integer.valueOf(101), elp.eval("aaaa")); 181 | elm.importStatic("org.glassfish.el.test.ELProcessorTest$MyBean.getBar"); 182 | assertEquals(Integer.valueOf(64), elp.eval("getBar()")); 183 | /* 184 | elm.importStatic("a.b.NonExisting.foobar"); 185 | elp.eval("foobar"); 186 | elp.eval("ELProcessorTest$MyBean.getFoo()"); 187 | */ 188 | } 189 | 190 | static public class MyBean { 191 | public static int aaaa = 101; 192 | public int getFoo() { 193 | return 100; 194 | } 195 | 196 | @SuppressWarnings("unused") 197 | public int getFoo(int i) { 198 | return 200; 199 | } 200 | public static int getBar() { 201 | return 64; 202 | } 203 | } 204 | } 205 | 206 | -------------------------------------------------------------------------------- /src/main/java/org/glassfish/expressly/parser/SimpleNode.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2022, 2022 Contributors to the Eclipse Foundation. 3 | * Copyright (c) 1997, 2018 Oracle and/or its affiliates. All rights reserved. 4 | * 5 | * This program and the accompanying materials are made available under the 6 | * terms of the Eclipse Public License v. 2.0, which is available at 7 | * http://www.eclipse.org/legal/epl-2.0. 8 | * 9 | * This Source Code may also be made available under the following Secondary 10 | * Licenses when the conditions for such availability set forth in the 11 | * Eclipse Public License v. 2.0 are satisfied: GNU General Public License, 12 | * version 2 with the GNU Classpath Exception, which is available at 13 | * https://www.gnu.org/software/classpath/license.html. 14 | * 15 | * SPDX-License-Identifier: EPL-2.0 OR GPL-2.0 WITH Classpath-exception-2.0 16 | */ 17 | 18 | package org.glassfish.expressly.parser; 19 | 20 | import static org.glassfish.expressly.parser.ELParserTreeConstants.jjtNodeName; 21 | 22 | import org.glassfish.expressly.lang.ELSupport; 23 | import org.glassfish.expressly.lang.EvaluationContext; 24 | import org.glassfish.expressly.util.MessageFactory; 25 | 26 | import jakarta.el.ELException; 27 | import jakarta.el.MethodInfo; 28 | import jakarta.el.MethodReference; 29 | import jakarta.el.PropertyNotWritableException; 30 | import jakarta.el.ValueReference; 31 | 32 | /** 33 | * @author Jacob Hookom [jacob@hookom.net] 34 | * @version $Change: 181177 $$DateTime: 2001/06/26 08:45:09 $$Author: kchung $ 35 | */ 36 | public abstract class SimpleNode extends ELSupport implements Node { 37 | 38 | protected int id; 39 | protected Node parent; 40 | protected Node[] children; 41 | protected String image; 42 | 43 | public SimpleNode(int i) { 44 | id = i; 45 | } 46 | 47 | @Override 48 | public void jjtOpen() { 49 | } 50 | 51 | @Override 52 | public void jjtClose() { 53 | } 54 | 55 | @Override 56 | public void jjtSetParent(Node node) { 57 | parent = node; 58 | } 59 | 60 | @Override 61 | public Node jjtGetParent() { 62 | return parent; 63 | } 64 | 65 | @Override 66 | public void jjtAddChild(Node n, int i) { 67 | if (children == null) { 68 | children = new Node[i + 1]; 69 | } else if (i >= children.length) { 70 | Node c[] = new Node[i + 1]; 71 | System.arraycopy(children, 0, c, 0, children.length); 72 | children = c; 73 | } 74 | children[i] = n; 75 | } 76 | 77 | @Override 78 | public Node jjtGetChild(int i) { 79 | return children[i]; 80 | } 81 | 82 | @Override 83 | public int jjtGetNumChildren() { 84 | return children == null ? 0 : children.length; 85 | } 86 | 87 | /* 88 | * You can override these two methods in subclasses of SimpleNode to customize the way the node appears when the tree is 89 | * dumped. If your output uses more than one line you should override toString(String), otherwise overriding toString() 90 | * is probably all you need to do. 91 | */ 92 | 93 | @Override 94 | public String toString() { 95 | if (image != null) { 96 | return jjtNodeName[id] + "[" + this.image + "]"; 97 | } 98 | 99 | return jjtNodeName[id]; 100 | } 101 | 102 | public String toString(String prefix) { 103 | return prefix + toString(); 104 | } 105 | 106 | /* 107 | * Override this method if you want to customize how the node dumps out its children. 108 | */ 109 | public void dump(String prefix) { 110 | System.out.println(toString(prefix)); 111 | if (children != null) { 112 | for (int i = 0; i < children.length; ++i) { 113 | SimpleNode n = (SimpleNode) children[i]; 114 | if (n != null) { 115 | n.dump(prefix + " "); 116 | } 117 | } 118 | } 119 | } 120 | 121 | @Override 122 | public String getImage() { 123 | return image; 124 | } 125 | 126 | public void setImage(String image) { 127 | this.image = image; 128 | } 129 | 130 | @Override 131 | public Class getType(EvaluationContext ctx) throws ELException { 132 | throw new UnsupportedOperationException(); 133 | } 134 | 135 | @Override 136 | public Object getValue(EvaluationContext ctx) throws ELException { 137 | throw new UnsupportedOperationException(); 138 | } 139 | 140 | @Override 141 | public ValueReference getValueReference(EvaluationContext ctx) throws ELException { 142 | return null; 143 | } 144 | 145 | @Override 146 | public boolean isReadOnly(EvaluationContext ctx) throws ELException { 147 | return true; 148 | } 149 | 150 | @Override 151 | public void setValue(EvaluationContext ctx, Object value) throws ELException { 152 | throw new PropertyNotWritableException(MessageFactory.get("error.syntax.set")); 153 | } 154 | 155 | @Override 156 | public void accept(NodeVisitor visitor) throws ELException { 157 | visitor.visit(this); 158 | if (children != null && children.length > 0) { 159 | for (int i = 0; i < children.length; i++) { 160 | this.children[i].accept(visitor); 161 | } 162 | } 163 | } 164 | 165 | @Override 166 | public Object invoke(EvaluationContext ctx, Class[] paramTypes, Object[] paramValues) throws ELException { 167 | throw new UnsupportedOperationException(); 168 | } 169 | 170 | @Override 171 | public MethodInfo getMethodInfo(EvaluationContext ctx, Class[] paramTypes) throws ELException { 172 | throw new UnsupportedOperationException(); 173 | } 174 | 175 | @Override 176 | public MethodReference getMethodReference(EvaluationContext ctx) { 177 | throw new UnsupportedOperationException(); 178 | } 179 | 180 | @Override 181 | public boolean equals(Object node) { 182 | if (!(node instanceof SimpleNode)) { 183 | return false; 184 | } 185 | 186 | SimpleNode simpleNode = (SimpleNode) node; 187 | if (this.id != simpleNode.id) { 188 | return false; 189 | } 190 | 191 | if (this.children == null && simpleNode.children == null) { 192 | if (this.image == null) { 193 | return simpleNode.image == null; 194 | } 195 | return this.image.equals(simpleNode.image); 196 | } 197 | 198 | if (this.children == null || simpleNode.children == null) { 199 | // One is null and the other is non-null 200 | return false; 201 | } 202 | if (this.children.length != simpleNode.children.length) { 203 | return false; 204 | } 205 | 206 | if (this.children.length == 0) { 207 | if (this.image == null) { 208 | return simpleNode.image == null; 209 | } 210 | return this.image.equals(simpleNode.image); 211 | } 212 | 213 | for (int i = 0; i < this.children.length; i++) { 214 | if (!this.children[i].equals(simpleNode.children[i])) { 215 | return false; 216 | } 217 | } 218 | 219 | return true; 220 | } 221 | 222 | @Override 223 | public boolean isParametersProvided() { 224 | return false; 225 | } 226 | 227 | @Override 228 | public int hashCode() { 229 | if (this.children == null || this.children.length == 0) { 230 | if (this.image != null) { 231 | return this.image.hashCode(); 232 | } 233 | return this.id; 234 | } 235 | int h = 0; 236 | for (int i = this.children.length - 1; i >= 0; i--) { 237 | h = h + h + h + this.children[i].hashCode(); 238 | } 239 | h = h + h + h + id; 240 | return h; 241 | } 242 | } 243 | -------------------------------------------------------------------------------- /src/main/java/org/glassfish/expressly/parser/AstFunction.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2022, 2022 Contributors to the Eclipse Foundation. 3 | * Copyright (c) 1997, 2018 Oracle and/or its affiliates. All rights reserved. 4 | * 5 | * This program and the accompanying materials are made available under the 6 | * terms of the Eclipse Public License v. 2.0, which is available at 7 | * http://www.eclipse.org/legal/epl-2.0. 8 | * 9 | * This Source Code may also be made available under the following Secondary 10 | * Licenses when the conditions for such availability set forth in the 11 | * Eclipse Public License v. 2.0 are satisfied: GNU General Public License, 12 | * version 2 with the GNU Classpath Exception, which is available at 13 | * https://www.gnu.org/software/classpath/license.html. 14 | * 15 | * SPDX-License-Identifier: EPL-2.0 OR GPL-2.0 WITH Classpath-exception-2.0 16 | */ 17 | 18 | package org.glassfish.expressly.parser; 19 | 20 | import java.lang.reflect.InvocationTargetException; 21 | import java.lang.reflect.Method; 22 | 23 | import org.glassfish.expressly.lang.EvaluationContext; 24 | import org.glassfish.expressly.util.MessageFactory; 25 | 26 | import jakarta.el.ELClass; 27 | import jakarta.el.ELException; 28 | import jakarta.el.FunctionMapper; 29 | import jakarta.el.LambdaExpression; 30 | import jakarta.el.ValueExpression; 31 | import jakarta.el.VariableMapper; 32 | 33 | /** 34 | * @author Jacob Hookom [jacob@hookom.net] 35 | * @version $Change: 181177 $$DateTime: 2001/06/26 08:45:09 $$Author: kchung $ 36 | */ 37 | public final class AstFunction extends SimpleNode { 38 | 39 | protected String localName = ""; 40 | 41 | protected String prefix = ""; 42 | 43 | public AstFunction(int id) { 44 | super(id); 45 | } 46 | 47 | public String getLocalName() { 48 | return localName; 49 | } 50 | 51 | public String getOutputName() { 52 | if (this.prefix.length() == 0) { 53 | return this.localName; 54 | } else { 55 | return this.prefix + ":" + this.localName; 56 | } 57 | } 58 | 59 | public String getPrefix() { 60 | return prefix; 61 | } 62 | 63 | @Override 64 | public Class getType(EvaluationContext ctx) throws ELException { 65 | FunctionMapper functionMapper = ctx.getFunctionMapper(); 66 | 67 | // quickly validate again for this request 68 | if (functionMapper == null) { 69 | throw new ELException(MessageFactory.get("error.fnMapper.null")); 70 | } 71 | 72 | Method functionMethod = functionMapper.resolveFunction(this.prefix, this.localName); 73 | if (functionMethod == null) { 74 | throw new ELException(MessageFactory.get("error.fnMapper.method", this.getOutputName())); 75 | } 76 | 77 | return functionMethod.getReturnType(); 78 | } 79 | 80 | /* 81 | * Find the object associated with the given name. Return null if the there is no such object. 82 | */ 83 | private Object findValue(EvaluationContext ctx, String name) { 84 | // First check if this is a Lambda argument 85 | if (ctx.isLambdaArgument(name)) { 86 | return ctx.getLambdaArgument(name); 87 | } 88 | 89 | // Next check if this an Jakarta Expression variable 90 | VariableMapper varMapper = ctx.getVariableMapper(); 91 | if (varMapper != null) { 92 | ValueExpression expr = varMapper.resolveVariable(name); 93 | if (expr != null) { 94 | return expr.getValue(ctx.getELContext()); 95 | } 96 | } 97 | 98 | // Check if this is resolvable by an ELResolver 99 | ctx.setPropertyResolved(false); 100 | Object ret = ctx.getELResolver().getValue(ctx, null, name); 101 | if (ctx.isPropertyResolved()) { 102 | return ret; 103 | } 104 | return null; 105 | } 106 | 107 | @Override 108 | public Object getValue(EvaluationContext ctx) throws ELException { 109 | 110 | // Check to see if a function is a bean that is a Lambdaexpression. 111 | // If so, invoke it. Also allow for the case that a Lambda expression 112 | // can return another Lambda expression. 113 | if (prefix.length() == 0) { 114 | Object val = findValue(ctx, this.localName); 115 | // Check the case of repeated lambda invocation, such as f()()() 116 | 117 | if ((val != null) && (val instanceof LambdaExpression)) { 118 | for (int i = 0; i < this.children.length; i++) { 119 | Object[] params = ((AstMethodArguments) this.children[i]).getParameters(ctx); 120 | if (!(val instanceof LambdaExpression)) { 121 | throw new ELException(MessageFactory.get("error.function.syntax", getOutputName())); 122 | } 123 | val = ((LambdaExpression) val).invoke(ctx, params); 124 | } 125 | return val; 126 | } 127 | } 128 | 129 | FunctionMapper functionMapper = ctx.getFunctionMapper(); 130 | 131 | Method functionMethod = null; 132 | if (functionMapper != null) { 133 | functionMethod = functionMapper.resolveFunction(this.prefix, this.localName); 134 | } 135 | 136 | if (functionMethod == null) { 137 | if (this.prefix.length() == 0 && ctx.getImportHandler() != null) { 138 | 139 | // Check if this is a constructor call for an imported class 140 | Class resolvedClass = ctx.getImportHandler().resolveClass(this.localName); 141 | String methodName = null; 142 | if (resolvedClass != null) { 143 | methodName = ""; 144 | } else { 145 | // Check if this is a imported static method 146 | resolvedClass = ctx.getImportHandler().resolveStatic(this.localName); 147 | methodName = this.localName; 148 | ; 149 | } 150 | 151 | if (resolvedClass != null) { 152 | // Use StaticFieldELResolver to invoke the constructor or the 153 | // static method. 154 | Object[] params = ((AstMethodArguments) this.children[0]).getParameters(ctx); 155 | return ctx.getELResolver().invoke(ctx, new ELClass(resolvedClass), methodName, null, params); 156 | } 157 | } 158 | 159 | // quickly validate for this request 160 | if (functionMapper == null) { 161 | throw new ELException(MessageFactory.get("error.fnMapper.null")); 162 | } 163 | 164 | throw new ELException(MessageFactory.get("error.fnMapper.method", this.getOutputName())); 165 | } 166 | 167 | Class[] paramTypes = functionMethod.getParameterTypes(); 168 | Object[] params = ((AstMethodArguments) this.children[0]).getParameters(ctx); 169 | Object result = null; 170 | for (int i = 0; i < params.length; i++) { 171 | try { 172 | params[i] = ctx.convertToType(params[i], paramTypes[i]); 173 | } catch (ELException ele) { 174 | throw new ELException(MessageFactory.get("error.function", this.getOutputName()), ele); 175 | } 176 | } 177 | 178 | try { 179 | result = functionMethod.invoke(null, params); 180 | } catch (IllegalAccessException iae) { 181 | throw new ELException(MessageFactory.get("error.function", this.getOutputName()), iae); 182 | } catch (InvocationTargetException ite) { 183 | throw new ELException(MessageFactory.get("error.function", this.getOutputName()), ite.getCause()); 184 | } 185 | 186 | return result; 187 | } 188 | 189 | public void setLocalName(String localName) { 190 | this.localName = localName; 191 | } 192 | 193 | public void setPrefix(String prefix) { 194 | this.prefix = prefix; 195 | } 196 | 197 | @Override 198 | public String toString() { 199 | return ELParserTreeConstants.jjtNodeName[id] + "[" + this.getOutputName() + "]"; 200 | } 201 | } 202 | --------------------------------------------------------------------------------