org.ocpsoft.rewrite.servlet.util.QueryStringBuilder Maven / Gradle / Ivy
/*
* Copyright 2011 Lincoln Baxter, III
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.ocpsoft.rewrite.servlet.util;
import java.io.UnsupportedEncodingException;
import java.net.URLDecoder;
import java.net.URLEncoder;
import java.util.ArrayList;
import java.util.Iterator;
import java.util.LinkedHashMap;
import java.util.LinkedHashSet;
import java.util.List;
import java.util.Map;
import java.util.Map.Entry;
import java.util.Set;
import org.ocpsoft.logging.Logger;
import org.ocpsoft.rewrite.exception.RewriteException;
import org.ocpsoft.urlbuilder.AddressBuilder;
/**
* Utility for building URL query strings.
*
* @deprecated Use {@link AddressBuilder} instead. May be removed in subsequent releases.
*
* @author Lincoln Baxter, III
*/
@Deprecated
public class QueryStringBuilder
{
private final static Logger log = Logger.getLogger(QueryStringBuilder.class);
private final Map> parameters = new LinkedHashMap>();
/**
* Return a new empty instance of {@link QueryStringBuilder}
*/
public static QueryStringBuilder createNew()
{
return new QueryStringBuilder();
}
/**
* Build a query string from the given URL. If a '?' character is encountered in the URL, the any characters up to
* and including the first '?' will be ignored. This method assumes that the given parameters have already been URL
* encoded.
*/
public static QueryStringBuilder createFromEncoded(final String parameters)
{
QueryStringBuilder queryString = new QueryStringBuilder();
queryString.addParameters(parameters);
return queryString;
}
/**
* Build a query string from the given map of name=value pairs. For parameters with more than one value, each value
* will be appended using the same name.
*/
public static QueryStringBuilder createFromArrays(final Map params)
{
return QueryStringBuilder.createNew().addParameterArrays(params);
}
/**
* Build a query string from the given map of name=value pairs. For parameters with more than one value, each value
* will be appended using the same name.
*/
public static QueryStringBuilder createFromLists(final Map> params)
{
return QueryStringBuilder.createNew().addParameterLists(params);
}
/**
* Get the query string portion of the given URL. If no query string separator character '?' can be found, return the
* string unchanged.
*/
public static String extractQuery(String url)
{
if (url != null)
{
int index = url.indexOf('?');
if (index >= 0)
{
url = url.substring(index + 1);
}
}
return url;
}
/**
* Add parameters from the given URL. If a '?' character is encountered in the URL, the any characters up to and
* including the first '?' will be ignored. If a parameter already exists, append new values to the existing list of
* values for that parameter.
*
* Note: This method assumes that the given string is already URL encoded.
*/
public QueryStringBuilder addParameters(final String url)
{
String temp = extractQuery(url);
if (temp != null)
{
temp = decodeHTMLAmpersands(temp);
int index = 0;
while ((index = temp.indexOf('&')) >= 0 || !temp.isEmpty())
{
String pair = temp;
if (index >= 0)
{
pair = temp.substring(0, index);
temp = temp.substring(index);
if (!temp.isEmpty())
temp = temp.substring(1);
}
else
temp = "";
String name;
String value;
int pos = pair.indexOf('=');
// for "n=", the value is "", for "n", the value is null
if (pos == -1)
{
name = pair;
value = null;
}
else
{
name = pair.substring(0, pos);
value = pair.substring(pos + 1, pair.length());
}
List list = parameters.get(name);
if (list == null)
{
list = new ArrayList();
parameters.put(name, list);
}
list.add(value);
}
}
return this;
}
private String decodeHTMLAmpersands(String url)
{
if (url != null)
{
int index = 0;
while ((index = url.indexOf("&")) >= 0)
{
url = url.substring(0, index + 1) + url.substring(index + 5);
}
}
return url;
}
/**
* Add a single parameter with the given values.
*/
public void addParameter(final String name, final String... values)
{
Map parameter = new LinkedHashMap();
parameter.put(name, values);
addParameterArrays(parameter);
}
/**
* Add parameters from the given map of name=value pairs. For parameters with more than one value, each value will be
* appended using the same name. If a parameter already exists, append new values to the existing list of values for
* that parameter.
*/
public QueryStringBuilder addParameterArrays(final Map params)
{
if (params != null)
{
for (Entry entry : params.entrySet())
{
List values = null;
if (entry.getValue() != null)
{
List temp = new ArrayList();
if (entry.getValue() != null)
{
for (String value : entry.getValue()) {
temp.add(value);
}
}
values = temp;
}
parameters.put(entry.getKey(), values);
}
}
return this;
}
/**
* Add parameters from the given map of name=value pairs. For parameters with more than one value, each value will be
* appended using the same name. If a parameter already exists, append new values to the existing list of values for
* that parameter.
*/
public QueryStringBuilder addParameterLists(final Map> params)
{
if (params != null)
{
for (Entry> entry : params.entrySet())
{
List values = null;
if (entry.getValue() != null)
{
values = new ArrayList(entry.getValue());
}
parameters.put(entry.getKey(), values);
}
}
return this;
}
/**
* Return a new {@link QueryStringBuilder} instance having called {@link URLDecoder#decode(String, String)} on each
* name=value pair.
*/
public QueryStringBuilder decode()
{
return new QueryStringBuilder().addParameterLists(getParameterMap(new QSDecoder()));
}
/**
* Return a new {@link QueryStringBuilder} instance having called {@link URLEncoder#encode(String, String)} on each
* name=value pair.
*/
public QueryStringBuilder encode()
{
return new QueryStringBuilder().addParameterLists(getParameterMap(new QSEncoder()));
}
/**
* Get the first value of given parameter name.
*
* @return The value of the parameter, null if the parameter does not exist, or "" if the parameter exists but has no
* values.
*/
public String getParameter(final String name)
{
List values = parameters.get(name);
if (values == null)
{
return null;
}
if (values.size() == 0)
{
return "";
}
return values.get(0);
}
/**
* Get the name, values[] map representing this query string.
*/
public Map> getParameterMap()
{
return getParameterMap(new NullEncodingHandler());
}
private Map> getParameterMap(final EncodingHandler handler)
{
Map> map = new LinkedHashMap>();
for (Map.Entry> entry : parameters.entrySet())
{
String key = handler.encode(entry.getKey());
List values = new ArrayList();
for (String value : entry.getValue()) {
if (value != null) {
values.add(handler.encode(value));
}
}
map.put(key, new ArrayList(values));
}
return map;
}
/**
* Get set of parameter names currently stored in this query string.
*/
public Set getParameterNames()
{
return new LinkedHashSet(parameters.keySet());
}
/**
* Get the array of values for a given parameter name.
*
* @return The values of the parameter, null if the parameter does not exist.
*/
public String[] getParameterValues(final String name)
{
List values = parameters.get(name);
if (values == null)
{
return null;
}
return values.toArray(new String[values.size()]);
}
/*
* Utility Methods
*/
/**
* Return true if this query string currently contains no parameters.
*/
public boolean isEmpty()
{
return parameters.isEmpty();
}
public List removeParameter(final String string)
{
return parameters.remove(string);
}
/**
* Convert the current parameters to a valid query string, including the leading '?' character.
*
*
* For example, a {@link QueryStringBuilder} with the values [key=>value, name=>value1,value2,value3] will become:
*
*
*
* ?key=value&name=value1&name=value2&name=value3
*
*
* @return If parameters exist, return a valid query string with leading '?' character. If no parameters exist,
* return an empty string.
*/
public String toQueryString()
{
StringBuilder result = new StringBuilder();
if ((null != parameters) && !parameters.isEmpty())
{
result.append("?");
Iterator>> iterator = parameters.entrySet().iterator();
while (iterator.hasNext())
{
Entry> entry = iterator.next();
String key = entry.getKey();
List values = entry.getValue();
if ((key != null) && !"".equals(key))
{
result.append(key);
if ((values != null) && !values.isEmpty())
{
for (int i = 0; i < values.size(); i++)
{
String value = values.get(i);
if ((value != null) && !"".equals(value))
{
result.append("=" + value);
}
else if ((value != null) && "".equals(value))
{
result.append("=");
}
if (i < (values.size() - 1))
{
result.append("&" + key);
}
}
}
}
if (iterator.hasNext())
{
result.append("&");
}
}
}
return result.toString();
}
@Override
public String toString()
{
return toQueryString();
}
private interface EncodingHandler
{
public String encode(String value);
}
private class NullEncodingHandler implements EncodingHandler
{
@Override
public String encode(final String value)
{
return value;
}
}
private class QSDecoder implements EncodingHandler
{
@Override
public String encode(final String value)
{
try {
return URLDecoder.decode(value, "UTF-8");
}
catch (UnsupportedEncodingException e) {
throw new RewriteException("Encoding type UTF-8 is not supported by this JVM.", e);
}
catch (IllegalArgumentException e)
{
log.warn("Could not decode query parameter: " + value);
return value;
}
}
}
private class QSEncoder implements EncodingHandler
{
@Override
public String encode(final String value)
{
try {
return URLEncoder.encode(value, "UTF-8");
}
catch (UnsupportedEncodingException e) {
throw new RewriteException("Encoding type UTF-8 is not supported by this JVM.", e);
}
catch (IllegalArgumentException e)
{
log.warn("Could not encode query parameter: " + value);
return value;
}
}
}
}