blob: a3b3f6021099ae408ee5691c8bb7c16737e2854b [file] [log] [blame]
/*
* Licensed to the Apache Software Foundation (ASF) under one or more
* contributor license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright ownership.
* The ASF licenses this file to You 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 flash.util;
import java.util.Iterator;
import java.util.LinkedHashMap;
import java.util.Map;
import java.util.StringTokenizer;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
public class URLHelper
{
private static Pattern URL_PATTERN = Pattern.compile("^(.*?)(\\?.*?)?(#.*)?$"); //$NON-NLS-1$
/**
* Everything before the "query" part of the URL. E.g. for
* "http://www.example.com/file?firstname=Bob&lastname=Smith#foo"
* this would be "http://www.example.com/file".
*/
private String m_everythingBeforeQuery;
/**
* The "query" in a URL is the "?firstname=Bob&lastname=Smith" part.
* m_query contains the query (including "?"), or contains "" if the
* URL has no query. Never null.
*/
private String m_query;
/**
* The "fragment" in a URL is the "#foo" part at the end of a URL.
* m_fragment contains the fragment (including "#"), or contains "" if the
* URL has no fragment. Never null.
*/
private String m_fragment;
public URLHelper(String url)
{
Matcher matcher = URL_PATTERN.matcher(url);
if (!matcher.matches())
throw new IllegalArgumentException(url);
if (matcher.matches())
{
m_everythingBeforeQuery = matcher.group(1);
m_query = matcher.group(2);
if (m_query == null) m_query = ""; //$NON-NLS-1$
m_fragment = matcher.group(3);
if (m_fragment == null) m_fragment = ""; //$NON-NLS-1$
}
}
/**
* Everything before the "query" part of the URL. E.g. for
* "http://www.example.com/file?firstname=Bob&lastname=Smith#foo"
* this would be "http://www.example.com/file".
*/
public String getEverythingBeforeQuery()
{
return m_everythingBeforeQuery;
}
public void setEverythingBeforeQuery(String everythingBeforeQuery)
{
assertValidArguments(everythingBeforeQuery, getQuery(), getFragment());
m_everythingBeforeQuery = everythingBeforeQuery;
}
/**
* Rturns the "query" portion of the URL, e.g. the
* "?firstname=Bob&lastname=Smith" part. m_query contains the query
* (including "?"), or "" if the URL has no query. Never null.
*/
public String getQuery()
{
return m_query;
}
/**
* Sets the "query" portion of the URL. This must be either the
* empty string or a string that begins with "?".
*/
public void setQuery(String query)
{
// if there is a query, make sure it starts with "?"
if (query.length() > 0 && query.charAt(0) != '?')
query = "?" + query; //$NON-NLS-1$
assertValidArguments(getEverythingBeforeQuery(), query, getFragment());
m_query = query;
}
/**
* Returns the "fragment" portion of the URL, e.g. the "#foo" part, or
* "" if the URL has no fragment. Never null.
*/
public String getFragment()
{
return m_fragment;
}
/**
* Sets the "fragment" portion of the URL. This must be either the
* empty string or a string that begins with "#".
* @param fragment
*/
public void setFragment(String fragment)
{
// if there is a fragment, make sure it starts with "#"
if (fragment.length() > 0 && fragment.charAt(0) != '#')
fragment = "#" + fragment; //$NON-NLS-1$
assertValidArguments(getEverythingBeforeQuery(), getQuery(), fragment);
m_fragment = fragment;
}
private static void assertValidArguments(String everythingBeforeQuery, String query, String fragment)
{
assert areArgumentsValid(everythingBeforeQuery, query, fragment);
}
/**
* This will test for various error conditions, e.g. a query string that
* contains "#" or has incorrect contents.
*/
private static boolean areArgumentsValid(String everythingBeforeQuery, String query, String fragment)
{
if (everythingBeforeQuery == null || query == null || fragment == null)
return false;
URLHelper newHelper = new URLHelper(everythingBeforeQuery + query + fragment);
if (!newHelper.getEverythingBeforeQuery().equals(everythingBeforeQuery) ||
!newHelper.getQuery().equals(query) ||
!newHelper.getFragment().equals(fragment))
{
return false;
}
return true;
}
/**
* Returns the entire URL.
*/
public String getURL()
{
return m_everythingBeforeQuery + m_query + m_fragment;
}
/**
* Returns the query portion of the URL, broken up into individual key/value
* pairs. Does NOT unescape the keys and values.
*/
public LinkedHashMap<String, String> getParameterMap()
{
LinkedHashMap<String, String> map;
StringTokenizer tokens = new StringTokenizer(getQuery(), "?&"); //$NON-NLS-1$
// multiply by 2 to create a sufficiently large HashMap
map = new LinkedHashMap<String, String>(tokens.countTokens() * 2);
while (tokens.hasMoreElements())
{
String nameValuePair = tokens.nextToken();
String name = nameValuePair;
String value = ""; //$NON-NLS-1$
int equalsIndex = nameValuePair.indexOf('=');
if (equalsIndex != -1)
{
name = nameValuePair.substring(0, equalsIndex);
if (name.length() > 0)
{
value = nameValuePair.substring(equalsIndex + 1);
}
}
map.put(name, value);
}
return map;
}
/**
* Sets the query portion of the URL.
*
* @param parameterMap
* a key/value mapping; these must already be escaped!
*/
public void setParameterMap(Map<String,String> parameterMap)
{
if ((parameterMap != null) && (!parameterMap.isEmpty()))
{
StringBuilder queryString = new StringBuilder();
Iterator<Map.Entry<String,String>> it = parameterMap.entrySet().iterator();
while (it.hasNext())
{
Map.Entry<String,String> entry = it.next();
String name = (String) entry.getKey();
String value = String.valueOf(entry.getValue());
queryString.append(name);
if ((value != null) && (!value.equals(""))) //$NON-NLS-1$
{
queryString.append('=');
queryString.append(value);
}
if (it.hasNext())
{
queryString.append('&');
}
}
setQuery(queryString.toString());
} else
{
setQuery(""); //$NON-NLS-1$
}
}
// shortcut for converting spaces to %20 in URIs
public static String escapeSpace(String uri)
{
return escapeCharacter(uri, ' ', "%20"); //$NON-NLS-1$
}
/**
* Locates characters 'c' in the scheme specific portion of a URI and
* translates them into 'to'
*/
public static String escapeCharacter(String uri, char c, String to)
{
StringBuilder sb = new StringBuilder();
int size = uri.length();
int at = uri.indexOf(':');
int lastAt = 0;
// skip the scheme
if (at > -1)
{
for(int i=0; i<=at; i++)
sb.append(uri.charAt(i));
lastAt = ++at;
}
// while we have 'c's in uri
while( (at = uri.indexOf(c, at)) > -1)
{
// original portion
for(int i=lastAt; i<at; i++)
sb.append(uri.charAt(i));
// conversion
sb.append(to);
lastAt = ++at; // advance to char after conversion
}
if (lastAt < size)
{
for(int i=lastAt; i<size; i++)
sb.append(uri.charAt(i));
}
return sb.toString();
}
}