001 /*
002 Licensed to the Apache Software Foundation (ASF) under one
003 or more contributor license agreements. See the NOTICE file
004 distributed with this work for additional information
005 regarding copyright ownership. The ASF licenses this file
006 to you under the Apache License, Version 2.0 (the
007 "License"); you may not use this file except in compliance
008 with the License. You may obtain a copy of the License at
009
010 http://www.apache.org/licenses/LICENSE-2.0
011
012 Unless required by applicable law or agreed to in writing,
013 software distributed under the License is distributed on an
014 "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
015 KIND, either express or implied. See the License for the
016 specific language governing permissions and limitations
017 under the License.
018 */
019 package org.apache.wiki.util;
020
021 import java.util.ArrayList;
022 import java.util.Enumeration;
023 import java.util.HashMap;
024 import java.util.List;
025 import java.util.Map;
026
027 import javax.servlet.http.HttpServletRequest;
028
029 /**
030 * A collection of (static) utilities used by the WikiForms code.
031 * FormUtil is mainly concerned with mapping HTTP parameters to
032 * WikiPlugin parameters.
033 *
034 */
035 public final class FormUtil
036 {
037 /**
038 * Private constructor to prevent direct instantiation.
039 */
040 private FormUtil()
041 {
042 }
043
044 /**
045 * <p>Looks for a named value in the Map. Returns either the
046 * value named by key, or values named by key.0, key.1, ...
047 * if the direct value is not found. The values are packed
048 * in an ArrayList.</p>
049 * <p>This is a utility method, mainly used when we don't know
050 * whether there was just one value, or several, in a mapping list
051 * (e.g. an HttpRequest / FORM checkbox).</p>
052 * @param params the Map container form parameters
053 * @param key the key to look up
054 * @return the List of keys
055 */
056 public static List getValues( Map params, String key )
057 {
058 if( params == null || key == null )
059 return new ArrayList(0);
060
061 Object entry = params.get( key );
062 if( entry != null )
063 {
064 ArrayList<Object> rval = new ArrayList<Object>(1);
065 rval.add( entry );
066 return rval;
067 }
068
069 return getNumberedValues( params, key );
070 }
071
072
073 /**
074 * Looks up all keys starting with a given prefix and returns
075 * the values in an ArrayList. The keys must be Strings.
076 *
077 * <p>For example, calling this method for a Map containing
078 * key-value pairs foo.1 = a, foo.2 = b, and foo.3 = c returns
079 * an ArrayList containing [a, b, c].
080 *
081 * <p>Handles both 0- and 1-indexed names. Parsing stops at the
082 * first gap in the numeric postfix.
083 *
084 * @param params a Map of string-object pairs, presumably containing
085 * key.1, key.2,...
086 * @param keyPrefix a String prefix; values will be looked up by adding
087 * ".0", ".1", and so on, until the first gap.
088 * @return ArrayList, containing the values corresponding to the
089 * keyPrefix, in order.
090 */
091 public static List getNumberedValues( Map params, String keyPrefix )
092 {
093 ArrayList<Object> rval = new ArrayList<Object>();
094 if( params == null ||
095 params.size() == 0 ||
096 keyPrefix == null ||
097 keyPrefix.length() == 0 )
098 return rval;
099
100 String fullPrefix = null;
101 if( keyPrefix.charAt( keyPrefix.length() - 1 ) == '.' )
102 fullPrefix = keyPrefix;
103 else
104 fullPrefix = keyPrefix + ".";
105
106 int ix = 0;
107 Object value = params.get( fullPrefix + (ix++) );
108 if( value == null )
109 value = params.get( fullPrefix + (ix++) );
110 if( value == null )
111 return rval;
112 while( true )
113 {
114 rval.add( value );
115 value = params.get( fullPrefix + (ix++) );
116 if( value == null )
117 break;
118 }
119
120 return rval;
121 }
122
123
124 /**
125 * <p>Converts the parameter contents of an HTTP request into a map,
126 * modifying the keys to preserve multiple values per key. This
127 * is done by adding an ordered suffix to the key:</p>
128 * <p><pre>foo=bar,baz,xyzzy</pre></p>
129 * <p>becomes</p>
130 * <p><pre>foo.0=bar foo.1=baz foo.2=xyzzy</pre></p>
131 * <p>If filterPrefix is specified, only keys starting with the prefix
132 * are included in the result map. If the prefix is null, all keys are
133 * checked.</p>
134 * <p>FIX: this is not necessarily encoding-safe: see
135 * WikiContext.getHttpParameter().</p>
136 * @param req the HTTP request
137 * @param filterPrefix the prefix
138 * @return the Map containing parsed key/value pairs
139 */
140 public static Map< String, String > requestToMap( HttpServletRequest req,
141 String filterPrefix )
142 {
143 HashMap<String,String> params = new HashMap<String,String>();
144
145 if( filterPrefix == null ) filterPrefix = "";
146
147 Enumeration en = req.getParameterNames();
148 while( en.hasMoreElements() )
149 {
150 String param = (String)en.nextElement();
151
152 if( param.startsWith( filterPrefix ) )
153 {
154 String realName = param.substring( filterPrefix.length() );
155 String[] values = req.getParameterValues( param );
156 if( values != null )
157 {
158 if( values.length == 1 )
159 {
160 params.put( realName, values[0] );
161 }
162 else
163 {
164 for( int i = 0; i < values.length; i++ )
165 {
166 if( values[i] != null && values[i].length() > 0 )
167 {
168 params.put( realName + "." + i, values[i] );
169 }
170 }
171 }
172 }
173 }
174 }
175
176 return params;
177 }
178
179 }