001: package org.apache.velocity.tools.view.tools;
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.Arrays;
023: import java.util.Enumeration;
024: import java.util.HashSet;
025: import java.util.Iterator;
026: import java.util.Map;
027: import java.util.Set;
028: import javax.servlet.http.HttpServletRequest;
029: import javax.servlet.http.HttpSession;
030: import javax.servlet.ServletContext;
031: import org.apache.velocity.context.AbstractContext;
032: import org.apache.velocity.context.Context;
033: import org.apache.velocity.tools.generic.ValueParser;
034: import org.apache.velocity.tools.view.context.ChainedContext;
035: import org.apache.velocity.tools.view.context.ViewContext;
036:
037: /**
038: * <p>View tool for convenient access to {@link ViewContext} data and
039: * meta-data.</p>
040: * <p><pre>
041: * Template example(s):
042: * #foreach( $key in $context.keys )
043: * $key = $context.get($key)
044: * #end
045: *
046: * Toolbox configuration:
047: * <tool>
048: * <key>context</key>
049: * <scope>request</scope>
050: * <class>org.apache.velocity.tools.view.tools.ContextTool</class>
051: * </tool>
052: * </pre></p>
053: *
054: * <p>This class is only designed for use as a request-scope VelocityView tool.</p>
055: *
056: * @author Nathan Bubna
057: * @since VelocityTools 1.3
058: * @version $Id: ContextTool.java 385122 2006-03-11 18:37:42Z nbubna $
059: */
060: public class ContextTool {
061: /**
062: * The key used for specifying whether to hide keys with '.' in them.
063: */
064: public static final String SAFE_MODE_KEY = "safe-mode";
065:
066: protected ViewContext context;
067: protected Map toolbox;
068: protected HttpServletRequest request;
069: protected HttpSession session;
070: protected ServletContext application;
071:
072: private boolean safeMode = true;
073:
074: /**
075: * Looks for a safe-mode configuration setting. By default,
076: * safe-mode is true and thus keys with '.' in them are hidden.
077: */
078: public void configure(Map params) {
079: if (params != null) {
080: ValueParser parser = new ValueParser(params);
081: safeMode = parser.getBoolean(SAFE_MODE_KEY, true);
082: }
083: }
084:
085: /**
086: * Initializes this instance for the current request.
087: *
088: * @param obj the ViewContext of the current request
089: */
090: public void init(Object obj) {
091: this .context = (ViewContext) obj;
092: this .request = context.getRequest();
093: this .session = request.getSession(false);
094: this .application = context.getServletContext();
095: }
096:
097: /**
098: * Returns the context being analyzed by this tool.
099: */
100: public ViewContext getThis() {
101: return this .context;
102: }
103:
104: /**
105: * <p>Returns a read-only view of the toolbox {@link Map}
106: * for this context.</p>
107: * @return an unmodifiable version of the toolbox for this request
108: * or {@code null} if there is none
109: */
110: public Map getToolbox() {
111: if (this .toolbox == null
112: && this .context instanceof ChainedContext) {
113: this .toolbox = ((ChainedContext) context).getToolbox();
114: }
115: return this .toolbox;
116: }
117:
118: /**
119: * <p>Return a {@link Set} of the available reference keys in the current
120: * context.</p>
121: */
122: public Set getKeys() {
123: Set keys = new HashSet();
124:
125: // get the tool keys, if there is a toolbox
126: Map tools = getToolbox();
127: if (tools != null) {
128: keys.addAll(tools.keySet());
129: }
130:
131: // recurse down the velocity context collecting keys
132: Context velctx = this .context.getVelocityContext();
133: while (velctx != null) {
134: Object[] ctxKeys = velctx.getKeys();
135: keys.addAll(Arrays.asList(ctxKeys));
136: if (velctx instanceof AbstractContext) {
137: velctx = ((AbstractContext) velctx).getChainedContext();
138: } else {
139: velctx = null;
140: }
141: }
142:
143: // get request attribute keys
144: Enumeration e = request.getAttributeNames();
145: while (e.hasMoreElements()) {
146: keys.add(e.nextElement());
147: }
148:
149: // get session attribute keys if we have a session
150: if (session != null) {
151: e = session.getAttributeNames();
152: while (e.hasMoreElements()) {
153: keys.add(e.nextElement());
154: }
155: }
156:
157: // get request attribute keys
158: e = application.getAttributeNames();
159: while (e.hasMoreElements()) {
160: keys.add(e.nextElement());
161: }
162:
163: // if we're in safe mode, remove keys that contain '.'
164: if (safeMode) {
165: for (Iterator i = keys.iterator(); i.hasNext();) {
166: String key = String.valueOf(i.next());
167: if (key.indexOf('.') >= 0) {
168: i.remove();
169: }
170: }
171: }
172:
173: // return the key set
174: return keys;
175: }
176:
177: /**
178: * <p>Return a {@link Set} of the available values in the current
179: * context.</p>
180: */
181: public Set getValues() {
182: //TODO: this could be a lot more efficient
183: Set keys = getKeys();
184: Set values = new HashSet(keys.size());
185: for (Iterator i = keys.iterator(); i.hasNext();) {
186: String key = String.valueOf(i.next());
187: values.add(this .context.getVelocityContext().get(key));
188: }
189: return values;
190: }
191:
192: /**
193: * <p>Returns {@code true} if the context contains a value for the specified
194: * reference name (aka context key).</p>
195: */
196: public boolean contains(Object refName) {
197: return (get(refName) != null);
198: }
199:
200: /**
201: * Retrieves the value for the specified reference name (aka context key).
202: */
203: public Object get(Object refName) {
204: String key = String.valueOf(refName);
205: if (safeMode && key.indexOf('.') >= 0) {
206: return null;
207: }
208: return this.context.getVelocityContext().get(key);
209: }
210:
211: }
|