View Javadoc

1   package org.apache.velocity.tools.view;
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.lang.reflect.Array;
23  import java.util.Map;
24  import java.util.HashMap;
25  import java.util.Collection;
26  import java.util.Set;
27  import java.util.HashSet;
28  import javax.servlet.ServletRequest;
29  import org.apache.velocity.tools.Scope;
30  import org.apache.velocity.tools.config.DefaultKey;
31  import org.apache.velocity.tools.config.ValidScope;
32  import org.apache.velocity.tools.generic.ValueParser;
33  
34  /**
35   * <p>Utility class for easy parsing of {@link ServletRequest} parameters.</p>
36   * <p><pre>
37   * Template example(s):
38   *   $params.foo                ->  bar
39   *   $params.getNumber('baz')   ->  12.6
40   *   $params.getInt('baz')      ->  12
41   *   $params.getNumbers('baz')  ->  [12.6]
42   *
43   * Toolbox configuration:
44   * &lt;tools&gt;
45   *   &lt;toolbox scope="request"&gt;
46   *     &lt;tool class="org.apache.velocity.tools.view.ParameterTool"/&gt;
47   *   &lt;/toolbox&gt;
48   * &lt;/tools&gt;
49   * </pre></p>
50   *
51   * <p>When used as a view tool, this should only be used in the request scope.
52   * This class is, however, quite useful in your application's controller, filter,
53   * or action code as well as in templates.</p>
54   *
55   * @author Nathan Bubna
56   * @version $Revision: 749733 $ $Date: 2009-03-03 12:24:17 -0800 (Tue, 03 Mar 2009) $
57   * @since VelocityTools 2.0
58   */
59  @DefaultKey("params")
60  @ValidScope(Scope.REQUEST)
61  public class ParameterTool extends ValueParser
62  {
63      private ServletRequest request;
64  
65      /**
66       * Constructs a new instance
67       */
68      public ParameterTool()
69      {}
70  
71      /**
72       * Constructs a new instance using the specified request.
73       *
74       * @param request the {@link ServletRequest} to be parsed
75       */
76      public ParameterTool(ServletRequest request)
77      {
78          setRequest(request);
79      }
80  
81      @Override
82      protected void configure(ValueParser values)
83      {
84          super.configure(values);
85  
86          ServletRequest req = (ServletRequest)values.getValue(ViewContext.REQUEST);
87          setRequest(req);
88      }
89  
90      /**
91       * Sets the current {@link ServletRequest}
92       *
93       * @param request the {@link ServletRequest} to be parsed
94       */
95      public void setRequest(ServletRequest request)
96      {
97          this.request = request;
98      }
99  
100     /**
101      * Returns the current {@link ServletRequest} for this instance.
102      *
103      * @return the current {@link ServletRequest}
104      * @throws UnsupportedOperationException if the request is null
105      */
106     protected ServletRequest getRequest()
107     {
108         if (request == null)
109         {
110             throw new UnsupportedOperationException("Request is null. ParameterTool must be initialized first!");
111         }
112         return request;
113     }
114 
115     /**
116      * Overrides ValueParser.getValue(String key) to retrieve the
117      * value from the ServletRequest instead of an arbitrary Map.
118      *
119      * @param key the parameter's key
120      * @return parameter matching the specified key or
121      *         <code>null</code> if there is no matching
122      *         parameter
123      */
124     @Override
125     public Object getValue(String key)
126     {
127         return getRequest().getParameter(key);
128     }
129 
130 
131     /**
132      * Overrides ValueParser.getValues(String key) to retrieve
133      * Strings from the ServletRequest instead of an arbitrary Map.
134      *
135      * @param key the key for the desired parameter
136      * @return an array of String objects containing all of the values
137      *         the given request parameter has, or <code>null</code>
138      *         if the parameter does not exist
139      */
140     @Override
141     public Object[] getValues(String key)
142     {
143         String[] strings = getRequest().getParameterValues(key);
144         if (strings == null || strings.length == 0)
145         {
146             return null;
147         }
148         else if (strings.length == 1)
149         {
150             return parseStringList(strings[0]);
151         }
152         return strings;
153     }
154 
155     /**
156      * Overrides ValueParser.setSource(Map source) to throw an
157      * UnsupportedOperationException, because this class uses
158      * a servlet request as its source, not a Map.
159      */
160     @Override
161     protected void setSource(Map source)
162     {
163         throw new UnsupportedOperationException();
164     }
165 
166     /**
167      * Overrides ValueParser.getSource() to return the result
168      * of getRequest().getParameterMap() and expand singleton
169      * arrays within it first.
170      */
171     @Override
172     protected Map getSource()
173     {
174         Map source = super.getSource();
175         if (source == null)
176         {
177             source = expandSingletonArrays(getRequest().getParameterMap());
178             super.setSource(source);
179         }
180         return source;
181     }
182 
183     /**
184      * Returns the map of all parameters available for the current request.
185      */
186     public Map getAll()
187     {
188         return getSource();
189     }
190 
191     private boolean isSingletonArray(Object value)
192     {
193         return (value != null &&
194                 value.getClass().isArray() &&
195                 Array.getLength(value) == 1);
196     }
197 
198     private Map<String,Object> expandSingletonArrays(Map<String,Object> original)
199     {
200         Map<String,Object> expanded = new HashMap<String,Object>(original);
201         for (Map.Entry<String,Object> entry : expanded.entrySet())
202         {
203             Object value = entry.getValue();
204             if (isSingletonArray(value))
205             {
206                 entry.setValue(Array.get(value, 0));
207             }
208         }
209         return expanded;
210     }
211 
212 }