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.HashMap;
23  
24  import org.apache.velocity.runtime.RuntimeServices;
25  import org.apache.velocity.runtime.RuntimeConstants;
26  import org.apache.velocity.runtime.directive.VMProxyArg;
27  import org.apache.velocity.util.introspection.IntrospectionCacheData;
28  import org.apache.velocity.runtime.resource.Resource;
29  import org.apache.velocity.app.event.EventCartridge;
30  import org.apache.velocity.exception.MethodInvocationException;
31  
32  /**
33   *  This is a special, internal-use-only context implementation to be
34   *  used for the new Velocimacro implementation.
35   *
36   *  The main distinguishing feature is the management of the VMProxyArg objects
37   *  in the put() and get() methods.
38   *
39   *  Further, this context also supports the 'VM local context' mode, where
40   *  any put() of references that aren't args to the VM are considered
41   *  local to the vm, protecting the global context.
42   *
43   *  @author <a href="mailto:geirm@optonline.net">Geir Magnusson Jr.</a>
44   *  @version $Id: VMContext.java 471908 2006-11-06 22:39:28Z henning $
45   */
46  public class VMContext implements InternalContextAdapter
47  {
48      /** container for our VMProxy Objects */
49      HashMap vmproxyhash = new HashMap();
50  
51      /** container for any local or constant VMProxy items */
52      HashMap localcontext = new HashMap();
53  
54      /** the base context store.  This is the 'global' context */
55      InternalContextAdapter innerContext = null;
56  
57      /** context that we are wrapping */
58      InternalContextAdapter wrappedContext = null;
59  
60      /** support for local context scope feature, where all references are local */
61      private  boolean localcontextscope = false;
62  
63       /**
64       *  CTOR, wraps an ICA
65       * @param inner
66       * @param rsvc
67       */
68      public VMContext( InternalContextAdapter  inner, RuntimeServices rsvc )
69      {
70          localcontextscope = rsvc.getBoolean( RuntimeConstants.VM_CONTEXT_LOCALSCOPE, false );
71  
72          wrappedContext = inner;
73          innerContext = inner.getBaseContext();
74      }
75  
76      /**
77       *  Return the inner / user context.
78       * @return The inner / user context.
79       */
80      public Context getInternalUserContext()
81      {
82          return innerContext.getInternalUserContext();
83      }
84  
85      /**
86       * @see org.apache.velocity.context.InternalWrapperContext#getBaseContext()
87       */
88      public InternalContextAdapter getBaseContext()
89      {
90          return innerContext.getBaseContext();
91      }
92  
93      /**
94       *  Used to put VMProxyArgs into this context.  It separates
95       *  the VMProxyArgs into constant and non-constant types
96       *  pulling out the value of the constant types so they can
97       *  be modified w/o damaging the VMProxyArg, and leaving the
98       *  dynamic ones, as they modify context rather than their own
99       *  state
100      *  @param  vmpa VMProxyArg to add
101      * @throws MethodInvocationException
102      */
103     public void addVMProxyArg(  VMProxyArg vmpa ) throws MethodInvocationException
104     {
105         /*
106          *  ask if it's a constant : if so, get the value and put into the
107          *  local context, otherwise, put the vmpa in our vmproxyhash
108          */
109 
110         String key = vmpa.getContextReference();
111 
112         if ( vmpa.isConstant() )
113         {
114             localcontext.put( key, vmpa.getObject( wrappedContext ) );
115         }
116         else
117         {
118             vmproxyhash.put( key, vmpa );
119         }
120     }
121 
122     /**
123      *  Impl of the Context.put() method.
124      *
125      *  @param key name of item to set
126      *  @param value object to set to key
127      *  @return old stored object
128      */
129     public Object put(final String key, final Object value)
130     {
131         return put(key, value, localcontextscope);
132     }
133 
134     /**
135      * Allows callers to explicitly put objects in the local context,
136      * no matter what the velocimacro.context.local setting says. Needed
137      * e.g. for loop variables in foreach.
138      *
139      *  @param key name of item to set.
140      *  @param value object to set to key.
141      *  @return old stored object
142      */
143     public Object localPut(final String key, final Object value)
144     {
145         return put(key, value, true);
146     }
147 
148     /**
149      *  Internal put method to select between local and global scope.
150      *
151      *  @param key name of item to set
152      *  @param value object to set to key
153      *  @param forceLocal True forces the object into the local scope.
154      *  @return old stored object
155      */
156     protected Object put(final String key, final Object value, final boolean forceLocal)
157     {
158         /*
159          *  first see if this is a vmpa
160          */
161 
162         VMProxyArg vmpa = (VMProxyArg) vmproxyhash.get( key );
163 
164         if( vmpa != null)
165         {
166             return vmpa.setObject( wrappedContext, value );
167         }
168         else
169         {
170             if(forceLocal)
171             {
172                 /*
173                  *  just put in the local context
174                  */
175                 return localcontext.put(key, value);
176             }
177             else
178             {
179                 /*
180                  *  ok, how about the local context?
181                  */
182 
183                 if (localcontext.containsKey(key))
184                 {
185                     return localcontext.put(key, value);
186                 }
187                 else
188                 {
189                     /*
190                      * otherwise, let them push it into the 'global' context
191                      */
192 
193                     return innerContext.put(key, value);
194                 }
195             }
196         }
197     }
198 
199     /**
200      *  Impl of the Context.gut() method.
201      *
202      *  @param key name of item to get
203      *  @return  stored object or null
204      */
205     public Object get( String key )
206     {
207         /*
208          * first, see if it's a VMPA
209          */
210 
211         Object o = null;
212 
213         VMProxyArg vmpa = (VMProxyArg) vmproxyhash.get( key );
214 
215         if( vmpa != null )
216         {
217             o = vmpa.getObject( wrappedContext );
218         }
219         else
220         {
221             /*
222              *  always try the local context then innerContext--even if  localcontextscope
223              */
224 
225             o = localcontext.get( key );
226 
227             if ( o == null)
228             {
229                 /*
230                  * last chance
231                  */
232 
233                 o = innerContext.get( key );
234             }
235         }
236 
237         return o;
238     }
239 
240     /**
241      * @see org.apache.velocity.context.Context#containsKey(java.lang.Object)
242      */
243     public boolean containsKey(Object key)
244     {
245         return false;
246     }
247 
248     /**
249      * @see org.apache.velocity.context.Context#getKeys()
250      */
251     public Object[] getKeys()
252     {
253         return vmproxyhash.keySet().toArray();
254     }
255 
256     /**
257      * @see org.apache.velocity.context.Context#remove(java.lang.Object)
258      */
259     public Object remove(Object key)
260     {
261         return vmproxyhash.remove( key );
262     }
263 
264     /**
265      * @see org.apache.velocity.context.InternalHousekeepingContext#pushCurrentTemplateName(java.lang.String)
266      */
267     public void pushCurrentTemplateName( String s )
268     {
269         innerContext.pushCurrentTemplateName( s );
270     }
271 
272     /**
273      * @see org.apache.velocity.context.InternalHousekeepingContext#popCurrentTemplateName()
274      */
275     public void popCurrentTemplateName()
276     {
277         innerContext.popCurrentTemplateName();
278     }
279 
280     /**
281      * @see org.apache.velocity.context.InternalHousekeepingContext#getCurrentTemplateName()
282      */
283     public String getCurrentTemplateName()
284     {
285         return innerContext.getCurrentTemplateName();
286     }
287 
288     /**
289      * @see org.apache.velocity.context.InternalHousekeepingContext#getTemplateNameStack()
290      */
291     public Object[] getTemplateNameStack()
292     {
293         return innerContext.getTemplateNameStack();
294     }
295 
296     /**
297      * @see org.apache.velocity.context.InternalHousekeepingContext#icacheGet(java.lang.Object)
298      */
299     public IntrospectionCacheData icacheGet( Object key )
300     {
301         return innerContext.icacheGet( key );
302     }
303 
304     /**
305      * @see org.apache.velocity.context.InternalHousekeepingContext#icachePut(java.lang.Object, org.apache.velocity.util.introspection.IntrospectionCacheData)
306      */
307     public void icachePut( Object key, IntrospectionCacheData o )
308     {
309         innerContext.icachePut( key, o );
310     }
311 
312     /**
313      * @see org.apache.velocity.context.InternalHousekeepingContext#getAllowRendering()
314      */
315     public boolean getAllowRendering()
316     {
317        return innerContext.getAllowRendering();
318     }
319 
320     /**
321      * @see org.apache.velocity.context.InternalHousekeepingContext#setAllowRendering(boolean)
322      */
323     public void setAllowRendering(boolean v)
324     {
325         innerContext.setAllowRendering(v);
326     }
327 
328     /**
329      * @see org.apache.velocity.context.InternalEventContext#attachEventCartridge(org.apache.velocity.app.event.EventCartridge)
330      */
331     public EventCartridge attachEventCartridge( EventCartridge ec )
332     {
333         EventCartridge cartridge = innerContext.attachEventCartridge( ec );
334         return cartridge;
335     }
336 
337     /**
338      * @see org.apache.velocity.context.InternalEventContext#getEventCartridge()
339      */
340     public EventCartridge getEventCartridge()
341     {
342         return innerContext.getEventCartridge();
343     }
344 
345 
346     /**
347      * @see org.apache.velocity.context.InternalHousekeepingContext#setCurrentResource(org.apache.velocity.runtime.resource.Resource)
348      */
349     public void setCurrentResource( Resource r )
350     {
351         innerContext.setCurrentResource( r );
352     }
353 
354     /**
355      * @see org.apache.velocity.context.InternalHousekeepingContext#getCurrentResource()
356      */
357     public Resource getCurrentResource()
358     {
359         return innerContext.getCurrentResource();
360     }
361 }
362 
363 
364