001: package org.apache.velocity.context;
002:
003: /*
004: * Licensed to the Apache Software Foundation (ASF) under one
005: * or more contributor license agreements. See the NOTICE file
006: * distributed with this work for additional information
007: * regarding copyright ownership. The ASF licenses this file
008: * to you under the Apache License, Version 2.0 (the
009: * "License"); you may not use this file except in compliance
010: * with the License. You may obtain a copy of the License at
011: *
012: * http://www.apache.org/licenses/LICENSE-2.0
013: *
014: * Unless required by applicable law or agreed to in writing,
015: * software distributed under the License is distributed on an
016: * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
017: * KIND, either express or implied. See the License for the
018: * specific language governing permissions and limitations
019: * under the License.
020: */
021:
022: import java.util.HashMap;
023:
024: import org.apache.velocity.runtime.RuntimeServices;
025: import org.apache.velocity.runtime.RuntimeConstants;
026: import org.apache.velocity.runtime.directive.VMProxyArg;
027: import org.apache.velocity.util.introspection.IntrospectionCacheData;
028: import org.apache.velocity.runtime.resource.Resource;
029: import org.apache.velocity.app.event.EventCartridge;
030: import org.apache.velocity.exception.MethodInvocationException;
031:
032: /**
033: * This is a special, internal-use-only context implementation to be
034: * used for the new Velocimacro implementation.
035: *
036: * The main distinguishing feature is the management of the VMProxyArg objects
037: * in the put() and get() methods.
038: *
039: * Further, this context also supports the 'VM local context' mode, where
040: * any put() of references that aren't args to the VM are considered
041: * local to the vm, protecting the global context.
042: *
043: * @author <a href="mailto:geirm@optonline.net">Geir Magnusson Jr.</a>
044: * @version $Id: VMContext.java 471908 2006-11-06 22:39:28Z henning $
045: */
046: public class VMContext implements InternalContextAdapter {
047: /** container for our VMProxy Objects */
048: HashMap vmproxyhash = new HashMap();
049:
050: /** container for any local or constant VMProxy items */
051: HashMap localcontext = new HashMap();
052:
053: /** the base context store. This is the 'global' context */
054: InternalContextAdapter innerContext = null;
055:
056: /** context that we are wrapping */
057: InternalContextAdapter wrappedContext = null;
058:
059: /** support for local context scope feature, where all references are local */
060: private boolean localcontextscope = false;
061:
062: /**
063: * CTOR, wraps an ICA
064: * @param inner
065: * @param rsvc
066: */
067: public VMContext(InternalContextAdapter inner, RuntimeServices rsvc) {
068: localcontextscope = rsvc.getBoolean(
069: RuntimeConstants.VM_CONTEXT_LOCALSCOPE, false);
070:
071: wrappedContext = inner;
072: innerContext = inner.getBaseContext();
073: }
074:
075: /**
076: * Return the inner / user context.
077: * @return The inner / user context.
078: */
079: public Context getInternalUserContext() {
080: return innerContext.getInternalUserContext();
081: }
082:
083: /**
084: * @see org.apache.velocity.context.InternalWrapperContext#getBaseContext()
085: */
086: public InternalContextAdapter getBaseContext() {
087: return innerContext.getBaseContext();
088: }
089:
090: /**
091: * Used to put VMProxyArgs into this context. It separates
092: * the VMProxyArgs into constant and non-constant types
093: * pulling out the value of the constant types so they can
094: * be modified w/o damaging the VMProxyArg, and leaving the
095: * dynamic ones, as they modify context rather than their own
096: * state
097: * @param vmpa VMProxyArg to add
098: * @throws MethodInvocationException
099: */
100: public void addVMProxyArg(VMProxyArg vmpa)
101: throws MethodInvocationException {
102: /*
103: * ask if it's a constant : if so, get the value and put into the
104: * local context, otherwise, put the vmpa in our vmproxyhash
105: */
106:
107: String key = vmpa.getContextReference();
108:
109: if (vmpa.isConstant()) {
110: localcontext.put(key, vmpa.getObject(wrappedContext));
111: } else {
112: vmproxyhash.put(key, vmpa);
113: }
114: }
115:
116: /**
117: * Impl of the Context.put() method.
118: *
119: * @param key name of item to set
120: * @param value object to set to key
121: * @return old stored object
122: */
123: public Object put(final String key, final Object value) {
124: return put(key, value, localcontextscope);
125: }
126:
127: /**
128: * Allows callers to explicitly put objects in the local context,
129: * no matter what the velocimacro.context.local setting says. Needed
130: * e.g. for loop variables in foreach.
131: *
132: * @param key name of item to set.
133: * @param value object to set to key.
134: * @return old stored object
135: */
136: public Object localPut(final String key, final Object value) {
137: return put(key, value, true);
138: }
139:
140: /**
141: * Internal put method to select between local and global scope.
142: *
143: * @param key name of item to set
144: * @param value object to set to key
145: * @param forceLocal True forces the object into the local scope.
146: * @return old stored object
147: */
148: protected Object put(final String key, final Object value,
149: final boolean forceLocal) {
150: /*
151: * first see if this is a vmpa
152: */
153:
154: VMProxyArg vmpa = (VMProxyArg) vmproxyhash.get(key);
155:
156: if (vmpa != null) {
157: return vmpa.setObject(wrappedContext, value);
158: } else {
159: if (forceLocal) {
160: /*
161: * just put in the local context
162: */
163: return localcontext.put(key, value);
164: } else {
165: /*
166: * ok, how about the local context?
167: */
168:
169: if (localcontext.containsKey(key)) {
170: return localcontext.put(key, value);
171: } else {
172: /*
173: * otherwise, let them push it into the 'global' context
174: */
175:
176: return innerContext.put(key, value);
177: }
178: }
179: }
180: }
181:
182: /**
183: * Impl of the Context.gut() method.
184: *
185: * @param key name of item to get
186: * @return stored object or null
187: */
188: public Object get(String key) {
189: /*
190: * first, see if it's a VMPA
191: */
192:
193: Object o = null;
194:
195: VMProxyArg vmpa = (VMProxyArg) vmproxyhash.get(key);
196:
197: if (vmpa != null) {
198: o = vmpa.getObject(wrappedContext);
199: } else {
200: /*
201: * always try the local context then innerContext--even if localcontextscope
202: */
203:
204: o = localcontext.get(key);
205:
206: if (o == null) {
207: /*
208: * last chance
209: */
210:
211: o = innerContext.get(key);
212: }
213: }
214:
215: return o;
216: }
217:
218: /**
219: * @see org.apache.velocity.context.Context#containsKey(java.lang.Object)
220: */
221: public boolean containsKey(Object key) {
222: return false;
223: }
224:
225: /**
226: * @see org.apache.velocity.context.Context#getKeys()
227: */
228: public Object[] getKeys() {
229: return vmproxyhash.keySet().toArray();
230: }
231:
232: /**
233: * @see org.apache.velocity.context.Context#remove(java.lang.Object)
234: */
235: public Object remove(Object key) {
236: return vmproxyhash.remove(key);
237: }
238:
239: /**
240: * @see org.apache.velocity.context.InternalHousekeepingContext#pushCurrentTemplateName(java.lang.String)
241: */
242: public void pushCurrentTemplateName(String s) {
243: innerContext.pushCurrentTemplateName(s);
244: }
245:
246: /**
247: * @see org.apache.velocity.context.InternalHousekeepingContext#popCurrentTemplateName()
248: */
249: public void popCurrentTemplateName() {
250: innerContext.popCurrentTemplateName();
251: }
252:
253: /**
254: * @see org.apache.velocity.context.InternalHousekeepingContext#getCurrentTemplateName()
255: */
256: public String getCurrentTemplateName() {
257: return innerContext.getCurrentTemplateName();
258: }
259:
260: /**
261: * @see org.apache.velocity.context.InternalHousekeepingContext#getTemplateNameStack()
262: */
263: public Object[] getTemplateNameStack() {
264: return innerContext.getTemplateNameStack();
265: }
266:
267: /**
268: * @see org.apache.velocity.context.InternalHousekeepingContext#icacheGet(java.lang.Object)
269: */
270: public IntrospectionCacheData icacheGet(Object key) {
271: return innerContext.icacheGet(key);
272: }
273:
274: /**
275: * @see org.apache.velocity.context.InternalHousekeepingContext#icachePut(java.lang.Object, org.apache.velocity.util.introspection.IntrospectionCacheData)
276: */
277: public void icachePut(Object key, IntrospectionCacheData o) {
278: innerContext.icachePut(key, o);
279: }
280:
281: /**
282: * @see org.apache.velocity.context.InternalHousekeepingContext#getAllowRendering()
283: */
284: public boolean getAllowRendering() {
285: return innerContext.getAllowRendering();
286: }
287:
288: /**
289: * @see org.apache.velocity.context.InternalHousekeepingContext#setAllowRendering(boolean)
290: */
291: public void setAllowRendering(boolean v) {
292: innerContext.setAllowRendering(v);
293: }
294:
295: /**
296: * @see org.apache.velocity.context.InternalEventContext#attachEventCartridge(org.apache.velocity.app.event.EventCartridge)
297: */
298: public EventCartridge attachEventCartridge(EventCartridge ec) {
299: EventCartridge cartridge = innerContext
300: .attachEventCartridge(ec);
301: return cartridge;
302: }
303:
304: /**
305: * @see org.apache.velocity.context.InternalEventContext#getEventCartridge()
306: */
307: public EventCartridge getEventCartridge() {
308: return innerContext.getEventCartridge();
309: }
310:
311: /**
312: * @see org.apache.velocity.context.InternalHousekeepingContext#setCurrentResource(org.apache.velocity.runtime.resource.Resource)
313: */
314: public void setCurrentResource(Resource r) {
315: innerContext.setCurrentResource(r);
316: }
317:
318: /**
319: * @see org.apache.velocity.context.InternalHousekeepingContext#getCurrentResource()
320: */
321: public Resource getCurrentResource() {
322: return innerContext.getCurrentResource();
323: }
324: }
|