You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@openjpa.apache.org by pp...@apache.org on 2009/09/11 05:22:03 UTC

svn commit: r813658 - in /openjpa/trunk: openjpa-persistence-jdbc/src/test/java/org/apache/openjpa/persistence/criteria/ openjpa-persistence/src/main/java/org/apache/openjpa/persistence/criteria/ openjpa-persistence/src/main/java/org/apache/openjpa/per...

Author: ppoddar
Date: Fri Sep 11 03:22:00 2009
New Revision: 813658

URL: http://svn.apache.org/viewvc?rev=813658&view=rev
Log:
OPENJPA-1288: stop re-alias(). Added new utility to check validity of names for JPA reserved words and special symbols. 

Added:
    openjpa/trunk/openjpa-persistence/src/main/java/org/apache/openjpa/persistence/util/ReservedWords.java   (with props)
Modified:
    openjpa/trunk/openjpa-persistence-jdbc/src/test/java/org/apache/openjpa/persistence/criteria/TestTypesafeCriteria.java
    openjpa/trunk/openjpa-persistence/src/main/java/org/apache/openjpa/persistence/criteria/OpenJPACriteriaBuilder.java
    openjpa/trunk/openjpa-persistence/src/main/java/org/apache/openjpa/persistence/criteria/ParameterExpressionImpl.java
    openjpa/trunk/openjpa-persistence/src/main/java/org/apache/openjpa/persistence/criteria/SelectionImpl.java

Modified: openjpa/trunk/openjpa-persistence-jdbc/src/test/java/org/apache/openjpa/persistence/criteria/TestTypesafeCriteria.java
URL: http://svn.apache.org/viewvc/openjpa/trunk/openjpa-persistence-jdbc/src/test/java/org/apache/openjpa/persistence/criteria/TestTypesafeCriteria.java?rev=813658&r1=813657&r2=813658&view=diff
==============================================================================
--- openjpa/trunk/openjpa-persistence-jdbc/src/test/java/org/apache/openjpa/persistence/criteria/TestTypesafeCriteria.java (original)
+++ openjpa/trunk/openjpa-persistence-jdbc/src/test/java/org/apache/openjpa/persistence/criteria/TestTypesafeCriteria.java Fri Sep 11 03:22:00 2009
@@ -1261,7 +1261,7 @@
         }
     }
     
-    public void testAlias() {
+    public void testAliasInOrderByClause() {
         String jpql = "SELECT AVG(a.balance) AS x FROM Account a ORDER BY x";
 
         OpenJPACriteriaQuery<Double> c = cb.createQuery(Double.class);
@@ -1275,4 +1275,63 @@
         assertEquivalence(c, jpql);
         assertEquals(jpql, c.toCQL());
     }
+    
+    public void testRealiasNotAllowed() {
+        OpenJPACriteriaQuery<Double> c = cb.createQuery(Double.class);
+        Root<Account> account = c.from(Account.class);
+        Selection<Double> term = cb.avg(account.get(Account_.balance));
+        term.alias("firsttime");
+        try {
+            term.alias("secondtime");
+            fail("Expected to fail on re-aliasing");
+        } catch (IllegalStateException e) {
+            // good
+        }
+    }
+    
+    public void testInvalidAliasNotAllowed() {
+        OpenJPACriteriaQuery<Double> c = cb.createQuery(Double.class);
+        Root<Account> account = c.from(Account.class);
+        Selection<Double> term = cb.avg(account.get(Account_.balance));
+        try {
+            term.alias("from");
+            fail("Expected to fail on reserved word as alias");
+        } catch (IllegalArgumentException e) {
+            // good
+            assertNull(term.getAlias());
+        }
+        try {
+            term.alias(" with a space");
+            fail("Expected to fail on invalid alias");
+        } catch (IllegalArgumentException e) {
+            // good
+            assertNull(term.getAlias());
+        }
+        try {
+            term.alias(" with?known_symbol");
+            fail("Expected to fail on invalid alias");
+        } catch (IllegalArgumentException e) {
+            // good
+            assertNull(term.getAlias());
+        }
+    }
+    
+    public void testInvalidParameterName() {
+        try {
+            cb.parameter(Integer.class, "from");
+            fail("Expected to fail on reserved word as alias");
+        } catch (IllegalArgumentException e) {
+        }
+        try {
+            cb.parameter(Integer.class, ":name");
+            fail("Expected to fail on invalid alias");
+        } catch (IllegalArgumentException e) {
+        }
+        try {
+            cb.parameter(Integer.class, "?3");
+            fail("Expected to fail on invalid alias");
+        } catch (IllegalArgumentException e) {
+        }
+    }
+
 }

Modified: openjpa/trunk/openjpa-persistence/src/main/java/org/apache/openjpa/persistence/criteria/OpenJPACriteriaBuilder.java
URL: http://svn.apache.org/viewvc/openjpa/trunk/openjpa-persistence/src/main/java/org/apache/openjpa/persistence/criteria/OpenJPACriteriaBuilder.java?rev=813658&r1=813657&r2=813658&view=diff
==============================================================================
--- openjpa/trunk/openjpa-persistence/src/main/java/org/apache/openjpa/persistence/criteria/OpenJPACriteriaBuilder.java (original)
+++ openjpa/trunk/openjpa-persistence/src/main/java/org/apache/openjpa/persistence/criteria/OpenJPACriteriaBuilder.java Fri Sep 11 03:22:00 2009
@@ -4,6 +4,7 @@
 import javax.persistence.criteria.Predicate;
 import javax.persistence.criteria.QueryBuilder;
 import javax.persistence.metamodel.Attribute;
+import javax.persistence.metamodel.Metamodel;
 
 /**
  * OpenJPA-specific extension to JPA 2.0 Criteria Query Builder API.
@@ -57,5 +58,9 @@
      * Create a mutable style to apply on query-by-example.
      */
     public ComparisonStyle qbeStyle();
-
+    
+    /**
+     * Gets the metamodel for the managed, persistent domain entities.
+     */
+    public Metamodel getMetamodel();
 }

Modified: openjpa/trunk/openjpa-persistence/src/main/java/org/apache/openjpa/persistence/criteria/ParameterExpressionImpl.java
URL: http://svn.apache.org/viewvc/openjpa/trunk/openjpa-persistence/src/main/java/org/apache/openjpa/persistence/criteria/ParameterExpressionImpl.java?rev=813658&r1=813657&r2=813658&view=diff
==============================================================================
--- openjpa/trunk/openjpa-persistence/src/main/java/org/apache/openjpa/persistence/criteria/ParameterExpressionImpl.java (original)
+++ openjpa/trunk/openjpa-persistence/src/main/java/org/apache/openjpa/persistence/criteria/ParameterExpressionImpl.java Fri Sep 11 03:22:00 2009
@@ -52,6 +52,8 @@
 	 */
     public ParameterExpressionImpl(Class<T> cls, String name) {
         super(cls);
+        if (name != null)
+            assertValidName(name);
         _name = name;
     }
 

Modified: openjpa/trunk/openjpa-persistence/src/main/java/org/apache/openjpa/persistence/criteria/SelectionImpl.java
URL: http://svn.apache.org/viewvc/openjpa/trunk/openjpa-persistence/src/main/java/org/apache/openjpa/persistence/criteria/SelectionImpl.java?rev=813658&r1=813657&r2=813658&view=diff
==============================================================================
--- openjpa/trunk/openjpa-persistence/src/main/java/org/apache/openjpa/persistence/criteria/SelectionImpl.java (original)
+++ openjpa/trunk/openjpa-persistence/src/main/java/org/apache/openjpa/persistence/criteria/SelectionImpl.java Fri Sep 11 03:22:00 2009
@@ -23,6 +23,8 @@
 import javax.persistence.criteria.Expression;
 import javax.persistence.criteria.Selection;
 
+import org.apache.openjpa.persistence.util.ReservedWords;
+
 /**
  * An item selected in the projection clause of Criteria query.
  * Base implementation for all concrete expressions.
@@ -34,7 +36,7 @@
 public abstract class SelectionImpl<X> implements Selection<X>, CriteriaExpression {
     private final Class<X> _cls;
     private String _alias;
-    private Boolean _autoAliased;
+    private Boolean _autoAliased; 
     
     /**
      * Construct with the immutable type represented by this selection term.
@@ -59,8 +61,13 @@
     
     /**
      * Sets the alias on this selection term.
+     * Alias can only be set once.
      */
     public Selection<X> alias(String alias) {
+        assertValidName(alias);
+        if (isAliased())
+            throw new IllegalStateException(this + " has been aliased to [" + _alias 
+                    + ". Can not alias again to " + alias);
         _alias = alias;
         _autoAliased = false;
         return this;
@@ -71,8 +78,8 @@
      * by calling {@linkplain #alias(String)}.
      */
     void setAutoAlias(String alias) {
-        if (Boolean.FALSE.equals(_autoAliased))
-            throw new IllegalStateException(this + " has been aliased. Can not set alias automatically");
+        if (isAliased())
+            throw new IllegalStateException(this + " has been aliased. Can not set alias internally");
         _alias = alias;
         _autoAliased = true;
     }
@@ -83,6 +90,15 @@
     boolean isAutoAliased() {
         return _autoAliased == null ? true : _autoAliased.booleanValue();
     }  
+    
+    /**
+     * Affirms if this expression has been assigned an alias by {@linkplain #alias(String)} method.
+     * An alias can be assigned also by internal implementation.
+     * @see #isAutoAliased() 
+     */
+    boolean isAliased() {
+        return Boolean.FALSE.equals(_autoAliased);
+    }  
 
     /**
      * Throws IllegalStateException because a selection term, by default, consists of single value.
@@ -98,6 +114,16 @@
         return false;
     }
     
+    void assertValidName(String name) {
+        if (name == null || name.trim().length() == 0)
+            throw new IllegalArgumentException("empty name is invalid");
+        if (ReservedWords.isKeyword(name)) 
+            throw new IllegalArgumentException("reserved word " + name + " is not valid");
+        Character ch = ReservedWords.hasSpecialCharacter(name);
+        if (ch != null) 
+            throw new IllegalArgumentException(name + " contains reserved symbol " + ch);
+    }
+    
     //  ------------------------------------------------------------------------------------
     //  Contract for CriteriaExpression implemented mostly as a no-op for easier derivation.
     //  ------------------------------------------------------------------------------------

Added: openjpa/trunk/openjpa-persistence/src/main/java/org/apache/openjpa/persistence/util/ReservedWords.java
URL: http://svn.apache.org/viewvc/openjpa/trunk/openjpa-persistence/src/main/java/org/apache/openjpa/persistence/util/ReservedWords.java?rev=813658&view=auto
==============================================================================
--- openjpa/trunk/openjpa-persistence/src/main/java/org/apache/openjpa/persistence/util/ReservedWords.java (added)
+++ openjpa/trunk/openjpa-persistence/src/main/java/org/apache/openjpa/persistence/util/ReservedWords.java Fri Sep 11 03:22:00 2009
@@ -0,0 +1,85 @@
+package org.apache.openjpa.persistence.util;
+
+import java.util.Arrays;
+import java.util.HashSet;
+import java.util.Set;
+
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.    
+ */
+
+/**
+ * Utility to test validity of identifier or parameter name.
+ * 
+ * @author Pinaki Poddar
+ * @since 2.0.0
+ *
+ */
+public class ReservedWords {
+    public static final Set<String> KEYWORDS = new HashSet<String>();
+    static {
+        KEYWORDS.addAll(Arrays.asList(
+            "ABS", "ALL", "AND", "ANY", "AS", "ASC", "AVG", 
+            "BETWEEN", "BIT_LENGTH", "BOTH", "BY", 
+            "CASE", "CHAR_LENGTH", "CHARACTER_LENGTH", "CLASS", "COALESCE", "CONCAT", "COUNT", 
+            "CURRENT_DATE", "CURRENT_TIME", "CURRENT_TIMESTAMP",
+            "DELETE", "DESC", "DISTINCT", 
+            "ELSE", "EMPTY", "END", "ENTRY", "ESCAPE", "EXISTS", 
+            "FALSE", "FETCH", "FROM", 
+            "GROUP", 
+            "HAVING", 
+            "IN", "INDEX", "INNER", "IS", 
+            "JOIN", 
+            "KEY", 
+            "LEADING", "LEFT", "LENGTH", "LIKE", "LOCATE", "LOWER", 
+            "MAX", "MEMBER", "MIN", "MOD", 
+            "NEW", "NOT", "NULL", "NULLIF", 
+            "OBJECT", "OF", "OR", "ORDER", "OUTER", 
+            "POSITION", 
+            "SELECT", "SET", "SIZE", "SOME", "SQRT", "SUBSTRING", "SUM", 
+            "THEN", "TRAILING", "TRIM", "TRUE", "TYPE", 
+            "UNKNOWN[50]", "UPDATE", "UPPER", 
+            "VALUE", 
+            "WHEN", "WHERE"));
+    };
+    
+    /**
+     * Affirms if the given string matches any of the JPA reserved words in a case-insensitive manner.
+     */
+    public static boolean isKeyword(String name) {
+        return name != null && KEYWORDS.contains(name.toUpperCase());
+    }
+    
+    /**
+     * Returns the special character contained in the given name if any.
+     * 
+     * @return null if no character in the given name is a special character.
+     */
+    public static Character hasSpecialCharacter(String name) {
+        if (name == null)
+            return null;
+        char[] chars = name.toCharArray();
+        if (!Character.isJavaIdentifierStart(chars[0]))
+                return chars[0];
+        for (int i = 1; i < chars.length; i++) {
+            if (!Character.isJavaIdentifierPart(chars[i]))
+                    return chars[i];
+        }
+        return null;
+    }
+}

Propchange: openjpa/trunk/openjpa-persistence/src/main/java/org/apache/openjpa/persistence/util/ReservedWords.java
------------------------------------------------------------------------------
    svn:eol-style = native