View Javadoc

1   package org.apache.velocity.tools;
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.Collections;
23  import java.util.HashMap;
24  import java.util.HashSet;
25  import java.util.Map;
26  import java.util.Set;
27  
28  /**
29   * <p>Instances of this class are typically created by a {@link ToolboxFactory}
30   * on a one-per-scope basis.  So, for each application, there would be one
31   * application-scoped Toolbox from which you would retrieve tool instances,
32   * and for each request, there would be one request-scoped Toolbox.
33   * Of course, none of the above is enforced.  There's no reason that you can't
34   * manually create a Toolbox or have multiple Toolboxes for each scope.
35   * </p><p>
36   * When a Toolbox creates a tool instance asked of it (see {@link #get}),
37   * it will cache that instance for future requests.
38   * </p>
39   *
40   * @author Nathan Bubna
41   * @version $Id: Toolbox.java 511959 2007-02-26 19:24:39Z nbubna $
42   */
43  public class Toolbox implements java.io.Serializable
44  {
45      /**
46       * The key used to place instances in various scopes.
47       */
48      public static final String KEY = Toolbox.class.getName();
49  
50      private static final long serialVersionUID = 888081253188664649L;
51  
52      private Map<String,ToolInfo> infoMap;
53      private Map<String,Object> properties;
54      private Map<String,Object> cache;
55  
56      public Toolbox(Map<String,ToolInfo> toolInfo)
57      {
58          this(toolInfo, null);
59      }
60  
61      public Toolbox(Map<String,ToolInfo> toolInfo, Map<String,Object> properties)
62      {
63          if (toolInfo == null)
64          {
65              this.infoMap = Collections.emptyMap();
66          }
67          else
68          {
69              this.infoMap = toolInfo;
70          }
71          this.properties = properties;
72      }
73  
74      protected void cacheData(Map<String,Object> data)
75      {
76          if (data != null && !data.isEmpty())
77          {
78              cache = new HashMap<String,Object>(data);
79          }
80      }
81  
82  
83      public Map<String,Object> getProperties()
84      {
85          return properties;
86      }
87  
88      public Object get(String key)
89      {
90          return get(key, null, null);
91      }
92  
93      public Object get(String key, String path)
94      {
95          return get(key, path, null);
96      }
97  
98      public Object get(String key, Map<String,Object> context)
99      {
100         return get(key, null, context);
101     }
102 
103     public Object get(String key, String path, Map<String,Object> context)
104     {
105         Object tool = null;
106         if (cache != null)
107         {
108             tool = getFromCache(key, path);
109         }
110         if (tool == null)
111         {
112             tool = getFromInfo(key, path, context);
113         }
114         return tool;
115     }
116 
117 
118     protected Object getFromCache(String key, String path)
119     {
120         if (cache == null)
121         {
122             return null;
123         }
124         else
125         {
126             Object tool = cache.get(key);
127             if (tool == null)
128             {
129                 return null;
130             }
131             else if (path == null)
132             {
133                 return tool;
134             }
135             else if (hasPermission(infoMap.get(key), path))
136             {
137                 return tool;
138             }
139             else
140             {
141                 return null;
142             }
143         }
144     }
145 
146     protected Object getFromInfo(String key, String path,
147                                  Map<String,Object> context)
148     {
149         ToolInfo info = infoMap.get(key);
150         if (info != null && (path == null || hasPermission(info, path)))
151         {
152             Object tool = info.create(context);
153             if (cache == null)
154             {
155                 cache = new HashMap<String,Object>();
156             }
157             cache.put(key, tool);
158             return tool;
159         }
160         return null;
161     }
162 
163     protected boolean hasPermission(ToolInfo info, String path)
164     {
165         if (info == null || path == null)
166         {
167             return true;
168         }
169         return info.hasPermission(path);
170     }
171 
172     public Set<String> getKeys()
173     {
174         // add keys for all available tools
175         Set<String> keys = new HashSet<String>(infoMap.keySet());
176         // be sure to add cache, which holds data keys
177         if (cache != null)
178         {
179             keys.addAll(cache.keySet());
180         }
181         return keys;
182     }
183 
184     /**
185      * Return a new {@link Map} link tools' keys to their {@link Class}es.
186      * This will not instantiate any tools, it is merely informational.
187      * This will not include the keys for any cached data. Note that inclusion
188      * in this map does NOT mean that all these tools will be available for
189      * all requests, as this map ignores all path restrictions on the tools.
190      */
191     public Map<String,Class> getToolClassMap()
192     {
193         Map<String,Class> classMap = new HashMap<String,Class>(infoMap.size());
194         for (Map.Entry<String,ToolInfo> entry : infoMap.entrySet())
195         {
196             classMap.put(entry.getKey(), entry.getValue().getToolClass());
197         }
198         return classMap;
199     }
200 
201     public Map<String,Object> getAll(Map<String,Object> context)
202     {
203         // request all tools we have info for
204         for (ToolInfo info : infoMap.values())
205         {
206             get(info.getKey(), context);
207         }
208         // then return a copy of the cache
209         return new HashMap<String,Object>(this.cache);
210     }
211 
212     /**
213      * Returns a new {@link Toolbox} that is a combination of
214      * this Toolbox with one or more specified {@link Toolbox}es.
215      * Neither this instance nor those specified are modified.
216      */
217     public Toolbox combine(Toolbox... toolboxes)
218     {
219         Map<String,ToolInfo> info = new HashMap<String,ToolInfo>(this.infoMap);
220         Map<String,Object> props = new HashMap<String,Object>(this.properties);
221         Map<String,Object> data = new HashMap<String,Object>(this.cache);
222         for (Toolbox toolbox : toolboxes)
223         {
224             info.putAll(toolbox.infoMap);
225             props.putAll(toolbox.properties);
226             data.putAll(toolbox.cache);
227         }
228         Toolbox combination = new Toolbox(info, props);
229         combination.cacheData(data);
230         return combination;
231     }
232 
233 }