You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@velocity.apache.org by nb...@apache.org on 2009/12/31 19:35:27 UTC

svn commit: r894920 - in /velocity/engine/trunk/src: java/org/apache/velocity/app/ java/org/apache/velocity/runtime/ java/org/apache/velocity/runtime/parser/ parser/ test/org/apache/velocity/test/issues/

Author: nbubna
Date: Thu Dec 31 18:35:25 2009
New Revision: 894920

URL: http://svn.apache.org/viewvc?rev=894920&view=rev
Log:
VELOCITY-742 add ability to remove or load directives at runtime (thanks to Jarkko Viinamaki)

Added:
    velocity/engine/trunk/src/test/org/apache/velocity/test/issues/Velocity742TestCase.java   (with props)
Modified:
    velocity/engine/trunk/src/java/org/apache/velocity/app/Velocity.java
    velocity/engine/trunk/src/java/org/apache/velocity/app/VelocityEngine.java
    velocity/engine/trunk/src/java/org/apache/velocity/runtime/RuntimeInstance.java
    velocity/engine/trunk/src/java/org/apache/velocity/runtime/RuntimeSingleton.java
    velocity/engine/trunk/src/java/org/apache/velocity/runtime/parser/Parser.java
    velocity/engine/trunk/src/parser/Parser.jjt

Modified: velocity/engine/trunk/src/java/org/apache/velocity/app/Velocity.java
URL: http://svn.apache.org/viewvc/velocity/engine/trunk/src/java/org/apache/velocity/app/Velocity.java?rev=894920&r1=894919&r2=894920&view=diff
==============================================================================
--- velocity/engine/trunk/src/java/org/apache/velocity/app/Velocity.java (original)
+++ velocity/engine/trunk/src/java/org/apache/velocity/app/Velocity.java Thu Dec 31 18:35:25 2009
@@ -491,4 +491,24 @@
     {
         return resourceExists(resourceName);
     }
+    
+    /**
+     * Remove a directive.
+     * 
+     * @param name name of the directive.
+     */
+    public void removeDirective(String name)
+    {
+        RuntimeSingleton.removeDirective(name);
+    }
+
+    /**
+     * Instantiates and loads the directive with some basic checks.
+     *
+     * @param directiveClass classname of directive to load
+     */
+    public void loadDirective(String directiveClass)
+    {
+        RuntimeSingleton.loadDirective(directiveClass);
+    }
 }

Modified: velocity/engine/trunk/src/java/org/apache/velocity/app/VelocityEngine.java
URL: http://svn.apache.org/viewvc/velocity/engine/trunk/src/java/org/apache/velocity/app/VelocityEngine.java?rev=894920&r1=894919&r2=894920&view=diff
==============================================================================
--- velocity/engine/trunk/src/java/org/apache/velocity/app/VelocityEngine.java (original)
+++ velocity/engine/trunk/src/java/org/apache/velocity/app/VelocityEngine.java Thu Dec 31 18:35:25 2009
@@ -516,4 +516,22 @@
         return ri.getApplicationAttribute(key);
      }
 
+     /**
+      * Remove a directive.
+      * @param name name of the directive.
+      */
+     public void removeDirective(String name)
+     {
+        ri.removeDirective(name);
+     }
+
+     /**
+      * Instantiates and loads the directive with some basic checks.
+      *
+      * @param directiveClass classname of directive to load
+      */
+     public void loadDirective(String directiveClass)
+     {
+        ri.loadDirective(directiveClass);
+     }
 }

Modified: velocity/engine/trunk/src/java/org/apache/velocity/runtime/RuntimeInstance.java
URL: http://svn.apache.org/viewvc/velocity/engine/trunk/src/java/org/apache/velocity/runtime/RuntimeInstance.java?rev=894920&r1=894919&r2=894920&view=diff
==============================================================================
--- velocity/engine/trunk/src/java/org/apache/velocity/runtime/RuntimeInstance.java (original)
+++ velocity/engine/trunk/src/java/org/apache/velocity/runtime/RuntimeInstance.java Thu Dec 31 18:35:25 2009
@@ -155,10 +155,16 @@
      * This is a hashtable of initialized directives.
      * The directives that populate this hashtable are
      * taken from the RUNTIME_DEFAULT_DIRECTIVES
-     * property file. This hashtable is passed
-     * to each parser that is created.
+     * property file. 
      */
-    private Hashtable runtimeDirectives;
+    private Map runtimeDirectives = new Hashtable();
+    /**
+     * Copy of the actual runtimeDirectives that is shared between
+     * parsers. Whenever directives are updated, the synchronized 
+     * runtimeDirectives is first updated and then an unsynchronized
+     * copy of it is passed to parsers.
+     */
+    private Map runtimeDirectivesShared;
 
     /**
      * Object that houses the configuration options for
@@ -882,12 +888,6 @@
      */
     private void initializeDirectives()
     {
-        /*
-         * Initialize the runtime directive table.
-         * This will be used for creating parsers.
-         */
-        runtimeDirectives = new Hashtable();
-
         Properties directiveProperties = new Properties();
 
         /*
@@ -973,9 +973,10 @@
      * Programatically add a directive.
      * @param directive
      */
-    public void addDirective(Directive directive) 
+    public synchronized void addDirective(Directive directive) 
     {
         runtimeDirectives.put(directive.getName(), directive);
+        updateSharedDirectivesMap();
     }
 
     /**
@@ -985,16 +986,31 @@
      */
     public Directive getDirective(String name) 
     {
-        return (Directive) runtimeDirectives.get(name);
+        return (Directive) runtimeDirectivesShared.get(name);
     }
 
     /**
      * Remove a directive.
      * @param name name of the directive.
      */
-    public void removeDirective(String name) 
+    public synchronized void removeDirective(String name) 
     {
         runtimeDirectives.remove(name);
+        updateSharedDirectivesMap();
+    }
+    
+    /**
+     * Makes an unsynchronized copy of the directives map
+     * that is used for Directive lookups by all parsers.
+     * 
+     * This follows Copy-on-Write pattern. The cost of creating
+     * a new map is acceptable since directives are typically
+     * set and modified only during Velocity setup phase.
+     */
+    private void updateSharedDirectivesMap()
+    {
+        Map tmp = new HashMap(runtimeDirectives);
+        runtimeDirectivesShared = tmp;
     }
 
     /**
@@ -1002,7 +1018,7 @@
      *
      *  @param directiveClass classname of directive to load
      */
-    private void loadDirective(String directiveClass)
+    public void loadDirective(String directiveClass)
     {
         try
         {
@@ -1114,7 +1130,6 @@
         requireInitialization();
 
         Parser parser = new Parser(this);
-        parser.setDirectives(runtimeDirectives);
         return parser;
     }
 

Modified: velocity/engine/trunk/src/java/org/apache/velocity/runtime/RuntimeSingleton.java
URL: http://svn.apache.org/viewvc/velocity/engine/trunk/src/java/org/apache/velocity/runtime/RuntimeSingleton.java?rev=894920&r1=894919&r2=894920&view=diff
==============================================================================
--- velocity/engine/trunk/src/java/org/apache/velocity/runtime/RuntimeSingleton.java (original)
+++ velocity/engine/trunk/src/java/org/apache/velocity/runtime/RuntimeSingleton.java Thu Dec 31 18:35:25 2009
@@ -648,4 +648,24 @@
     {
         return ri;
     }
+    
+    /**
+     * Remove a directive.
+     * 
+     * @param name name of the directive.
+     */
+    public static void removeDirective(String name)
+    {
+        ri.removeDirective(name);
+    }
+
+    /**
+     * Instantiates and loads the directive with some basic checks.
+     *
+     * @param directiveClass classname of directive to load
+     */
+    public static void loadDirective(String directiveClass)
+    {
+        ri.loadDirective(directiveClass);
+    }
 }

Modified: velocity/engine/trunk/src/java/org/apache/velocity/runtime/parser/Parser.java
URL: http://svn.apache.org/viewvc/velocity/engine/trunk/src/java/org/apache/velocity/runtime/parser/Parser.java?rev=894920&r1=894919&r2=894920&view=diff
==============================================================================
--- velocity/engine/trunk/src/java/org/apache/velocity/runtime/parser/Parser.java (original)
+++ velocity/engine/trunk/src/java/org/apache/velocity/runtime/parser/Parser.java Thu Dec 31 18:35:25 2009
@@ -29,11 +29,6 @@
 */
 public class Parser/*@bgen(jjtree)*/implements ParserTreeConstants, ParserConstants {/*@bgen(jjtree)*/
   protected JJTParserState jjtree = new JJTParserState();/**
-     * This Map contains a list of all of the dynamic directives.
-     */
-    private Map directives = new HashMap();
-
-    /**
      * Keep track of defined macros, used for escape processing
      */
     private Map macroNames = new HashMap();
@@ -153,28 +148,19 @@
     }
 
     /**
-     *  This method sets the directives Hashtable
-     */
-    public void setDirectives(Hashtable directives)
-    {
-        this.directives = new HashMap(directives);
-    }
-
-    /**
      *  This method gets a Directive from the directives Hashtable
      */
     public Directive getDirective(String directive)
     {
-        return (Directive) directives.get(directive);
+        return (Directive) rsvc.getDirective(directive);
     }
 
     /**
-     *  This method finds out of the directive exists in the directives
-     *  Hashtable.
+     *  This method finds out of the directive exists in the directives Map.
      */
     public boolean isDirective(String directive)
     {
-        return directives.containsKey(directive);
+        return rsvc.getDirective(directive) != null;
     }
 
 
@@ -733,7 +719,7 @@
             directiveName = t.image.substring(1);
         }
 
-        d = (Directive) directives.get(directiveName);
+        d = getDirective(directiveName);
 
         /*
          *  Velocimacro support : if the directive is macro directive
@@ -2754,6 +2740,142 @@
     finally { jj_save(11, xla); }
   }
 
+  private boolean jj_3_12() {
+    if (jj_scan_token(LBRACKET)) return true;
+    Token xsp;
+    xsp = jj_scanpos;
+    if (jj_scan_token(31)) jj_scanpos = xsp;
+    xsp = jj_scanpos;
+    if (jj_3R_36()) {
+    jj_scanpos = xsp;
+    if (jj_3R_37()) return true;
+    }
+    xsp = jj_scanpos;
+    if (jj_scan_token(31)) jj_scanpos = xsp;
+    if (jj_scan_token(DOUBLEDOT)) return true;
+    return false;
+  }
+
+  private boolean jj_3R_65() {
+    if (jj_scan_token(STRING_LITERAL)) return true;
+    return false;
+  }
+
+  private boolean jj_3_7() {
+    if (jj_scan_token(DOT)) return true;
+    Token xsp;
+    xsp = jj_scanpos;
+    if (jj_3_8()) {
+    jj_scanpos = xsp;
+    if (jj_3R_32()) return true;
+    }
+    while (true) {
+      xsp = jj_scanpos;
+      if (jj_3R_89()) { jj_scanpos = xsp; break; }
+    }
+    return false;
+  }
+
+  private boolean jj_3R_61() {
+    if (jj_3R_29()) return true;
+    Token xsp;
+    while (true) {
+      xsp = jj_scanpos;
+      if (jj_3R_97()) { jj_scanpos = xsp; break; }
+    }
+    return false;
+  }
+
+  private boolean jj_3R_39() {
+    if (jj_scan_token(LCURLY)) return true;
+    if (jj_scan_token(IDENTIFIER)) return true;
+    Token xsp;
+    while (true) {
+      xsp = jj_scanpos;
+      if (jj_3R_74()) { jj_scanpos = xsp; break; }
+    }
+    while (true) {
+      xsp = jj_scanpos;
+      if (jj_3_9()) { jj_scanpos = xsp; break; }
+    }
+    if (jj_scan_token(RCURLY)) return true;
+    return false;
+  }
+
+  private boolean jj_3R_40() {
+    if (jj_scan_token(INTEGER_LITERAL)) return true;
+    return false;
+  }
+
+  private boolean jj_3R_88() {
+    if (jj_scan_token(LPAREN)) return true;
+    return false;
+  }
+
+  private boolean jj_3R_87() {
+    if (jj_3R_71()) return true;
+    return false;
+  }
+
+  private boolean jj_3R_86() {
+    if (jj_3R_70()) return true;
+    return false;
+  }
+
+  private boolean jj_3R_38() {
+    if (jj_scan_token(IDENTIFIER)) return true;
+    Token xsp;
+    while (true) {
+      xsp = jj_scanpos;
+      if (jj_3R_63()) { jj_scanpos = xsp; break; }
+    }
+    while (true) {
+      xsp = jj_scanpos;
+      if (jj_3_7()) { jj_scanpos = xsp; break; }
+    }
+    return false;
+  }
+
+  private boolean jj_3R_85() {
+    if (jj_3R_69()) return true;
+    return false;
+  }
+
+  private boolean jj_3R_84() {
+    if (jj_3R_68()) return true;
+    return false;
+  }
+
+  private boolean jj_3R_83() {
+    if (jj_3R_67()) return true;
+    return false;
+  }
+
+  private boolean jj_3R_67() {
+    if (jj_scan_token(FLOATING_POINT_LITERAL)) return true;
+    return false;
+  }
+
+  private boolean jj_3R_24() {
+    Token xsp;
+    xsp = jj_scanpos;
+    if (jj_3R_38()) {
+    jj_scanpos = xsp;
+    if (jj_3R_39()) return true;
+    }
+    return false;
+  }
+
+  private boolean jj_3R_82() {
+    if (jj_3R_66()) return true;
+    return false;
+  }
+
+  private boolean jj_3R_81() {
+    if (jj_3R_40()) return true;
+    return false;
+  }
+
   private boolean jj_3R_80() {
     if (jj_3R_24()) return true;
     return false;
@@ -3093,11 +3215,6 @@
     return false;
   }
 
-  private boolean jj_3R_25() {
-    if (jj_3R_24()) return true;
-    return false;
-  }
-
   private boolean jj_3R_68() {
     if (jj_scan_token(LEFT_CURLEY)) return true;
     Token xsp;
@@ -3114,6 +3231,11 @@
     return false;
   }
 
+  private boolean jj_3R_25() {
+    if (jj_3R_24()) return true;
+    return false;
+  }
+
   private boolean jj_3_1() {
     if (jj_3R_24()) return true;
     return false;
@@ -3338,142 +3460,6 @@
     return false;
   }
 
-  private boolean jj_3_12() {
-    if (jj_scan_token(LBRACKET)) return true;
-    Token xsp;
-    xsp = jj_scanpos;
-    if (jj_scan_token(31)) jj_scanpos = xsp;
-    xsp = jj_scanpos;
-    if (jj_3R_36()) {
-    jj_scanpos = xsp;
-    if (jj_3R_37()) return true;
-    }
-    xsp = jj_scanpos;
-    if (jj_scan_token(31)) jj_scanpos = xsp;
-    if (jj_scan_token(DOUBLEDOT)) return true;
-    return false;
-  }
-
-  private boolean jj_3R_65() {
-    if (jj_scan_token(STRING_LITERAL)) return true;
-    return false;
-  }
-
-  private boolean jj_3_7() {
-    if (jj_scan_token(DOT)) return true;
-    Token xsp;
-    xsp = jj_scanpos;
-    if (jj_3_8()) {
-    jj_scanpos = xsp;
-    if (jj_3R_32()) return true;
-    }
-    while (true) {
-      xsp = jj_scanpos;
-      if (jj_3R_89()) { jj_scanpos = xsp; break; }
-    }
-    return false;
-  }
-
-  private boolean jj_3R_61() {
-    if (jj_3R_29()) return true;
-    Token xsp;
-    while (true) {
-      xsp = jj_scanpos;
-      if (jj_3R_97()) { jj_scanpos = xsp; break; }
-    }
-    return false;
-  }
-
-  private boolean jj_3R_39() {
-    if (jj_scan_token(LCURLY)) return true;
-    if (jj_scan_token(IDENTIFIER)) return true;
-    Token xsp;
-    while (true) {
-      xsp = jj_scanpos;
-      if (jj_3R_74()) { jj_scanpos = xsp; break; }
-    }
-    while (true) {
-      xsp = jj_scanpos;
-      if (jj_3_9()) { jj_scanpos = xsp; break; }
-    }
-    if (jj_scan_token(RCURLY)) return true;
-    return false;
-  }
-
-  private boolean jj_3R_40() {
-    if (jj_scan_token(INTEGER_LITERAL)) return true;
-    return false;
-  }
-
-  private boolean jj_3R_88() {
-    if (jj_scan_token(LPAREN)) return true;
-    return false;
-  }
-
-  private boolean jj_3R_87() {
-    if (jj_3R_71()) return true;
-    return false;
-  }
-
-  private boolean jj_3R_86() {
-    if (jj_3R_70()) return true;
-    return false;
-  }
-
-  private boolean jj_3R_38() {
-    if (jj_scan_token(IDENTIFIER)) return true;
-    Token xsp;
-    while (true) {
-      xsp = jj_scanpos;
-      if (jj_3R_63()) { jj_scanpos = xsp; break; }
-    }
-    while (true) {
-      xsp = jj_scanpos;
-      if (jj_3_7()) { jj_scanpos = xsp; break; }
-    }
-    return false;
-  }
-
-  private boolean jj_3R_85() {
-    if (jj_3R_69()) return true;
-    return false;
-  }
-
-  private boolean jj_3R_84() {
-    if (jj_3R_68()) return true;
-    return false;
-  }
-
-  private boolean jj_3R_83() {
-    if (jj_3R_67()) return true;
-    return false;
-  }
-
-  private boolean jj_3R_67() {
-    if (jj_scan_token(FLOATING_POINT_LITERAL)) return true;
-    return false;
-  }
-
-  private boolean jj_3R_24() {
-    Token xsp;
-    xsp = jj_scanpos;
-    if (jj_3R_38()) {
-    jj_scanpos = xsp;
-    if (jj_3R_39()) return true;
-    }
-    return false;
-  }
-
-  private boolean jj_3R_82() {
-    if (jj_3R_66()) return true;
-    return false;
-  }
-
-  private boolean jj_3R_81() {
-    if (jj_3R_40()) return true;
-    return false;
-  }
-
   /** Generated Token Manager. */
   public ParserTokenManager token_source;
   /** Current token. */

Modified: velocity/engine/trunk/src/parser/Parser.jjt
URL: http://svn.apache.org/viewvc/velocity/engine/trunk/src/parser/Parser.jjt?rev=894920&r1=894919&r2=894920&view=diff
==============================================================================
--- velocity/engine/trunk/src/parser/Parser.jjt (original)
+++ velocity/engine/trunk/src/parser/Parser.jjt Thu Dec 31 18:35:25 2009
@@ -106,11 +106,6 @@
 public class Parser
 {
     /**
-     * This Map contains a list of all of the dynamic directives.
-     */
-    private Map directives = new HashMap();
-    
-    /**
      * Keep track of defined macros, used for escape processing
      */
     private Map macroNames = new HashMap();
@@ -230,28 +225,19 @@
     }
 
     /**
-     *  This method sets the directives Hashtable
-     */
-    public void setDirectives(Hashtable directives)
-    {
-        this.directives = new HashMap(directives);
-    }
-
-    /**
      *  This method gets a Directive from the directives Hashtable
      */
     public Directive getDirective(String directive)
     {
-        return (Directive) directives.get(directive);
+        return (Directive) rsvc.getDirective(directive);
     }
 
     /**
-     *  This method finds out of the directive exists in the directives
-     *  Hashtable.
+     *  This method finds out of the directive exists in the directives Map.
      */
     public boolean isDirective(String directive)
     {
-        return directives.containsKey(directive);
+        return rsvc.getDirective(directive) != null;
     }
 
 
@@ -1449,7 +1435,7 @@
             directiveName = t.image.substring(1);
         }
 
-        d = (Directive) directives.get(directiveName);
+        d = getDirective(directiveName);
 
         /*
          *  Velocimacro support : if the directive is macro directive

Added: velocity/engine/trunk/src/test/org/apache/velocity/test/issues/Velocity742TestCase.java
URL: http://svn.apache.org/viewvc/velocity/engine/trunk/src/test/org/apache/velocity/test/issues/Velocity742TestCase.java?rev=894920&view=auto
==============================================================================
--- velocity/engine/trunk/src/test/org/apache/velocity/test/issues/Velocity742TestCase.java (added)
+++ velocity/engine/trunk/src/test/org/apache/velocity/test/issues/Velocity742TestCase.java Thu Dec 31 18:35:25 2009
@@ -0,0 +1,56 @@
+package org.apache.velocity.test.issues;
+
+/*
+ * 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.    
+ */
+
+import org.apache.velocity.app.VelocityEngine;
+import org.apache.velocity.test.BaseTestCase;
+import org.apache.velocity.exception.ResourceNotFoundException;
+
+/**
+ * This class tests VELOCITY-742.
+ */
+public class Velocity742TestCase extends BaseTestCase
+{
+    public Velocity742TestCase(String name)
+    {
+        super(name);
+    }
+    
+    protected void setUpEngine(VelocityEngine engine)
+    {
+        // we need to call init here because otherwise it is not called until assertEvalEquals
+        // and therefore the removeDirective call is ignored.
+        engine.init();
+    }
+
+    public void testDisableAndRestoreDirective()
+    {
+        String s = "#include('doesnotexist.vm') directive is disabled";
+        
+        // first remove  the #include directive and see that is treated as normal text
+        engine.removeDirective("include");
+        assertEvalEquals(s, s);
+        
+        // now reload the directive and see that the include directive works again and
+        // Velocity throws ResourceNotFoundException because it can't find the template
+        engine.loadDirective("org.apache.velocity.runtime.directive.Include");
+        assertEvalException(s, ResourceNotFoundException.class);
+    }
+}

Propchange: velocity/engine/trunk/src/test/org/apache/velocity/test/issues/Velocity742TestCase.java
------------------------------------------------------------------------------
    svn:eol-style = native

Propchange: velocity/engine/trunk/src/test/org/apache/velocity/test/issues/Velocity742TestCase.java
------------------------------------------------------------------------------
    svn:keywords = Revision

Propchange: velocity/engine/trunk/src/test/org/apache/velocity/test/issues/Velocity742TestCase.java
------------------------------------------------------------------------------
    svn:mime-type = text/plain