View Javadoc

1   package org.apache.velocity.context;
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.HashSet;
23  import java.util.Set;
24  
25  import org.apache.velocity.VelocityContext;
26  import org.apache.velocity.app.event.EventCartridge;
27  import org.apache.velocity.runtime.RuntimeConstants;
28  import org.apache.velocity.runtime.RuntimeServices;
29  import org.apache.velocity.runtime.resource.Resource;
30  import org.apache.velocity.util.ClassUtils;
31  import org.apache.velocity.util.introspection.IntrospectionCacheData;
32  
33  /**
34   *  This is a special, internal-use-only context implementation to be
35   *  used for the #evaluate directive.
36   *
37   *  We use this context to chain the existing context, preventing any changes
38   *  from impacting the parent context.  By separating this context into a 
39   *  separate class it also allows for the future possibility of changing
40   *  the context behavior for the #evaluate directive.
41   *  
42   *  Note that the context used to store values local to #evaluate()
43   *  is user defined but defaults to {@link VelocityContext}.
44   *
45   *  @author <a href="mailto:wglass@forio.com">Will Glass-Husain</a>
46   *  @version $Id: EvaluateContext.java 522413 2007-03-26 04:34:15Z wglass $
47   */
48  public class EvaluateContext implements InternalContextAdapter
49  {
50      /** container for any local items */
51      Context localContext;
52  
53      /** the base context store.  This is the 'global' context */
54      InternalContextAdapter innerContext = null;
55  
56      boolean allowRendering = true;
57      
58       /**
59       *  CTOR, wraps an ICA
60       * @param inner context for parent template
61       * @param rsvc 
62       */
63      public EvaluateContext( InternalContextAdapter  inner, RuntimeServices rsvc )
64      {
65          innerContext = inner.getBaseContext();
66          initContext(rsvc);
67      }
68  
69      /**
70       * Initialize the context based on user-configured class 
71       * @param rsvc
72       */
73      private void initContext( RuntimeServices rsvc )
74      {
75          String contextClass = rsvc.getString(RuntimeConstants.EVALUATE_CONTEXT_CLASS);
76  
77          if (contextClass != null && contextClass.length() > 0)
78          {
79              Object o = null;
80  
81              try
82              {
83                  o = ClassUtils.getNewInstance( contextClass );
84              }
85              catch (ClassNotFoundException cnfe)
86              {
87                  String err = "The specified class for #evaluate() context (" + contextClass
88                  + ") does not exist or is not accessible to the current classloader.";
89                  rsvc.getLog().error(err);
90                  throw new RuntimeException(err,cnfe);
91              }
92              catch (Exception e)
93              {
94                  String err = "The specified class for #evaluate() context (" + contextClass
95                  + ") can not be loaded.";
96                  rsvc.getLog().error(err,e);
97                  throw new RuntimeException(err);
98              }
99  
100             if (!(o instanceof Context))
101             {                
102                 String err = "The specified class for #evaluate() context (" + contextClass
103                 + ") does not implement " + Context.class.getName() + ".";
104                 rsvc.getLog().error(err);
105                 throw new RuntimeException(err);
106             }
107             
108             localContext = (Context) o; 
109 
110         }
111         else
112         {
113             String err = "No class specified for #evaluate() context.";
114             rsvc.getLog().error(err);
115             throw new RuntimeException(err);
116         }
117         
118     }
119     
120     /**
121      *  Return the inner / user context.
122      * @return The inner / user context.
123      */
124     public Context getInternalUserContext()
125     {
126         return innerContext.getInternalUserContext();
127     }
128 
129     /**
130      * @see org.apache.velocity.context.InternalWrapperContext#getBaseContext()
131      */
132     public InternalContextAdapter getBaseContext()
133     {
134         return innerContext.getBaseContext();
135     }
136 
137     /**
138      *  Put method also stores values in local scope 
139      *
140      *  @param key name of item to set
141      *  @param value object to set to key
142      *  @return old stored object
143      */
144     public Object put(String key, Object value)
145     {
146         /*
147          *  just put in the local context
148          */
149         return localContext.put(key, value);
150 
151     }
152 
153     /**
154      *  Retrieves from local or global context.
155      *
156      *  @param key name of item to get
157      *  @return  stored object or null
158      */
159     public Object get( String key )
160     {
161         /*
162          *  always try the local context then innerContext
163          */
164 
165         Object o = localContext.get( key );
166 
167         if ( o == null)
168         {
169             o = innerContext.get( key );
170         }
171 
172         return o;
173     }
174 
175     /**
176      * @see org.apache.velocity.context.Context#containsKey(java.lang.Object)
177      */
178     public boolean containsKey(Object key)
179     {
180         return localContext.containsKey(key) || innerContext.containsKey(key);
181     }
182 
183     /**
184      * @see org.apache.velocity.context.Context#getKeys()
185      */
186     public Object[] getKeys()
187     {
188         Set keys = new HashSet();
189         Object[] localKeys = localContext.getKeys();
190         for (int i=0; i < localKeys.length; i++)
191         {
192             keys.add(localKeys[i]);
193         }
194         
195         Object[] innerKeys = innerContext.getKeys();
196         for (int i=0; i < innerKeys.length; i++)
197         {
198             keys.add(innerKeys[i]);
199         }
200         return keys.toArray();
201     }
202 
203     /**
204      * @see org.apache.velocity.context.Context#remove(java.lang.Object)
205      */
206     public Object remove(Object key)
207     {
208         return localContext.remove( key );
209     }
210 
211     /**
212      * @see org.apache.velocity.context.InternalHousekeepingContext#pushCurrentTemplateName(java.lang.String)
213      */
214     public void pushCurrentTemplateName( String s )
215     {
216         innerContext.pushCurrentTemplateName( s );
217     }
218 
219     /**
220      * @see org.apache.velocity.context.InternalHousekeepingContext#popCurrentTemplateName()
221      */
222     public void popCurrentTemplateName()
223     {
224         innerContext.popCurrentTemplateName();
225     }
226 
227     /**
228      * @see org.apache.velocity.context.InternalHousekeepingContext#getCurrentTemplateName()
229      */
230     public String getCurrentTemplateName()
231     {
232         return innerContext.getCurrentTemplateName();
233     }
234 
235     /**
236      * @see org.apache.velocity.context.InternalHousekeepingContext#getTemplateNameStack()
237      */
238     public Object[] getTemplateNameStack()
239     {
240         return innerContext.getTemplateNameStack();
241     }
242 
243     /**
244      * @see org.apache.velocity.context.InternalHousekeepingContext#icacheGet(java.lang.Object)
245      */
246     public IntrospectionCacheData icacheGet( Object key )
247     {
248         return innerContext.icacheGet( key );
249     }
250 
251     /**
252      * Allows callers to explicitly put objects in the local context.
253      * Objects added to the context through this method always end up
254      * in the top-level context of possible wrapped contexts.
255      *
256      *  @param key name of item to set.
257      *  @param value object to set to key.
258      *  @return old stored object
259      */
260     public Object localPut(final String key, final Object value)
261     {
262         return localContext.put(key, value);
263     }
264 
265     /**
266      * @see org.apache.velocity.context.InternalHousekeepingContext#icachePut(java.lang.Object, org.apache.velocity.util.introspection.IntrospectionCacheData)
267      */
268     public void icachePut( Object key, IntrospectionCacheData o )
269     {
270         innerContext.icachePut( key, o );
271     }
272 
273     /**
274      * @see org.apache.velocity.context.InternalHousekeepingContext#getAllowRendering()
275      */
276     public boolean getAllowRendering()
277     {
278        return allowRendering && innerContext.getAllowRendering();
279     }
280 
281     /**
282      * @see org.apache.velocity.context.InternalHousekeepingContext#setAllowRendering(boolean)
283      */
284     public void setAllowRendering(boolean v)
285     {
286         allowRendering = false;
287     }
288 
289     /**
290      * @see org.apache.velocity.context.InternalEventContext#attachEventCartridge(org.apache.velocity.app.event.EventCartridge)
291      */
292     public EventCartridge attachEventCartridge( EventCartridge ec )
293     {
294         EventCartridge cartridge = innerContext.attachEventCartridge( ec );
295         return cartridge;
296     }
297 
298     /**
299      * @see org.apache.velocity.context.InternalEventContext#getEventCartridge()
300      */
301     public EventCartridge getEventCartridge()
302     {
303         return innerContext.getEventCartridge();
304     }
305 
306 
307     /**
308      * @see org.apache.velocity.context.InternalHousekeepingContext#setCurrentResource(org.apache.velocity.runtime.resource.Resource)
309      */
310     public void setCurrentResource( Resource r )
311     {
312         innerContext.setCurrentResource( r );
313     }
314 
315     /**
316      * @see org.apache.velocity.context.InternalHousekeepingContext#getCurrentResource()
317      */
318     public Resource getCurrentResource()
319     {
320         return innerContext.getCurrentResource();
321     }
322 }
323 
324 
325