1 /* 2 * CDDL HEADER START 3 * 4 * The contents of this file are subject to the terms of the 5 * Common Development and Distribution License (the "License"). 6 * You may not use this file except in compliance with the License. 7 * 8 * See LICENSE.txt included in this distribution for the specific 9 * language governing permissions and limitations under the License. 10 * 11 * When distributing Covered Code, include this CDDL HEADER in each 12 * file and include the License file at LICENSE.txt. 13 * If applicable, add the following below this CDDL HEADER, with the 14 * fields enclosed by brackets "[]" replaced with your own identifying 15 * information: Portions Copyright [yyyy] [name of copyright owner] 16 * 17 * CDDL HEADER END 18 */ 19 20 /* 21 * Copyright (c) 2017, 2019, Chris Fraire <cfraire@me.com>. 22 */ 23 package org.opengrok.indexer.util; 24 25 import java.util.regex.Pattern; 26 27 /** 28 * Represents a container for utility methods concerned with URIs. 29 */ 30 public class UriUtils { 31 32 /** 33 * Represents the immutable return value of 34 * {@link #trimUri(String, boolean, Pattern)}. 35 */ 36 public static final class TrimUriResult { 37 private final String uri; 38 private final int pushBackCount; 39 TrimUriResult(String uri, int pushBackCount)40 TrimUriResult(String uri, int pushBackCount) { 41 this.uri = uri; 42 this.pushBackCount = pushBackCount; 43 } 44 getUri()45 public String getUri() { 46 return uri; 47 } 48 getPushBackCount()49 public int getPushBackCount() { 50 return pushBackCount; 51 } 52 } 53 54 /** 55 * Trims a URI, specifying whether to enlist the 56 * {@link StringUtils#countURIEndingPushback(String)} algorithm or the 57 * {@link StringUtils#countPushback(String, Pattern)} or both. 58 * <p> 59 * If the pushback count is equal to the length of {@code url}, then the 60 * pushback is set to zero -- in order to avoid a never-ending lexical loop. 61 * 62 * @param uri the URI string 63 * @param shouldCheckEnding a value indicating whether to call 64 * {@link StringUtils#countURIEndingPushback(String)} 65 * @param collateralCapture optional pattern to call with 66 * {@link StringUtils#countPushback(String, Pattern)} 67 * @return a defined instance 68 */ trimUri(String uri, boolean shouldCheckEnding, Pattern collateralCapture)69 public static TrimUriResult trimUri(String uri, boolean shouldCheckEnding, 70 Pattern collateralCapture) { 71 72 int n = 0; 73 while (true) { 74 /* 75 * An ending-pushback could be present before a collateral capture, 76 * so detect both in a loop (on a shrinking `url') until no more 77 * shrinking should occur. 78 */ 79 80 int subN = 0; 81 if (shouldCheckEnding) { 82 subN = StringUtils.countURIEndingPushback(uri); 83 } 84 int ccn = StringUtils.countPushback(uri, collateralCapture); 85 if (ccn > subN) { 86 subN = ccn; 87 } 88 89 // Increment if positive, but not if equal to the current length. 90 if (subN > 0 && subN < uri.length()) { 91 uri = uri.substring(0, uri.length() - subN); 92 n += subN; 93 } else { 94 break; 95 } 96 } 97 return new TrimUriResult(uri, n); 98 } 99 100 /** Private to enforce static. */ UriUtils()101 private UriUtils() { 102 } 103 } 104