2 * Copyright 2000-2015 JetBrains s.r.o.
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
8 * http://www.apache.org/licenses/LICENSE-2.0
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
16 package com.intellij.util;
18 import com.intellij.openapi.util.text.StringUtil;
19 import com.intellij.util.io.URLUtil;
20 import org.jetbrains.annotations.NotNull;
21 import org.jetbrains.annotations.Nullable;
23 public final class UrlImpl implements Url {
24 private final String scheme;
25 private final String authority;
27 private final String path;
28 private String decodedPath;
30 private final String parameters;
32 private String externalForm;
33 private UrlImpl withoutParameters;
35 public UrlImpl(@NotNull String path) {
36 this(null, null, path, null);
39 UrlImpl(@NotNull String scheme, @Nullable String authority, @Nullable String path) {
40 this(scheme, authority, path, null);
43 public UrlImpl(@Nullable String scheme, @Nullable String authority, @Nullable String path, @Nullable String parameters) {
45 this.authority = authority;
46 this.path = StringUtil.notNullize(path);
47 this.parameters = StringUtil.nullize(parameters);
51 public Url resolve(@NotNull String subPath) {
52 return new UrlImpl(scheme, authority, path.isEmpty() ? subPath : (path + "/" + subPath), parameters);
57 public String getPath() {
58 if (decodedPath == null) {
59 decodedPath = URLUtil.unescapePercentSequences(path);
66 public String getScheme() {
72 public String getAuthority() {
77 public boolean isInLocalFileSystem() {
78 return URLUtil.FILE_PROTOCOL.equals(scheme);
83 public String getParameters() {
88 public String toDecodedForm() {
89 StringBuilder builder = new StringBuilder();
91 builder.append(scheme);
92 if (authority == null) {
96 builder.append(URLUtil.SCHEME_SEPARATOR);
99 if (authority != null) {
100 builder.append(authority);
103 builder.append(getPath());
104 if (parameters != null) {
105 builder.append(parameters);
107 return builder.toString();
112 public String toExternalForm() {
113 if (externalForm != null) {
117 // relative path - special url, encoding is not required
118 // authority is null in case of URI
119 if ((authority == null || (!path.isEmpty() && path.charAt(0) != '/')) && !isInLocalFileSystem()) {
120 return toDecodedForm();
123 String result = Urls.toUriWithoutParameters(this).toASCIIString();
124 if (parameters != null) {
125 result += parameters;
127 externalForm = result;
133 public Url trimParameters() {
134 if (parameters == null) {
137 else if (withoutParameters == null) {
138 withoutParameters = new UrlImpl(scheme, authority, path, null);
140 return withoutParameters;
144 public String toString() {
145 return toExternalForm();
149 public boolean equals(Object o) {
153 if (!(o instanceof UrlImpl)) {
157 UrlImpl url = (UrlImpl)o;
158 return StringUtil.equals(scheme, url.scheme) && StringUtil.equals(authority, url.authority) && getPath().equals(url.getPath()) && StringUtil.equals(parameters, url.parameters);
162 public boolean equalsIgnoreCase(@Nullable Url o) {
166 if (!(o instanceof UrlImpl)) {
170 UrlImpl url = (UrlImpl)o;
171 return StringUtil.equalsIgnoreCase(scheme, url.scheme) &&
172 StringUtil.equalsIgnoreCase(authority, url.authority) &&
173 getPath().equalsIgnoreCase(url.getPath()) &&
174 StringUtil.equalsIgnoreCase(parameters, url.parameters);
178 public boolean equalsIgnoreParameters(@Nullable Url url) {
179 return url != null && equals(url.trimParameters());
182 private int computeHashCode(boolean caseSensitive) {
183 int result = stringHashCode(scheme, caseSensitive);
184 result = 31 * result + stringHashCode(authority, caseSensitive);
185 result = 31 * result + stringHashCode(getPath(), caseSensitive);
186 result = 31 * result + stringHashCode(parameters, caseSensitive);
190 private static int stringHashCode(@Nullable CharSequence string, boolean caseSensitive) {
191 return string == null ? 0 : (caseSensitive ? string.hashCode() : StringUtil.stringHashCodeInsensitive(string));
195 public int hashCode() {
196 return computeHashCode(true);
200 public int hashCodeCaseInsensitive() {
201 return computeHashCode(false);