View Javadoc

1   package org.apache.velocity.tools.generic;
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.Arrays;
23  import java.util.HashSet;
24  import java.util.Iterator;
25  import java.util.Map;
26  import java.util.Set;
27  import org.apache.velocity.context.AbstractContext;
28  import org.apache.velocity.context.Context;
29  import org.apache.velocity.tools.Scope;
30  import org.apache.velocity.tools.ToolContext;
31  import org.apache.velocity.tools.config.DefaultKey;
32  import org.apache.velocity.tools.config.InvalidScope;
33  import org.apache.velocity.tools.generic.ValueParser;
34  
35  /**
36   * <p>Tool for convenient access to {@link Context} data and
37   *  meta-data.</p>
38   * <p><pre>
39   * Template example(s):
40   *  #foreach( $key in $context.keys )
41   *    $key = $context.get($key)
42   *  #end
43   *
44   * Toolbox configuration:
45   * &lt;tools&gt;
46   *   &lt;toolbox scope="request"&gt;
47   *     &lt;tool class="org.apache.velocity.tools.generic.ContextTool"/&gt;
48   *   &lt;/toolbox&gt;
49   * &lt;/tools&gt;
50   * </pre></p>
51   *
52   * <p>This class is only designed for use as a request-scope tool.</p>
53   *
54   * @author Nathan Bubna
55   * @since VelocityTools 2.0
56   * @version $Id: ContextTool.java 385122 2006-03-11 18:37:42Z nbubna $
57   */
58  @DefaultKey("context")
59  @InvalidScope({Scope.APPLICATION,Scope.SESSION})
60  public class ContextTool extends SafeConfig
61  {
62      protected Context context;
63      protected Map<String,Object> toolbox;
64  
65      /**
66       * Initializes this instance for the current request.
67       * Also looks for a safe-mode configuration setting. By default,
68       * safeMode is true and thus keys with '.' in them are hidden.
69       */
70      protected void configure(ValueParser parser)
71      {
72          this.context = (Context)parser.getValue(ToolContext.CONTEXT_KEY);
73      }
74  
75  
76      /**
77       * Returns the context being analyzed by this tool.
78       */
79      public Context getThis()
80      {
81          return this.context;
82      }
83  
84      /**
85       * <p>Returns a read-only view of the toolbox {@link Map}
86       * for this context.</p>
87       * @return a map of all available tools for this request
88       *         or {@code null} if such a map is not available
89       */
90      public Map<String,Object> getToolbox()
91      {
92          if (this.toolbox == null && this.context instanceof ToolContext)
93          {
94              this.toolbox = ((ToolContext)context).getToolbox();
95          }
96          return this.toolbox;
97      }
98  
99      /**
100      * <p>Return a {@link Set} of the available reference keys in the current
101      * context.</p>
102      */
103     public Set getKeys()
104     {
105         Set keys = new HashSet();
106 
107         // fill the keyset in extendable method
108         fillKeyset(keys);
109 
110         // if we're in safe mode, remove keys that contain '.'
111         if (isSafeMode())
112         {
113             for (Iterator i = keys.iterator(); i.hasNext(); )
114             {
115                 String key = String.valueOf(i.next());
116                 if (key.indexOf('.') >= 0)
117                 {
118                     i.remove();
119                 }
120             }
121         }
122         // return the key set
123         return keys;
124     }
125 
126 
127     /**
128      * Actually do the work of filling in the set of keys
129      * for {@link #getKeys} here so subclasses can add keys too.
130      */
131     protected void fillKeyset(Set keys)
132     {
133         //NOTE: we don't need to manually add the toolbox keys here
134         //      because retrieval of those depends on the context being
135         //      a ToolContext which would already give tool keys below
136 
137         // recurse down the velocity context collecting keys
138         Context velctx = this.context;
139         while (velctx != null)
140         {
141             Object[] ctxKeys = velctx.getKeys();
142             keys.addAll(Arrays.asList(ctxKeys));
143             if (velctx instanceof AbstractContext)
144             {
145                 velctx = ((AbstractContext)velctx).getChainedContext();
146             }
147             else
148             {
149                 velctx = null;
150             }
151         }
152     }
153 
154     /**
155      * <p>Return a {@link Set} of the available values in the current
156      * context.</p>
157      */
158     public Set getValues()
159     {
160         //TODO: this could be a lot more efficient
161         Set keys = getKeys();
162         Set values = new HashSet(keys.size());
163         for (Iterator i = keys.iterator(); i.hasNext(); )
164         {
165             String key = String.valueOf(i.next());
166             values.add(this.context.get(key));
167         }
168         return values;
169     }
170 
171 
172     /**
173      * <p>Returns {@code true} if the context contains a value for the specified
174      * reference name (aka context key).</p>
175      */
176     public boolean contains(Object refName)
177     {
178         return (get(refName) != null);
179     }
180 
181     /**
182      * Retrieves the value for the specified reference name (aka context key).
183      */
184     public Object get(Object refName)
185     {
186         String key = String.valueOf(refName);
187         if (isSafeMode() && key.indexOf('.') >= 0)
188         {
189             return null;
190         }
191         return this.context.get(key);
192     }
193 
194 }