001// --------------------------------------------------------------------------------
002// Copyright 2002-2025 Echo Three, LLC
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// --------------------------------------------------------------------------------
016
017package com.echothree.util.common.string;
018
019import java.io.UnsupportedEncodingException;
020import java.net.URLEncoder;
021import java.util.Map;
022import javax.servlet.http.HttpServletRequest;
023import javax.servlet.http.HttpServletResponse;
024
025public class UrlUtils {
026    
027    private UrlUtils() {
028        super();
029    }
030    
031    private static class UrlUtilsHolder {
032        static UrlUtils instance = new UrlUtils();
033    }
034    
035    public static UrlUtils getInstance() {
036        return UrlUtilsHolder.instance;
037    }
038    
039    public StringBuilder buildBaseUrl(HttpServletRequest request) {
040        var scheme = request.getScheme();
041        var serverName = request.getServerName();
042        var serverPort = request.getServerPort();
043        var contextPath = request.getContextPath();
044        var servletPath = request.getServletPath();
045        var includeServerPort = (scheme.equals("http") && serverPort != 80) || (scheme.equals("https") && serverPort != 443);
046        
047        return new StringBuilder(scheme).append("://").append(serverName).append(includeServerPort? ":" + serverPort: "").append(contextPath).append(servletPath);
048    }
049
050    public StringBuilder buildParams(StringBuilder url, Map<String, String> params) {
051        if(params != null && params.size() > 0) {
052            var entrySet = params.entrySet();
053            var isFirst = true;
054
055            for(var entry : entrySet) {
056                url.append(isFirst ? '?' : '&');
057                try {
058                    url.append(entry.getKey()).append('=').append(URLEncoder.encode(entry.getValue(), "UTF-8"));
059                } catch(UnsupportedEncodingException uee) {
060                    // If UTF-8 isn't a supported encoding, then there are severe problems.
061                    throw new RuntimeException(uee);
062                }
063                isFirst = false;
064            }
065        }
066
067        return url;
068    }
069
070    public String buildUrl(HttpServletRequest request, HttpServletResponse response, String path, Map<String, String> params) {
071        return response.encodeURL(buildParams(buildBaseUrl(request).append(path), params).toString());
072    }
073    
074}