class UrlHelper {

    public static String getCanonicalUrl(String url) {
        if (url == null) {
            return "";
        }

        try {

            URL urlObj = new URL(url);

            // get all url parts
            String protocol = urlObj.getProtocol();
            String port = "";
            if (urlObj.getPort() != -1 && urlObj.getPort() != urlObj.getDefaultPort()) {
                port = ":" + urlObj.getPort();
            }
            String host = urlObj.getHost().toLowerCase();
            String path = urlObj.getPath();
            String[] query = null;
            if (urlObj.getQuery() != null) {
                query = urlObj.getQuery().split("&");

                // sort query parts alphabetically
                Arrays.sort(query);
            }

            // correct path to eliminate ".." and recreate path accordingly
            String[] parts = path.split("/");
            path = "/";

            if (parts.length > 0) {
                for (int i = 0; i < parts.length; i++) {
                    parts[i] = parts[i].trim();
                    // throw away ".." and a directory above it
                    if (parts[i].equals("..")) {
                        parts[i] = "";
                        // if there is a directory above this one in the path
                        if (parts.length > 1 && i > 0) {
                            parts[i - 1] = "";
                        }
                    }
                }
                for (String part : parts) {
                    if (part.length() > 0) {
                        path += part + "/";
                    }
                }

                // delete trailing slash if path ends with a file
                if (parts[parts.length - 1].contains(".")) {
                    path = path.substring(0, path.length() - 1);
                }
                // delete index.* if there is no query
                if (parts[parts.length - 1].contains("index") && query == null) {
                    path = path.replaceAll("index\\..+$", "");
                }

            }

            String queryPart = query != null ? "?" + StringUtils.join(query, "&") : "";
            return protocol + "://" + port + host + path + queryPart;

        } catch (MalformedURLException e) {
            LOGGER.trace("could not determine canonical url for {}", url);
            return "";
        }
    }

    private  UrlHelper();

}