View Javadoc
1   /*
2    * #%L
3    * wcm.io
4    * %%
5    * Copyright (C) 2014 wcm.io
6    * %%
7    * Licensed under the Apache License, Version 2.0 (the "License");
8    * you may not use this file except in compliance with the License.
9    * You may obtain a copy of the License at
10   *
11   *      http://www.apache.org/licenses/LICENSE-2.0
12   *
13   * Unless required by applicable law or agreed to in writing, software
14   * distributed under the License is distributed on an "AS IS" BASIS,
15   * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
16   * See the License for the specific language governing permissions and
17   * limitations under the License.
18   * #L%
19   */
20  package io.wcm.sling.commons.request;
21  
22  import java.nio.charset.StandardCharsets;
23  import java.util.Map;
24  
25  import javax.servlet.ServletRequest;
26  
27  import org.apache.commons.lang3.BooleanUtils;
28  import org.apache.commons.lang3.StringUtils;
29  import org.apache.commons.lang3.math.NumberUtils;
30  import org.jetbrains.annotations.NotNull;
31  import org.jetbrains.annotations.Nullable;
32  import org.osgi.annotation.versioning.ProviderType;
33  
34  /**
35   * Several helper methods for getting parameters from the servlet request.
36   * This class automatically converts string parameters from ISO-8859-1 to UTF-8, because UTF-8 form data
37   * is expected by default. This is only done if no request parameter "_charset_" with an explicit encoding is set.
38   * If it is set, the {@link org.apache.sling.api.SlingHttpServletRequest} automatically converts the parameter data.
39   */
40  @ProviderType
41  public final class RequestParam {
42  
43    /**
44     * The name of the form encoding parameter.
45     * If such a form parameter is set in a request the {@link org.apache.sling.api.SlingHttpServletRequest} automatically
46     * transcodes all parameters to this encoding.
47     */
48    public static final @NotNull String PARAMETER_FORMENCODING = "_charset_";
49  
50    private RequestParam() {
51      // Utility class - no instancing allowed
52    }
53  
54    /**
55     * Returns a request parameter.<br>
56     * In addition the method fixes problems with incorrect UTF-8 characters returned by the servlet engine.
57     * All character data is converted from ISO-8859-1 to UTF-8 if not '_charset_' parameter is provided.
58     * @param request Request.
59     * @param param Parameter name.
60     * @return Parameter value or null if it is not set.
61     */
62    public static @Nullable String get(@NotNull ServletRequest request, @NotNull String param) {
63      return get(request, param, null);
64    }
65  
66    /**
67     * Returns a request parameter.<br>
68     * In addition the method fixes problems with incorrect UTF-8 characters returned by the servlet engine.
69     * All character data is converted from ISO-8859-1 to UTF-8 if not '_charset_' parameter is provided.
70     * @param request Request.
71     * @param param Parameter name.
72     * @param defaultValue Default value.
73     * @return Parameter value or the default value if it is not set.
74     */
75    public static @Nullable String get(@NotNull ServletRequest request, @NotNull String param, @Nullable String defaultValue) {
76      String value = request.getParameter(param);
77      if (value != null) {
78        // convert encoding to UTF-8 if not form encoding parameter is set
79        if (!hasFormEncodingParam(request)) {
80          value = convertISO88591toUTF8(value);
81        }
82        return value;
83      }
84      else {
85        return defaultValue;
86      }
87    }
88  
89    /**
90     * Returns a request parameter array.<br>
91     * The method fixes problems with incorrect UTF-8 characters returned by the servlet engine.
92     * All character data is converted from ISO-8859-1 to UTF-8.
93     * @param request Request.
94     * @param param Parameter name.
95     * @return Parameter value array value or null if it is not set.
96     */
97    public static String @Nullable [] getMultiple(@NotNull ServletRequest request, @NotNull String param) {
98      String[] values = request.getParameterValues(param);
99      if (values == null) {
100       return null;
101     }
102     // convert encoding to UTF-8 if not form encoding parameter is set
103     if (!hasFormEncodingParam(request)) {
104       String[] convertedValues = new String[values.length];
105       for (int i = 0; i < values.length; i++) {
106         if (values[i] != null) {
107           convertedValues[i] = convertISO88591toUTF8(values[i]);
108         }
109       }
110       return convertedValues;
111     }
112     else {
113       return values;
114     }
115   }
116 
117   /**
118    * Returns a request parameter.<br>
119    * In addition the method fixes problems with incorrect UTF-8 characters returned by the servlet engine.
120    * All character data is converted from ISO-8859-1 to UTF-8.
121    * @param requestMap Request Parameter map.
122    * @param param Parameter name.
123    * @return Parameter value or null if it is not set.
124    */
125   public static @Nullable String get(@NotNull Map<String, String[]> requestMap, @NotNull String param) {
126     String value = null;
127     String[] valueArray = requestMap.get(param);
128     if (valueArray != null && valueArray.length > 0) {
129       value = valueArray[0];
130     }
131     // convert encoding to UTF-8 if not form encoding parameter is set
132     if (value != null && !hasFormEncodingParam(requestMap)) {
133       value = convertISO88591toUTF8(value);
134     }
135     return value;
136   }
137 
138   /**
139    * Returns a request parameter as integer.
140    * @param request Request.
141    * @param param Parameter name.
142    * @return Parameter value or 0 if it does not exist or is not a number.
143    */
144   public static int getInt(@NotNull ServletRequest request, @NotNull String param) {
145     return getInt(request, param, 0);
146   }
147 
148   /**
149    * Returns a request parameter as integer.
150    * @param request Request.
151    * @param param Parameter name.
152    * @param defaultValue Default value.
153    * @return Parameter value or default value if it does not exist or is not a number.
154    */
155   public static int getInt(@NotNull ServletRequest request, @NotNull String param, int defaultValue) {
156     String value = request.getParameter(param);
157     return NumberUtils.toInt(value, defaultValue);
158   }
159 
160   /**
161    * Returns a request parameter as long.
162    * @param request Request.
163    * @param param Parameter name.
164    * @return Parameter value or 0 if it does not exist or is not a number.
165    */
166   public static long getLong(@NotNull ServletRequest request, @NotNull String param) {
167     return getLong(request, param, 0L);
168   }
169 
170   /**
171    * Returns a request parameter as long.
172    * @param request Request.
173    * @param param Parameter name.
174    * @param defaultValue Default value.
175    * @return Parameter value or default value if it does not exist or is not a number.
176    */
177   public static long getLong(@NotNull ServletRequest request, @NotNull String param, long defaultValue) {
178     String value = request.getParameter(param);
179     return NumberUtils.toLong(value, defaultValue);
180   }
181 
182   /**
183    * Returns a request parameter as float.
184    * @param request Request.
185    * @param param Parameter name.
186    * @return Parameter value or 0 if it does not exist or is not a number.
187    */
188   public static float getFloat(@NotNull ServletRequest request, @NotNull String param) {
189     return getFloat(request, param, 0f);
190   }
191 
192   /**
193    * Returns a request parameter as float.
194    * @param request Request.
195    * @param param Parameter name.
196    * @param defaultValue Default value.
197    * @return Parameter value or default value if it does not exist or is not a number.
198    */
199   public static float getFloat(@NotNull ServletRequest request, @NotNull String param, float defaultValue) {
200     String value = request.getParameter(param);
201     return NumberUtils.toFloat(value, defaultValue);
202   }
203 
204   /**
205    * Returns a request parameter as double.
206    * @param request Request.
207    * @param param Parameter name.
208    * @return Parameter value or 0 if it does not exist or is not a number.
209    */
210   public static double getDouble(@NotNull ServletRequest request, @NotNull String param) {
211     return getDouble(request, param, 0d);
212   }
213 
214   /**
215    * Returns a request parameter as double.
216    * @param request Request.
217    * @param param Parameter name.
218    * @param defaultValue Default value.
219    * @return Parameter value or default value if it does not exist or is not a number.
220    */
221   public static double getDouble(@NotNull ServletRequest request, @NotNull String param, double defaultValue) {
222     String value = request.getParameter(param);
223     return NumberUtils.toDouble(value, defaultValue);
224   }
225 
226   /**
227    * Returns a request parameter as boolean.
228    * @param request Request.
229    * @param param Parameter name.
230    * @return Parameter value or <code>false</code> if it does not exist or cannot be interpreted as boolean.
231    */
232   public static boolean getBoolean(@NotNull ServletRequest request, @NotNull String param) {
233     return getBoolean(request, param, false);
234   }
235 
236   /**
237    * Returns a request parameter as boolean.
238    * @param request Request.
239    * @param param Parameter name.
240    * @param defaultValue Default value.
241    * @return Parameter value or default value if it does not exist or <code>false</code> if it cannot be interpreted as
242    *         boolean.
243    */
244   public static boolean getBoolean(@NotNull ServletRequest request, @NotNull String param, boolean defaultValue) {
245     String value = request.getParameter(param);
246     Boolean boolValue = BooleanUtils.toBooleanObject(value);
247     if (boolValue != null) {
248       return boolValue.booleanValue();
249     }
250     return defaultValue;
251   }
252 
253   /**
254    * Returns a request parameter as enum value.
255    * @param <T> Enum type
256    * @param request Request.
257    * @param param Parameter name.
258    * @param enumClass Enum class
259    * @return Parameter value or null if it is not set or an invalid enum value.
260    */
261   public static <T extends Enum> @Nullable T getEnum(@NotNull ServletRequest request, @NotNull String param, @NotNull Class<T> enumClass) {
262     return getEnum(request, param, enumClass, null);
263   }
264 
265   /**
266    * Returns a request parameter as enum value.
267    * @param <T> Enum type
268    * @param request Request.
269    * @param param Parameter name.
270    * @param enumClass Enum class
271    * @param defaultValue Default value.
272    * @return Parameter value or the default value if it is not set or an invalid enum value.
273    */
274   @SuppressWarnings("unchecked")
275   public static <T extends Enum> @Nullable T getEnum(@NotNull ServletRequest request, @NotNull String param, @NotNull Class<T> enumClass,
276       @Nullable T defaultValue) {
277     String value = get(request, param);
278     if (StringUtils.isNotEmpty(value)) {
279       try {
280         return (T)Enum.valueOf(enumClass, value);
281       }
282       catch (IllegalArgumentException ex) {
283         // ignore, return default
284       }
285     }
286     return defaultValue;
287   }
288 
289   /**
290    * @param request Servlet request
291    * @return Checks if form encoding parameter is set
292    */
293   private static boolean hasFormEncodingParam(@NotNull ServletRequest request) {
294     return StringUtils.isNotEmpty(request.getParameter(PARAMETER_FORMENCODING));
295   }
296 
297   /**
298    * @param requestMap Request map
299    * @return Checks if form encoding parameter is set
300    */
301   private static boolean hasFormEncodingParam(@NotNull Map<String, String[]> requestMap) {
302     String[] valueArray = requestMap.get(PARAMETER_FORMENCODING);
303     return valueArray != null && valueArray.length > 0;
304   }
305 
306   /**
307    * Converts a string from ISO-8559-1 encoding to UTF-8.
308    * @param value ISO-8559-1 value
309    * @return UTF-8 value
310    */
311   private static String convertISO88591toUTF8(String value) {
312     return new String(value.getBytes(StandardCharsets.ISO_8859_1), StandardCharsets.UTF_8);
313   }
314 
315 }