/* * Copyright 2000-2013 Enonic AS * http://www.enonic.com/license */ package com.enonic.esl.net; import java.util.Iterator; import java.util.List; import java.util.Map; import java.util.StringTokenizer; import com.enonic.esl.containers.MultiValueMap; public class URL { public static class Parameter { private String key; private List values; private Parameter( String key, List values ) { this.key = key; this.values = values; } public String getKey() { return key; } public List getValues() { return values; } } private static class ParameterIterator implements Iterator { private Iterator entryIterator; private ParameterIterator( MultiValueMap queryParams ) { entryIterator = queryParams.entrySet().iterator(); } public boolean hasNext() { return entryIterator.hasNext(); } public Object next() { Map.Entry entry = (Map.Entry) entryIterator.next(); String key = entry.getKey().toString(); List values = (List) entry.getValue(); return new Parameter( key, values ); } public void remove() { entryIterator.remove(); } } private String baseURL; private MultiValueMap queryParams = new MultiValueMap(); private String label; public URL( String url ) { if ( url != null && url.trim().length() > 0 ) { String urlString; int labelIndex = url.indexOf( '#' ); if ( labelIndex >= 0 ) { this.label = url.substring( labelIndex + 1 ); urlString = url.substring( 0, labelIndex ); } else { urlString = url; } StringTokenizer tokenizer = new StringTokenizer( urlString, "?" ); this.baseURL = tokenizer.nextToken(); if ( tokenizer.hasMoreTokens() ) { String queryString = tokenizer.nextToken( "" ).substring( 1 ); tokenizer = new StringTokenizer( queryString, "&" ); while ( tokenizer.hasMoreTokens() ) { String token = tokenizer.nextToken(); String name; String value = null; int equalIdx = token.indexOf( '=' ); if ( equalIdx == -1 ) { name = token; } else { name = token.substring( 0, equalIdx ); value = token.substring( equalIdx + 1 ); } if ( value != null ) { queryParams.put( name, value ); } } } } else { throw new IllegalArgumentException( "URL cannot be empty" ); } } public URL( StringBuffer url ) { this( url.toString() ); } /** * Add a parameter. It will be appended to the URL string as a "name=value" pair. Previously added parameters with the same name are * preserved, as multiple values pr. name is allowed. * * @param name String * @param value String * @return <code>true</code> if the value was added, <code>false</code> otherwise. */ public boolean addParameter( String name, String value ) { if ( name == null || name.length() == 0 ) { return false; } if ( value == null || value.length() == 0 ) { return false; } queryParams.put( URLUtil.encode( name ), URLUtil.encode( value ) ); return true; } /** * Add parameters from av multi-value map. Iterates over the map's values and append them to the URL string as "name=value" pairs. * Previously added parameters with the same names as those added are preserved, as multiple values pr. name is allowed. * * @param valueMap MultiValueMap */ public void addParameters( MultiValueMap valueMap ) { for ( Object key : valueMap.keySet() ) { for ( Object value : ( valueMap.getValueList( key ) ) ) { queryParams.put( URLUtil.encode( key.toString() ), URLUtil.encode( value.toString() ) ); } } } public boolean setParameter( String name, int value ) { return setParameter( name, String.valueOf( value ) ); } public boolean setParameter( String name, String value ) { if ( name == null || name.length() == 0 ) { return false; } if ( value == null || value.length() == 0 ) { queryParams.put( URLUtil.encode( name ), "", true ); } else { queryParams.put( URLUtil.encode( name ), URLUtil.encode( value ), true ); } return true; } public List getParameters( String name ) { if ( name == null || name.length() == 0 ) { return null; } return queryParams.getValueList( name ); } public MultiValueMap getParameterMap() { return queryParams; } public String getParameter( String name ) { if ( name == null || name.length() == 0 ) { return null; } List valueList = queryParams.getValueList( name ); if ( valueList != null && valueList.size() > 0 ) { return (String) valueList.get( 0 ); } else { return null; } } public void removeParameter( String name ) { if ( name == null || name.length() == 0 ) { return; } queryParams.remove( name ); } public Iterator parameterIterator() { return new ParameterIterator( queryParams ); } public String toString() { StringBuffer url = new StringBuffer( baseURL ); Iterator keyIterator = queryParams.keySet().iterator(); boolean firstParam = true; while ( keyIterator.hasNext() ) { String key = (String) keyIterator.next(); for ( Object value : queryParams.getValueList( key ) ) { if ( firstParam ) { url.append( '?' ); firstParam = false; } else { url.append( '&' ); } url.append( key ); url.append( '=' ); url.append( value ); } } if ( label != null ) { if ( firstParam ) { // First param has still not been added, so there are no parameters and the & is not needed. url.append( "#" ); } else { // HACK: adds an extra '&' to the URL to bypass the bug concerning // request.sendRedirect() // and Internet Explorer url.append( "&#" ); } url.append( label ); } return url.toString(); } public void setLabel( String string ) { label = string; } public boolean hasParameter( String name ) { return queryParams.containsKey( name ); } }