Giter VIP home page Giter VIP logo

ognl's People

Contributors

aleksandr-m avatar chenzhang22 avatar danielfernandez avatar dependabot[bot] avatar github-actions[bot] avatar harawata avatar hengyunabc avatar jcgh4164838gh792c124b5 avatar jefferyxhy avatar jessepav avatar jkuhnert avatar johnou avatar kazuki43zoo avatar ksucontract avatar lukaszlenart avatar marvin-enthus avatar marvkis avatar mlw5415 avatar petergeneric avatar peteruhnak avatar quaff avatar rainerh avatar renovate[bot] avatar rolandhe avatar sebthom avatar vlastimil-dolejs avatar yasserzamani avatar zhuster avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

ognl's Issues

OgnlRuntime.findParameterTypes() is wrong

I have a class that has 2 parameters:
Configure<Parent, Child>
which has method
setParent(Parent p)
and a concrete implementation ConfigureProfileItems extends Configure<Profile, Item>.

When OgnlRuntime enters the findParameterTypes() method the first time it determines that the parameter type should be {Profile} and caches it appropriately. The second time it enters this method it looks up the generic methods cache and compares this to the GenericTypes of the strutsAction.getGenericSuperClass() i.e. comparing {Profile} to {Profile, Item}. This fails and therefore has to recomputed every single time for this method.

Furthermore I have another class that extends ConfigureProfileItems therefore type.getGenericSuperclass() == null, so it is determined that the setParent() only parameter is an Object when the only parameter should be a Profile (since it extends ConfigureProfileItems).

Here is a suggested fix for this method that will determine the parameter types correctly and cache them correctly.

public class OgnlRuntime {

private static class GenericMethodParamKey {
    Class<?> actionClass;
    Method m;

    private GenericMethodParamKey(Class<?> actionClass, Method m) {
        this.actionClass = actionClass;
        this.m = m;
    }

    @Override
    public int hashCode() {
        final int prime = 31;
        int result = 1;
        result = prime * result + ((actionClass == null) ? 0 : actionClass.getName().hashCode());
        result = prime * result + ((m == null) ? 0 : m.hashCode());
        return result;
    }
}
private static Hashtable<Method, Class<?>[]> nonGenericMethodParams = new Hashtable<Method, Class<?>[]>();
private static Hashtable<GenericMethodParamKey, Class<?>[]> genericMethodParams = new Hashtable<GenericMethodParamKey, Class<?>[]>();

public static Class<?>[] findParameterTypes(Class<?> clazz, Method m) {

    // Check the non generic methods
    Class<?>[] types = nonGenericMethodParams.get(m);
    if (types != null) {
        return types;
    }

    // Check the generic methods
    GenericMethodParamKey key = new GenericMethodParamKey(clazz, m);
    types = genericMethodParams.get(key);
    if (types != null) {
        return types;
    }

    Type[] params = determineMethodParams(clazz, m);
    types = new Class<?>[params.length];
    boolean nonGeneric = true;

    // replace any parameters on the method with their bound types
    for (int i = 0; i < types.length; i++) {
        Type type = params[i];
        if (type instanceof Class<?>) {
            Class<?> paramClass = (Class<?>) type;
            types[i] = paramClass;
        } else {
            Class<?> paramClass = m.getParameterTypes()[i];
            types[i] = paramClass;
        }
        nonGeneric =  nonGeneric && types[i] == m.getParameterTypes()[i];
    }

    if (nonGeneric) {
        nonGenericMethodParams.put(m, types);
    } else {
        genericMethodParams.put(key, types);
    }

    return types;
}

/**
 * This method gets the method parameters for method m called from class clazz, replacing any generic types
 * that are class-wide parameters.
 * 
 * If the method has any parameterization of its own, these types are still present in the result
 * @param clazz
 * @param m
 * @return
 */
private static Type[] determineMethodParams(Class<?> clazz, Method m) {

    // If this class is the methods declaring class then get the generic method parameters
    if (m.getDeclaringClass() == clazz) {
        return getMethodParameterTypes(m);
    }

    // Get the parameter types as defined in clazz's super class
    Class<?> superClazz = clazz.getSuperclass();
    Type[] types = determineMethodParams(superClazz, m);

    // replace the parameter types with overriding clazz's parameters
    Type superClass = clazz.getGenericSuperclass();
    if (superClass != null && ParameterizedType.class.isInstance(superClass)) {
        ParameterizedTypeImpl parameterizedType = (ParameterizedTypeImpl) superClass;

        // Compare Class2<S,T> and Class1<E,F> extends Class2<F,Integer> to replace
        // any Class2 variable S with Class1 variable F and Class2 variable T with java.lang.Integer
        Type[] actualTypes = parameterizedType.getActualTypeArguments();
        TypeVariable<?>[] classTypes = clazz.getSuperclass().getTypeParameters();

        for (int i = 0; i < types.length; i++) {
            Type type = types[i];

            for (int j = 0; j < actualTypes.length; j++) {
                TypeVariable<?> classType = classTypes[j];
                if (type.toString().equals(classType.getName())) {

                    // Generic method parameter is being overridden by subclass
                    types[i] = actualTypes[j];
                }
            }
        }
    }
    return types;
}

/**
 * This method gets the generic parameter types of a method 
 * @param method
 */
private static Type[] getMethodParameterTypes(Method method) {

    // Get Generic Types
    Type[] types = method.getGenericParameterTypes();

    // Replace any bounds where method like public <T extends E> void doSomething(T t); where
    // E is a class parameter
    TypeVariable<?>[] vars = method.getTypeParameters();
    for (int i = 0; i < types.length; i++) {
        Type type = types[i];

        for (int j = 0; j < vars.length; j++) {
            TypeVariable<?> typeVariable = vars[j];
            if (typeVariable.getName().equals(type.toString())) {
                types[i] = typeVariable.getBounds()[0];

                // Reset j incase we have a case where public <T extends E, S extends T> void doSomething(S s);
                j = -1;
                type = types[i];
            }
        }
    }
    return types;
}

}

Can ognl support java8 lambda expressions

List<String> list = Arrays.asList("a","b","c","d"); list.forEach(s -> System.out.println(s));
but it may cause Exception:
String expression = "{'a','b','c','d'}.foreach(s -> java.lang.System.out.println(s))"; Ognl.getValue(expression, context, root);

OGNLContext deprecated constructor crashes

In current release 3.2.11 and master the deprecated constructor public OgnlContext(Map values) in line 117 is unusable and should be removed immediately (or fixed). Currently it will always leads to a NullPointerException in line 170 of the class. To my understanding functionality marked with 'deprecated' should no longer be used (as it will be removed in a future release), but should not be unusable 'by concept'.

Error Use Ognl for Android.

I want to use the OGNL on my Android Project,
and I add the dependency in my project's build.gradle.
but it throw an exception:
ognl.OgnlException: alias [java.lang.RuntimeException: java.lang.NoClassDefFoundError: Failed resolution of: Ljava/beans/Introspector;]。
How can I solve this problem?

Exception selecting overloaded method in 3.1.4

In Thymeleaf there is an Aggregates class which contains an overloaded avg(...) method. See the specific class here.

All the different variants of this method look like this:

    public BigDecimal avg(final Iterable<? extends Number> target) {...}
    public BigDecimal avg(final Number[] target) {...}
    public BigDecimal avg(final byte[] target) {...}
    public BigDecimal avg(final short[] target) {...}
    public BigDecimal avg(final int[] target) {...}
    public BigDecimal avg(final long[] target) {...}    
    public BigDecimal avg(final float[] target) {...}
    public BigDecimal avg(final double[] target) {...}

In one of my tests, I create an object using an OGNL expression, like:

nums01 = { 5, 5 }

Which creates a java.util.ArrayList<java.lang.Integer> for the nums01 variable.

Then I use this variable as an argument to an avg call in an OGNL expression such as:

#aggregates.avg(nums01)

This worked perfectly until OGNL 3.1.3, and the first version of the overloaded method (the one receiving an Iterable<? extends Number>) was executed. However, in OGNL 3.1.4 I receive this exception:

java.lang.IllegalArgumentException: Can't decide wich method to use: "public java.math.BigDecimal org.thymeleaf.expression.Aggregates.avg(float[])" or "public java.math.BigDecimal org.thymeleaf.expression.Aggregates.avg(long[])"
    at ognl.OgnlRuntime.findBestMethod(OgnlRuntime.java:1427)
    at ognl.OgnlRuntime.getAppropriateMethod(OgnlRuntime.java:1283)
    at ognl.OgnlRuntime.callAppropriateMethod(OgnlRuntime.java:1452)
    at ognl.ObjectMethodAccessor.callMethod(ObjectMethodAccessor.java:68)
    at ognl.OgnlRuntime.callMethod(OgnlRuntime.java:1598)
    at ognl.ASTMethod.getValueBody(ASTMethod.java:91)
    at ognl.SimpleNode.evaluateGetValueBody(SimpleNode.java:212)
    at ognl.SimpleNode.getValue(SimpleNode.java:258)
    at ognl.ASTChain.getValueBody(ASTChain.java:141)
    at ognl.SimpleNode.evaluateGetValueBody(SimpleNode.java:212)
    at ognl.SimpleNode.getValue(SimpleNode.java:258)
    at ognl.Ognl.getValue(Ognl.java:494)
    at ognl.Ognl.getValue(Ognl.java:458)

Unicode Proerty is not supported

I wrote unicode test case

public class InExpressionUnicodeTest extends TestCase {

public void test_String_In()
        throws Exception
{
    OgnlContext context = (OgnlContext) Ognl.createDefaultContext(null);
    Object node = Ognl.parseExpression("#이름 in {\"홍길동\", \"둘리\", \"Africa\", \"Rome\"}");
    Object root = null;

    context.put("이름", "홍길동");
    assertEquals(Boolean.TRUE, Ognl.getValue(node, context, root));
  }

}

OGNL throw Exception
ognl.ExpressionSyntaxException: Malformed OGNL expression: #이름 in {"홍길동", "둘리", "Africa", "Rome"} [ognl.TokenMgrError: Lexical error at line 1, column 2. Encountered: "\uc774" (51060), after : ""]

I debugging codes, and I modify OgnlParserTokenManager.java

Modify line 786
else if (curChar < 128) -> else

Delete line 853-875

after that modification, almost every test case success include my unicode test.

I guess, OgnlParserTokenManager work well with only ascii ( < 128)

(I modify OgnlParserTokenManager.java it self, because I don't know how to use JavaCC. (I don't know how to fix ognl.jj ognl.jjt)

Unit tests don't work if expressions are not compiled

Hi,

most of the unit tests are only tested against compiled OGNL expressions. When we do the unit-tests against interpreded and compiled expressions, we see that a lot of unit tests fail:

Results :

Failed tests:
  myMap[null](org.ognl.test.InterfaceInheritanceTest)
  beans.evenOdd.next(org.ognl.test.InterfaceInheritanceTest)
  #root[1](org.ognl.test.ArrayElementsTest)
  intValue(org.ognl.test.ArrayElementsTest)
  array(org.ognl.test.ArrayElementsTest)
  floatValue(org.ognl.test.NumberFormatExceptionTest)
  intValue(org.ognl.test.NumberFormatExceptionTest)
  intValue(org.ognl.test.NumberFormatExceptionTest)
  bigIntValue(org.ognl.test.NumberFormatExceptionTest)
  bigIntValue(org.ognl.test.NumberFormatExceptionTest)
  bigDecValue(org.ognl.test.NumberFormatExceptionTest)
  bigDecValue(org.ognl.test.NumberFormatExceptionTest)
  intValue(org.ognl.test.PropertyTest)
  booleanValue(org.ognl.test.PropertyTest)
  'disableButton(this,"' + map.get('button-testing') + '");clearElement(&quot;testFtpMessage&quot;)'(org.ognl.test.PropertyTest)
  ids (null)(org.ognl.test.GenericsTest)
  stringValue(org.ognl.test.MethodWithConversionTest)
  values[1](org.ognl.test.IndexedPropertyTest)
  property['hoodak'](org.ognl.test.IndexedPropertyTest)
  newValue(org.ognl.test.SetterTest)
  settableList[0](org.ognl.test.SetterTest)
  settableList[2](org.ognl.test.SetterTest)
  settableList[$](org.ognl.test.SetterTest)
  settableList[^](org.ognl.test.SetterTest)
  settableList[|](org.ognl.test.SetterTest)
  map.newValue(org.ognl.test.SetterTest)
  map.(someMissingKey || newValue)(org.ognl.test.SetterTest)
  map.(newValue && aKey)(org.ognl.test.SetterTest)
  map[0]="map.newValue", map[0](#this)(org.ognl.test.SetterTest)
  openTransitionWin(org.ognl.test.SetterTest)
  --1f (1.0)(org.ognl.test.ArithmeticAndLogicalOperatorsTest)
  5f-2F (3.0)(org.ognl.test.ArithmeticAndLogicalOperatorsTest)
  -1b (-1)(org.ognl.test.ArithmeticAndLogicalOperatorsTest)
  +1b (1)(org.ognl.test.ArithmeticAndLogicalOperatorsTest)
  --1b (1)(org.ognl.test.ArithmeticAndLogicalOperatorsTest)
  2*2.0b (4.0)(org.ognl.test.ArithmeticAndLogicalOperatorsTest)
  5/2.B (2)(org.ognl.test.ArithmeticAndLogicalOperatorsTest)
  5.0B/2 (2.5)(org.ognl.test.ArithmeticAndLogicalOperatorsTest)
  5+2b (7)(org.ognl.test.ArithmeticAndLogicalOperatorsTest)
  5-2B (3)(org.ognl.test.ArithmeticAndLogicalOperatorsTest)
  5.+2b*3 (11.0)(org.ognl.test.ArithmeticAndLogicalOperatorsTest)
  (5.+2b)*3 (21.0)(org.ognl.test.ArithmeticAndLogicalOperatorsTest)
  5. & 3 (1)(org.ognl.test.ArithmeticAndLogicalOperatorsTest)
  5&(3|5^3) (5)(org.ognl.test.ArithmeticAndLogicalOperatorsTest)
  -1h (-1)(org.ognl.test.ArithmeticAndLogicalOperatorsTest)
  +1H (1)(org.ognl.test.ArithmeticAndLogicalOperatorsTest)
  --1h (1)(org.ognl.test.ArithmeticAndLogicalOperatorsTest)
  2h*2 (4)(org.ognl.test.ArithmeticAndLogicalOperatorsTest)
  5/2h (2)(org.ognl.test.ArithmeticAndLogicalOperatorsTest)
  5h+2 (7)(org.ognl.test.ArithmeticAndLogicalOperatorsTest)
  5-2h (3)(org.ognl.test.ArithmeticAndLogicalOperatorsTest)
  5+2H*3 (11)(org.ognl.test.ArithmeticAndLogicalOperatorsTest)
  (5+2H)*3 (21)(org.ognl.test.ArithmeticAndLogicalOperatorsTest)
  ~1h (-2)(org.ognl.test.ArithmeticAndLogicalOperatorsTest)
  5h%2 (1)(org.ognl.test.ArithmeticAndLogicalOperatorsTest)
  5h<<2 (20)(org.ognl.test.ArithmeticAndLogicalOperatorsTest)
  5h>>2 (1)(org.ognl.test.ArithmeticAndLogicalOperatorsTest)
  5h>>1+1 (1)(org.ognl.test.ArithmeticAndLogicalOperatorsTest)
  -5h>>>2 (-2)(org.ognl.test.ArithmeticAndLogicalOperatorsTest)
  5.b & 3 (1)(org.ognl.test.ArithmeticAndLogicalOperatorsTest)
  5h ^3 (6)(org.ognl.test.ArithmeticAndLogicalOperatorsTest)
  5h&3|5^3 (7)(org.ognl.test.ArithmeticAndLogicalOperatorsTest)
  5H&(3|5^3) (5)(org.ognl.test.ArithmeticAndLogicalOperatorsTest)
  1 band 0 (0)(org.ognl.test.ArithmeticAndLogicalOperatorsTest)
  attribute["bar"](org.ognl.test.ObjectIndexedPropertyTest)
  1234L (1234)(org.ognl.test.ConstantTest)
  12.34f (12.34)(org.ognl.test.ConstantTest)
  intValue(org.ognl.test.SetterWithConversionTest)
  intValue(org.ognl.test.SetterWithConversionTest)
  intValue(org.ognl.test.SetterWithConversionTest)
  stringValue(org.ognl.test.SetterWithConversionTest)
  stringValue(org.ognl.test.SetterWithConversionTest)
  anotherStringValue(org.ognl.test.SetterWithConversionTest)
  anotherStringValue(org.ognl.test.SetterWithConversionTest)
  anotherIntValue(org.ognl.test.SetterWithConversionTest)
  anotherIntValue(org.ognl.test.SetterWithConversionTest)
  tab.searchCriteriaSelections[index1][index2](org.ognl.test.IndexAccessTest)
  map['bar'].value(org.ognl.test.IndexAccessTest)
  thing["x"].val(org.ognl.test.IndexAccessTest)
  messages.format('ShowAllCount', {one}) (foo)(org.ognl.test.MethodTest)
  messages.format('ShowAllCount', {one, two}) (foo)(org.ognl.test.MethodTest)
  floatValue(org.ognl.test.PrimitiveNullHandlingTest)
  intValue(org.ognl.test.PrimitiveNullHandlingTest)
  booleanValue(org.ognl.test.PrimitiveNullHandlingTest)
  booleanValue(org.ognl.test.PrimitiveNullHandlingTest)

Tests in error:
  getValues(org.ognl.test.IndexedPropertyTest)
  testMethods.getBean('TestBean') (NamedBean: TestBean)(org.ognl.test.MethodTest)
  testMethods.testProperty (Hello World!)(org.ognl.test.MethodTest)

Tests run: 735, Failures: 85, Errors: 3, Skipped: 0
diff --git a/src/test/java/org/ognl/test/OgnlTestCase.java b/src/test/java/org/ognl/test/OgnlTestCase.java
index 5639350..dac2238 100644
--- a/src/test/java/org/ognl/test/OgnlTestCase.java
+++ b/src/test/java/org/ognl/test/OgnlTestCase.java
@@ -194,6 +194,25 @@ public class OgnlTestCase extends TestCase {
         try {
             SimpleNode expr;

+            if (_compileExpressions) {
+                // round 1 - parse only
+                _compileExpressions = false;
+                testedResult = _expectedResult;
+                expr = getExpression();
+
+                assertEquals(_expectedResult, Ognl.getValue(expr, _context, _root));
+
+                if (hasSetValue)
+                {
+                    testedResult = hasExpectedAfterSetResult ? expectedAfterSetResult : setValue;
+                    Ognl.setValue(expr, _context, _root, setValue);
+
+                    assertEquals(testedResult, Ognl.getValue(expr, _context, _root));
+                }
+                // round two - compile expressions
+                _compileExpressions = true;
+            }
+
             testedResult = _expectedResult;
             expr = getExpression();

Might be a thing for OGNL-4 ?

Why not compile ExpressionNode?

RT, and code is here

    protected String generateSetter(OgnlContext context, CtClass newClass, CtClass objClass, ClassPool pool,
                                    CtMethod valueSetter, Node expression, Object root)
            throws Exception
    {
        if (ExpressionNode.class.isInstance(expression)
            || ASTConst.class.isInstance(expression))
            throw new UnsupportedCompilationException("Can't compile expression/constant setters.");

        ...
        return body;
    }

capitalizeBeanPropertyName

Hi,
in class OnglRuntime, method capitalizeBeanPropertyName
the code:
char first = propertyName.charAt(0);
char second = propertyName.charAt(1);
if ((Character.isLowerCase(first)) && (Character.isUpperCase(second))) {
return propertyName;
}
char[] chars = propertyName.toCharArray();
chars[0] = Character.toUpperCase(chars[0]);

when i define a field name "iType" and setter method setIType(eclipse automatic generated setter method), then capitalizeBeanPropertyName method return "iType", this results method "_getSetMethod" cann't find the setter method for "iType".
the further infuence, struts2 2.3.28 reference the ongl library 3.0.14, when I defined a field the name such as "iType" in a Action class, the i can't auto inject the request parameter for "iType".
I find the ognl version "3.0.6" has not the problem. I find this issue just when i upgrade struts2 from version 2.3.15 to 2.3.28.
Please check the problem if it exists, Thanks in advance!

OgnlRuntime.clearCache() Doesn't Clear All Caches

The OgnlRuntime.clearCache() method does not empty the cacheSetMethod and cacheGetMethod caches. The inability to clear this cache is leading to the following error:

java.lang.IllegalArgumentException: object is not an instance of declaring class

It appears that the issue occurs when classes are reloaded by a different classloader. If we had the ability to clear the caches mentioned above we believe it would fix our issue.

In our case we are using Spring Boot Dev Tools. When the application restarts and classes are reloaded we have no way to clear the caches mentioned above.

Relates to OGNL-257

java.lang.ArithmeticException: / by zero

I want to use the API 'OGNL.getValue' get specific value from an object, some properties in the object have symbol ‘/’, the problem 'java.lang.ArithmeticException: / by zero' will occur when call the API 'OGNL.getValue', is there some solutions to solve this problem?

Is there a reason for why some AST nodes are not public?

Is there a reason for why some AST nodes are not public?

E.g.ASTEq, ASTAdd are private
but e.g. ASTChain, ASTCtor, ASTProperty are public.

This makes it impossible to create a visitor, unless I put it into ognl package itself.

Evaluate "false" as false

OGNL currently evaluates String objects with any value to true, but this makes OGNL's boolean coercion incompatible with two other very used Expression Languages: JSP EL and Spring EL, both of which would evaluate "true" and "false" as booleans true and false, respectively (even if they diverge in their evaluation of other non-booleanish String values).

It would be great if OGNL modified this behaviour in order to evaluate "false" as false (and better even if "off" and "no" were included in the pack, but that might be asking too much ;-)).

For me, it would allow me to remove this hugely ugly, javassist-based hack from thymeleaf: https://github.com/thymeleaf/thymeleaf/blob/159f963907e9d5e3943843031845df28934adafc/src/main/java/org/thymeleaf/standard/expression/OgnlVariableExpressionEvaluator.java#L201-L261

Java8Test is failed

I've performed the Java8Test on local PC. But testGetDeclaredMethods is failed.
Probably, the OgnlRuntime.getDeclaredMethods cannot scan a declared method in a super interface.

Is this bug?

package ognl;

import java.beans.IntrospectionException;
import java.lang.reflect.Method;
import java.util.List;

import junit.framework.TestCase;

public class Java8Test extends TestCase {

    public void testDefaultMethodOnClass() {
        /* defaultMethod(); */
        List defaultMethod = OgnlRuntime.getMethods(ClassWithDefaults.class, "defaultMethod", false);
        assertNotNull(defaultMethod);
        Method method = OgnlRuntime.getReadMethod(ClassWithDefaults.class, "defaultMethod");
        assertNotNull(method);
    }

    public void testDefaultMethodOnSubClass() {
        /* defaultMethod(); */
        List defaultMethod = OgnlRuntime.getMethods(SubClassWithDefaults.class, "defaultMethod", false);
        assertNotNull(defaultMethod);
        Method method = OgnlRuntime.getReadMethod(SubClassWithDefaults.class, "defaultMethod");
        assertNotNull(method);
    }
    
    public void testGetDeclaredMethods() throws IntrospectionException, OgnlException{
    	List defaultMethod = OgnlRuntime.getDeclaredMethods(SubClassWithDefaults.class, "name", false);
    	assertNotNull(defaultMethod);
    	defaultMethod = OgnlRuntime.getDeclaredMethods(ClassWithDefaults.class, "name", false);
    	assertNotNull(defaultMethod); // fail this line
    }

}

class SubClassWithDefaults extends ClassWithDefaults {

	public String getName() { return "name"; }

}

class ClassWithDefaults implements SubInterfaceWithDefaults {

}

interface InterfaceWithDefaults {
    default public void defaultMethod() { }
    default public String getName() { return "name"; }
}
interface SubInterfaceWithDefaults extends InterfaceWithDefaults {
}
junit.framework.AssertionFailedError
	at junit.framework.Assert.fail(Assert.java:48)
	at junit.framework.Assert.assertTrue(Assert.java:20)
	at junit.framework.Assert.assertNotNull(Assert.java:218)
	at junit.framework.Assert.assertNotNull(Assert.java:211)
	at ognl.Java8Test.testGetDeclaredMethods(Java8Test.java:31)
	at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
	at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
	at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
	at java.lang.reflect.Method.invoke(Method.java:498)
	at junit.framework.TestCase.runTest(TestCase.java:168)
	at junit.framework.TestCase.runBare(TestCase.java:134)
	at junit.framework.TestResult$1.protect(TestResult.java:110)
	at junit.framework.TestResult.runProtected(TestResult.java:128)
	at junit.framework.TestResult.run(TestResult.java:113)
	at junit.framework.TestCase.run(TestCase.java:124)
	at junit.framework.TestSuite.runTest(TestSuite.java:243)
	at junit.framework.TestSuite.run(TestSuite.java:238)
	at org.junit.internal.runners.JUnit38ClassRunner.run(JUnit38ClassRunner.java:83)
	at org.junit.runner.JUnitCore.run(JUnitCore.java:157)
	at com.intellij.junit4.JUnit4IdeaTestRunner.startRunnerWithArgs(JUnit4IdeaTestRunner.java:68)
	at com.intellij.rt.execution.junit.IdeaTestRunner$Repeater.startRunnerWithArgs(IdeaTestRunner.java:47)
	at com.intellij.rt.execution.junit.JUnitStarter.prepareStreamsAndStart(JUnitStarter.java:242)
	at com.intellij.rt.execution.junit.JUnitStarter.main(JUnitStarter.java:70)

IllegalArgumentException when calling Ognl.getValue(Object, Object, Class)

Tested with 3.2.14.

Calling Ognl.getValue(Object, Object, Class) calls Ognl.createDefaultContext(Object) (which is marked as deprecated). This then calls constructor OgnlContext(ClassResolver, TypeConverter, MemberAccess) with all null arguments, which finally calls the other constructor OgnlContext(MemberAccess, ClassResolver, TypeConverter, Map) which throws IllegalArgumentException("MemberAccess implementation must be provided - null not permitted!").

I'm not sure whether the internal use of a deprecated call is a bug (deprecated is not supposed to mean broken, after all), or whether further overloads of Ognl.getValue (I'm actually calling Ognl.getValue(String, Object) which calls Ognl.getValue(String, Object, Class), which calls Ognl.getValue(Object, Object, Class)) ought to have been deprecated (although ditto), or whether something else is amiss, but there is clearly an issue here.

The issue was introduced in version 3.2.2, in commit e30b211

This library (3.2.6) vs Apache commons library (4.0)?

Hi,
I note that the Apache commons ognl library hasn't had an update in about 2 years, but this library has. Is this just because the 4.0 (commons) lib is seen is super stable and needs no fixes, or is choosing to depend on this library due to the ongoing support / fixes etc. for a new project the right choice?

Output in System.err 'Two methods with same method

Here is a repro:

  @Test
  public void test() throws Exception {
    String expressiosn = "list.isEmpty()";
    Object expr = Ognl.parseExpression(expressiosn);
    OgnlContext ctx = new OgnlContext();
    List<String> list = Collections.singletonList("string");
    ctx.put("list", list);
    Object value = Ognl.getValue(expr, ctx);
    Assert.assertFalse((Boolean)value);
  }

The above test passes, but the following message is output in System.err.

Two methods with same method signature but not providing classes assignable? "public abstract boolean java.util.List.isEmpty()" and "public boolean java.util.AbstractCollection.isEmpty()" please report!

  • The line that outputs the message is here.
  • This seems to be a side effect of ca37319 .

This was reported on MyBatis tracker a while ago.

Getting "NoSuchPropertyException" Randomly

Hi,

We are using mybatis-3.3.0. Recently we got one strange error from mybatis code while executing a query that gets executed successfully many times during the day, but failed several times.

Below is the stacktrace:

org.apache.ibatis.ognl.NoSuchPropertyException: OrderEO.cinemaAddress
at org.apache.ibatis.scripting.xmltags.OgnlCache.getValue(OgnlCache.java:46) ~[mybatis-3.3.0.jar:3.3.0]
at org.apache.ibatis.scripting.xmltags.ExpressionEvaluator.evaluateBoolean(ExpressionEvaluator.java:32) ~[mybatis-3.3.0.jar:3.3.0]
at org.apache.ibatis.scripting.xmltags.IfSqlNode.apply(IfSqlNode.java:34) ~[mybatis-3.3.0.jar:3.3.0]
at org.apache.ibatis.scripting.xmltags.MixedSqlNode.apply(MixedSqlNode.java:33) ~[mybatis-3.3.0.jar:3.3.0]
at org.apache.ibatis.scripting.xmltags.TrimSqlNode.apply(TrimSqlNode.java:55) ~[mybatis-3.3.0.jar:3.3.0]
at org.apache.ibatis.scripting.xmltags.MixedSqlNode.apply(MixedSqlNode.java:33) ~[mybatis-3.3.0.jar:3.3.0]
at org.apache.ibatis.scripting.xmltags.DynamicSqlSource.getBoundSql(DynamicSqlSource.java:41) ~[mybatis-3.3.0.jar:3.3.0]
at org.apache.ibatis.mapping.MappedStatement.getBoundSql(MappedStatement.java:280) ~[mybatis-3.3.0.jar:3.3.0]
at org.apache.ibatis.executor.CachingExecutor.query(CachingExecutor.java:80) ~[mybatis-3.3.0.jar:3.3.0]
at org.apache.ibatis.session.defaults.DefaultSqlSession.selectList(DefaultSqlSession.java:120) ~[mybatis-3.3.0.jar:3.3.0]
at org.apache.ibatis.session.defaults.DefaultSqlSession.selectList(DefaultSqlSession.java:113) ~[mybatis-3.3.0.jar:3.3.0]
at org.apache.ibatis.session.defaults.DefaultSqlSession.selectOne(DefaultSqlSession.java:73) ~[mybatis-3.3.0.jar:3.3.0]
at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method) ~[?:1.8.0_45]
at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62) ~[?:1.8.0_45]
at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43) ~[?:1.8.0_45]
at java.lang.reflect.Method.invoke(Method.java:497) ~[?:1.8.0_45]
at org.mybatis.spring.SqlSessionTemplate$SqlSessionInterceptor.invoke(SqlSessionTemplate.java:358) ~[mybatis-spring-1.2.2.jar:1.2.2]
... 36 more
Caused by: org.apache.ibatis.ognl.NoSuchPropertyException: OrderXEO.cinemaAddress
at org.apache.ibatis.ognl.ObjectPropertyAccessor.getProperty(ObjectPropertyAccessor.java:151) ~[mybatis-3.3.0.jar:3.3.0]
at org.apache.ibatis.ognl.OgnlRuntime.getProperty(OgnlRuntime.java:2434) ~[mybatis-3.3.0.jar:3.3.0]
at org.apache.ibatis.ognl.ASTProperty.getValueBody(ASTProperty.java:114) ~[mybatis-3.3.0.jar:3.3.0]
at org.apache.ibatis.ognl.SimpleNode.evaluateGetValueBody(SimpleNode.java:212) ~[mybatis-3.3.0.jar:3.3.0]
at org.apache.ibatis.ognl.SimpleNode.getValue(SimpleNode.java:258) ~[mybatis-3.3.0.jar:3.3.0]
at org.apache.ibatis.ognl.ASTChain.getValueBody(ASTChain.java:141) ~[mybatis-3.3.0.jar:3.3.0]
at org.apache.ibatis.ognl.SimpleNode.evaluateGetValueBody(SimpleNode.java:212) ~[mybatis-3.3.0.jar:3.3.0]
at org.apache.ibatis.ognl.SimpleNode.getValue(SimpleNode.java:258) ~[mybatis-3.3.0.jar:3.3.0]
at org.apache.ibatis.ognl.ASTNotEq.getValueBody(ASTNotEq.java:50) ~[mybatis-3.3.0.jar:3.3.0]
at org.apache.ibatis.ognl.SimpleNode.evaluateGetValueBody(SimpleNode.java:212) ~[mybatis-3.3.0.jar:3.3.0]
at org.apache.ibatis.ognl.SimpleNode.getValue(SimpleNode.java:258) ~[mybatis-3.3.0.jar:3.3.0]
at org.apache.ibatis.ognl.ASTAnd.getValueBody(ASTAnd.java:61) ~[mybatis-3.3.0.jar:3.3.0]
at org.apache.ibatis.ognl.SimpleNode.evaluateGetValueBody(SimpleNode.java:212) ~[mybatis-3.3.0.jar:3.3.0]
at org.apache.ibatis.ognl.SimpleNode.getValue(SimpleNode.java:258) ~[mybatis-3.3.0.jar:3.3.0]
at org.apache.ibatis.ognl.Ognl.getValue(Ognl.java:494) ~[mybatis-3.3.0.jar:3.3.0]
at org.apache.ibatis.ognl.Ognl.getValue(Ognl.java:458) ~[mybatis-3.3.0.jar:3.3.0]
at org.apache.ibatis.scripting.xmltags.OgnlCache.getValue(OgnlCache.java:44) ~[mybatis-3.3.0.jar:3.3.0]
at org.apache.ibatis.scripting.xmltags.ExpressionEvaluator.evaluateBoolean(ExpressionEvaluator.java:32) ~[mybatis-3.3.0.jar:3.3.0]
at org.apache.ibatis.scripting.xmltags.IfSqlNode.apply(IfSqlNode.java:34) ~[mybatis-3.3.0.jar:3.3.0]
at org.apache.ibatis.scripting.xmltags.MixedSqlNode.apply(MixedSqlNode.java:33) ~[mybatis-3.3.0.jar:3.3.0]
at org.apache.ibatis.scripting.xmltags.TrimSqlNode.apply(TrimSqlNode.java:55) ~[mybatis-3.3.0.jar:3.3.0]
at org.apache.ibatis.scripting.xmltags.MixedSqlNode.apply(MixedSqlNode.java:33) ~[mybatis-3.3.0.jar:3.3.0]
at org.apache.ibatis.scripting.xmltags.DynamicSqlSource.getBoundSql(DynamicSqlSource.java:41) ~[mybatis-3.3.0.jar:3.3.0]
at org.apache.ibatis.mapping.MappedStatement.getBoundSql(MappedStatement.java:280) ~[mybatis-3.3.0.jar:3.3.0]
at org.apache.ibatis.executor.CachingExecutor.query(CachingExecutor.java:80) ~[mybatis-3.3.0.jar:3.3.0]
at org.apache.ibatis.session.defaults.DefaultSqlSession.selectList(DefaultSqlSession.java:120) ~[mybatis-3.3.0.jar:3.3.0]
at org.apache.ibatis.session.defaults.DefaultSqlSession.selectList(DefaultSqlSession.java:113) ~[mybatis-3.3.0.jar:3.3.0]
at org.apache.ibatis.session.defaults.DefaultSqlSession.selectOne(DefaultSqlSession.java:73) ~[mybatis-3.3.0.jar:3.3.0]
at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method) ~[?:1.8.0_45]
at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62) ~[?:1.8.0_45]
at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43) ~[?:1.8.0_45]
at java.lang.reflect.Method.invoke(Method.java:497) ~[?:1.8.0_45]
at org.mybatis.spring.SqlSessionTemplate$SqlSessionInterceptor.invoke(SqlSessionTemplate.java:358) ~[mybatis-spring-1.2.2.jar:1.2.2]

Any help to find root cause of above error will be greatly appreciated.
Ps. We have met a similar problem when using mybatis-3.1.0, which has fixed in mybatis-3.3.0. Is this the similar cause of ognl?

MemberAccess support private static method and private field, but do not support private static field.

MemberAccess support private static method and private field, but do not support private static field.

Demo:

import java.lang.reflect.AccessibleObject;
import java.lang.reflect.Member;
import java.lang.reflect.Modifier;
import java.util.Map;

import ognl.ClassResolver;
import ognl.MemberAccess;
import ognl.Ognl;
import ognl.OgnlContext;
import ognl.OgnlException;

public class MyDemo {

	private static String statidField = "fff";

	private String privateField = "ppp";

	private static String staticFunc() {
		return "static func";
	}

	private static MyDemo newInstance() {
		return new MyDemo();
	}

	public static void main(String[] args) throws OgnlException {
		OgnlContext context = new OgnlContext(new ClassResolver() {
			@Override
			public Class classForName(String className, Map context) throws ClassNotFoundException {
				return Class.forName(className);
			}

		}, null, new DefaultMemberAccess(true));

		context.setTraceEvaluations(true);

		Object root = null;

		System.out.println(Ognl.getValue("@MyDemo@staticFunc()", context, root));
		System.out.println(Ognl.getValue("@MyDemo@newInstance().privateField", context, root));
		// exception
		System.out.println(Ognl.getValue("@MyDemo@statidField", context, root));
	}

	public static class DefaultMemberAccess implements MemberAccess {
		public boolean allowPrivateAccess = false;
		public boolean allowProtectedAccess = false;
		public boolean allowPackageProtectedAccess = false;

		/*
		 * ===================================================================
		 * Constructors
		 * ===================================================================
		 */
		public DefaultMemberAccess(boolean allowAllAccess) {
			this(allowAllAccess, allowAllAccess, allowAllAccess);
		}

		public DefaultMemberAccess(boolean allowPrivateAccess, boolean allowProtectedAccess,
				boolean allowPackageProtectedAccess) {
			super();
			this.allowPrivateAccess = allowPrivateAccess;
			this.allowProtectedAccess = allowProtectedAccess;
			this.allowPackageProtectedAccess = allowPackageProtectedAccess;
		}

		/*
		 * =================================================================== Public
		 * methods ===================================================================
		 */
		public boolean getAllowPrivateAccess() {
			return allowPrivateAccess;
		}

		public void setAllowPrivateAccess(boolean value) {
			allowPrivateAccess = value;
		}

		public boolean getAllowProtectedAccess() {
			return allowProtectedAccess;
		}

		public void setAllowProtectedAccess(boolean value) {
			allowProtectedAccess = value;
		}

		public boolean getAllowPackageProtectedAccess() {
			return allowPackageProtectedAccess;
		}

		public void setAllowPackageProtectedAccess(boolean value) {
			allowPackageProtectedAccess = value;
		}

		/*
		 * ===================================================================
		 * MemberAccess interface
		 * ===================================================================
		 */
		public Object setup(Map context, Object target, Member member, String propertyName) {
			Object result = null;

			if (isAccessible(context, target, member, propertyName)) {
				AccessibleObject accessible = (AccessibleObject) member;

				if (!accessible.isAccessible()) {
					result = Boolean.TRUE;
					accessible.setAccessible(true);
				}
			}
			return result;
		}

		public void restore(Map context, Object target, Member member, String propertyName, Object state) {
			if (state != null) {
				((AccessibleObject) member).setAccessible(((Boolean) state).booleanValue());
			}
		}

		/**
		 * Returns true if the given member is accessible or can be made accessible by
		 * this object.
		 */
		public boolean isAccessible(Map context, Object target, Member member, String propertyName) {
			int modifiers = member.getModifiers();
			boolean result = Modifier.isPublic(modifiers);

			if (!result) {
				if (Modifier.isPrivate(modifiers)) {
					result = getAllowPrivateAccess();
				} else {
					if (Modifier.isProtected(modifiers)) {
						result = getAllowProtectedAccess();
					} else {
						result = getAllowPackageProtectedAccess();
					}
				}
			}
			return result;
		}
	}
}

Output:

static func
ppp
Exception in thread "main" ognl.OgnlException: Could not get static field statidField from class MyDemo [java.lang.NoSuchFieldException: statidField]
	at ognl.ASTStaticField.isNodeConstant(ASTStaticField.java:108)
	at ognl.SimpleNode.isConstant(SimpleNode.java:325)
	at ognl.SimpleNode.evaluateGetValueBody(SimpleNode.java:202)
	at ognl.SimpleNode.getValue(SimpleNode.java:236)
	at ognl.Ognl.getValue(Ognl.java:493)
	at ognl.Ognl.getValue(Ognl.java:595)
	at ognl.Ognl.getValue(Ognl.java:565)
	at MyDemo.main(MyDemo.java:42)
Caused by: java.lang.NoSuchFieldException: statidField
	at java.lang.Class.getField(Class.java:1703)
	at ognl.ASTStaticField.isNodeConstant(ASTStaticField.java:92)
	... 7 more
/-- Encapsulated exception ------------\
java.lang.NoSuchFieldException: statidField
	at java.lang.Class.getField(Class.java:1703)
	at ognl.ASTStaticField.isNodeConstant(ASTStaticField.java:92)
	at ognl.SimpleNode.isConstant(SimpleNode.java:325)
	at ognl.SimpleNode.evaluateGetValueBody(SimpleNode.java:202)
	at ognl.SimpleNode.getValue(SimpleNode.java:236)
	at ognl.Ognl.getValue(Ognl.java:493)
	at ognl.Ognl.getValue(Ognl.java:595)
	at ognl.Ognl.getValue(Ognl.java:565)
	at MyDemo.main(MyDemo.java:42)
\--------------------------------------/

Class reference is failed when include 'or' at a package name

If package name includes "or" (e.g. "jp.or.example"), the Ognl#parseExpression(String) is failed as follow:

  • Code
    public void test_class_reference()
        throws Throwable
    {
        OgnlContext context = (OgnlContext) Ognl.createDefaultContext(null, new DefaultMemberAccess(false));
        {
            Node expr = (Node) Ognl.parseExpression("@java.util.UUID@randomUUID()"); // It's OK
            Object v = expr.getValue(context, null);
            System.out.println(v);
        }
        {
            Node expr = (Node) Ognl.parseExpression("@jp.or.example.IdUtils@generateId()"); // It's failed on parsing phase
            Object v = expr.getValue(context, null);
            System.out.println(v);
        }
    }
  • Stack Trace
ognl.ExpressionSyntaxException: Malformed OGNL expression: @jp.or.example.IdUtils@generateId()
 [ognl.ParseException: Encountered " "or" "or "" at line 1, column 5.
Was expecting:
    <IDENT> ...
    ]
	at ognl.Ognl.parseExpression(Ognl.java:179)
	at org.ognl.test.enhance.TestExpressionCompiler.test_class_reference(TestExpressionCompiler.java:55)
	at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
	at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
	at java.base/jdk.internal.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
	at java.base/java.lang.reflect.Method.invoke(Method.java:566)
	at junit.framework.TestCase.runTest(TestCase.java:176)
	at junit.framework.TestCase.runBare(TestCase.java:141)
	at junit.framework.TestResult$1.protect(TestResult.java:122)
	at junit.framework.TestResult.runProtected(TestResult.java:142)
	at junit.framework.TestResult.run(TestResult.java:125)
	at junit.framework.TestCase.run(TestCase.java:129)
	at junit.framework.TestSuite.runTest(TestSuite.java:252)
	at junit.framework.TestSuite.run(TestSuite.java:247)
	at org.junit.internal.runners.JUnit38ClassRunner.run(JUnit38ClassRunner.java:86)
	at org.junit.runner.JUnitCore.run(JUnitCore.java:137)
	at com.intellij.junit4.JUnit4IdeaTestRunner.startRunnerWithArgs(JUnit4IdeaTestRunner.java:68)
	at com.intellij.rt.junit.IdeaTestRunner$Repeater.startRunnerWithArgs(IdeaTestRunner.java:33)
	at com.intellij.rt.junit.JUnitStarter.prepareStreamsAndStart(JUnitStarter.java:230)
	at com.intellij.rt.junit.JUnitStarter.main(JUnitStarter.java:58)
Caused by: ognl.ParseException: Encountered " "or" "or "" at line 1, column 5.
Was expecting:
    <IDENT> ...
    
	at ognl.OgnlParser.generateParseException(OgnlParser.java:3232)
	at ognl.OgnlParser.jj_consume_token(OgnlParser.java:3098)
	at ognl.OgnlParser.className(OgnlParser.java:1822)
	at ognl.OgnlParser.classReference(OgnlParser.java:1795)
	at ognl.OgnlParser.staticReference(OgnlParser.java:1762)

TypeConverter / OgnlOps 'double boxing'

Hi,

I just pushed a new branch that also addresses another 'inconsistency' issue I was fighting in the past:
The automatic Type-Conversion puts a List (or Collection) into an array by doing new Object[] { } instead of using the items of the list for the array. I think this would be the more desired behaviour. I also fixed the related unit tests from #16 / #19 respectively and added some new tests.

The commit [410dee5](secadm@410dee5f64410f98ad4171150dc19869abd7de4c] (branch TypeConverterDoubleArrayBoxing) addresses the issue.

This patch is based on #23 / #24 and so i'll create a pull request after #24 ist merged or the pull request will also provide #24. But maybe both requests can be reviewed together.

Bye,
Chris

Log flood with "Two methods with same score(0)"

Our logs are being flooded with the message:
Two methods with same score(0): "public java.lang.String myPackage.MyClass.myMethod(myPackage.MyModelClass,int)" and "public abstract java.lang.String myPackage.MyClassAbstract.myMethod(java.lang.Object,int)" please report!

We are on the latest version of struts (struts2-core-2.5.14.jar) which uses ognl-3.1.15.

This issue seems to come from OgnlRuntime.java at line 1430.

I grepped on future versions of OgnlRuntime.java from your github for 'abstract' ignoring case and found code in 3.1.16 and 3.2.3, and 3.2.4. I tried applying the logic from these code fixes in a locally compiled OgnlRuntime, but the problem did not go away. I don't completely understand your score calculation, but some of the other flags (isInterface, etc) seem to preclude our implementation.

The only thing I could do to workaround this was to put above this sysout line:
if (!Modifier.isAbstract(m.getModifiers()))

Our implementation is:
<<MyClassAbstract.java>>
package myPackage;
public abstract class MyClassAbstract {
public abstract String myMethod (E element, int i);

<<MyClass.java>>
package myPackage;
public class MyClass extends MyClassAbstract < MyModelClass > {
public String myMethod (MyModelClass myModel, int i) {

Please advise.

"Two vararg methods with same score" for resteasy ClientWebTarget.request()

In OGNL 3.2.20 I'm experiencing the following log message. I think this error may be spurious here since there's a no-args method as well as 2 varargs methods.

Two vararg methods with same score(0): "public javax.ws.rs.client.Invocation$Builder org.jboss.resteasy.client.jaxrs.internal.ClientWebTarget.request(javax.ws.rs.core.MediaType[])" and "public javax.ws.rs.client.Invocation$Builder org.jboss.resteasy.client.jaxrs.internal.ClientWebTarget.request(java.lang.String[])" please report!

The OGNL statement being executed is:

someWebTarget.request().get()

Here's the method being called: https://github.com/resteasy/Resteasy/blob/main/resteasy-client/src/main/java/org/jboss/resteasy/client/jaxrs/internal/ClientWebTarget.java#L358

Constructor of OgnlContext with single Map Parameter throws Runtime Exception

Hello OGNL Team,
the latest available ognl library from maven central 3.2.4 will always give a RuntimeException when instantiate OgnlContext will only a Map parameter.
In the source code i found that internally the constructor:

public OgnlContext(MemberAccess memberAccess, ClassResolver classResolver, TypeConverter typeConverter, Map values)

will be called with null values for not given params. This gives a
throw new RuntimeException("MemberAccess implementation must be provided!")

My used library(thymelead) calls this single param constructor and i needed to patch it manually. Is there a default implementation for MemberAccess?

Updating from 3.1.X to 3.2.X breaks

When I try to upgrade objectify from 3.1.X to 3.2.X. The following code breaks.

public class Demo {

	public void test() {

		OgnlContext ctx = new OgnlContext();

	}
}

The code should pass, but it throws an error:

Demo.java:[11,20] error: no suitable constructor found for OgnlContext(no arguments)

addDefaultContext hava a bug

https://github.com/jkuhnert/ognl/blob/496a53b63ccde1ad4e7ff2ebd1bbe7091a035b61/src/main/java/ognl/Ognl.java#L324

When the argument memberAccess passed by the overloaded method above is null, a runtime exception will occur

@Deprecated
 public static Map addDefaultContext(Object root, Map context)
 {
     return addDefaultContext(root, null, null, null, context);
 }

test code:

public static void main(String[] args) throws OgnlException {
        User root = new User();
        root.setId(19612);
        root.setName("sakura");
        Map context = new HashMap();
        context.put("who", "Who am i");

        String who1 = (String) Ognl.getValue("#who", context, root);
        System.out.println(who1);
    }

error message:

Exception in thread "main" java.lang.RuntimeException: MemberAccess implementation must be provided!
	at ognl.OgnlContext.<init>(OgnlContext.java:140)

Negative number is considered an arithmetic expression

With the newly introduced check for arithmetic expressions, negative numbers are considered to be arithmetic expressions.

I can understand that one does not want to have arithmetic expressions in parameter names. OTOH, I would not consider a negative number as an arithmetic expression.

Note that this has also been reported to the struts2 project under https://issues.apache.org/jira/browse/WW-4651

@lukaszlenart asked me to post this here as well.

Add Automatic-Module-Name for JPMS

In order to have the OGNL jar artifact properly work as a dependency in JPMS (a required module in a Java 9+ modular application), OGNL should choose a module name that gives dependent software some kind of guarantee on the module name that should be used for it, whatever the version. This can be done even if OGNL is not turned yet into a module as such, by merely adding an Automatic-Module-Name: <name> entry to the MANIFEST.MF file.

This works as a kind of reserve for module names and allows software using OGNL to properly express OGNL as a dependency in a requires clause in module-info.java, even if OGNL has not been modularised yet.

Note there are two main approaches for module naming (see this). Apache Commons OGNL has already chosen the reverse-DNS approach (see their pom.xml) so it is org.apache.commons.ognl there, but given OGNL 3 and OGNL 4 will be completely package- and code-incompatible (ognl.* vs org.apache.commons.ognl.* packages), I'm not sure it would make sense to adopt org.apache.commons.ognl here too as a module name for the sake of compatibility. So using simply ognl as name could be a sensible option here too. Especially given the fact that Apache Commons OGNL seems dead.

Fail invoking for varargs setter method

Fail to invoke a varargs setter method via Ognl#setValue as follow:

package org.ognl.test.issues;

import ognl.DefaultMemberAccess;
import ognl.Ognl;
import ognl.OgnlException;
import org.hamcrest.core.IsEqual;
import org.junit.Assert;
import org.junit.Test;

public class ReproTest {

  @Test // Success
  public void testForArray() throws OgnlException, NoSuchMethodException {
    Bean bean = new Bean();
    Ognl.setValue("chars", Ognl.createDefaultContext(null, new DefaultMemberAccess(false)), bean, new Character[]{'%', '_'});
    Assert.assertThat(bean.chars.length, IsEqual.equalTo(2));
    Assert.assertThat(bean.chars[0], IsEqual.equalTo('%'));
    Assert.assertThat(bean.chars[1], IsEqual.equalTo('_'));
  }

  @Test // Fail
  public void testForVarArgs() throws OgnlException, NoSuchMethodException {
    Bean bean = new Bean();
    Ognl.setValue("strings", Ognl.createDefaultContext(null, new DefaultMemberAccess(false)), bean, new String[]{"%", "_"});
    Assert.assertThat(bean.strings.length, IsEqual.equalTo(2));
    Assert.assertThat(bean.strings[0], IsEqual.equalTo("%"));
    Assert.assertThat(bean.strings[1], IsEqual.equalTo("_"));
  }

  static class Bean {
    private Character[] chars;
    private String[] strings;

    public void setChars(Character[] chars) {
      this.chars = chars;
    }
    public Character[] getChars() {
      return chars;
    }
    public void setStrings(String... strings) {
      this.strings = strings;
    }
    public String[] getStrings() {
      return strings;
    }
  }

}

Perhaps the implementation of the methods around here will have an impact.

OgnlContext(Map) construct always throws exception

In this commit e30b211 OgnlContext(MemberAccess memberAccess, ClassResolver classResolver, TypeConverter typeConverter, Map values) was updates to throw an exception if memberAccess is null.

The constructor OgnlContext(Map values) always passes null and thus cannot ever work.

This impacts Thymeleaf since it calls OgnlContext(Map values) from its OGNL expression code.

Unit tests fail when using Java 8 to build maven package

Hi,

When doing a "mvn test" with Java 8 the tests fail with these error messages:

Results :

Failed tests:
  messages.format('ShowAllCount', one) (foo)(org.ognl.test.MethodTest)

Tests in error:
  {'1','2','3'}(org.ognl.test.ArrayElementsTest)
  { true, !false }(org.ognl.test.ArrayElementsTest)
  {stringValue, getMap()}(org.ognl.test.PropertyTest)
  {'stringValue', map["test"].map["size"]}(org.ognl.test.PropertyTest)
  test_Complicated_List(org.ognl.test.ASTPropertyTest)
  null in {true,false,null} (true)(org.ognl.test.ArithmeticAndLogicalOperatorsTest)
  null not in {true,false,null} (false)(org.ognl.test.ArithmeticAndLogicalOperatorsTest)
  5 in {true,false,null} (false)(org.ognl.test.ArithmeticAndLogicalOperatorsTest)
  5 not in {true,false,null} (true)(org.ognl.test.ArithmeticAndLogicalOperatorsTest)
  #y + "1" (11)(org.ognl.test.ArithmeticAndLogicalOperatorsTest)
  "1" + #y (11)(org.ognl.test.ArithmeticAndLogicalOperatorsTest)
  { false, true, null, 0, 1. } ([false, true, null, 0, 1.0])(org.ognl.test.ConstantTest)
  messages.format('ShowAllCount', {one}) (foo)(org.ognl.test.MethodTest)
  messages.format('ShowAllCount', {one, two}) (foo)(org.ognl.test.MethodTest)
  {theInt + 1}(org.ognl.test.PropertyArithmeticAndLogicalOperatorsTest)

Tests run: 730, Failures: 1, Errors: 15, Skipped: 0

In the logs we see a lot of messages like:

Running org.ognl.test.ArrayElementsTest
Caught exception java.lang.RuntimeException: java.io.IOException: invalid constant type: 18
Caught exception java.lang.RuntimeException: java.io.IOException: invalid constant type: 18
Tests run: 11, Failures: 0, Errors: 2, Skipped: 0, Time elapsed: 0.026 sec <<< FAILURE!

The invalid constant type exception referes to Java 8 classes. Okay, OGNL uses javassist to access the java objects. The utilized version is 3.11, which dosn't support Java 8.
Updating javassist 3.11.0.GA to 3.20.0-GA changes the error message:

Results :

Failed tests:
  messages.format('ShowAllCount', one) (foo)(org.ognl.test.MethodTest)
  messages.format('ShowAllCount', {one}) (foo)(org.ognl.test.MethodTest)
  messages.format('ShowAllCount', {one, two}) (foo)(org.ognl.test.MethodTest)

Tests run: 730, Failures: 3, Errors: 0, Skipped: 0

When using java 1.7 all tests pass. Amazing ;)

So I did some further investigations and this are my findings:
For Java 1.8 the message.format calls resulted in those function calls:

messages.format('ShowAllCount', one) -> calls format(String key, Object param1)
messages.format('ShowAllCount', {one}) -> calls format(String key, Object param1)
    param1 is Array[1]... Okay, Array matches to object...
messages.format('ShowAllCount', {one, two}) -> calls format(String key, Object param1)
    param1 is Array[1, 2]... Okay, Array matches to object...

Then I found out following facts;

  • The unit-tests pre-compile the expressions. (Hint to me: We get different results if expressions are compiled vs. just parsed - needs further investigations)
  • The compiler produces different code during ASTChain.toGetSource():
    • Java 1.7: .getMessages()).format("ShowAllCount", (java.lang.Object[]) ref1($$))
    • Java 1.8: .getMessages()).format("ShowAllCount", ($w) ((org.ognl.test.objects.Simple)$2)..getOne())
  • Further investigations brought up that OgnlRuntime.getReadMethod() returns different methods:
    • Java 1.7: public java.lang.String org.ognl.test.objects.Messages.format(java.lang.String,java.lang.Object[])
    • Java 1.8: public java.lang.String org.ognl.test.objects.Messages.format(java.lang.String,java.lang.Object)

Okay, the root cause is: OgnlRuntime.getReadMethod() obtains a list of methods by calling

            BeanInfo info = Introspector.getBeanInfo(target);
            MethodDescriptor[] methods = info.getMethodDescriptors();

and iterating through this list, returning the first method that could propably match. And info.getMethodDescriptors() returns the list in a different order depending on the java version.

Okay, how to solve this?

My only idea would be to extend this getReadMethod() with following functionallity:

  • collect all possible matchin methods
  • if we have more then one candidate:
    • calculate a 'weight' for each method depending how 'good' the arguments match
    • sort the list by wight and return the best candidate

Any other ideas?

Issue with SecurityManager and 3.0.19

Security Manager still does not work correctly with OGNL. The only workaround appears to be OgnlRuntime.setSecurityManager(null),

We get

java.lang.IllegalAccessException: Method [public java.lang.String com.opensymphony.xwork2.ActionSupport.execute() throws java.lang.Exception] cannot be accessed.

Can you please either fix Ognl's ability to work with security manager , or provide an example working policy file

Varargs method not found if no varargs are given

I have a method

interface Accessible {
        default Accessible access(Object... args) {
            return /* whatever */;
        }
}

When calling access() without arguments, a java.lang.NoSuchMethodException is thrown because the varargs method is not found.

Remove javassist dependency.

It looks like that starting from OGNL 2.7 a dependency on javassist was introduced.

Many projects still use OGNL 2.6.9 but won't upgrade to 2.7.x or 3.0 (because of this too).

Please remove this dependency if it's possible.

License and Copyright does not match

You have migrated to Apache 2.0 license but Copyright notices in the source file still referring to earlier license which was not Apache 2.0. Please update all source files to include Apache 2.0 Copyright notice.

Illegal reflective access warning when using "_parameter.containsKey() and Collections.singletonMap

Greetings,
I first reported this issue in mybatis/mybatis-3#2421 but then I realized it might be more appropriate here.

When I have some sql statements containing <if test="_parameter.containsKey('foo')"> and the parameters are in a Collections.singletonMap I get the following warning in the console:

WARNING: An illegal reflective access operation has occurred
WARNING: Illegal reflective access by ognl.AccessibleObjectHandlerPreJDK9 (file:/C:/Users/shenz/.m2/repository/ognl/ognl/3.3.1/ognl-3.3.1.jar) to method java.util.Collections$SingletonMap.containsKey(java.lang.Object)
WARNING: Please consider reporting this to the maintainers of ognl.AccessibleObjectHandlerPreJDK9
WARNING: Use --illegal-access=warn to enable warnings of further illegal reflective access operations
WARNING: All illegal access operations will be denied in a future release

This does not happen when using java.util.Map.

I am using Java 11.0.13.

"hashCode()" being called when accessing a "code" field

If we have a public code field in a class, such as:

public class Something {
   public String code = "abc123";
}

And, being s an object of type Something, we execute this expression:

s.code

Instead of returning "abc123", the hash code will be returned because the hashCode() method will be selected for execution.

The responsible for this is this block of code in OgnlRuntime: https://github.com/jkuhnert/ognl/blob/751084b4802b488e0386ab702e230cceca296254/src/java/ognl/OgnlRuntime.java#L2947-L2954

if (methods[i].getName().toLowerCase().endsWith(name)
    && !methods[i].getName().startsWith("set")
    && methods[i].getMethod().getReturnType() != Void.TYPE) {

    Method m = methods[i].getMethod();
    if (!candidates.contains(m))
        candidates.add(m);
}

IMHO the check applied here is far too lenient, especially given the fact that field names have not been checked yet by the time this executes…

Compile expression throws no such class with custom ClassResolver

I impliment a ClassResolver that imports a custom package other than java.lang.
It throws when compiling expression calling static method of class under my custom package.

Express is like this @Calbit@cal(x), and the package path is cn.agentd.ognl.util.

stacktrace

Exception in thread "main" javassist.CannotCompileException: [source error] no such class: Calbit
	at javassist.CtBehavior.setBody(CtBehavior.java:474)
	at javassist.CtBehavior.setBody(CtBehavior.java:440)
	at ognl.enhance.ExpressionCompiler.generateGetter(ExpressionCompiler.java:553)
	at ognl.enhance.ExpressionCompiler.compileExpression(ExpressionCompiler.java:419)
	at ognl.OgnlRuntime.compileExpression(OgnlRuntime.java:435)
	at ognl.Ognl.compileExpression(Ognl.java:141)
	at cn.agentd.ognl.Demo.main(Demo.java:27)
Caused by: compile error: no such class: Calbit
	at javassist.compiler.MemberResolver.searchImports(MemberResolver.java:479)
	at javassist.compiler.MemberResolver.lookupClass(MemberResolver.java:422)
	at javassist.compiler.TypeChecker.atCallExpr(TypeChecker.java:683)
	at javassist.compiler.JvstTypeChecker.atCallExpr(JvstTypeChecker.java:170)
	at javassist.compiler.ast.CallExpr.accept(CallExpr.java:49)
	at javassist.compiler.JvstTypeChecker.atCastToWrapper(JvstTypeChecker.java:138)
	at javassist.compiler.JvstTypeChecker.atCastExpr(JvstTypeChecker.java:110)
	at javassist.compiler.ast.CastExpr.accept(CastExpr.java:59)
	at javassist.compiler.CodeGen.doTypeCheck(CodeGen.java:266)
	at javassist.compiler.CodeGen.compileExpr(CodeGen.java:253)
	at javassist.compiler.CodeGen.atReturnStmnt2(CodeGen.java:641)
	at javassist.compiler.JvstCodeGen.atReturnStmnt(JvstCodeGen.java:443)
	at javassist.compiler.CodeGen.atStmnt(CodeGen.java:393)
	at javassist.compiler.ast.Stmnt.accept(Stmnt.java:53)
	at javassist.compiler.CodeGen.atStmnt(CodeGen.java:381)
	at javassist.compiler.ast.Stmnt.accept(Stmnt.java:53)
	at javassist.compiler.CodeGen.atMethodBody(CodeGen.java:321)
	at javassist.compiler.Javac.compileBody(Javac.java:228)
	at javassist.CtBehavior.setBody(CtBehavior.java:466)
	... 6 more

ArrayIndexOutOfBoundsException when trying to access BeanFactory

Hi,

when trying to access a BeanFactory with factory.getBean("test") an ArrayIndexOutOfBoundsExceptions is thrown:

java.lang.ArrayIndexOutOfBoundsException
    at java.lang.System.arraycopy(Native Method)
    at ognl.OgnlRuntime.callAppropriateMethod(OgnlRuntime.java:1265)
    at ognl.ObjectMethodAccessor.callMethod(ObjectMethodAccessor.java:68)
    at ognl.OgnlRuntime.callMethod(OgnlRuntime.java:1370)
    at ognl.ASTMethod.getValueBody(ASTMethod.java:90)
    at ognl.SimpleNode.evaluateGetValueBody(SimpleNode.java:212)
    at ognl.SimpleNode.getValue(SimpleNode.java:258)
    at ognl.ASTChain.getValueBody(ASTChain.java:141)
    at ognl.SimpleNode.evaluateGetValueBody(SimpleNode.java:212)
    at ognl.SimpleNode.getValue(SimpleNode.java:258)
    at ognl.ASTMethod.getValueBody(ASTMethod.java:87)
...

I created a small Dummy-BeanFactory to reproduce the issue:

package org.ognl.test.objects;

import java.util.Arrays;

public class BeanFactory {
    //---------------------------------------------------------------------
    // Implementation of BeanFactory interface
    //---------------------------------------------------------------------

    public Object getBean(String name) {
        return "NamedBean: "+name;
    }

    public <T> T getBean(String name, Class<T> requiredType) {
        return (T) ("NamedTypedBean: "+name+" "+requiredType.getSimpleName());
    }

    public <T> T getBean(Class<T> requiredType) {
        return (T) ("TypedBean: "+requiredType.getSimpleName());
    }

    public Object getBean(String name, Object... args) {
        return "NamedBeanWithArgs: "+name+" "+Arrays.toString(args);
    }

}

.. might also be related to the issue in #16

OGNL issues with java 16 and 17

WARNING: An illegal reflective access operation has occurred
WARNING: Illegal reflective access by ognl.OgnlRuntime (file:XXXXXXXXXXXXXXXXXXXXXX/WEB-INF/lib/ognl-3.0.21.jar) to method java.util.HashMap$Node.getValue()
WARNING: Please consider reporting this to the maintainers of ognl.OgnlRuntime
WARNING: Use --illegal-access=warn to enable warnings of further illegal reflective access operations
WARNING: All illegal access operations will be denied in a future release

This warning message happens while I was running java 15. But since java 16 on wards struts-jquery-chart-tags stop working because they rely on ognl to assign dynamic data value. Access operation to to method java.util.HashMap$Node.getValue() is denied.

Is there any solution or idea?

I am running ognl 3.2.1.
Higher releases shows us the error below:
java.lang.NoClassDefFoundError: ognl/DefaultMemberAccess

OgnlOps#isEqual comparison of two enum thrown IllegalArgumentException

OgnlOps#isEqual comparison of two enum thrown IllegalArgumentException

Only in this case:
enum Op {
NE("<>"), // getClass() is "Op$1"
EQ("=") // getClass() is "Op$2"
}
Op.NE.getClass(). isAssignableFrom(Op.EQ.getClass()) // false

Now:

OgnlOps#isEqual(Object, Object)    // line 124 
is
result = (object1 != null) && (object2 != null)
                    && (object1.equals(object2) || (compareWithConversion(object1, object2) == 0));

OgnlOps#compareWithConversion(Object, Object)   // line 87 ~ 95
if ((t1 == NONNUMERIC) && (t2 == NONNUMERIC)) {
                // **FIXME: when enum is abstract**
                if ((v1 instanceof Comparable) && v1.getClass().isAssignableFrom(v2.getClass())) {
                    result = ((Comparable) v1).compareTo(v2);
                    break;
                } else {
                    throw new IllegalArgumentException("invalid comparison: " + v1.getClass().getName() + " and "
                            + v2.getClass().getName());
                }
            }

Temporary solution
"Op.NE.name() == 'NE'"

Tip:

before version is ok;
OgnlOps#isEqual(Object, Object) 
    result = compareWithConversion(object1, object2, true) == 0 || object1.equals(object2);
 OgnlOps#compareWithConversion(Object, Object, boolean)
   if(!equals) {   // **HERE because equals args is true **
         throw new IllegalArgumentException("invalid comparison: " + v1.getClass().getName() + " and " + v2.getClass().getName());
   }

Struts2 2.5 and struts2-jquery-plugin

I got a problem while using struts2 2.5.9 and struts2-jquery-plugin 4.0.3.
Actionmessages and actionErrors does not show up anymore. FieldError is displayed saying that value type for this fields (actionmessages and actionerrors) are not valid.

I read 2.5 api and nothing changed about it. addActionMessage() and addActionError() still receive a String as argument.
No exception is thrown. I do think the problem - if there is some - may be struts2-jquery-plugin 4.0.3. This jar contains jquery-2.2.4 which is a vulnerable version of jquery, and looking for something in google dev tools I got this:


  1. A page or script is accessing at least one of navigator.userAgent, navigator.appVersion, and navigator.platform. Starting in Chrome 101, the amount of information available in the User Agent string will be reduced.
    To fix this issue, replace the usage of navigator.userAgent, navigator.appVersion, and navigator.platform with feature detection, progressive enhancement, or migrate to navigator.userAgentData.
    Note that for performance reasons, only the first access to one of the properties is shown.

  1. Synchronous XMLHttpRequest on the main thread is deprecated because of its detrimental effects to the end user's experience. For more help, check https://xhr.spec.whatwg.org/ .

AFFECTED RESOURCES:
jquery-2.2.4.min.js:4


  1. One or more documents in this page is in Quirks Mode, which will render the affected document(s) with quirks incompatible with the current HTML and CSS specifications.
    Quirks Mode exists mostly due to historical reasons. If this is not intentional, you can add or modify the DOCTYPE to be <!DOCTYPE html> to render the page in No Quirks Mode.

AFFECTED RESOURCES:

Document in the DOM tree Mode URL
document Limited Quirks Mode http://localhost:8080/ProjXXXXX/registerCostumer.action?actionErrors=Client+already+registered.

What the server got is:
xxxxxxxxxx.action?actionErrors=No+results+for+this.+

The message passed to addActionError is ok. But it does not show, instead a fieldError.

Any idea about this? I tried to look for validations for the fields actionmessages and errormessages in the project and found nothing.
It is like some validation is going on and failed because I got the message from messages.properties for every invalid field Value:
xwork.default.invalid.fieldvalue = Invalid Value for this field {0}

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.