xref: /OpenGrok/opengrok-indexer/src/main/java/org/opengrok/indexer/util/UriUtils.java (revision 5d9f3aa0ca3da3a714233f987fa732f62c0965f6)
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