001/* 002 * The contents of this file are subject to the terms of the Common Development and 003 * Distribution License (the License). You may not use this file except in compliance with the 004 * License. 005 * 006 * You can obtain a copy of the License at legal/CDDLv1.0.txt. See the License for the 007 * specific language governing permission and limitations under the License. 008 * 009 * When distributing Covered Software, include this CDDL Header Notice in each file and include 010 * the License file at legal/CDDLv1.0.txt. If applicable, add the following below the CDDL 011 * Header, with the fields enclosed by brackets [] replaced by your own identifying 012 * information: "Portions copyright [year] [name of copyright owner]". 013 * 014 * Copyright 2015 ForgeRock AS. 015 */ 016 017package org.forgerock.http.util; 018 019import static java.util.Collections.*; 020 021import java.util.ArrayList; 022import java.util.List; 023import java.util.regex.Pattern; 024 025/** 026 * Utilities for manipulating paths. 027 */ 028public final class Paths { 029 private static final Pattern PATH_SPLIT_PATTERN = Pattern.compile("/"); 030 031 /** 032 * Returns the URL path decoding of the provided object's string 033 * representation. 034 * 035 * @param value 036 * The value to be URL path decoded. 037 * @return The URL path decoding of the provided object's string 038 * representation. 039 */ 040 public static String urlDecode(final Object value) { 041 return Uris.urlDecodePathElement(value.toString()); 042 } 043 044 /** 045 * Returns the URL path encoding of the provided object's string 046 * representation. 047 * 048 * @param value 049 * The value to be URL path encoded. 050 * @return The URL path encoding of the provided object's string 051 * representation. 052 */ 053 public static String urlEncode(final Object value) { 054 return Uris.urlEncodePathElement(value.toString()); 055 } 056 057 /** 058 * Converts a path into a list of URL-decoded path elements. If the leading path element 059 * is empty it is dropped, meaning that {@code null}, {@code ""} and {@code "/"} will 060 * all return an empty list, and {@code "//"} will return a list with two elements, both 061 * empty strings, as all intermediate and trailing empty paths are retained. 062 * 063 * @param rawPath The raw, URL-encoded path string. 064 * @return An immutable list of the path elements. 065 */ 066 public static List<String> getPathElements(String rawPath) { 067 String[] pathElements = null; 068 if (rawPath != null) { 069 if (rawPath.startsWith("/")) { 070 rawPath = rawPath.substring(1); 071 } 072 pathElements = PATH_SPLIT_PATTERN.split(rawPath, -1); 073 if (pathElements.length == 1 && pathElements[0].isEmpty()) { 074 pathElements = null; 075 } 076 } 077 078 List<String> elements; 079 if (pathElements == null) { 080 elements = emptyList(); 081 } else { 082 List<String> decodedElements = new ArrayList<>(pathElements.length); 083 for (String element : pathElements) { 084 decodedElements.add(Paths.urlDecode(element)); 085 } 086 elements = decodedElements; 087 } 088 return unmodifiableList(elements); 089 } 090 091 /** 092 * Joins a list of URL-decoded path elements into a url-encoded path. 093 * @param elements The list of (URL-decoded) elements. 094 * @return The raw path. 095 */ 096 public static String joinPath(List<String> elements) { 097 if (elements == null) { 098 return ""; 099 } 100 StringBuilder s = new StringBuilder(); 101 for (String element : elements) { 102 if (s.length() > 0) { 103 s.append("/"); 104 } 105 s.append(urlEncode(element)); 106 } 107 return s.toString(); 108 } 109 110 private Paths() { 111 // utilities only. 112 } 113}