001/*
002 *  Copyright 2012 Anyware Services
003 *
004 *  Licensed under the Apache License, Version 2.0 (the "License");
005 *  you may not use this file except in compliance with the License.
006 *  You may obtain a copy of the License at
007 *
008 *      http://www.apache.org/licenses/LICENSE-2.0
009 *
010 *  Unless required by applicable law or agreed to in writing, software
011 *  distributed under the License is distributed on an "AS IS" BASIS,
012 *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
013 *  See the License for the specific language governing permissions and
014 *  limitations under the License.
015 */
016package org.ametys.core.util;
017
018import java.io.UnsupportedEncodingException;
019import java.net.URI;
020import java.net.URISyntaxException;
021import java.util.Map;
022
023/**
024 * Utility class for encoding URL.
025 */
026public final class URLEncoder
027{
028    private static final String __NAME_VALUE_SEPARATOR = "=";
029    private static final String __PARAMETER_SEPARATOR = "&";
030    
031    private URLEncoder()
032    {
033        // empty
034    }
035    
036    /**
037     * Encode a parameter's value using UTF-8 encoding
038     * @param value the value or the name of the request's parameter to encode
039     * @return the encoded value.
040     */
041    public static String encodeParameter(String value)
042    {
043        try
044        {
045            return java.net.URLEncoder.encode(value, "UTF-8"); 
046        }
047        catch (UnsupportedEncodingException e)
048        {
049            throw new RuntimeException("Unable to encode parameter " + value, e);
050        }
051    }
052    
053    /**
054     * Encode an URL path 
055     * @param path the path to encode (before question-mark character)
056     * @return the encoded path.
057     */
058    public static String encodePath(String path)
059    {
060        try
061        {
062            return new URI(null, null, path, null, null).toASCIIString().replaceAll("\\+", "%2B");
063        }
064        catch (URISyntaxException e)
065        {
066            throw new RuntimeException("Unable to encode path " + path, e);
067        }
068    }
069    
070    /**
071     * Encode an URL path
072     * @param path the path to encode (before question-mark character)
073     * @param parameters the parameters. Can be null.
074     * @return the encoded path
075     */
076    public static String encodeURI(String path, Map<String, String> parameters)
077    {
078        StringBuilder sb = new StringBuilder();
079        sb.append(encodePath(path));
080        
081        if (parameters != null && !parameters.isEmpty())
082        {
083            StringBuilder query = new StringBuilder();
084            
085            for (String paramName : parameters.keySet())
086            {
087                String encodedName = encodeParameter(paramName);
088                String encodedValue = encodeParameter(parameters.get(paramName));
089                
090                if (query.length() > 0) 
091                {
092                    query.append(__PARAMETER_SEPARATOR);
093                }
094                
095                query.append(encodedName)
096                    .append(__NAME_VALUE_SEPARATOR)
097                    .append(encodedValue);
098            }
099            
100            sb.append("?").append(query.toString());
101        }
102        
103        return sb.toString();
104        
105    }
106}