diff -Nru mvel-2.3.1/debian/changelog mvel-2.4.0/debian/changelog --- mvel-2.3.1/debian/changelog 2016-10-03 11:21:52.000000000 +0000 +++ mvel-2.4.0/debian/changelog 2017-12-01 23:03:58.000000000 +0000 @@ -1,3 +1,20 @@ +mvel (2.4.0-1) unstable; urgency=medium + + * Team upload. + * New upstream version 2.4.0. + * Change homepage address to github.com because codehaus.org is gone. + * Switch to compat level 10. + * Use only Build-Depends field. + * wrap-and-sort -sa. + * Declare compliance with Debian Policy 4.1.2. + * Remove --has-package-version flag. + * d/copyright: Use https for Format field. + * Refresh use_system_asm.diff. + * Add java9.patch and work around the FTBFS with Java 9 by ignoring doclint + errors. Thanks to Chris West for the report. (Closes: #875775) + + -- Markus Koschany Sat, 02 Dec 2017 00:03:58 +0100 + mvel (2.3.1-1) unstable; urgency=medium * Team upload. diff -Nru mvel-2.3.1/debian/compat mvel-2.4.0/debian/compat --- mvel-2.3.1/debian/compat 2016-10-03 11:12:59.000000000 +0000 +++ mvel-2.4.0/debian/compat 2017-12-01 23:03:58.000000000 +0000 @@ -1 +1 @@ -9 +10 diff -Nru mvel-2.3.1/debian/control mvel-2.4.0/debian/control --- mvel-2.3.1/debian/control 2016-10-03 11:12:59.000000000 +0000 +++ mvel-2.4.0/debian/control 2017-12-01 23:03:58.000000000 +0000 @@ -2,26 +2,33 @@ Section: java Priority: optional Maintainer: Debian Java Maintainers -Uploaders: Damien Raude-Morvan -Build-Depends: debhelper (>= 9), default-jdk, maven-debian-helper -Build-Depends-Indep: default-jdk-doc, - junit4, - libasm-java (>= 5.0), - libmaven-bundle-plugin-java, - libmaven-compiler-plugin-java (>= 2.0.2), - libmaven-jar-plugin-java (>= 2.2), - libmaven-javadoc-plugin-java, - libsurefire-java (>= 2.4.3), - libxstream-java -Standards-Version: 3.9.8 +Uploaders: + Damien Raude-Morvan +Build-Depends: + debhelper (>= 10), + default-jdk, + default-jdk-doc, + junit4, + libasm-java (>= 5.0), + libmaven-bundle-plugin-java, + libmaven-compiler-plugin-java (>= 2.0.2), + libmaven-jar-plugin-java (>= 2.2), + libmaven-javadoc-plugin-java, + libsurefire-java (>= 2.4.3), + libxstream-java, + maven-debian-helper +Standards-Version: 4.1.2 Vcs-Git: https://anonscm.debian.org/git/pkg-java/mvel.git Vcs-Browser: https://anonscm.debian.org/cgit/pkg-java/mvel.git -Homepage: http://mvel.codehaus.org +Homepage: https://github.com/mvel/mvel/ Package: libmvel-java Architecture: all -Depends: ${maven:Depends}, ${misc:Depends} -Recommends: ${maven:OptionalDepends} +Depends: + ${maven:Depends}, + ${misc:Depends} +Recommends: + ${maven:OptionalDepends} Description: expression language for Java-based applications - Library MVEL may be useful as an extension to anything from use in JSP Tag Libraries, to the configuration facilities of your library/framework. @@ -32,9 +39,13 @@ Package: libmvel-java-doc Architecture: all Section: doc -Depends: ${maven:DocDepends}, ${misc:Depends} -Recommends: ${maven:DocOptionalDepends} -Suggests: libmvel-java +Depends: + ${maven:DocDepends}, + ${misc:Depends} +Recommends: + ${maven:DocOptionalDepends} +Suggests: + libmvel-java Description: expression language for Java-based applications - Javadoc MVEL may be useful as an extension to anything from use in JSP Tag Libraries, to the configuration facilities of your library/framework. diff -Nru mvel-2.3.1/debian/copyright mvel-2.4.0/debian/copyright --- mvel-2.3.1/debian/copyright 2016-10-03 11:12:59.000000000 +0000 +++ mvel-2.4.0/debian/copyright 2017-12-01 23:03:58.000000000 +0000 @@ -1,4 +1,4 @@ -Format: http://www.debian.org/doc/packaging-manuals/copyright-format/1.0/ +Format: https://www.debian.org/doc/packaging-manuals/copyright-format/1.0/ Upstream-Name: MVEL Upstream-Contact: Mike Brock Source: http://mvel.codehaus.org diff -Nru mvel-2.3.1/debian/libmvel-java-doc.install mvel-2.4.0/debian/libmvel-java-doc.install --- mvel-2.3.1/debian/libmvel-java-doc.install 2016-10-03 11:12:59.000000000 +0000 +++ mvel-2.4.0/debian/libmvel-java-doc.install 2017-12-01 23:03:58.000000000 +0000 @@ -1,2 +1 @@ target/apidocs/* usr/share/doc/libmvel-java/api - diff -Nru mvel-2.3.1/debian/libmvel-java.poms mvel-2.4.0/debian/libmvel-java.poms --- mvel-2.3.1/debian/libmvel-java.poms 2016-10-03 11:12:59.000000000 +0000 +++ mvel-2.4.0/debian/libmvel-java.poms 2017-12-01 23:03:58.000000000 +0000 @@ -25,4 +25,4 @@ # --site-xml=: Optional, the location for site.xml if it needs to be installed. # Empty by default. [mh_install] # -pom.xml --has-package-version --java-lib +pom.xml --java-lib diff -Nru mvel-2.3.1/debian/patches/java9.patch mvel-2.4.0/debian/patches/java9.patch --- mvel-2.3.1/debian/patches/java9.patch 1970-01-01 00:00:00.000000000 +0000 +++ mvel-2.4.0/debian/patches/java9.patch 2017-12-01 23:03:58.000000000 +0000 @@ -0,0 +1,30 @@ +From: Markus Koschany +Date: Sat, 2 Dec 2017 09:54:39 +0100 +Subject: java9 + +Work around FTBFS with Java 9 by ignoring the doclint errors. + +Bug-Debian: https://bugs.debian.org/875775 +Forwarded: no +--- + pom.xml | 7 +++++++ + 1 file changed, 7 insertions(+) + +diff --git a/pom.xml b/pom.xml +index dbed0b0..fdb10b9 100644 +--- a/pom.xml ++++ b/pom.xml +@@ -80,6 +80,13 @@ + + + ++ ++ org.apache.maven.plugins ++ maven-javadoc-plugin ++ ++ false ++ ++ + + maven-enforcer-plugin + 1.0 diff -Nru mvel-2.3.1/debian/patches/series mvel-2.4.0/debian/patches/series --- mvel-2.3.1/debian/patches/series 2016-10-03 11:14:39.000000000 +0000 +++ mvel-2.4.0/debian/patches/series 2017-12-01 23:03:58.000000000 +0000 @@ -1 +1,2 @@ use_system_asm.diff +java9.patch diff -Nru mvel-2.3.1/debian/patches/use_system_asm.diff mvel-2.4.0/debian/patches/use_system_asm.diff --- mvel-2.3.1/debian/patches/use_system_asm.diff 2016-10-03 11:19:18.000000000 +0000 +++ mvel-2.4.0/debian/patches/use_system_asm.diff 2017-12-01 23:03:58.000000000 +0000 @@ -3,7 +3,7 @@ Forwarded: no --- a/src/main/java/org/mvel2/optimizers/impl/asm/ASMAccessorOptimizer.java +++ b/src/main/java/org/mvel2/optimizers/impl/asm/ASMAccessorOptimizer.java -@@ -23,10 +23,10 @@ +@@ -23,10 +23,10 @@ import org.mvel2.MVEL; import org.mvel2.OptimizationFailure; import org.mvel2.ParserContext; import org.mvel2.PropertyAccessException; @@ -18,7 +18,7 @@ import org.mvel2.ast.FunctionInstance; import org.mvel2.ast.TypeDescriptor; import org.mvel2.ast.WithNode; -@@ -74,12 +74,12 @@ +@@ -74,12 +74,12 @@ import static org.mvel2.DataConversion.c import static org.mvel2.DataConversion.convert; import static org.mvel2.MVEL.eval; import static org.mvel2.MVEL.isAdvancedDebugging; @@ -37,7 +37,7 @@ import static org.mvel2.ast.TypeDescriptor.getClassReference; import static org.mvel2.integration.GlobalListenerFactory.hasGetListeners; import static org.mvel2.integration.GlobalListenerFactory.notifyGetListeners; -@@ -734,7 +734,7 @@ +@@ -734,7 +734,7 @@ public class ASMAccessorOptimizer extend if (clazz.isPrimitive()) { mv.visitFieldInsn(GETSTATIC, toNonPrimitiveType(clazz).getName().replace(".", "/"), "TYPE", "Ljava/lang/Class;"); } else { @@ -74,7 +74,7 @@ import org.mvel2.integration.VariableResolverFactory; --- a/src/test/java/org/mvel2/tests/core/PropertyHandlerTests.java +++ b/src/test/java/org/mvel2/tests/core/PropertyHandlerTests.java -@@ -3,9 +3,9 @@ +@@ -3,9 +3,9 @@ package org.mvel2.tests.core; import junit.framework.TestCase; import org.mvel2.MVEL; import org.mvel2.PropertyAccessor; @@ -86,16 +86,16 @@ import org.mvel2.integration.*; import org.mvel2.optimizers.OptimizerFactory; -@@ -389,4 +389,4 @@ - - assertEquals("foobie", wo.getFieldValue("foo")); +@@ -416,4 +416,4 @@ public class PropertyHandlerTests extend + Serializable compiled = MVEL.compileExpression("prop"); + assertEquals("Property", MVEL.executeExpression(compiled, new C())); } -} \ No newline at end of file +} --- a/src/main/java/org/mvel2/optimizers/OptimizerFactory.java +++ b/src/main/java/org/mvel2/optimizers/OptimizerFactory.java -@@ -43,9 +43,9 @@ +@@ -43,9 +43,9 @@ public class OptimizerFactory { */ try { if (OptimizerFactory.class.getClassLoader() != null) { diff -Nru mvel-2.3.1/pom.xml mvel-2.4.0/pom.xml --- mvel-2.3.1/pom.xml 2016-09-07 08:18:50.000000000 +0000 +++ mvel-2.4.0/pom.xml 2017-10-27 08:52:36.000000000 +0000 @@ -5,7 +5,7 @@ org.mvel mvel2 jar - 2.3.1.Final + 2.4.0.Final mvel http://mvel.codehaus.org/ @@ -31,7 +31,7 @@ scm:git:git@github.com:mvel/mvel.git scm:git:git@github.com:mvel/mvel.git scm:git:git@github.com:mvel/mvel.git - mvel2-2.3.1.Final + mvel2-2.4.0.Final jira diff -Nru mvel-2.3.1/samples/scripts/accentChild.mvel mvel-2.4.0/samples/scripts/accentChild.mvel --- mvel-2.3.1/samples/scripts/accentChild.mvel 1970-01-01 00:00:00.000000000 +0000 +++ mvel-2.4.0/samples/scripts/accentChild.mvel 2017-10-27 08:52:36.000000000 +0000 @@ -0,0 +1 @@ +Hello mister Gaël Périé \ No newline at end of file diff -Nru mvel-2.3.1/samples/scripts/accentTopLevel.mvel mvel-2.4.0/samples/scripts/accentTopLevel.mvel --- mvel-2.3.1/samples/scripts/accentTopLevel.mvel 1970-01-01 00:00:00.000000000 +0000 +++ mvel-2.4.0/samples/scripts/accentTopLevel.mvel 2017-10-27 08:52:36.000000000 +0000 @@ -0,0 +1 @@ +@include{'./accentChild.mvel'} \ No newline at end of file diff -Nru mvel-2.3.1/src/main/java/org/mvel2/compiler/AbstractParser.java mvel-2.4.0/src/main/java/org/mvel2/compiler/AbstractParser.java --- mvel-2.3.1/src/main/java/org/mvel2/compiler/AbstractParser.java 2016-09-07 08:18:50.000000000 +0000 +++ mvel-2.4.0/src/main/java/org/mvel2/compiler/AbstractParser.java 2017-10-27 08:52:36.000000000 +0000 @@ -17,6 +17,10 @@ */ package org.mvel2.compiler; +import java.io.Serializable; +import java.util.HashMap; +import java.util.WeakHashMap; + import org.mvel2.CompileException; import org.mvel2.ErrorDetail; import org.mvel2.Operator; @@ -82,17 +86,10 @@ import org.mvel2.util.ErrorUtil; import org.mvel2.util.ExecutionStack; import org.mvel2.util.FunctionParser; -import org.mvel2.util.PropertyTools; import org.mvel2.util.ProtoParser; -import java.io.Serializable; -import java.util.HashMap; -import java.util.WeakHashMap; - import static java.lang.Boolean.FALSE; import static java.lang.Boolean.TRUE; -import static java.lang.Double.parseDouble; -import static java.lang.Thread.currentThread; import static org.mvel2.Operator.*; import static org.mvel2.ast.TypeDescriptor.getClassReference; import static org.mvel2.util.ArrayTools.findFirst; @@ -1409,7 +1406,7 @@ } } - if (pCtx != null && pCtx.hasImports() && isArrayType(expr, st, end)) { + if (pCtx != null && isArrayType(expr, st, end)) { if (pCtx.hasImport(new String(expr, st, cursor - st - 2))) { lastWasIdentifier = true; TypeDescriptor typeDescriptor = new TypeDescriptor(expr, st, cursor - st, fields); diff -Nru mvel-2.3.1/src/main/java/org/mvel2/compiler/CompiledExpression.java mvel-2.4.0/src/main/java/org/mvel2/compiler/CompiledExpression.java --- mvel-2.3.1/src/main/java/org/mvel2/compiler/CompiledExpression.java 2016-09-07 08:18:50.000000000 +0000 +++ mvel-2.4.0/src/main/java/org/mvel2/compiler/CompiledExpression.java 2017-10-27 08:52:36.000000000 +0000 @@ -18,6 +18,8 @@ package org.mvel2.compiler; +import java.io.Serializable; + import org.mvel2.ParserConfiguration; import org.mvel2.ast.ASTNode; import org.mvel2.ast.TypeCast; @@ -28,8 +30,6 @@ import org.mvel2.optimizers.OptimizerFactory; import org.mvel2.util.ASTLinkedList; -import java.io.Serializable; - import static org.mvel2.MVELRuntime.execute; import static org.mvel2.optimizers.OptimizerFactory.setThreadAccessorOptimizer; @@ -56,7 +56,7 @@ this.knownEgressType = astMap.isSingleNode() ? astMap.firstNonSymbol().getEgressType() : egressType; this.literalOnly = literalOnly; this.parserConfiguration = parserConfiguration; - this.importInjectionRequired = parserConfiguration.getImports() != null && !parserConfiguration.getImports().isEmpty(); + this.importInjectionRequired = !parserConfiguration.getImports().isEmpty(); } public ASTNode getFirstNode() { diff -Nru mvel-2.3.1/src/main/java/org/mvel2/compiler/ExpressionCompiler.java mvel-2.4.0/src/main/java/org/mvel2/compiler/ExpressionCompiler.java --- mvel-2.3.1/src/main/java/org/mvel2/compiler/ExpressionCompiler.java 2016-09-07 08:18:50.000000000 +0000 +++ mvel-2.4.0/src/main/java/org/mvel2/compiler/ExpressionCompiler.java 2017-10-27 08:52:36.000000000 +0000 @@ -18,14 +18,29 @@ package org.mvel2.compiler; -import org.mvel2.*; -import org.mvel2.ast.*; -import org.mvel2.util.*; - import java.util.Iterator; import java.util.List; import java.util.Map; +import org.mvel2.CompileException; +import org.mvel2.ErrorDetail; +import org.mvel2.MVEL; +import org.mvel2.Operator; +import org.mvel2.ParserContext; +import org.mvel2.ast.ASTNode; +import org.mvel2.ast.Assignment; +import org.mvel2.ast.LiteralNode; +import org.mvel2.ast.NewObjectNode; +import org.mvel2.ast.OperatorNode; +import org.mvel2.ast.Substatement; +import org.mvel2.ast.Union; +import org.mvel2.util.ASTLinkedList; +import org.mvel2.util.CompilerTools; +import org.mvel2.util.ErrorUtil; +import org.mvel2.util.ExecutionStack; +import org.mvel2.util.ParseTools; +import org.mvel2.util.StringAppender; + import static org.mvel2.DataConversion.canConvert; import static org.mvel2.DataConversion.convert; import static org.mvel2.Operator.PTABLE; @@ -277,7 +292,11 @@ } if (!verifyOnly) { - return new CompiledExpression(finalizePayload(astBuild, secondPassOptimization, pCtx), pCtx.getSourceFile(), returnType, pCtx.getParserConfiguration(), literalOnly == 1); + try { + return new CompiledExpression(finalizePayload(astBuild, secondPassOptimization, pCtx), pCtx.getSourceFile(), returnType, pCtx.getParserConfiguration(), literalOnly == 1); + } catch (RuntimeException e) { + throw new CompileException(e.getMessage(), expr, st, e); + } } else { try { diff -Nru mvel-2.3.1/src/main/java/org/mvel2/compiler/PropertyVerifier.java mvel-2.4.0/src/main/java/org/mvel2/compiler/PropertyVerifier.java --- mvel-2.3.1/src/main/java/org/mvel2/compiler/PropertyVerifier.java 2016-09-07 08:18:50.000000000 +0000 +++ mvel-2.4.0/src/main/java/org/mvel2/compiler/PropertyVerifier.java 2017-10-27 08:52:36.000000000 +0000 @@ -18,7 +18,25 @@ package org.mvel2.compiler; -import org.mvel2.*; +import java.lang.reflect.Field; +import java.lang.reflect.Member; +import java.lang.reflect.Method; +import java.lang.reflect.Modifier; +import java.lang.reflect.ParameterizedType; +import java.lang.reflect.Type; +import java.lang.reflect.TypeVariable; +import java.util.ArrayList; +import java.util.Collection; +import java.util.Collections; +import java.util.HashMap; +import java.util.LinkedList; +import java.util.List; +import java.util.Map; + +import org.mvel2.CompileException; +import org.mvel2.ErrorDetail; +import org.mvel2.MVEL; +import org.mvel2.ParserContext; import org.mvel2.ast.Function; import org.mvel2.optimizers.AbstractOptimizer; import org.mvel2.optimizers.impl.refl.nodes.WithAccessor; @@ -27,9 +45,6 @@ import org.mvel2.util.ParseTools; import org.mvel2.util.StringAppender; -import java.lang.reflect.*; -import java.util.*; - import static org.mvel2.util.ParseTools.*; import static org.mvel2.util.PropertyTools.getFieldOrAccessor; @@ -138,9 +153,6 @@ private void recordTypeParmsForProperty(String property) { if (pCtx.isStrictTypeEnforcement()) { - if ((paramTypes = pCtx.getTypeParameters(property)) == null) { - pCtx.addTypeParameters(property, pCtx.getVarOrInputType(property)); - } pCtx.setLastTypeParameters(pCtx.getTypeParametersAsArray(property)); } } @@ -198,7 +210,7 @@ pCtx.setLastTypeParameters(pt.getActualTypeArguments()); Type[] gpt = pt.getActualTypeArguments(); - Type[] classArgs = ((Class) pt.getRawType()).getTypeParameters(); + Type[] classArgs = type2Class(pt.getRawType()).getTypeParameters(); if (gpt.length > 0 && paramTypes == null) paramTypes = new HashMap(); for (int i = 0; i < gpt.length; i++) { @@ -234,13 +246,7 @@ || (Map.class.isAssignableFrom(ctx) && (switchStateReg = true)))) { Type parm = pCtx.getLastTypeParameters()[switchStateReg ? 1 : 0]; pCtx.setLastTypeParameters(null); - - if (parm instanceof ParameterizedType) { - return Object.class; - } - else { - return (Class) parm; - } + return parm instanceof ParameterizedType ? Object.class : (Class) parm; } if (pCtx != null && "length".equals(property) && ctx.isArray()) { @@ -341,7 +347,7 @@ ParameterizedType pt = (ParameterizedType) parametricReturnType; Type[] gpt = pt.getActualTypeArguments(); - Type[] classArgs = ((Class) pt.getRawType()).getTypeParameters(); + Type[] classArgs = type2Class(pt.getRawType()).getTypeParameters(); if (gpt.length > 0 && paramTypes == null) paramTypes = new HashMap(); for (int i = 0; i < gpt.length; i++) { @@ -364,7 +370,7 @@ /** * If the paramTypes Map contains the known type, return that type. */ - return (Class) paramTypes.get(returnTypeArg); + return type2Class( paramTypes.get(returnTypeArg) ); } return m.getReturnType(); @@ -393,16 +399,10 @@ if (pCtx.isStrictTypeEnforcement()) { if (Map.class.isAssignableFrom(property.length() != 0 ? ctx = getBeanProperty(ctx, property) : ctx)) { - ctx = (Class) (pCtx.getLastTypeParameters().length != 0 ? pCtx.getLastTypeParameters()[1] : Object.class); + ctx = type2Class(pCtx.getLastTypeParameters() != null && pCtx.getLastTypeParameters().length != 0 ? pCtx.getLastTypeParameters()[1] : Object.class); } else if (Collection.class.isAssignableFrom(ctx)) { - if (pCtx.getLastTypeParameters().length == 0 ) { - ctx = Object.class; - } else { - Type type = pCtx.getLastTypeParameters()[0]; - if (type instanceof Class) ctx = (Class)type; - else ctx = (Class)((ParameterizedType)type).getRawType(); - } + ctx = pCtx.getLastTypeParameters() == null || pCtx.getLastTypeParameters().length == 0 ? Object.class : type2Class(pCtx.getLastTypeParameters()[0]); } else if (ctx.isArray()) { ctx = ctx.getComponentType(); @@ -620,7 +620,7 @@ TypeVariable[] typeVariables = ctx.getTypeParameters(); for (int i = 0; i < typeVariables.length; i++) { Type typeArg = pCtx.getLastTypeParameters()[i]; - typeArgs.put(typeVariables[i].getName(), typeArg instanceof Class ? (Class) pCtx.getLastTypeParameters()[i] : Object.class); + typeArgs.put(typeVariables[i].getName(), typeArg instanceof Class ? type2Class( pCtx.getLastTypeParameters()[i] ) : Object.class); } } @@ -639,7 +639,7 @@ /** * If the paramTypes Map contains the known type, return that type. */ - return (Class) paramTypes.get(returnTypeArg); + return type2Class(paramTypes.get(returnTypeArg)); } else if (typeArgs.containsKey(returnTypeArg)) { /** @@ -668,6 +668,10 @@ return getReturnType(ctx, m); } + private static Class type2Class(Type type) { + return type instanceof Class ? (Class) type : (Class) ((ParameterizedType) type).getRawType(); + } + private Class getWithProperty(Class ctx) { String root = new String(expr, 0, cursor - 1).trim(); diff -Nru mvel-2.3.1/src/main/java/org/mvel2/integration/PropertyHandlerFactory.java mvel-2.4.0/src/main/java/org/mvel2/integration/PropertyHandlerFactory.java --- mvel-2.3.1/src/main/java/org/mvel2/integration/PropertyHandlerFactory.java 2016-09-07 08:18:50.000000000 +0000 +++ mvel-2.4.0/src/main/java/org/mvel2/integration/PropertyHandlerFactory.java 2017-10-27 08:52:36.000000000 +0000 @@ -57,14 +57,7 @@ } public static void registerPropertyHandler(Class clazz, PropertyHandler propertyHandler) { - do { - propertyHandlerClass.put(clazz, propertyHandler); - - for (Class c : clazz.getInterfaces()) { - propertyHandlerClass.put(c, propertyHandler); - } - } - while ((clazz = clazz.getSuperclass()) != null && clazz != Object.class); + propertyHandlerClass.put(clazz, propertyHandler); } public static void setNullPropertyHandler(PropertyHandler handler) { diff -Nru mvel-2.3.1/src/main/java/org/mvel2/jsr223/MvelBindings.java mvel-2.4.0/src/main/java/org/mvel2/jsr223/MvelBindings.java --- mvel-2.3.1/src/main/java/org/mvel2/jsr223/MvelBindings.java 1970-01-01 00:00:00.000000000 +0000 +++ mvel-2.4.0/src/main/java/org/mvel2/jsr223/MvelBindings.java 2017-10-27 08:52:36.000000000 +0000 @@ -0,0 +1,171 @@ +package org.mvel2.jsr223; + +import java.util.Collection; +import java.util.HashMap; +import java.util.Map; +import java.util.Set; + +import javax.script.Bindings; + +public class MvelBindings implements Bindings { + + /** + * The Map field stores the attributes. + */ + private Map map; + + /** + * Constructor uses an existing Map to store the values. + * + * @param m The Map backing this SimpleBindings. + * @throws NullPointerException if m is null + */ + public MvelBindings(Map m) { + if (m == null) { + throw new NullPointerException(); + } + this.map = m; + } + + /** + * Default constructor uses a HashMap. + */ + public MvelBindings() { + this(new HashMap()); + } + + /** + * Sets the specified key/value in the underlying map field. + * + * @param name Name of value + * @param value Value to set. + * + * @return Previous value for the specified key. Returns null if key was previously unset. + * + * @throws NullPointerException if the name is null. + * @throws IllegalArgumentException if the name is empty. + */ + public Object put(String name, Object value) { + return map.put(name, value); + } + + /** + * putAll is implemented using Map.putAll. + * + * @param toMerge The Map of values to add. + * + * @throws NullPointerException if toMerge map is null or if some key in the map is null. + * @throws IllegalArgumentException if some key in the map is an empty String. + */ + public void putAll(Map toMerge) { + if (toMerge == null) { + throw new NullPointerException("toMerge map is null"); + } + for (Map.Entry entry : toMerge.entrySet()) { + String key = entry.getKey(); + put(key, entry.getValue()); + } + } + + /** {@inheritDoc} */ + public void clear() { + map.clear(); + } + + /** + * Returns true if this map contains a mapping for the specified key. More formally, + * returns true if and only if this map contains a mapping for a key k such + * that (key==null ? k==null : key.equals(k)). (There can be at most one such mapping.) + * + * @param key key whose presence in this map is to be tested. + * @return true if this map contains a mapping for the specified key. + * + * @throws NullPointerException if key is null + * @throws ClassCastException if key is not String + * @throws IllegalArgumentException if key is empty String + */ + public boolean containsKey(Object key) { + return map.containsKey(key); + } + + /** {@inheritDoc} */ + public boolean containsValue(Object value) { + return map.containsValue(value); + } + + /** {@inheritDoc} */ + public Set> entrySet() { + return map.entrySet(); + } + + /** + * Returns the value to which this map maps the specified key. Returns null if the map + * contains no mapping for this key. A return value of null does not necessarily + * indicate that the map contains no mapping for the key; it's also possible that the map + * explicitly maps the key to null. The containsKey operation may be used to + * distinguish these two cases. + * + *

+ * More formally, if this map contains a mapping from a key k to a value v + * such that (key==null ? k==null : + * key.equals(k)), then this method returns v; otherwise it returns null. + * (There can be at most one such mapping.) + * + * @param key key whose associated value is to be returned. + * @return the value to which this map maps the specified key, or null if the map + * contains no mapping for this key. + * + * @throws NullPointerException if key is null + * @throws ClassCastException if key is not String + * @throws IllegalArgumentException if key is empty String + */ + public Object get(Object key) { + return map.get(key); + } + + /** {@inheritDoc} */ + public boolean isEmpty() { + return map.isEmpty(); + } + + /** {@inheritDoc} */ + public Set keySet() { + return map.keySet(); + } + + /** + * Removes the mapping for this key from this map if it is present (optional operation). More + * formally, if this map contains a mapping from key k to value v such that + * (key==null ? k==null : key.equals(k)), that mapping is removed. (The map can + * contain at most one such mapping.) + * + *

+ * Returns the value to which the map previously associated the key, or null if the map + * contained no mapping for this key. (A null return can also indicate that the map + * previously associated null with the specified key if the implementation supports + * null values.) The map will not contain a mapping for the specified key once the call + * returns. + * + * @param key key whose mapping is to be removed from the map. + * @return previous value associated with specified key, or null if there was no + * mapping for key. + * + * @throws NullPointerException if key is null + * @throws ClassCastException if key is not String + * @throws IllegalArgumentException if key is empty String + */ + public Object remove(Object key) { + return map.remove(key); + } + + /** {@inheritDoc} */ + public int size() { + return map.size(); + } + + /** {@inheritDoc} */ + public Collection values() { + return map.values(); + } + +} diff -Nru mvel-2.3.1/src/main/java/org/mvel2/jsr223/MvelCompiledScript.java mvel-2.4.0/src/main/java/org/mvel2/jsr223/MvelCompiledScript.java --- mvel-2.3.1/src/main/java/org/mvel2/jsr223/MvelCompiledScript.java 1970-01-01 00:00:00.000000000 +0000 +++ mvel-2.4.0/src/main/java/org/mvel2/jsr223/MvelCompiledScript.java 2017-10-27 08:52:36.000000000 +0000 @@ -0,0 +1,29 @@ +package org.mvel2.jsr223; + +import java.io.Serializable; + +import javax.script.CompiledScript; +import javax.script.ScriptContext; +import javax.script.ScriptEngine; +import javax.script.ScriptException; + +public class MvelCompiledScript extends CompiledScript { + + private final MvelScriptEngine scriptEngine; + private final Serializable compiledScript; + + public MvelCompiledScript(MvelScriptEngine engine, Serializable compiledScript) { + this.scriptEngine = engine; + this.compiledScript = compiledScript; + } + + @Override + public Object eval(ScriptContext context) throws ScriptException { + return scriptEngine.evaluate(compiledScript, context); + } + + @Override + public ScriptEngine getEngine() { + return scriptEngine; + } +} diff -Nru mvel-2.3.1/src/main/java/org/mvel2/jsr223/MvelScriptEngineFactory.java mvel-2.4.0/src/main/java/org/mvel2/jsr223/MvelScriptEngineFactory.java --- mvel-2.3.1/src/main/java/org/mvel2/jsr223/MvelScriptEngineFactory.java 1970-01-01 00:00:00.000000000 +0000 +++ mvel-2.4.0/src/main/java/org/mvel2/jsr223/MvelScriptEngineFactory.java 2017-10-27 08:52:36.000000000 +0000 @@ -0,0 +1,100 @@ +package org.mvel2.jsr223; + +import java.util.ArrayList; +import java.util.List; + +import javax.script.ScriptEngine; +import javax.script.ScriptEngineFactory; + +import org.mvel2.MVEL; + +public class MvelScriptEngineFactory implements ScriptEngineFactory { + private static final String ENGINE_NAME = MVEL.NAME; + private static final String ENGINE_VERSION = MVEL.VERSION; + private static final String LANGUAGE_NAME = "mvel"; + private static final String LANGUAGE_VERSION = MVEL.VERSION; + + private static final List NAMES = new ArrayList(); + private static final List EXTENSIONS = new ArrayList(); + private static final List MIME_TYPES = new ArrayList(); + + private static final MvelScriptEngine MVEL_SCRIPT_ENGINE = new MvelScriptEngine(); + + public MvelScriptEngineFactory() { + NAMES.add(LANGUAGE_NAME); + } + + @Override + public String getEngineName() { + return ENGINE_NAME; + } + + @Override + public String getEngineVersion() { + return ENGINE_VERSION; + } + + @Override + public List getExtensions() { + return EXTENSIONS; + } + + @Override + public List getMimeTypes() { + return MIME_TYPES; + } + + @Override + public List getNames() { + return NAMES; + } + + @Override + public String getLanguageName() { + return LANGUAGE_NAME; + } + + @Override + public String getLanguageVersion() { + return LANGUAGE_VERSION; + } + + @Override + public Object getParameter(String key) { + if (key.equals(ScriptEngine.NAME)) { + return getLanguageName(); + } else if (key.equals(ScriptEngine.ENGINE)) { + return getEngineName(); + } else if (key.equals(ScriptEngine.ENGINE_VERSION)) { + return getEngineVersion(); + } else if (key.equals(ScriptEngine.LANGUAGE)) { + return getLanguageName(); + } else if (key.equals(ScriptEngine.LANGUAGE_VERSION)) { + return getLanguageVersion(); + } else if (key.equals("THREADING")) { + return "THREAD-ISOLATED"; + } else { + return null; + } + } + + @Override + public String getMethodCallSyntax(String obj, String m, String... args) { + return null; + } + + @Override + public String getOutputStatement(String toDisplay) { + return null; + } + + @Override + public String getProgram(String... statements) { + return null; + } + + @Override + public ScriptEngine getScriptEngine() { + return MVEL_SCRIPT_ENGINE; + } +} diff -Nru mvel-2.3.1/src/main/java/org/mvel2/jsr223/MvelScriptEngine.java mvel-2.4.0/src/main/java/org/mvel2/jsr223/MvelScriptEngine.java --- mvel-2.3.1/src/main/java/org/mvel2/jsr223/MvelScriptEngine.java 1970-01-01 00:00:00.000000000 +0000 +++ mvel-2.4.0/src/main/java/org/mvel2/jsr223/MvelScriptEngine.java 2017-10-27 08:52:36.000000000 +0000 @@ -0,0 +1,86 @@ +package org.mvel2.jsr223; + +import java.io.IOException; +import java.io.Reader; +import java.io.Serializable; + +import javax.script.*; + +import org.mvel2.MVEL; + +public class MvelScriptEngine extends AbstractScriptEngine implements ScriptEngine, Compilable { + + private volatile MvelScriptEngineFactory factory; + + @Override + public Object eval(String script, ScriptContext context) throws ScriptException { + Serializable expression = compiledScript(script); + return evaluate(expression, context); + } + + @Override + public Object eval(Reader reader, ScriptContext context) throws ScriptException { + return this.eval(readFully(reader), context); + } + + @Override + public Bindings createBindings() { + return new MvelBindings(); + } + + @Override + public ScriptEngineFactory getFactory() { + if (this.factory == null) { + synchronized (this) { + if (this.factory == null) { + this.factory = new MvelScriptEngineFactory(); + } + } + } + + return this.factory; + } + + private static String readFully(Reader reader) throws ScriptException { + char[] arr = new char[8192]; + StringBuilder buf = new StringBuilder(); + + int numChars; + try { + while ((numChars = reader.read(arr, 0, arr.length)) > 0) { + buf.append(arr, 0, numChars); + } + } catch (IOException var5) { + throw new ScriptException(var5); + } + + return buf.toString(); + } + + @Override + public CompiledScript compile(String script) throws ScriptException { + return new MvelCompiledScript(this, compiledScript(script)); + } + + @Override + public CompiledScript compile(Reader reader) throws ScriptException { + return this.compile(readFully(reader)); + } + + public Serializable compiledScript(String script) throws ScriptException { + try { + Serializable expression = MVEL.compileExpression(script); + return expression; + } catch (Exception e) { + throw new ScriptException(e); + } + } + + public Object evaluate(Serializable expression, ScriptContext context) throws ScriptException { + try { + return MVEL.executeExpression(expression, context.getBindings(ScriptContext.ENGINE_SCOPE)); + } catch (Exception e) { + throw new ScriptException(e); + } + } +} diff -Nru mvel-2.3.1/src/main/java/org/mvel2/optimizers/impl/asm/ASMAccessorOptimizer.java mvel-2.4.0/src/main/java/org/mvel2/optimizers/impl/asm/ASMAccessorOptimizer.java --- mvel-2.3.1/src/main/java/org/mvel2/optimizers/impl/asm/ASMAccessorOptimizer.java 2016-09-07 08:18:50.000000000 +0000 +++ mvel-2.4.0/src/main/java/org/mvel2/optimizers/impl/asm/ASMAccessorOptimizer.java 2017-10-27 08:52:36.000000000 +0000 @@ -204,7 +204,7 @@ synchronized (Runtime.getRuntime()) { cw.visit(OPCODES_VERSION, Opcodes.ACC_PUBLIC + Opcodes.ACC_SUPER, className = "ASMAccessorImpl_" + valueOf(cw.hashCode()).replaceAll("\\-", "_") + (System.currentTimeMillis() / 10) + - ((int) Math.random() * 100), + ((int) (Math.random() * 100)), null, "java/lang/Object", new String[]{NAMESPACE + "compiler/Accessor"}); } @@ -235,7 +235,7 @@ synchronized (Runtime.getRuntime()) { cw.visit(OPCODES_VERSION, Opcodes.ACC_PUBLIC + Opcodes.ACC_SUPER, className = "ASMAccessorImpl_" + valueOf(cw.hashCode()).replaceAll("\\-", "_") + (System.currentTimeMillis() / 10) + - ((int) Math.random() * 100), + ((int) (Math.random() * 100)), null, "java/lang/Object", new String[]{NAMESPACE + "compiler/Accessor"}); } diff -Nru mvel-2.3.1/src/main/java/org/mvel2/ParserConfiguration.java mvel-2.4.0/src/main/java/org/mvel2/ParserConfiguration.java --- mvel-2.3.1/src/main/java/org/mvel2/ParserConfiguration.java 2016-09-07 08:18:50.000000000 +0000 +++ mvel-2.4.0/src/main/java/org/mvel2/ParserConfiguration.java 2017-10-27 08:52:36.000000000 +0000 @@ -18,53 +18,42 @@ package org.mvel2; -import org.mvel2.ast.Proto; -import org.mvel2.compiler.AbstractParser; -import org.mvel2.integration.Interceptor; -import org.mvel2.util.MethodStub; - import java.io.Serializable; import java.lang.reflect.Field; import java.lang.reflect.Method; import java.lang.reflect.Modifier; +import java.util.Collections; import java.util.EnumSet; import java.util.HashMap; import java.util.HashSet; -import java.util.Iterator; import java.util.LinkedHashSet; import java.util.Map; import java.util.Set; import java.util.concurrent.ConcurrentHashMap; +import org.mvel2.ast.Proto; +import org.mvel2.compiler.AbstractParser; +import org.mvel2.integration.Interceptor; +import org.mvel2.util.MethodStub; + import static org.mvel2.util.ParseTools.forNameWithInner; /** * The resusable parser configuration object. */ public class ParserConfiguration implements Serializable { - private static final int MAX_NEGATIVE_CACHE_SIZE; - protected Map imports; + protected final Map imports = new ConcurrentHashMap(); protected HashSet packageImports; protected Map interceptors; protected transient ClassLoader classLoader; - private transient Set nonValidImports; + private final transient Set nonValidImports = Collections.newSetFromMap( new ConcurrentHashMap() ); private boolean allowNakedMethCall = MVEL.COMPILER_OPT_ALLOW_NAKED_METH_CALL; private boolean allowBootstrapBypass = true; - static { - String negCacheSize = System.getProperty("mvel2.compiler.max_neg_cache_size"); - if (negCacheSize != null) { - MAX_NEGATIVE_CACHE_SIZE = Integer.parseInt(negCacheSize); - } - else { - MAX_NEGATIVE_CACHE_SIZE = 1000; - } - } - public ParserConfiguration() { } @@ -89,18 +78,18 @@ } public Class getImport(String name) { - if (imports != null && imports.containsKey(name) && imports.get(name) instanceof Class) { + if (imports.containsKey(name) && imports.get(name) instanceof Class) { return (Class) imports.get(name); } return (Class) (AbstractParser.LITERALS.get(name) instanceof Class ? AbstractParser.LITERALS.get(name) : null); } public MethodStub getStaticImport(String name) { - return imports != null ? (MethodStub) imports.get(name) : null; + return (MethodStub) imports.get(name); } public Object getStaticOrClassImport(String name) { - return (imports != null && imports.containsKey(name) ? imports.get(name) : AbstractParser.LITERALS.get(name)); + return imports.containsKey(name) ? imports.get(name) : AbstractParser.LITERALS.get(name); } public void addPackageImport(String packageName) { @@ -112,7 +101,6 @@ private boolean addClassMemberStaticImports(String packageName) { try { Class c = Class.forName(packageName); - initImports(); if (c.isEnum()) { //noinspection unchecked @@ -142,8 +130,6 @@ public void addAllImports(Map imports) { if (imports == null) return; - initImports(); - Object o; for (Map.Entry entry : imports.entrySet()) { @@ -159,7 +145,7 @@ private boolean checkForDynamicImport(String className) { if (packageImports == null) return false; if (!Character.isJavaIdentifierStart(className.charAt(0))) return false; - if (nonValidImports != null && nonValidImports.contains(className)) return false; + if (nonValidImports.contains(className)) return false; int found = 0; Class cls = null; @@ -184,29 +170,20 @@ } public boolean hasImport(String name) { - return (imports != null && imports.containsKey(name)) || + return (imports.containsKey(name)) || AbstractParser.CLASS_LITERALS.containsKey(name) || checkForDynamicImport(name); } - private void initImports() { - if (this.imports == null) { - this.imports = new ConcurrentHashMap(); - } - } - public void addImport(Class cls) { - initImports(); addImport(cls.getSimpleName(), cls); } public void addImport(String name, Class cls) { - initImports(); this.imports.put(name, cls); } public void addImport(String name, Proto proto) { - initImports(); this.imports.put(name, proto); } @@ -215,7 +192,6 @@ } public void addImport(String name, MethodStub method) { - initImports(); this.imports.put(name, method); } @@ -256,7 +232,7 @@ } public boolean hasImports() { - return !(imports != null && imports.isEmpty()) || (packageImports != null && packageImports.size() != 0); + return !imports.isEmpty() || (packageImports != null && packageImports.size() != 0); } public ClassLoader getClassLoader() { @@ -268,7 +244,6 @@ } public void setAllImports(Map imports) { - initImports(); this.imports.clear(); if (imports != null) this.imports.putAll(imports); } @@ -279,21 +254,11 @@ } private void cacheNegativeHitForDynamicImport(String negativeHit) { - if (nonValidImports == null) { - nonValidImports = new LinkedHashSet(); - } - else if (nonValidImports.size() > 1000) { - Iterator i = nonValidImports.iterator(); - i.next(); - i.remove(); - } - nonValidImports.add(negativeHit); } public void flushCaches() { - if (nonValidImports != null) - nonValidImports.clear(); + nonValidImports.clear(); } public boolean isAllowNakedMethCall() { diff -Nru mvel-2.3.1/src/main/java/org/mvel2/ParserContext.java mvel-2.4.0/src/main/java/org/mvel2/ParserContext.java --- mvel-2.3.1/src/main/java/org/mvel2/ParserContext.java 2016-09-07 08:18:50.000000000 +0000 +++ mvel-2.4.0/src/main/java/org/mvel2/ParserContext.java 2017-10-27 08:52:36.000000000 +0000 @@ -18,6 +18,23 @@ package org.mvel2; +import java.io.Serializable; +import java.lang.reflect.Field; +import java.lang.reflect.Method; +import java.lang.reflect.Modifier; +import java.lang.reflect.Type; +import java.lang.reflect.TypeVariable; +import java.util.ArrayList; +import java.util.Collection; +import java.util.Collections; +import java.util.HashMap; +import java.util.HashSet; +import java.util.LinkedHashMap; +import java.util.List; +import java.util.Map; +import java.util.Set; +import java.util.TreeSet; + import org.mvel2.ast.Function; import org.mvel2.ast.LineLabel; import org.mvel2.ast.Proto; @@ -29,10 +46,6 @@ import org.mvel2.util.MethodStub; import org.mvel2.util.ReflectionUtil; -import java.io.Serializable; -import java.lang.reflect.*; -import java.util.*; - /** * The ParserContext is the main environment object used for sharing state throughout the entire * parser/compileShared process.

@@ -374,7 +387,6 @@ } public boolean hasProtoImport(String name) { - if (parserConfiguration.getImports() == null) return false; Object o = parserConfiguration.getImports().get(name); return o != null && o instanceof Proto; } @@ -458,8 +470,7 @@ scope.addAll(variables.keySet()); scope.addAll(inputs.keySet()); - if (parserConfiguration.getImports() != null) - scope.addAll(parserConfiguration.getImports().keySet()); + scope.addAll( parserConfiguration.getImports().keySet() ); if (inputs.containsKey("this")) { Class ctxType = inputs.get("this"); @@ -833,18 +844,6 @@ return globalFunctions != null && globalFunctions.size() != 0; } - public void addTypeParameters(String name, Class type) { - if (typeParameters == null) typeParameters = new HashMap>(); - - Map newPkg = new HashMap(); - - for (Type t : type.getTypeParameters()) { - newPkg.put(t.toString(), Object.class); - } - - typeParameters.put(name, newPkg); - } - public void addTypeParameters(Map> typeParameters) { if (typeParameters == null) return; if (this.typeParameters == null) typeParameters = new HashMap>(); @@ -1063,11 +1062,6 @@ return this; } - public ParserContext withTypeParameter(String name, Class type) { - addTypeParameters(name, type); - return this; - } - public ParserContext withTypeParameters(Map> typeParameters) { addTypeParameters(typeParameters); return this; diff -Nru mvel-2.3.1/src/main/java/org/mvel2/templates/res/CompiledIncludeNode.java mvel-2.4.0/src/main/java/org/mvel2/templates/res/CompiledIncludeNode.java --- mvel-2.3.1/src/main/java/org/mvel2/templates/res/CompiledIncludeNode.java 2016-09-07 08:18:50.000000000 +0000 +++ mvel-2.4.0/src/main/java/org/mvel2/templates/res/CompiledIncludeNode.java 2017-10-27 08:52:36.000000000 +0000 @@ -85,31 +85,24 @@ } public static String readInFile(TemplateRuntime runtime, File file) { + FileInputStream instream = null; + BufferedReader in = null; + final StringBuilder appender = new StringBuilder(); + try { - FileInputStream instream = new FileInputStream(file); - BufferedInputStream bufstream = new BufferedInputStream(instream); - + instream = openInputStream(file); runtime.getRelPath().push(file.getParent()); - byte[] buf = new byte[10]; - int read; - int i; - - StringBuilder appender = new StringBuilder(); - - while ((read = bufstream.read(buf)) != -1) { - for (i = 0; i < read; i++) { - appender.append((char) buf[i]); - } - } - - bufstream.close(); - instream.close(); - + in = new BufferedReader(new InputStreamReader(instream, "UTF-8")); + + String currentLine; + + while ((currentLine = in.readLine()) != null) { + appender.append(currentLine); + } + runtime.getRelPath().pop(); - return appender.toString(); - } catch (FileNotFoundException e) { throw new TemplateError("cannot include template '" + file.getPath() + "': file not found."); @@ -117,5 +110,56 @@ catch (IOException e) { throw new TemplateError("unknown I/O exception while including '" + file.getPath() + "' (stacktrace nested)", e); } + finally + { + if (in != null) { + try { + in.close(); + } catch (IOException e) { + throw new TemplateError("cannot close the reader on template file '" + file.getPath() + "'."); + } + } + if (instream != null) { + try { + instream.close(); + } catch (IOException e) { + throw new TemplateError("cannot close the stream on template file '" + file.getPath() + "'."); + } + } + } + } + + /** + * Opens a {@link FileInputStream} for the specified file, else providing a + * detail error message than simply calling new FileInputStream(file). + * + *

+ * An exception is thrown if + *

    + *
  • the file parameter is null, + *
  • the file does not exist, + *
  • the file object exists but is a directory, + *
  • the file exists but cannot be read. + *
+ * + * @param file the file to open for input, can be {@code null} + * @return a new {@link FileInputStream} for the specified file + * @throws FileNotFoundException if the file is null or does not exist + * @throws IOException if the file object is a directory or cannot be read + */ + private static FileInputStream openInputStream(final File file) throws IOException { + if (file == null) { + throw new FileNotFoundException("file parameter is null"); + } else if (file.exists()) { + if (file.isDirectory()) { + throw new IOException("File '" + file + "' exists but is a directory"); + } + if (file.canRead() == false) { + throw new IOException("File '" + file + "' cannot be read"); + } + } else { + throw new FileNotFoundException("File '" + file + "' does not exist"); + } + return new FileInputStream(file); } } \ No newline at end of file diff -Nru mvel-2.3.1/src/main/java/org/mvel2/util/CompilerTools.java mvel-2.4.0/src/main/java/org/mvel2/util/CompilerTools.java --- mvel-2.3.1/src/main/java/org/mvel2/util/CompilerTools.java 2016-09-07 08:18:50.000000000 +0000 +++ mvel-2.4.0/src/main/java/org/mvel2/util/CompilerTools.java 2017-10-27 08:52:36.000000000 +0000 @@ -18,6 +18,9 @@ package org.mvel2.util; +import java.util.LinkedHashMap; +import java.util.Map; + import org.mvel2.CompileException; import org.mvel2.Operator; import org.mvel2.ParserContext; @@ -48,10 +51,8 @@ import org.mvel2.integration.VariableResolverFactory; import org.mvel2.integration.impl.ClassImportResolverFactory; -import java.util.LinkedHashMap; -import java.util.Map; - import static org.mvel2.Operator.PTABLE; +import static org.mvel2.Operator.TERNARY; import static org.mvel2.util.ASTBinaryTree.buildTree; import static org.mvel2.util.ParseTools.__resolveType; import static org.mvel2.util.ParseTools.boxPrimitive; @@ -342,6 +343,10 @@ optimizedAst.addTokenNode(new Soundslike(tk, astLinkedList.nextNode(), pCtx)); break; + case TERNARY: + if ( pCtx.isStrongTyping() && tk.getEgressType() != Boolean.class && tk.getEgressType() != Boolean.TYPE ) + throw new RuntimeException( "Condition of ternary operator is not of type boolean. Found " + tk.getEgressType() ); + default: optimizedAst.addTokenNode(tk, tkOp); } diff -Nru mvel-2.3.1/src/main/java/org/mvel2/util/JITClassLoader.java mvel-2.4.0/src/main/java/org/mvel2/util/JITClassLoader.java --- mvel-2.3.1/src/main/java/org/mvel2/util/JITClassLoader.java 2016-09-07 08:18:50.000000000 +0000 +++ mvel-2.4.0/src/main/java/org/mvel2/util/JITClassLoader.java 2017-10-27 08:52:36.000000000 +0000 @@ -18,9 +18,6 @@ package org.mvel2.util; -import java.lang.reflect.Field; -import sun.misc.Unsafe; - public class JITClassLoader extends ClassLoader implements MVELClassLoader { public JITClassLoader(ClassLoader classLoader) { super(classLoader); diff -Nru mvel-2.3.1/src/main/java/org/mvel2/util/ParseTools.java mvel-2.4.0/src/main/java/org/mvel2/util/ParseTools.java --- mvel-2.3.1/src/main/java/org/mvel2/util/ParseTools.java 2016-09-07 08:18:50.000000000 +0000 +++ mvel-2.4.0/src/main/java/org/mvel2/util/ParseTools.java 2017-10-27 08:52:36.000000000 +0000 @@ -18,24 +18,6 @@ package org.mvel2.util; -import org.mvel2.CompileException; -import org.mvel2.DataTypes; -import org.mvel2.MVEL; -import org.mvel2.Operator; -import org.mvel2.OptimizationFailure; -import org.mvel2.ParserContext; -import org.mvel2.ast.ASTNode; -import org.mvel2.compiler.AbstractParser; -import org.mvel2.compiler.BlankLiteral; -import org.mvel2.compiler.CompiledExpression; -import org.mvel2.compiler.ExecutableAccessor; -import org.mvel2.compiler.ExecutableAccessorSafe; -import org.mvel2.compiler.ExecutableLiteral; -import org.mvel2.compiler.ExpressionCompiler; -import org.mvel2.integration.VariableResolverFactory; -import org.mvel2.integration.impl.ClassImportResolverFactory; -import org.mvel2.math.MathProcessor; - import java.io.File; import java.io.FileInputStream; import java.io.FileNotFoundException; @@ -61,6 +43,24 @@ import java.util.Map; import java.util.WeakHashMap; +import org.mvel2.CompileException; +import org.mvel2.DataTypes; +import org.mvel2.MVEL; +import org.mvel2.Operator; +import org.mvel2.OptimizationFailure; +import org.mvel2.ParserContext; +import org.mvel2.ast.ASTNode; +import org.mvel2.compiler.AbstractParser; +import org.mvel2.compiler.BlankLiteral; +import org.mvel2.compiler.CompiledExpression; +import org.mvel2.compiler.ExecutableAccessor; +import org.mvel2.compiler.ExecutableAccessorSafe; +import org.mvel2.compiler.ExecutableLiteral; +import org.mvel2.compiler.ExpressionCompiler; +import org.mvel2.integration.VariableResolverFactory; +import org.mvel2.integration.impl.ClassImportResolverFactory; +import org.mvel2.math.MathProcessor; + import static java.lang.Class.forName; import static java.lang.Double.parseDouble; import static java.lang.String.valueOf; @@ -254,7 +254,7 @@ } boolean isVarArgs = meth.isVarArgs(); - if (parmTypes.length != arguments.length && !isVarArgs) { + if ( isArgsNumberNotCompatible( arguments, parmTypes, isVarArgs ) ) { continue; } @@ -300,6 +300,10 @@ return bestCandidate; } + private static boolean isArgsNumberNotCompatible( Class[] arguments, Class[] parmTypes, boolean isVarArgs ) { + return ( isVarArgs && parmTypes.length-1 > arguments.length ) || ( !isVarArgs && parmTypes.length != arguments.length ); + } + private static boolean isMoreSpecialized( Method newCandidate, Method oldCandidate ) { return oldCandidate.getReturnType().isAssignableFrom( newCandidate.getReturnType()) && oldCandidate.getDeclaringClass().isAssignableFrom( newCandidate.getDeclaringClass()); @@ -459,7 +463,8 @@ for (Constructor construct : getConstructors(cls)) { boolean isVarArgs = construct.isVarArgs(); - if ((parmTypes = getConstructors(construct)).length != arguments.length && !construct.isVarArgs()) { + parmTypes = getConstructors(construct); + if ( isArgsNumberNotCompatible( arguments, parmTypes, isVarArgs ) ) { continue; } else if (arguments.length == 0 && parmTypes.length == 0) { diff -Nru mvel-2.3.1/src/main/resources/META-INF/services/javax.script.ScriptEngineFactory mvel-2.4.0/src/main/resources/META-INF/services/javax.script.ScriptEngineFactory --- mvel-2.3.1/src/main/resources/META-INF/services/javax.script.ScriptEngineFactory 1970-01-01 00:00:00.000000000 +0000 +++ mvel-2.4.0/src/main/resources/META-INF/services/javax.script.ScriptEngineFactory 2017-10-27 08:52:36.000000000 +0000 @@ -0,0 +1 @@ +org.mvel2.jsr223.MvelScriptEngineFactory \ No newline at end of file diff -Nru mvel-2.3.1/src/test/java/org/mvel2/jsr223/MvelScriptEngineTest.java mvel-2.4.0/src/test/java/org/mvel2/jsr223/MvelScriptEngineTest.java --- mvel-2.3.1/src/test/java/org/mvel2/jsr223/MvelScriptEngineTest.java 1970-01-01 00:00:00.000000000 +0000 +++ mvel-2.4.0/src/test/java/org/mvel2/jsr223/MvelScriptEngineTest.java 2017-10-27 08:52:36.000000000 +0000 @@ -0,0 +1,45 @@ +package org.mvel2.jsr223; + +import javax.script.Compilable; +import javax.script.CompiledScript; +import javax.script.ScriptEngine; +import javax.script.ScriptEngineManager; +import javax.script.ScriptException; +import javax.script.SimpleBindings; +import org.junit.Test; + +import static org.junit.Assert.assertEquals; + +public class MvelScriptEngineTest { + + @Test + public void testScriptEngine() throws ScriptException { + ScriptEngineManager scriptEngineManager = new ScriptEngineManager(); + scriptEngineManager.registerEngineName( "mvel", new MvelScriptEngineFactory()); + ScriptEngine scriptEngine = scriptEngineManager.getEngineByName("mvel"); + + SimpleBindings simpleBindings = new SimpleBindings(); + simpleBindings.put("a", 1); + simpleBindings.put("b", 2); + + int c = (Integer) scriptEngine.eval("a + b", simpleBindings); + assertEquals(c, 3); + + } + + @Test + public void testScriptEngineCompiledScript() throws ScriptException { + ScriptEngineManager scriptEngineManager = new ScriptEngineManager(); + scriptEngineManager.registerEngineName( "mvel", new MvelScriptEngineFactory()); + ScriptEngine scriptEngine = scriptEngineManager.getEngineByName("mvel"); + + SimpleBindings simpleBindings = new SimpleBindings(); + simpleBindings.put("a", 1); + simpleBindings.put("b", 2); + + Compilable compilableScriptEngine = (Compilable) scriptEngine; + CompiledScript compiledScript = compilableScriptEngine.compile("a+ b"); + int c = (Integer) compiledScript.eval(simpleBindings); + assertEquals(c, 3); + } +} \ No newline at end of file diff -Nru mvel-2.3.1/src/test/java/org/mvel2/tests/core/CoreConfidenceTests.java mvel-2.4.0/src/test/java/org/mvel2/tests/core/CoreConfidenceTests.java --- mvel-2.3.1/src/test/java/org/mvel2/tests/core/CoreConfidenceTests.java 2016-09-07 08:18:50.000000000 +0000 +++ mvel-2.4.0/src/test/java/org/mvel2/tests/core/CoreConfidenceTests.java 2017-10-27 08:52:36.000000000 +0000 @@ -1,5 +1,33 @@ package org.mvel2.tests.core; +import java.awt.*; +import java.io.BufferedReader; +import java.io.File; +import java.io.IOException; +import java.io.OutputStream; +import java.io.PrintStream; +import java.io.Serializable; +import java.lang.reflect.Field; +import java.lang.reflect.Method; +import java.lang.reflect.Modifier; +import java.math.BigDecimal; +import java.math.BigInteger; +import java.net.URL; +import java.net.URLClassLoader; +import java.util.ArrayList; +import java.util.Arrays; +import java.util.Calendar; +import java.util.Collection; +import java.util.Collections; +import java.util.Date; +import java.util.HashMap; +import java.util.HashSet; +import java.util.LinkedHashMap; +import java.util.List; +import java.util.Map; +import java.util.Set; +import java.util.Vector; + import junit.framework.TestCase; import org.mvel2.CompileException; import org.mvel2.DataConversion; @@ -53,34 +81,6 @@ import org.mvel2.util.ParseTools; import org.mvel2.util.ReflectionUtil; -import java.awt.*; -import java.io.BufferedReader; -import java.io.File; -import java.io.IOException; -import java.io.OutputStream; -import java.io.PrintStream; -import java.io.Serializable; -import java.lang.reflect.Field; -import java.lang.reflect.Method; -import java.lang.reflect.Modifier; -import java.math.BigDecimal; -import java.math.BigInteger; -import java.net.URL; -import java.net.URLClassLoader; -import java.util.ArrayList; -import java.util.Arrays; -import java.util.Calendar; -import java.util.Collection; -import java.util.Collections; -import java.util.Date; -import java.util.HashMap; -import java.util.HashSet; -import java.util.LinkedHashMap; -import java.util.List; -import java.util.Map; -import java.util.Set; -import java.util.Vector; - import static java.util.Collections.unmodifiableCollection; import static org.mvel2.MVEL.*; import static org.mvel2.util.ParseTools.loadFromFile; @@ -4515,4 +4515,105 @@ Map vars = new HashMap() {{ put("a", new O1()); }}; assertEquals("value", MVEL.executeExpression(MVEL.compileExpression("a.getObj().getValue()", parserContext), vars)); } + + public class Convention { + private final Map> comms; + public Convention( Map> comms ) { + this.comms = comms; + } + public Map> getComms(){ + return comms; + } + } + + public void testParseGenericMap() { + final ParserContext parserContext = new ParserContext(); + parserContext.setStrictTypeEnforcement(true); + parserContext.setStrongTyping(true); + parserContext.addInput("conv", Convention.class); + assertEquals(List.class, MVEL.analyze("conv.getComms().get(\"test\")", parserContext)); + } + + public static class Thingy implements Serializable { + private String name; + private String version; + private Object[] items; + + public Thingy(String name, String version, Object... items) { + this.name = name; + this.version = version; + this.items = items; + } + + public Thingy(String name) { + this.name = name; + this.version = null; + this.items = null; + } + + public void print() { + System.out.println("Printing rule " + name); + } + + public String getName() { + return name; + } + } + + public void testInvokeVarargConstructor() { + ParserConfiguration conf = new ParserConfiguration(); + conf.addImport( Thingy.class ); + ParserContext pctx = new ParserContext( conf ); + pctx.setStrictTypeEnforcement(true); + pctx.setStrongTyping(true); + pctx.addInput("name", String.class); + Map vars = new HashMap() {{ put("name", "test"); }}; + Thingy result = (Thingy) MVEL.executeExpression(MVEL.compileExpression("new Thingy(name)", pctx), vars); + assertEquals( "test", result.getName() ); + } + + public void testGenericsWithOr() { + final ParserContext parserContext = new ParserContext(); + parserContext.setStrictTypeEnforcement(true); + parserContext.setStrongTyping(true); + parserContext.addInput("o", OrderLine.class); + parserContext.addInput("p", Product.class); + Class clazz = MVEL.analyze("p.id == o.product.id || p.category == o.product.category", parserContext); + assertEquals(Boolean.class, clazz); + } + + public interface OrderLine { + T getProduct(); + } + + public interface Product { + String getId(); + String getCategory(); + } + + public void testAnalyzeTernary() { + final ParserContext parserContext = new ParserContext(); + parserContext.setStrictTypeEnforcement(true); + parserContext.setStrongTyping(true); + parserContext.addInput("value", String.class); + parserContext.addInput("x", Integer.class); + parserContext.addInput("y", Integer.class); + parserContext.addInput("z", Integer.class); + Class clazz = MVEL.analyze("z = (value == \"ALU\" ? x : y);", parserContext); + assertEquals(Integer.class, clazz); + } + + public void testAnalyzeWrongTernary() { + final ParserContext parserContext = new ParserContext(); + parserContext.setStrictTypeEnforcement(true); + parserContext.setStrongTyping(true); + parserContext.addInput("value", String.class); + parserContext.addInput("x", Integer.class); + parserContext.addInput("y", Integer.class); + parserContext.addInput("z", Integer.class); + try { + Class clazz = MVEL.analyze( "z = (value = \"ALU\" ? x : y);", parserContext ); + fail("parse of this expression should raise an error"); + } catch (Exception e) { } + } } \ No newline at end of file diff -Nru mvel-2.3.1/src/test/java/org/mvel2/tests/core/MVELIncludeTest.java mvel-2.4.0/src/test/java/org/mvel2/tests/core/MVELIncludeTest.java --- mvel-2.3.1/src/test/java/org/mvel2/tests/core/MVELIncludeTest.java 1970-01-01 00:00:00.000000000 +0000 +++ mvel-2.4.0/src/test/java/org/mvel2/tests/core/MVELIncludeTest.java 2017-10-27 08:52:36.000000000 +0000 @@ -0,0 +1,38 @@ +package org.mvel2.tests.core; + +import junit.framework.TestCase; +import org.mvel2.integration.impl.ImmutableDefaultFactory; +import org.mvel2.templates.CompiledTemplate; +import org.mvel2.templates.TemplateCompiler; +import org.mvel2.templates.TemplateRuntime; +import org.mvel2.util.StringAppender; + +import java.io.File; +import java.io.IOException; +import java.util.HashMap; + +/** + * @author PÉRIÉ Fabien + */ +public class MVELIncludeTest extends TestCase { + + private File file; + + public void setUp() { + file = new File("samples/scripts/accentTopLevel.mvel"); + } + + /** + * evalFile with sub template in utf-8 encoding + * + * @throws IOException + */ + public void testEvalFile1() throws IOException { + final CompiledTemplate template = TemplateCompiler.compileTemplate(file); + + final String tr = (String) new TemplateRuntime(template.getTemplate(), null, template.getRoot(), "./samples/scripts/") + .execute(new StringAppender(), new HashMap(), new ImmutableDefaultFactory()); + assertEquals("Hello mister Gaël Périé", tr); + } + +} diff -Nru mvel-2.3.1/src/test/java/org/mvel2/tests/core/PropertyHandlerTests.java mvel-2.4.0/src/test/java/org/mvel2/tests/core/PropertyHandlerTests.java --- mvel-2.3.1/src/test/java/org/mvel2/tests/core/PropertyHandlerTests.java 2016-09-07 08:18:50.000000000 +0000 +++ mvel-2.4.0/src/test/java/org/mvel2/tests/core/PropertyHandlerTests.java 2017-10-27 08:52:36.000000000 +0000 @@ -389,4 +389,31 @@ assertEquals("foobie", wo.getFieldValue("foo")); } + + public class A {} + + public class B extends A implements Cloneable { + } + + public class C extends A implements Cloneable { + public String prop = "Property"; + } + + public void testPropertyHandlerPreCompile() { + MVEL.COMPILER_OPT_ALLOW_OVERRIDE_ALL_PROPHANDLING = true; + PropertyHandlerFactory.registerPropertyHandler(B.class, new PropertyHandler() { + @Override + public Object getProperty(String name, Object contextObj, VariableResolverFactory variableFactory) { + return "Handled property"; + } + @Override + public Object setProperty(String name, Object contextObj, VariableResolverFactory variableFactory, + Object value) { + return null; + } + }); + + Serializable compiled = MVEL.compileExpression("prop"); + assertEquals("Property", MVEL.executeExpression(compiled, new C())); + } } \ No newline at end of file