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