Index: platform/store.ldap/trunk/src/java/org/datanucleus/store/ldap/query/QueryToLDAPFilterMapper.java
===================================================================
--- platform/store.ldap/trunk/src/java/org/datanucleus/store/ldap/query/QueryToLDAPFilterMapper.java	(revision 3864)
+++ platform/store.ldap/trunk/src/java/org/datanucleus/store/ldap/query/QueryToLDAPFilterMapper.java	(working copy)
@@ -35,19 +35,21 @@
 import org.datanucleus.exceptions.NucleusException;
 import org.datanucleus.metadata.AbstractClassMetaData;
 import org.datanucleus.metadata.AbstractMemberMetaData;
+import org.datanucleus.query.QueryUtils;
 import org.datanucleus.query.compiler.QueryCompilation;
 import org.datanucleus.query.evaluator.AbstractExpressionEvaluator;
 import org.datanucleus.query.expression.Expression;
 import org.datanucleus.query.expression.InvokeExpression;
 import org.datanucleus.query.expression.Literal;
+import org.datanucleus.query.expression.ParameterExpression;
 import org.datanucleus.query.expression.PrimaryExpression;
 import org.datanucleus.query.expression.Expression.Operator;
+import org.datanucleus.query.symbol.SymbolTable;
 import org.datanucleus.store.ldap.LDAPUtils;
 
 /**
- * Class which maps a compiled query to an LDAP filter. Utilizes the filter of the java query and adds 
- * them to the underlying LDAP filter. All other components are not handled here and instead processed 
- * by the in-memory evaluator.
+ * Class which maps a compiled query to an LDAP filter. Utilizes the filter of the java query and adds them to the
+ * underlying LDAP filter. All other components are not handled here and instead processed by the in-memory evaluator.
  */
 public class QueryToLDAPFilterMapper extends AbstractExpressionEvaluator
 {
@@ -57,6 +59,9 @@
     /** The class meta data */
     AbstractClassMetaData acmd;
 
+    /** Symbol table for the compiled query. */
+    SymbolTable symtbl;
+
     /** The stack */
     Stack stack = new Stack();
 
@@ -72,6 +77,7 @@
     public QueryToLDAPFilterMapper(QueryCompilation compilation, AbstractClassMetaData acmd)
     {
         this.filterExpr = compilation.getExprFilter();
+        this.symtbl = compilation.getSymbolTable();
         this.acmd = acmd;
     }
 
@@ -195,9 +201,28 @@
         ExprNode filter;
         if (left instanceof PrimaryExpression && right instanceof Literal)
         {
-            filter = getFilterForPrimaryLiteralValue(operator, (PrimaryExpression) left, ((Literal) right));
+            String param = QueryUtils.getStringValueForExpression((Literal) right, symtbl);
+            filter = getFilterForPrimaryLiteralValue(operator, (PrimaryExpression) left, param);
             stack.push(filter);
         }
+        else if (left instanceof PrimaryExpression && right instanceof String)
+        {
+            String param = (String) right;
+            filter = getFilterForPrimaryLiteralValue(operator, (PrimaryExpression) left, param);
+            stack.push(filter);
+        }
+        else if (left instanceof PrimaryExpression && right instanceof Character)
+        {
+            String param = ((Character) right).toString();
+            filter = getFilterForPrimaryLiteralValue(operator, (PrimaryExpression) left, param);
+            stack.push(filter);
+        }
+        else if (left instanceof PrimaryExpression && right instanceof Number)
+        {
+            String param = ((Number) right).toString();
+            filter = getFilterForPrimaryLiteralValue(operator, (PrimaryExpression) left, param);
+            stack.push(filter);
+        }
         else
         {
             // TODO: implement other cases
@@ -219,6 +244,13 @@
         return expr;
     }
 
+    protected Object processParameterExpression(ParameterExpression expr)
+    {
+        Object value = QueryUtils.getValueForParameterExpression(symtbl, expr);
+        stack.push(value);
+        return value;
+    }
+
     /*
      * Support for startsWith and endsWith
      */
@@ -234,19 +266,19 @@
             if (method.equals("startsWith"))
             {
                 // TODO Check if the field we invoke on is String-based
-                Literal param = (Literal) expr.getParameters().get(0);
-                String value = getValue(param);
+                Expression param = (Expression) expr.getParameters().get(0);
+                String value = QueryUtils.getStringValueForExpression(param, symtbl);
                 filter = new SubstringNode(attribute);
-                filter.setInitial(value);
+                filter.setInitial(getEscapedValue(value));
                 stack.push(filter);
             }
             else if (method.equals("endsWith"))
             {
                 // TODO Check if the field we invoke on is String-based
-                Literal param = (Literal) expr.getParameters().get(0);
-                String value = getValue(param);
+                Expression param = (Expression) expr.getParameters().get(0);
+                String value = QueryUtils.getStringValueForExpression(param, symtbl);
                 filter = new SubstringNode(attribute);
-                filter.setFinal(value);
+                filter.setFinal(getEscapedValue(value));
                 stack.push(filter);
             }
             else
@@ -263,31 +295,8 @@
         return filter;
     }
 
-    private String getValue(Literal param)
+    private String getEscapedValue(String value)
     {
-        String value = null;
-        if (param.getLiteral() instanceof String)
-        {
-            value = (String) param.getLiteral();
-        }
-        else if (param.getLiteral() instanceof Character)
-        {
-            value = ((Character) param.getLiteral()).toString();
-        }
-        else if (param.getLiteral() instanceof Number)
-        {
-            value = ((Number) param.getLiteral()).toString();
-        }
-        else if (param.getLiteral() == null)
-        {
-            value = null;
-        }
-        else
-        {
-            // TODO: handle other and binary values
-            throw new NucleusException("Case not handled yet: param=" + param.getLiteral());
-        }
-
         /*
          * From RFC 4515: The <valueencoding> rule ensures that the entire filter string is a valid UTF-8 string and
          * provides that the octets that represent the ASCII characters "*" (ASCII 0x2a), "(" (ASCII 0x28), ")" (ASCII
@@ -306,10 +315,10 @@
         return value;
     }
 
-    private ExprNode getFilterForPrimaryLiteralValue(Operator operator, PrimaryExpression expr, Literal param)
+    private ExprNode getFilterForPrimaryLiteralValue(Operator operator, PrimaryExpression expr, String param)
     {
         String attribute = getLdapAttributeType(expr);
-        Value value = new ClientStringValue(getValue(param));
+        Value value = new ClientStringValue(getEscapedValue(param));
 
         ExprNode filter = null;
         if (operator == Expression.OP_EQ)
Index: test/accessplatform/trunk/test.jdo.ldap/src/test/org/jpox/tests/JDOQLBasicTest.java
===================================================================
--- test/accessplatform/trunk/test.jdo.ldap/src/test/org/jpox/tests/JDOQLBasicTest.java	(revision 3864)
+++ test/accessplatform/trunk/test.jdo.ldap/src/test/org/jpox/tests/JDOQLBasicTest.java	(working copy)
@@ -234,6 +234,17 @@
             c = (Collection) q.execute();
             assertEquals(0, c.size());
             pm.currentTransaction().commit();
+
+            // same test with parameter expression
+            pm.currentTransaction().begin();
+            q = pm.newQuery(Person.class);
+            q.declareParameters("java.lang.String name");
+            q.setFilter("firstName == name");
+            c = (Collection) q.execute("Ana");
+            assertEquals(1, c.size());
+            it = c.iterator();
+            assertEquals("Ana", ((Person) it.next()).getFirstName());
+            pm.currentTransaction().commit();
         }
         finally
         {
@@ -270,6 +281,17 @@
             Iterator it2 = c2.iterator();
             assertEquals("Ana", ((Person) it2.next()).getFirstName());
             pm.currentTransaction().commit();
+
+            //same test with parameter expression
+            pm.currentTransaction().begin();
+            Query q3 = pm.newQuery(Person.class);
+            q3.declareParameters("java.lang.String p1, java.lang.String p2, int p3");
+            q3.setFilter("firstName == p1 && lastName == p2 && age == p3");
+            Collection c3 = (Collection) q3.execute("Ana", "Hick", Integer.valueOf(35) );
+            assertEquals(1, c3.size());
+            Iterator it3 = c3.iterator();
+            assertEquals("Ana", ((Person) it3.next()).getFirstName());
+            pm.currentTransaction().commit();
         }
         finally
         {
@@ -326,6 +348,18 @@
             assertEquals("Ana", ((Person) it.next()).getFirstName());
             assertEquals("Lami", ((Person) it.next()).getFirstName());
             pm.currentTransaction().commit();
+
+            // same test with parameter expression
+            pm.currentTransaction().begin();
+            q = pm.newQuery(Person.class);
+            q.declareParameters("java.lang.String p1");
+            q.setFilter("firstName != p1");
+            c = (Collection) q.execute("Bugs");
+            assertEquals(2, c.size());
+            it = c.iterator();
+            assertEquals("Ana", ((Person) it.next()).getFirstName());
+            assertEquals("Lami", ((Person) it.next()).getFirstName());
+            pm.currentTransaction().commit();
         }
         finally
         {
@@ -463,6 +497,17 @@
             Iterator it = c.iterator();
             assertEquals("Bugs", ((Person) it.next()).getFirstName());
             pm.currentTransaction().commit();
+
+            // same test with parameter expression
+            pm.currentTransaction().begin();
+            q = pm.newQuery(Person.class);
+            q.declareParameters("java.lang.String p1");
+            q.setFilter("firstName.startsWith(p1)");
+            c = (Collection) q.execute("B");
+            assertEquals(1, c.size());
+            it = c.iterator();
+            assertEquals("Bugs", ((Person) it.next()).getFirstName());
+            pm.currentTransaction().commit();
         }
         finally
         {
@@ -490,6 +535,17 @@
             Iterator it = c.iterator();
             assertEquals("Ana", ((Person) it.next()).getFirstName());
             pm.currentTransaction().commit();
+
+            // same test with parameter expression
+            pm.currentTransaction().begin();
+            q = pm.newQuery(Person.class);
+            q.declareParameters("java.lang.String p1");
+            q.setFilter("firstName.endsWith(p1)");
+            c = (Collection) q.execute("a");
+            assertEquals(1, c.size());
+            it = c.iterator();
+            assertEquals("Ana", ((Person) it.next()).getFirstName());
+            pm.currentTransaction().commit();
         }
         finally
         {

