V8 inspector: debug sourcemap-backed files
[idea/community.git] / platform / platform-impl / src / com / intellij / util / UrlImpl.java
1 /*
2  * Copyright 2000-2015 JetBrains s.r.o.
3  *
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
7  *
8  * http://www.apache.org/licenses/LICENSE-2.0
9  *
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.
15  */
16 package com.intellij.util;
17
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;
22
23 public final class UrlImpl implements Url {
24   private final String scheme;
25   private final String authority;
26
27   private final String path;
28   private String decodedPath;
29
30   private final String parameters;
31
32   private String externalForm;
33   private UrlImpl withoutParameters;
34
35   public UrlImpl(@NotNull String path) {
36     this(null, null, path, null);
37   }
38
39   UrlImpl(@NotNull String scheme, @Nullable String authority, @Nullable String path) {
40     this(scheme, authority, path, null);
41   }
42
43   public UrlImpl(@Nullable String scheme, @Nullable String authority, @Nullable String path, @Nullable String parameters) {
44     this.scheme = scheme;
45     this.authority = authority;
46     this.path = StringUtil.notNullize(path);
47     this.parameters = StringUtil.nullize(parameters);
48   }
49
50   @Override
51   public Url resolve(@NotNull String subPath) {
52     return new UrlImpl(scheme, authority, path.isEmpty() ? subPath : (path + "/" + subPath), parameters);
53   }
54
55   @NotNull
56   @Override
57   public String getPath() {
58     if (decodedPath == null) {
59       decodedPath = URLUtil.unescapePercentSequences(path);
60     }
61     return decodedPath;
62   }
63
64   @Nullable
65   @Override
66   public String getScheme() {
67     return scheme;
68   }
69
70   @Override
71   @Nullable
72   public String getAuthority() {
73     return authority;
74   }
75
76   @Override
77   public boolean isInLocalFileSystem() {
78     return URLUtil.FILE_PROTOCOL.equals(scheme);
79   }
80
81   @Nullable
82   @Override
83   public String getParameters() {
84     return parameters;
85   }
86
87   @Override
88   public String toDecodedForm() {
89     StringBuilder builder = new StringBuilder();
90     if (scheme != null) {
91       builder.append(scheme);
92       if (authority == null) {
93         builder.append(':');
94       }
95       else {
96         builder.append(URLUtil.SCHEME_SEPARATOR);
97       }
98
99       if (authority != null) {
100         builder.append(authority);
101       }
102     }
103     builder.append(getPath());
104     if (parameters != null) {
105       builder.append(parameters);
106     }
107     return builder.toString();
108   }
109
110   @Override
111   @NotNull
112   public String toExternalForm() {
113     if (externalForm != null) {
114       return externalForm;
115     }
116
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();
121     }
122
123     String result = Urls.toUriWithoutParameters(this).toASCIIString();
124     if (parameters != null) {
125       result += parameters;
126     }
127     externalForm = result;
128     return result;
129   }
130
131   @Override
132   @NotNull
133   public Url trimParameters() {
134     if (parameters == null) {
135       return this;
136     }
137     else if (withoutParameters == null) {
138       withoutParameters = new UrlImpl(scheme, authority, path, null);
139     }
140     return withoutParameters;
141   }
142
143   @Override
144   public String toString() {
145     return toExternalForm();
146   }
147
148   @Override
149   public boolean equals(Object o) {
150     if (this == o) {
151       return true;
152     }
153     if (!(o instanceof UrlImpl)) {
154       return false;
155     }
156
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);
159   }
160
161   @Override
162   public boolean equalsIgnoreCase(@Nullable Url o) {
163     if (this == o) {
164       return true;
165     }
166     if (!(o instanceof UrlImpl)) {
167       return false;
168     }
169
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);
175   }
176
177   @Override
178   public boolean equalsIgnoreParameters(@Nullable Url url) {
179     return url != null && equals(url.trimParameters());
180   }
181
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);
187     return result;
188   }
189
190   private static int stringHashCode(@Nullable CharSequence string, boolean caseSensitive) {
191     return string == null ? 0 : (caseSensitive ? string.hashCode() : StringUtil.stringHashCodeInsensitive(string));
192   }
193
194   @Override
195   public int hashCode() {
196     return computeHashCode(true);
197   }
198
199   @Override
200   public int hashCodeCaseInsensitive() {
201     return computeHashCode(false);
202   }
203 }