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 * <tools> 45 * <toolbox scope="request"> 46 * <tool class="org.apache.velocity.tools.view.ParameterTool"/> 47 * </toolbox> 48 * </tools> 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 }