View Javadoc

1   package org.apache.velocity.tools;
2   
3   /*
4    * Licensed to the Apache Software Foundation (ASF) under one
5    * or more contributor license agreements.  See the NOTICE file
6    * distributed with this work for additional information
7    * regarding copyright ownership.  The ASF licenses this file
8    * to you under the Apache License, Version 2.0 (the
9    * "License"); you may not use this file except in compliance
10   * with the License.  You may obtain a copy of the License at
11   *
12   *   http://www.apache.org/licenses/LICENSE-2.0
13   *
14   * Unless required by applicable law or agreed to in writing,
15   * software distributed under the License is distributed on an
16   * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
17   * KIND, either express or implied.  See the License for the
18   * specific language governing permissions and limitations
19   * under the License.
20   */
21  
22  import java.util.ArrayList;
23  import java.util.HashMap;
24  import java.util.HashSet;
25  import java.util.List;
26  import java.util.Map;
27  import java.util.Set;
28  import org.apache.velocity.app.VelocityEngine;
29  import org.apache.velocity.context.Context;
30  
31  /**
32   * {@link Context} implementation that keeps a list of {@link Toolbox}es
33   * and returns them as requested, using its internal context Map as the
34   * dynamic properties passed to the requested tools when they are first
35   * created.
36   *
37   * @author Nathan Bubna
38   * @version $Id: ToolContext.java 511959 2007-02-26 19:24:39Z nbubna $
39   */
40  public class ToolContext implements Context
41  {
42      public static final String PATH_KEY = "requestPath";
43      public static final String CONTEXT_KEY = "velocityContext";
44      public static final String ENGINE_KEY = "velocityEngine";
45      public static final String LOCALE_KEY = "locale";
46      public static final String LOG_KEY = "log";
47      public static final String CATCH_EXCEPTIONS_KEY = "catchExceptions";
48  
49      private List<Toolbox> toolboxes = new ArrayList<Toolbox>();
50      // this is meant solely for tool setup,
51      // values in here are not part of the Context
52      private Map<String,Object> toolProps = new HashMap<String,Object>(12);
53      // this is only for values added during use of this context
54      private Map<String,Object> localContext = new HashMap<String,Object>();
55      private boolean userOverwrite = true;
56  
57      public ToolContext()
58      {
59          // add this as a common tool property
60          putToolProperty(CONTEXT_KEY, this);
61      }
62  
63      /**
64       * Creates an instance that automatically has the specified
65       * VelocityEngine and related tool properties set.
66       */
67      public ToolContext(VelocityEngine engine)
68      {
69          this();
70  
71          putVelocityEngine(engine);
72      }
73  
74      /**
75       * Creates an instance starting with the specified tool properties.
76       */
77      public ToolContext(Map<String,Object> toolProps)
78      {
79          this();
80  
81          if (toolProps != null)
82          {
83              this.toolProps.putAll(toolProps);
84          }
85      }
86  
87      /**
88       * Set whether or not tool references can be overwritten within a template.
89       * The default value is {@code true}.  Set this to false if you want to
90       * ensure that your tool references are never replaced within the course
91       * of a template.
92       */
93      public void setUserCanOverwriteTools(boolean overwrite)
94      {
95          this.userOverwrite = overwrite;
96      }
97  
98      /**
99       * Default is {@code true}.
100      * @see #setUserCanOverwriteTools
101      */
102     public boolean getUserCanOverwriteTools()
103     {
104         return this.userOverwrite;
105     }
106 
107     public void addToolbox(Toolbox toolbox)
108     {
109         toolboxes.add(toolbox);
110     }
111 
112     /**
113      * Returns a {@link Map} of all tools available to this
114      * context. NOTE: this is not a cheap operation as it will
115      * request and initialize an instance of every available tool.
116      */
117     public Map<String,Object> getToolbox()
118     {
119         Map<String,Object> aggregate = new HashMap<String,Object>();
120         Map<String,Object> toolProps = getToolProperties();
121         for (Toolbox toolbox : getToolboxes())
122         {
123             aggregate.putAll(toolbox.getAll(toolProps));
124         }
125         return aggregate;
126     }
127 
128     /**
129      * Gets a map of keys to classes for all available tools.
130      * This does not include any data nor any local context values.
131      */
132     public Map<String,Class> getToolClassMap()
133     {
134         Map<String,Class> toolClasses = new HashMap<String,Class>();
135         // go thru toolboxes backwards so final map matches
136         // what would be found in lookups
137         int n = getToolboxes().size();
138         for (int i = n - 1; i >= 0; i--)
139         {
140             Toolbox toolbox = getToolboxes().get(i);
141             toolClasses.putAll(toolbox.getToolClassMap());
142         }
143         return toolClasses;
144     }
145 
146     protected List<Toolbox> getToolboxes()
147     {
148         return this.toolboxes;
149     }
150 
151     protected Map<String,Object> getToolProperties()
152     {
153         return this.toolProps;
154     }
155 
156     /**
157      * Puts the specified VelocityEngine in the tool properties,
158      * as well as the Log for that engine.  Last, if the specified
159      * engine has a MethodExceptionEventHandler configured, then
160      * this will automatically set {@link #CATCH_EXCEPTIONS_KEY}
161      * to false in the tool properties.
162      */
163     public void putVelocityEngine(VelocityEngine engine)
164     {
165         // add the engine and log as common tool properties
166         putToolProperty(ENGINE_KEY, engine);
167         putToolProperty(LOG_KEY, engine.getLog());
168 
169         // tell interested tools not to catch exceptions whenever there's a
170         // method exception event handler configured for the engine
171         Object ehme =
172             engine.getProperty(VelocityEngine.EVENTHANDLER_METHODEXCEPTION);
173         if (ehme != null)
174         {
175             putToolProperty(CATCH_EXCEPTIONS_KEY, Boolean.FALSE);
176         }
177     }
178 
179     public Object putToolProperty(String key, Object value)
180     {
181         return toolProps.put(key, value);
182     }
183 
184     public void putToolProperties(Map<String,Object> props)
185     {
186         if (props != null)
187         {
188             for (Map.Entry<String,Object> prop : props.entrySet())
189             {
190                 putToolProperty(prop.getKey(), prop.getValue());
191             }
192         }
193     }
194 
195     public Object put(String key, Object value)
196     {
197         return localContext.put(key, value);
198     }
199 
200     public Object get(String key)
201     {
202         // for user overwriting, it's all a matter of which we check first
203         Object value = userOverwrite ? internalGet(key) : findTool(key);
204         if (value == null)
205         {
206             value = userOverwrite ? findTool(key) : internalGet(key);
207         }
208         return value;
209     }
210 
211     protected Object internalGet(String key)
212     {
213         return localContext.get(key);
214     }
215 
216     protected Object findTool(String key)
217     {
218         String path = (String)toolProps.get(PATH_KEY);
219         for (Toolbox toolbox : getToolboxes())
220         {
221             Object tool = toolbox.get(key, path, toolProps);
222             if (tool != null)
223             {
224                 return tool;
225             }
226         }
227         return null;
228     }
229         
230 
231     public Set<String> keySet()
232     {
233         Set<String> keys = new HashSet<String>();
234         for (Toolbox toolbox : getToolboxes())
235         {
236             keys.addAll(toolbox.getKeys());
237         }
238         keys.addAll(localContext.keySet());
239         return keys;
240     }
241 
242     public boolean containsKey(Object key)
243     {
244         return keySet().contains(key);
245     }
246 
247     public Object[] getKeys()
248     {
249         return keySet().toArray();
250     }
251 
252     public Object remove(Object key)
253     {
254         //tools and their props cannot be removed
255         return localContext.remove(key);
256     }
257 
258     public void putAll(Map context)
259     {
260         localContext.putAll(context);
261     }
262 }