SLING-9777 Better handling for invalid URIs when using SlingUri (special
characters, spaces)
diff --git a/src/main/java/org/apache/sling/api/uri/SlingUri.java b/src/main/java/org/apache/sling/api/uri/SlingUri.java
index 2ad757e..bfe8022 100644
--- a/src/main/java/org/apache/sling/api/uri/SlingUri.java
+++ b/src/main/java/org/apache/sling/api/uri/SlingUri.java
@@ -29,9 +29,14 @@
import org.osgi.annotation.versioning.ProviderType;
/**
+ * <p>
* Represents an immutable URI in the same way as java.net.URI but is extended with Sling-specific URI parts (e.g. selectors). A SlingUri
* usually points to a resource but alternatively, can also contain an opaque URI like {@code mailto:} or {@code javascript:}. Use
* {@link SlingUri#adjust(Consumer)} or {@link SlingUriBuilder} to create new or modified Sling URIs.
+ * </p>
+ * <p>
+ * Opposed to {@link URI}, the regular getters of {@code SlingUri} will not return decoded values, rather the values for user info, path,
+ * query and fragment are returned exactly as set before.
*
* @since 1.0.0 (Sling API Bundle 2.23.0)
*/
@@ -97,7 +102,7 @@
/**
* Returns the selector string.
*
- * @return returns the selector string or null if the URI does not contain selector(s)
+ * @return returns the selector string or null if the URI does not contain selector(s) (in line with {@link RequestPathInfo})
*/
@Override
@Nullable
diff --git a/src/main/java/org/apache/sling/api/uri/SlingUriBuilder.java b/src/main/java/org/apache/sling/api/uri/SlingUriBuilder.java
index 7088672..eaa87d2 100644
--- a/src/main/java/org/apache/sling/api/uri/SlingUriBuilder.java
+++ b/src/main/java/org/apache/sling/api/uri/SlingUriBuilder.java
@@ -18,8 +18,11 @@
*/
package org.apache.sling.api.uri;
+import java.io.UnsupportedEncodingException;
import java.net.URI;
import java.net.URISyntaxException;
+import java.net.URLEncoder;
+import java.nio.charset.StandardCharsets;
import java.util.Arrays;
import java.util.Collections;
import java.util.Iterator;
@@ -42,7 +45,7 @@
import org.slf4j.LoggerFactory;
/**
- * Builder for SlingUris.
+ * Builder for SlingUris that allows to set any properties of a {@link SlingUri}.
* <p>
* Example:
*
@@ -67,9 +70,11 @@
private static final int HTTPS_DEFAULT_PORT = 443;
private static final String HTTP_SCHEME = "http";
private static final int HTTP_DEFAULT_PORT = 80;
+ private static final String FILE_SCHEME = "file";
- static final char CHAR_HASH = '#';
- static final char CHAR_QM = '?';
+ static final String CHAR_HASH = "#";
+ static final String CHAR_QM = "?";
+ static final char CHAR_AMP = '&';
static final char CHAR_AT = '@';
static final char CHAR_SEMICOLON = ';';
static final char CHAR_EQUALS = '=';
@@ -79,6 +84,7 @@
static final String CHAR_SLASH = "/";
static final String SELECTOR_DOT_REGEX = "\\.(?!\\.?/)"; // (?!\\.?/) to avoid matching ./ and ../
static final String PATH_PARAMETERS_REGEX = ";([a-zA-z0-9]+)=(?:\\'([^']*)\\'|([^/]+))";
+ static final String BEST_EFFORT_INVALID_URI_MATCHER = "^(?:([^:#@]+):)?(?://(?:([^@#]+)@)?([^/#:]+)(?::([0-9]+))?)?(?:([^?#]+))?(?:\\?([^#]*))?(?:#(.*))?$";
/**
* Creates a builder without any URI parameters set.
@@ -112,7 +118,7 @@
.setFragment(slingUri.getFragment())
.setSchemeSpecificPart(slingUri.isOpaque() ? slingUri.getSchemeSpecificPart() : null)
.setResourceResolver(slingUri instanceof ImmutableSlingUri
- ? ((ImmutableSlingUri) slingUri).getBuilder().resourceResolver
+ ? ((ImmutableSlingUri) slingUri).getData().resourceResolver
: null);
}
@@ -172,19 +178,24 @@
*/
@NotNull
public static SlingUriBuilder createFrom(@NotNull URI uri, @Nullable ResourceResolver resourceResolver) {
- String path = uri.getPath();
+ String path = uri.getRawPath();
boolean pathExists = isNotBlank(path);
- boolean schemeSpecificRelevant = !pathExists && uri.getQuery() == null;
+ String uriQuery = uri.getRawQuery();
+ boolean schemeSpecificRelevant = !pathExists && uriQuery == null;
+ String uriHost = uri.getHost();
+ if (FILE_SCHEME.equals(uri.getScheme()) && uriHost == null) {
+ uriHost = ""; // ensure three slashes in file URIs without host
+ }
return create()
.setResourceResolver(resourceResolver)
.setScheme(uri.getScheme())
- .setUserInfo(uri.getUserInfo())
- .setHost(uri.getHost())
+ .setUserInfo(uri.getRawUserInfo())
+ .setHost(uriHost)
.setPort(uri.getPort())
.setPath(pathExists ? path : null)
- .setQuery(uri.getQuery())
- .setFragment(uri.getFragment())
- .setSchemeSpecificPart(schemeSpecificRelevant ? uri.getSchemeSpecificPart() : null);
+ .setQuery(uriQuery)
+ .setFragment(uri.getRawFragment())
+ .setSchemeSpecificPart(schemeSpecificRelevant ? uri.getRawSchemeSpecificPart() : null);
}
/**
@@ -203,15 +214,43 @@
return createFrom(uri, resourceResolver);
} catch (URISyntaxException e) {
LOG.debug("Invalid URI {}: {}", uriStr, e.getMessage(), e);
- // best effort
- String[] invalidUriParts = uriStr.split(CHAR_COLON, 2);
- if (invalidUriParts.length == 1) {
- return create().setSchemeSpecificPart(invalidUriParts[0]);
- } else {
- return create()
- .setScheme(invalidUriParts[0])
- .setSchemeSpecificPart(invalidUriParts[1]);
- }
+ // best effort to match input, see SlingUriInvalidUrisTest
+ return parseBestEffort(uriStr, resourceResolver);
+ }
+ }
+
+ private static SlingUriBuilder parseBestEffort(String uriStr, ResourceResolver resourceResolver) {
+ Matcher matcher = Pattern.compile(BEST_EFFORT_INVALID_URI_MATCHER).matcher(uriStr);
+ matcher.find();
+
+ String scheme = matcher.group(1);
+ String userInfo = matcher.group(2);
+ String host = matcher.group(3);
+ String port = matcher.groupCount() >= 4 ? matcher.group(4) : null;
+ String path = matcher.groupCount() >= 5 ? matcher.group(5) : null;
+ String query = matcher.groupCount() >= 6 ? matcher.group(6) : null;
+ String fragment = matcher.groupCount() >= 7 ? matcher.group(7) : null;
+ if (!isBlank(scheme) && isBlank(host)) {
+ // opaque case
+ return create()
+ .setResourceResolver(resourceResolver)
+ .setScheme(scheme)
+ .setSchemeSpecificPart(path)
+ .setFragment(fragment);
+ } else if (!isBlank(host) || !isBlank(path)) {
+ return create()
+ .setResourceResolver(resourceResolver)
+ .setScheme(scheme)
+ .setUserInfo(userInfo)
+ .setHost(host)
+ .setPort(port != null ? Integer.parseInt(port) : -1)
+ .setPath(path)
+ .setQuery(query)
+ .setFragment(fragment);
+ } else {
+ return create()
+ .setResourceResolver(resourceResolver)
+ .setSchemeSpecificPart(uriStr);
}
}
@@ -495,6 +534,51 @@
}
/**
+ * Add a query parameter to the query of the URI. Key and value are URL-encoded before adding the parameter to the query string.
+ *
+ * @param parameterName the parameter name
+ * @param value the parameter value
+ * @return the builder for method chaining
+ */
+ @NotNull
+ public SlingUriBuilder addQueryParameter(@NotNull String parameterName, @NotNull String value) {
+ if (schemeSpecificPart != null) {
+ return this;
+ }
+ try {
+ this.query = (this.query == null ? "" : this.query + CHAR_AMP)
+ + URLEncoder.encode(parameterName, StandardCharsets.UTF_8.name())
+ + "=" + URLEncoder.encode(value, StandardCharsets.UTF_8.name());
+ } catch (UnsupportedEncodingException e) {
+ throw new IllegalStateException("Encoding not supported: " + StandardCharsets.UTF_8, e);
+ }
+ return this;
+ }
+
+ /**
+ * <p>
+ * Replace all query parameters of the URL. Both keys and values are URL-encoded before adding them to the query string.
+ * </p>
+ * <p>
+ * For adding multiple query parameters with the same name prefer to use {@link #addQueryParameter(String, String)}.
+ * </p>
+ *
+ * @param queryParameters the map with the query parameters
+ * @return the builder for method chaining
+ */
+ @NotNull
+ public SlingUriBuilder setQueryParameters(@NotNull Map<String, String> queryParameters) {
+ if (schemeSpecificPart != null) {
+ return this;
+ }
+ setQuery(null); // reset first
+ for (Map.Entry<String, String> parameter : queryParameters.entrySet()) {
+ addQueryParameter(parameter.getKey(), parameter.getValue());
+ }
+ return this;
+ }
+
+ /**
* Set the fragment of the URI.
*
* @param fragment the fragment
@@ -502,9 +586,6 @@
*/
@NotNull
public SlingUriBuilder setFragment(@Nullable String fragment) {
- if (schemeSpecificPart != null) {
- return this;
- }
this.fragment = fragment;
return this;
}
@@ -563,6 +644,168 @@
}
/**
+ * Returns the resource path.
+ *
+ * @return returns the resource path or null if the URI does not contain a path.
+ */
+ @Nullable
+ public String getResourcePath() {
+ return resourcePath;
+ }
+
+ /**
+ * Returns the selector string
+ *
+ * @return returns the selector string or null if the URI does not contain selector(s) (in line with {@link RequestPathInfo})
+ */
+ @Nullable
+ public String getSelectorString() {
+ return !selectors.isEmpty() ? String.join(CHAR_DOT, selectors) : null;
+ }
+
+ /**
+ * Returns the selectors array.
+ *
+ * @return the selectors array (empty if the URI does not contain selector(s), never null)
+ */
+ @NotNull
+ public String[] getSelectors() {
+ return selectors.toArray(new String[selectors.size()]);
+ }
+
+ /**
+ * Returns the extension.
+ *
+ * @return the extension or null if the URI does not contain an extension
+ */
+ @Nullable
+ public String getExtension() {
+ return extension;
+ }
+
+ /**
+ * Returns the path parameters.
+ *
+ * @return the path parameters or an empty Map if the URI does not contain any
+ */
+ @Nullable
+ public Map<String, String> getPathParameters() {
+ return pathParameters;
+ }
+
+ /**
+ * Returns the suffix part of the URI
+ *
+ * @return the suffix string or null if the URI does not contain a suffix
+ */
+ @Nullable
+ public String getSuffix() {
+ return suffix;
+ }
+
+ /**
+ * Returns the corresponding suffix resource or null if
+ * <ul>
+ * <li>no resource resolver is available (depends on the create method used in SlingUriBuilder)</li>
+ * <li>the URI does not contain a suffix</li>
+ * <li>if the suffix resource could not be found</li>
+ * </ul>
+ *
+ * @return the suffix resource if available or null
+ */
+ @Nullable
+ public Resource getSuffixResource() {
+ if (isNotBlank(suffix) && resourceResolver != null) {
+ return resourceResolver.getResource(suffix);
+ } else {
+ return null;
+ }
+ }
+
+ /**
+ * Returns the joint path of resource path, selectors, extension and suffix.
+ *
+ * @return the path or null if no path is set
+ */
+ @Nullable
+ public String getPath() {
+ return assemblePath(true);
+ }
+
+ /**
+ * Returns the scheme-specific part of the URI, compare with Javadoc of {@link URI}.
+ *
+ * @return scheme specific part of the URI
+ */
+ @Nullable
+ public String getSchemeSpecificPart() {
+ if (isOpaque()) {
+ return schemeSpecificPart;
+ } else {
+ return toStringInternal(false, false);
+ }
+ }
+
+ /**
+ * Returns the query.
+ *
+ * @return the query part of the URI or null if the URI does not contain a query
+ */
+ @Nullable
+ public String getQuery() {
+ return query;
+ }
+
+ /**
+ * Returns the fragment.
+ *
+ * @return the fragment or null if the URI does not contain a fragment
+ */
+ @Nullable
+ public String getFragment() {
+ return fragment;
+ }
+
+ /**
+ * Returns the scheme.
+ *
+ * @return the scheme or null if not set
+ */
+ @Nullable
+ public String getScheme() {
+ return scheme;
+ }
+
+ /**
+ * Returns the host.
+ *
+ * @return returns the host of the SlingUri or null if not set
+ */
+ @Nullable
+ public String getHost() {
+ return host;
+ }
+
+ /**
+ * Returns the port.
+ *
+ * @return returns the port of the SlingUri or -1 if not set
+ */
+ public int getPort() {
+ return port;
+ }
+
+ /**
+ * Returns the user info.
+ *
+ * @return the user info of the SlingUri or null if not set
+ */
+ @Nullable
+ public String getUserInfo() {
+ return userInfo;
+ }
+
+ /**
* Will take over scheme and authority (user info, host and port) from provided URI.
*
* @param uri the URI
@@ -607,7 +850,6 @@
return toStringInternal(true, true);
}
-
/**
* Returns true the URI is either a relative or absolute path (this is the case if scheme and host is empty and the URI path is set)
*
@@ -661,13 +903,13 @@
if (includeScheme && isAbsolute()) {
requestUri.append(scheme + CHAR_COLON);
}
- if (isNotBlank(host)) {
+ if (host != null) {
requestUri.append(CHAR_SLASH + CHAR_SLASH);
if (isNotBlank(userInfo)) {
requestUri.append(userInfo + CHAR_AT);
}
requestUri.append(host);
- if (port > 0
+ if (port > 0
&& !(HTTP_SCHEME.equals(scheme) && port == HTTP_DEFAULT_PORT)
&& !(HTTPS_SCHEME.equals(scheme) && port == HTTPS_DEFAULT_PORT)) {
requestUri.append(CHAR_COLON);
@@ -767,117 +1009,107 @@
@Override
public String getResourcePath() {
- return resourcePath;
+ return getData().getResourcePath();
}
- // returns null in line with
- // https://sling.apache.org/apidocs/sling11/org/apache/sling/api/request/RequestPathInfo.html#getSelectorString--
@Override
public String getSelectorString() {
- return !selectors.isEmpty() ? String.join(CHAR_DOT, selectors) : null;
+ return getData().getSelectorString();
}
@Override
public String[] getSelectors() {
- return selectors.toArray(new String[selectors.size()]);
+ return getData().getSelectors();
}
@Override
public String getExtension() {
- return extension;
+ return getData().getExtension();
}
@Override
public Map<String, String> getPathParameters() {
- return Collections.unmodifiableMap(pathParameters);
+ return Collections.unmodifiableMap(getData().getPathParameters());
}
@Override
public String getSuffix() {
- return suffix;
+ return getData().getSuffix();
}
@Override
public String getPath() {
- return assemblePath(true);
+ return getData().getPath();
}
@Override
public String getSchemeSpecificPart() {
- if (isOpaque()) {
- return schemeSpecificPart;
- } else {
- return toStringInternal(false, false);
- }
+ return getData().getSchemeSpecificPart();
}
@Override
public String getQuery() {
- return query;
+ return getData().getQuery();
}
@Override
public String getFragment() {
- return fragment;
+ return getData().getFragment();
}
@Override
public String getScheme() {
- return scheme;
+ return getData().getScheme();
}
@Override
public String getHost() {
- return host;
+ return getData().getHost();
}
@Override
public int getPort() {
- return port;
+ return getData().getPort();
}
@Override
public Resource getSuffixResource() {
- if (isNotBlank(suffix) && resourceResolver != null) {
- return resourceResolver.resolve(suffix);
- } else {
- return null;
- }
+ return getData().getSuffixResource();
}
@Override
public String getUserInfo() {
- return userInfo;
+ return getData().getUserInfo();
}
@Override
public boolean isOpaque() {
- return getBuilder().isOpaque();
+ return getData().isOpaque();
}
@Override
public boolean isPath() {
- return getBuilder().isPath();
+ return getData().isPath();
}
@Override
public boolean isAbsolutePath() {
- return getBuilder().isAbsolutePath();
+ return getData().isAbsolutePath();
}
@Override
public boolean isRelativePath() {
- return getBuilder().isRelativePath();
+ return getData().isRelativePath();
}
@Override
public boolean isAbsolute() {
- return getBuilder().isAbsolute();
+ return getData().isAbsolute();
}
@Override
public String toString() {
- return toStringInternal(true, true);
+ return getData().toString();
}
@Override
@@ -890,7 +1122,7 @@
}
}
- private SlingUriBuilder getBuilder() {
+ private SlingUriBuilder getData() {
return SlingUriBuilder.this;
}
@@ -924,61 +1156,61 @@
return false;
ImmutableSlingUri other = (ImmutableSlingUri) obj;
if (extension == null) {
- if (other.getBuilder().extension != null)
+ if (other.getData().extension != null)
return false;
- } else if (!extension.equals(other.getBuilder().extension))
+ } else if (!extension.equals(other.getData().extension))
return false;
if (fragment == null) {
- if (other.getBuilder().fragment != null)
+ if (other.getData().fragment != null)
return false;
- } else if (!fragment.equals(other.getBuilder().fragment))
+ } else if (!fragment.equals(other.getData().fragment))
return false;
if (host == null) {
- if (other.getBuilder().host != null)
+ if (other.getData().host != null)
return false;
- } else if (!host.equals(other.getBuilder().host))
+ } else if (!host.equals(other.getData().host))
return false;
if (pathParameters == null) {
- if (other.getBuilder().pathParameters != null)
+ if (other.getData().pathParameters != null)
return false;
- } else if (!pathParameters.equals(other.getBuilder().pathParameters))
+ } else if (!pathParameters.equals(other.getData().pathParameters))
return false;
- if (port != other.getBuilder().port)
+ if (port != other.getData().port)
return false;
if (query == null) {
- if (other.getBuilder().query != null)
+ if (other.getData().query != null)
return false;
- } else if (!query.equals(other.getBuilder().query))
+ } else if (!query.equals(other.getData().query))
return false;
if (resourcePath == null) {
- if (other.getBuilder().resourcePath != null)
+ if (other.getData().resourcePath != null)
return false;
- } else if (!resourcePath.equals(other.getBuilder().resourcePath))
+ } else if (!resourcePath.equals(other.getData().resourcePath))
return false;
if (scheme == null) {
- if (other.getBuilder().scheme != null)
+ if (other.getData().scheme != null)
return false;
- } else if (!scheme.equals(other.getBuilder().scheme))
+ } else if (!scheme.equals(other.getData().scheme))
return false;
if (schemeSpecificPart == null) {
- if (other.getBuilder().schemeSpecificPart != null)
+ if (other.getData().schemeSpecificPart != null)
return false;
- } else if (!schemeSpecificPart.equals(other.getBuilder().schemeSpecificPart))
+ } else if (!schemeSpecificPart.equals(other.getData().schemeSpecificPart))
return false;
if (selectors == null) {
- if (other.getBuilder().selectors != null)
+ if (other.getData().selectors != null)
return false;
- } else if (!selectors.equals(other.getBuilder().selectors))
+ } else if (!selectors.equals(other.getData().selectors))
return false;
if (suffix == null) {
- if (other.getBuilder().suffix != null)
+ if (other.getData().suffix != null)
return false;
- } else if (!suffix.equals(other.getBuilder().suffix))
+ } else if (!suffix.equals(other.getData().suffix))
return false;
if (userInfo == null) {
- if (other.getBuilder().userInfo != null)
+ if (other.getData().userInfo != null)
return false;
- } else if (!userInfo.equals(other.getBuilder().userInfo))
+ } else if (!userInfo.equals(other.getData().userInfo))
return false;
return true;
}
diff --git a/src/main/java/org/apache/sling/api/uri/package-info.java b/src/main/java/org/apache/sling/api/uri/package-info.java
index c6b4053..4a8466a 100644
--- a/src/main/java/org/apache/sling/api/uri/package-info.java
+++ b/src/main/java/org/apache/sling/api/uri/package-info.java
@@ -16,7 +16,7 @@
* specific language governing permissions and limitations
* under the License.
*/
-@Version("1.0.0")
+@Version("1.1.0")
package org.apache.sling.api.uri;
import org.osgi.annotation.versioning.Version;
diff --git a/src/test/java/org/apache/sling/api/uri/SlingUriBuilderTest.java b/src/test/java/org/apache/sling/api/uri/SlingUriBuilderTest.java
index 0f33031..5a59045 100644
--- a/src/test/java/org/apache/sling/api/uri/SlingUriBuilderTest.java
+++ b/src/test/java/org/apache/sling/api/uri/SlingUriBuilderTest.java
@@ -25,6 +25,8 @@
import java.net.URI;
import java.net.URISyntaxException;
+import java.util.LinkedHashMap;
+import java.util.Map;
import org.apache.sling.api.SlingHttpServletRequest;
import org.apache.sling.api.request.RequestPathInfo;
@@ -150,6 +152,42 @@
assertEquals("https://example.com:8080/path/to/page.html", testUri.toString());
}
+ @Test
+ public void testAddQueryParameter() throws URISyntaxException {
+ String testPath = "/path/to/page.html";
+ SlingUri testUri = SlingUriBuilder.parse(testPath, null)
+ .addQueryParameter("param1", "val1")
+ .build();
+ assertEquals("/path/to/page.html?param1=val1", testUri.toString());
+ }
+
+ @Test
+ public void testAddQueryParameterValueEncoded() throws URISyntaxException {
+ String testPath = "/path/to/page.html";
+ SlingUri testUri = SlingUriBuilder.parse(testPath, null)
+ .addQueryParameter("redirect", "http://www.example.com/path/to/file.txt?q=3&test=3#test")
+ .addQueryParameter("param2", "true")
+ .build();
+ assertEquals(
+ "/path/to/page.html?redirect=http%3A%2F%2Fwww.example.com%2Fpath%2Fto%2Ffile.txt%3Fq%3D3%26test%3D3%23test¶m2=true",
+ testUri.toString());
+ }
+
+ @Test
+ public void testSetQueryParameterValueEncoded() throws URISyntaxException {
+ String testPath = "/path/to/page.html?param=value"; // existing query parameters are meant to be replaced
+
+ Map<String, String> queryParams = new LinkedHashMap<>();
+ queryParams.put("param1", "value1");
+ queryParams.put("param2[*]", "value2");
+ queryParams.put("param3", "value3%@");
+
+ SlingUri testUri = SlingUriBuilder.parse(testPath, null)
+ .setQueryParameters(queryParams)
+ .build();
+ assertEquals("/path/to/page.html?param1=value1¶m2%5B*%5D=value2¶m3=value3%25%40", testUri.toString());
+ }
+
@Test(expected = IllegalStateException.class)
public void testBuilderMayOnlyBeUsedToBuildAnUri() {
SlingUriBuilder builder = SlingUriBuilder.parse("/path/to/page.html", null);
diff --git a/src/test/java/org/apache/sling/api/uri/SlingUriEncodingTest.java b/src/test/java/org/apache/sling/api/uri/SlingUriEncodingTest.java
new file mode 100644
index 0000000..a5c1add
--- /dev/null
+++ b/src/test/java/org/apache/sling/api/uri/SlingUriEncodingTest.java
@@ -0,0 +1,109 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+package org.apache.sling.api.uri;
+
+import static org.junit.Assert.assertEquals;
+
+import java.io.UnsupportedEncodingException;
+import java.net.URISyntaxException;
+import java.net.URLDecoder;
+import java.nio.charset.StandardCharsets;
+
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.mockito.junit.MockitoJUnitRunner;
+
+@RunWith(MockitoJUnitRunner.class)
+public class SlingUriEncodingTest {
+
+ @Test
+ public void testUriWithEuroSign() throws URISyntaxException, UnsupportedEncodingException {
+
+ testUriUnchangedForEncodedAndDecodedStr("/test-with-euro-sign-%E2%82%AC-suffix.pdf", true, true, false, false, false);
+ }
+
+ @Test
+ public void testUriWithSpaces() throws URISyntaxException, UnsupportedEncodingException {
+
+ testUriUnchangedForEncodedAndDecodedStr("/test+with+spaces%20in+different%20encodings", true, true, false, false, false);
+ }
+
+ @Test
+ public void testUriWithSpecialCharacters() throws URISyntaxException, UnsupportedEncodingException {
+
+ testUriUnchangedForEncodedAndDecodedStr(
+ "/path/with/many/special/chars/%2B%26%2B-%25%3D%2A%5E%3F%23%5E%21%24%3D%3D%5E_-_%24%2B%24%3D%5E%3F%3F%2B%26%40%3D%25%40-%24",
+ true, true, false, false, false);
+ }
+
+ @Test
+ public void testUriWithSpecialCharactersInUserInfo() throws URISyntaxException, UnsupportedEncodingException {
+
+ testUriUnchangedForEncodedAndDecodedStr(
+ "http://user:%2B%26%2B-%25%3D%2A%5E%3F%23@example.com/path.txt",
+ false, false, false, true, false);
+ }
+
+ @Test
+ public void testUriWithSpecialCharactersInQuery() throws URISyntaxException, UnsupportedEncodingException {
+
+ testUriUnchangedForEncodedAndDecodedStr(
+ "http://example.com/path.txt?testParam=%2B%26%2B-%25%3D%2A%5E%3F%23",
+ false, false, false, true, false);
+ }
+
+ @Test
+ public void testUriWithSpecialCharactersInFragment() throws URISyntaxException, UnsupportedEncodingException {
+
+ testUriUnchangedForEncodedAndDecodedStr(
+ "http://example.com/path.txt?testParam=testVal#%2B%26%2B-%25%3D%2A%5E%3F%23",
+ false, false, false, true, false);
+ }
+
+ private void testUriUnchangedForEncodedAndDecodedStr(String testUriStrEncoded, boolean isPath, boolean isAbsolutePath,
+ boolean isRelativePath, boolean isAbsolute, boolean isOpaque) throws UnsupportedEncodingException {
+
+ testUriUnchanged(testUriStrEncoded, isPath, isAbsolutePath, isRelativePath, isAbsolute, isOpaque);
+
+ // decoded variant should also stay unchanged
+ String testUriStrDecoded = URLDecoder.decode(testUriStrEncoded, StandardCharsets.UTF_8.name());
+ testUriUnchanged(testUriStrDecoded, isPath, isAbsolutePath, isRelativePath, isAbsolute, isOpaque);
+ }
+
+ public static SlingUri testUriUnchanged(String testUri, boolean isPath, boolean isAbsolutePath, boolean isRelativePath,
+ boolean isAbsolute, boolean isOpaque) {
+ SlingUri slingUri = SlingUriBuilder.parse(testUri, null).build();
+
+ assertEquals("Uri toString() same as input", testUri, slingUri.toString());
+
+ assertEquals("isPath()", isPath, slingUri.isPath());
+ assertEquals("isAbsolutePath()", isAbsolutePath, slingUri.isAbsolutePath());
+ assertEquals("isRelativePath()", isRelativePath, slingUri.isRelativePath());
+ assertEquals("isAbsolute()", isAbsolute, slingUri.isAbsolute());
+ assertEquals("isOpaque()", isOpaque, slingUri.isOpaque());
+
+ SlingUri slingUriParsedFromSameInput = SlingUriBuilder.parse(testUri, null).build();
+ assertEquals("uris parsed from same input are expected to be equal", slingUriParsedFromSameInput, slingUri);
+ assertEquals("uris parsed from same input are expected to have the same hash code", slingUriParsedFromSameInput.hashCode(),
+ slingUri.hashCode());
+
+ return slingUri;
+ }
+
+}
diff --git a/src/test/java/org/apache/sling/api/uri/SlingUriInvalidUrisTest.java b/src/test/java/org/apache/sling/api/uri/SlingUriInvalidUrisTest.java
index 48a9aff..c78b0a7 100644
--- a/src/test/java/org/apache/sling/api/uri/SlingUriInvalidUrisTest.java
+++ b/src/test/java/org/apache/sling/api/uri/SlingUriInvalidUrisTest.java
@@ -19,7 +19,6 @@
package org.apache.sling.api.uri;
import static org.junit.Assert.assertEquals;
-import static org.junit.Assert.assertNull;
import static org.junit.Assert.fail;
import java.net.URI;
@@ -36,14 +35,34 @@
public class SlingUriInvalidUrisTest {
@Parameters(name = "Invalid URI: {0}")
- public static Collection<String> data() {
- return Arrays.asList(":foo", "https://", "https:", "@:", "://", "::::");
+ public static Collection<String[]> data() {
+ return Arrays.asList(
+ // test fix URIs with spaces
+ new String[] { "/path/with/spaces/A name with spaces.pdf", "/test.pdf" },
+ new String[] { "http://example.com/path/with/spaces/A name with spaces.pdf", "http://example.com/test.pdf" },
+ new String[] { "http://user:pw@example.com/path/with/spaces/A name with spaces.sel1.pdf/suffix?par1=val1&par2=val2#frag",
+ "http://user:pw@example.com/test.sel1.pdf/suffix?par1=val1&par2=val2#frag" },
+ new String[] { "http://user:pw with spaces@example.com", "http://user:pw with spaces@example.com/test" },
+
+ // duplicate fragment
+ new String[] { "#fragment1#fragment2", "/test" },
+
+ // short invalid URIs
+ new String[] { "\\path\\on\\windows", "/test" },
+ new String[] { "https://", "https://" },
+ new String[] { "special:", "special:/test" },
+ new String[] { "@:", "/test" },
+ new String[] { ":foo", "/test" },
+ new String[] { "://", "/test" },
+ new String[] { "::::", "/test" });
}
private final String invalidUri;
+ private final String invalidUriAdjustedAfterSetPath;
- public SlingUriInvalidUrisTest(String invalidUri) {
+ public SlingUriInvalidUrisTest(String invalidUri, String invalidUriAdjustedAfterSetPath) {
this.invalidUri = invalidUri;
+ this.invalidUriAdjustedAfterSetPath = invalidUriAdjustedAfterSetPath;
}
@Test
@@ -59,14 +78,6 @@
}
@Test
- public void testAdjustInvalidUriNoEffect() {
-
- SlingUri slingUri = SlingUriBuilder.parse(invalidUri, null).build();
- SlingUri slingUriAdjusted = slingUri.adjust(b -> b.setResourcePath("/test"));
- assertNull("setResourcePath() should have been ignored for uri " + invalidUri, slingUriAdjusted.getResourcePath());
- }
-
- @Test
public void testAdjustInvalidUriToValidUri() {
SlingUri slingUri = SlingUriBuilder.parse(invalidUri, null).build();
@@ -75,4 +86,14 @@
slingUriAdjusted.getResourcePath());
}
+ @Test
+ public void testAdjustInvalidUri() {
+
+ SlingUri slingUri = SlingUriBuilder.parse(invalidUri, null).build();
+ SlingUri slingUriAdjusted = slingUri.adjust(b -> b.setResourcePath("/test"));
+ assertEquals("setResourcePath('/test') to invalid URI '" + invalidUri + "' should result in: "
+ + invalidUriAdjustedAfterSetPath, invalidUriAdjustedAfterSetPath, slingUriAdjusted.toString());
+ }
+
+
}
diff --git a/src/test/java/org/apache/sling/api/uri/SlingUriTest.java b/src/test/java/org/apache/sling/api/uri/SlingUriTest.java
index 3e11d9a..6284fb9 100644
--- a/src/test/java/org/apache/sling/api/uri/SlingUriTest.java
+++ b/src/test/java/org/apache/sling/api/uri/SlingUriTest.java
@@ -21,11 +21,18 @@
import static java.util.Arrays.asList;
import static org.junit.Assert.assertArrayEquals;
import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertNotEquals;
+import static org.junit.Assert.assertNull;
+import static org.junit.Assert.assertTrue;
+import static org.mockito.Mockito.mock;
+import static org.mockito.Mockito.when;
import java.net.URI;
import java.util.List;
import java.util.function.Consumer;
+import org.apache.commons.lang3.StringUtils;
+import org.apache.sling.api.resource.Resource;
import org.apache.sling.api.resource.ResourceResolver;
import org.junit.Test;
import org.junit.runner.RunWith;
@@ -81,6 +88,47 @@
}
@Test
+ public void testSlingUriDomainIPv4() {
+
+ String testUriStr = "https://88.39.107.39:888/test/to/path.sel1.json/suffix/path?p1=2&p2=3#frag3939";
+ testUri(testUriStr, false, false, false, true, false, slingUri -> {
+ assertEquals("https", slingUri.getScheme());
+ assertEquals("//88.39.107.39:888/test/to/path.sel1.json/suffix/path?p1=2&p2=3", slingUri.getSchemeSpecificPart());
+ assertEquals(null, slingUri.getUserInfo());
+ assertEquals("88.39.107.39", slingUri.getHost());
+ assertEquals(888, slingUri.getPort());
+ assertEquals("/test/to/path", slingUri.getResourcePath());
+ assertEquals("sel1", slingUri.getSelectorString());
+ assertArrayEquals(new String[] { "sel1" }, slingUri.getSelectors());
+ assertEquals("json", slingUri.getExtension());
+ assertEquals("/suffix/path", slingUri.getSuffix());
+ assertEquals("p1=2&p2=3", slingUri.getQuery());
+ assertEquals("frag3939", slingUri.getFragment());
+ }, asList(resolver, null));
+ }
+
+ @Test
+ public void testSlingUriDomainIPv6() {
+
+ String testUriStr = "https://[FEDC:BA98:7654:3210:FEDC:BA98:7654:3210]:8080/index.sel1.json/suffix/path?p1=2&p2=3#frag3939";
+ testUri(testUriStr, false, false, false, true, false, slingUri -> {
+ assertEquals("https", slingUri.getScheme());
+ assertEquals("//[FEDC:BA98:7654:3210:FEDC:BA98:7654:3210]:8080/index.sel1.json/suffix/path?p1=2&p2=3",
+ slingUri.getSchemeSpecificPart());
+ assertEquals(null, slingUri.getUserInfo());
+ assertEquals("[FEDC:BA98:7654:3210:FEDC:BA98:7654:3210]", slingUri.getHost());
+ assertEquals(8080, slingUri.getPort());
+ assertEquals("/index", slingUri.getResourcePath());
+ assertEquals("sel1", slingUri.getSelectorString());
+ assertArrayEquals(new String[] { "sel1" }, slingUri.getSelectors());
+ assertEquals("json", slingUri.getExtension());
+ assertEquals("/suffix/path", slingUri.getSuffix());
+ assertEquals("p1=2&p2=3", slingUri.getQuery());
+ assertEquals("frag3939", slingUri.getFragment());
+ }, asList(resolver, null));
+ }
+
+ @Test
public void testFullUriWithoutSchemeSimple() {
String testUriStr = "//cdn.example.com/test/js_file.js";
@@ -313,9 +361,7 @@
@Test
public void testJavascriptUri() {
- String testUriStr = "javascript:void(0)";
-
- testUri(testUriStr, false, false, false, true, true, slingUri -> {
+ testUri("javascript:void(0)", false, false, false, true, true, slingUri -> {
assertEquals("javascript", slingUri.getScheme());
assertEquals(null, slingUri.getUserInfo());
assertEquals(null, slingUri.getHost());
@@ -330,6 +376,24 @@
}
@Test
+ public void testJavascriptUriLong() {
+
+ testUri("javascript:console.log('long js'); return true;", false, false, false, true, true, slingUri -> {
+ assertEquals("javascript", slingUri.getScheme());
+ assertEquals(null, slingUri.getUserInfo());
+ assertEquals(null, slingUri.getHost());
+ assertEquals(-1, slingUri.getPort());
+ assertEquals(null, slingUri.getSelectorString());
+ assertEquals(null, slingUri.getExtension());
+ assertEquals(null, slingUri.getSuffix());
+ assertEquals("console.log('long js'); return true;", slingUri.getSchemeSpecificPart());
+ assertEquals(null, slingUri.getQuery());
+ assertEquals(null, slingUri.getFragment());
+ }, null, true);
+
+ }
+
+ @Test
public void testMailtotUri() {
String testUriStr = "mailto:jon.doe@example.com";
@@ -338,6 +402,7 @@
assertEquals(null, slingUri.getUserInfo());
assertEquals(null, slingUri.getHost());
assertEquals(-1, slingUri.getPort());
+ assertEquals(null, slingUri.getResourcePath());
assertEquals(null, slingUri.getSelectorString());
assertEquals(null, slingUri.getExtension());
assertEquals(null, slingUri.getSuffix());
@@ -348,6 +413,161 @@
}
@Test
+ public void testFileUriLocal() {
+ testUri("file:///path/to/test/file.txt", false, false, false, true, false, slingUri -> {
+ assertEquals("file", slingUri.getScheme());
+ assertEquals(null, slingUri.getUserInfo());
+ assertEquals("", slingUri.getHost());
+ assertEquals(-1, slingUri.getPort());
+ assertEquals("/path/to/test/file", slingUri.getResourcePath());
+ assertEquals(null, slingUri.getSelectorString());
+ assertEquals("txt", slingUri.getExtension());
+ assertEquals(null, slingUri.getSuffix());
+ assertEquals("///path/to/test/file.txt", slingUri.getSchemeSpecificPart());
+ assertEquals(null, slingUri.getQuery());
+ assertEquals(null, slingUri.getFragment());
+ }, asList(resolver, null));
+ }
+
+ @Test
+ public void testFileUriWithHost() {
+ testUri("file://example.com:80/path/to/test/file.txt", false, false, false, true, false, slingUri -> {
+ assertEquals("file", slingUri.getScheme());
+ assertEquals(null, slingUri.getUserInfo());
+ assertEquals("example.com", slingUri.getHost());
+ assertEquals(80, slingUri.getPort());
+ assertEquals("/path/to/test/file", slingUri.getResourcePath());
+ assertEquals(null, slingUri.getSelectorString());
+ assertEquals("txt", slingUri.getExtension());
+ assertEquals(null, slingUri.getSuffix());
+ assertEquals("//example.com:80/path/to/test/file.txt", slingUri.getSchemeSpecificPart());
+ assertEquals(null, slingUri.getQuery());
+ assertEquals(null, slingUri.getFragment());
+ }, asList(resolver, null));
+ }
+
+ @Test
+ public void testSpecialFileUris() {
+ testUri("file:/path/to/test/file.txt", false, false, false, true, false, slingUri -> {
+ assertEquals("file", slingUri.getScheme());
+ assertEquals(null, slingUri.getUserInfo());
+ assertEquals("", slingUri.getHost());
+ assertEquals(-1, slingUri.getPort());
+ assertEquals("/path/to/test/file", slingUri.getResourcePath());
+ assertEquals(null, slingUri.getSelectorString());
+ assertEquals("txt", slingUri.getExtension());
+ assertEquals(null, slingUri.getSuffix());
+ assertEquals("///path/to/test/file.txt", slingUri.getSchemeSpecificPart());
+ assertEquals(null, slingUri.getQuery());
+ assertEquals(null, slingUri.getFragment());
+ assertEquals("file:///path/to/test/file.txt", slingUri.toString());
+ }, null, true /* single slash is expanded to correct three slashes */);
+
+ testUri("file:///c:/WINDOWS/clock.avi", false, false, false, true, false, slingUri -> {
+ assertEquals("file", slingUri.getScheme());
+ assertEquals(null, slingUri.getUserInfo());
+ assertEquals("", slingUri.getHost());
+ assertEquals(-1, slingUri.getPort());
+ assertEquals("/c:/WINDOWS/clock", slingUri.getResourcePath());
+ assertEquals(null, slingUri.getSelectorString());
+ assertEquals("avi", slingUri.getExtension());
+ assertEquals(null, slingUri.getSuffix());
+ assertEquals("///c:/WINDOWS/clock.avi", slingUri.getSchemeSpecificPart());
+ assertEquals(null, slingUri.getQuery());
+ assertEquals(null, slingUri.getFragment());
+ }, asList(resolver, null));
+ }
+
+ @Test
+ public void testCalltoUri() {
+ testUri("callto:screenname", false, false, false, true, true, slingUri -> {
+ assertEquals("callto", slingUri.getScheme());
+ assertEquals(null, slingUri.getUserInfo());
+ assertEquals(null, slingUri.getHost());
+ assertEquals(-1, slingUri.getPort());
+ assertEquals(null, slingUri.getResourcePath());
+ assertEquals(null, slingUri.getSelectorString());
+ assertEquals(null, slingUri.getExtension());
+ assertEquals(null, slingUri.getSuffix());
+ assertEquals("screenname", slingUri.getSchemeSpecificPart());
+ assertEquals(null, slingUri.getQuery());
+ assertEquals(null, slingUri.getFragment());
+ }, asList(resolver, null));
+
+ }
+
+ @Test
+ public void testSmsUri() {
+
+ testUri("sms:+15105550101,+15105550102?body=hello%20there", false, false, false, true, true, slingUri -> {
+ assertEquals("sms", slingUri.getScheme());
+ assertEquals(null, slingUri.getUserInfo());
+ assertEquals(null, slingUri.getHost());
+ assertEquals(-1, slingUri.getPort());
+ assertEquals(null, slingUri.getResourcePath());
+ assertEquals(null, slingUri.getSelectorString());
+ assertEquals(null, slingUri.getExtension());
+ assertEquals(null, slingUri.getSuffix());
+ assertEquals("+15105550101,+15105550102?body=hello%20there", slingUri.getSchemeSpecificPart());
+ assertEquals(null, slingUri.getQuery());
+ assertEquals(null, slingUri.getFragment());
+ }, asList(resolver, null));
+ }
+
+ @Test
+ public void testRsyncUri() {
+
+ testUri("rsync://testhost:333/path", false, false, false, true, false, slingUri -> {
+ assertEquals("rsync", slingUri.getScheme());
+ assertEquals(null, slingUri.getUserInfo());
+ assertEquals("testhost", slingUri.getHost());
+ assertEquals(333, slingUri.getPort());
+ assertEquals("/path", slingUri.getResourcePath());
+ assertEquals(null, slingUri.getSelectorString());
+ assertEquals(null, slingUri.getExtension());
+ assertEquals(null, slingUri.getSuffix());
+ assertEquals("//testhost:333/path", slingUri.getSchemeSpecificPart());
+ assertEquals(null, slingUri.getQuery());
+ assertEquals(null, slingUri.getFragment());
+ }, asList(resolver, null));
+ }
+
+ @Test
+ public void testViewSourceUri() {
+ testUri("view-source:http://en.wikipedia.org/wiki/URI_scheme", false, false, false, true, true, slingUri -> {
+ assertEquals("view-source", slingUri.getScheme());
+ assertEquals(null, slingUri.getUserInfo());
+ assertEquals(null, slingUri.getHost());
+ assertEquals(-1, slingUri.getPort());
+ assertEquals(null, slingUri.getResourcePath());
+ assertEquals(null, slingUri.getSelectorString());
+ assertEquals(null, slingUri.getExtension());
+ assertEquals(null, slingUri.getSuffix());
+ assertEquals("http://en.wikipedia.org/wiki/URI_scheme", slingUri.getSchemeSpecificPart());
+ assertEquals(null, slingUri.getQuery());
+ assertEquals(null, slingUri.getFragment());
+ }, asList(resolver, null));
+ }
+
+ @Test
+ public void testGitUrl() {
+ testUri("git://github.com/user/project-name.git", false, false, false, true, false, slingUri -> {
+ assertEquals("git", slingUri.getScheme());
+ assertEquals(null, slingUri.getUserInfo());
+ assertEquals("github.com", slingUri.getHost());
+ assertEquals(-1, slingUri.getPort());
+ assertEquals("/user/project-name", slingUri.getResourcePath());
+
+ assertEquals(null, slingUri.getSelectorString());
+ assertEquals("git", slingUri.getExtension());
+ assertEquals(null, slingUri.getSuffix());
+ assertEquals("//github.com/user/project-name.git", slingUri.getSchemeSpecificPart());
+ assertEquals(null, slingUri.getQuery());
+ assertEquals(null, slingUri.getFragment());
+ }, asList(resolver, null));
+ }
+
+ @Test
public void testHashOnlyUri() {
testUri("#", false, false, false, false, false, slingUri -> {
@@ -427,6 +647,42 @@
}, asList(resolver, null));
}
+ @Test
+ public void testDataUrl() {
+
+ // data url according to https://tools.ietf.org/html/rfc2397
+ String dataUrl = "data:image/gif;base64,R0lGODdhMAAwAPAAAAAAAP///ywAAAAAMAAw" +
+ "AAAC8IyPqcvt3wCcDkiLc7C0qwyGHhSWpjQu5yqmCYsapyuvUUlvONmOZtfzgFz" +
+ "ByTB10QgxOR0TqBQejhRNzOfkVJ+5YiUqrXF5Y5lKh/DeuNcP5yLWGsEbtLiOSp" +
+ "a/TPg7JpJHxyendzWTBfX0cxOnKPjgBzi4diinWGdkF8kjdfnycQZXZeYGejmJl" +
+ "ZeGl9i2icVqaNVailT6F5iJ90m6mvuTS4OK05M0vDk0Q4XUtwvKOzrcd3iq9uis" +
+ "F81M1OIcR7lEewwcLp7tuNNkM3uNna3F2JQFo97Vriy/Xl4/f1cf5VWzXyym7PH" +
+ "hhx4dbgYKAAA7";
+
+ testUri(dataUrl, false, false, false, true, true, slingUri -> {
+ assertEquals("data", slingUri.getScheme());
+ assertEquals(StringUtils.substringAfter(dataUrl, ":"), slingUri.getSchemeSpecificPart());
+ assertEquals(null, slingUri.getQuery());
+ assertEquals(null, slingUri.getFragment());
+ }, asList(resolver, null));
+ }
+
+ @Test
+ public void testGetSuffixResource() {
+ Resource expectedSuffixResource = mock(Resource.class);
+ when(resolver.getResource("/suffix/path")).thenReturn(expectedSuffixResource);
+ SlingUri slingUri = SlingUriBuilder.parse("/test/to/path.sel1.json/suffix/path?p1=2&p2=3#frag3939", resolver).build();
+ Resource suffixResource = slingUri.getSuffixResource();
+ assertTrue("Suffix resource equal to mock", expectedSuffixResource == suffixResource);
+
+ SlingUri slingUriDifferentSuffix = slingUri.adjust(b -> b.setSuffix("/suffix/path/non-existing"));
+ assertNull("Suffix resource is null if resource does not exist", slingUriDifferentSuffix.getSuffixResource());
+
+ SlingUri slingUriNoSuffix = slingUri.adjust(b -> b.setSuffix(null));
+ assertNull("Suffix resource is null if suffix is null", slingUriNoSuffix.getSuffixResource());
+
+ }
+
// -- helper methods
public static void testUri(String testUri, boolean isPath, boolean isAbsolutePath, boolean isRelativePath, boolean isAbsolute,
boolean isOpaque, Consumer<SlingUri> additionalAssertions, List<ResourceResolver> resourceResolvers) {
@@ -436,12 +692,6 @@
}
public static SlingUri testUri(String testUri, boolean isPath, boolean isAbsolutePath, boolean isRelativePath, boolean isAbsolute,
- boolean isOpaque, Consumer<SlingUri> additionalAssertions) {
- return testUri(testUri, isPath, isAbsolutePath, isRelativePath, isAbsolute, isOpaque, additionalAssertions,
- (ResourceResolver) null);
- }
-
- public static SlingUri testUri(String testUri, boolean isPath, boolean isAbsolutePath, boolean isRelativePath, boolean isAbsolute,
boolean isOpaque, Consumer<SlingUri> additionalAssertions, ResourceResolver resourceResolver) {
return testUri(testUri, isPath, isAbsolutePath, isRelativePath, isAbsolute, isOpaque, additionalAssertions, resourceResolver,
false);
@@ -452,8 +702,15 @@
SlingUri slingUri = SlingUriBuilder.parse(testUri, resourceResolver).build();
if (!urlIsRestructured) {
+ URI javaUri = slingUri.toUri();
assertEquals("Uri toString() same as input", testUri, slingUri.toString());
- assertEquals("Uri toUri().toString() same as input", testUri, slingUri.toUri().toString());
+ assertEquals("Uri toUri().toString() same as input", testUri, javaUri.toString());
+ assertEquals("isOpaque() matches to java URI impl", javaUri.isOpaque(), slingUri.isOpaque());
+ assertEquals("getSchemeSpecificPart() matches to java URI impl", javaUri.getRawSchemeSpecificPart(),
+ slingUri.getSchemeSpecificPart());
+ assertEquals("getFragment() matches to java URI impl", javaUri.getRawFragment(), slingUri.getFragment());
+ assertEquals("getQuery() matches to java URI impl", javaUri.getRawQuery(), slingUri.getQuery());
+ assertEquals("isAbsolute() matches to java URI impl", javaUri.isAbsolute(), slingUri.isAbsolute());
}
assertEquals("isPath()", isPath, slingUri.isPath());
@@ -462,18 +719,13 @@
assertEquals("isAbsolute()", isAbsolute, slingUri.isAbsolute());
assertEquals("isOpaque()", isOpaque, slingUri.isOpaque());
- URI javaUri = slingUri.toUri();
- assertEquals("isOpaque() matches to java URI impl", javaUri.isOpaque(), slingUri.isOpaque());
- assertEquals("getSchemeSpecificPart() matches to java URI impl", javaUri.getSchemeSpecificPart(),
- slingUri.getSchemeSpecificPart());
- assertEquals("getFragment() matches to java URI impl", javaUri.getFragment(), slingUri.getFragment());
- assertEquals("getQuery() matches to java URI impl", javaUri.getQuery(), slingUri.getQuery());
- assertEquals("isAbsolute() matches to java URI impl", javaUri.isAbsolute(), slingUri.isAbsolute());
-
additionalAssertions.accept(slingUri);
SlingUri slingUriParsedFromSameInput = SlingUriBuilder.parse(testUri, resourceResolver).build();
assertEquals("uris parsed from same input are expected to be equal", slingUriParsedFromSameInput, slingUri);
+ assertNotEquals("not equal to different URI", SlingUriBuilder.parse("special://host:393/path.txt/suffix", resourceResolver).build(),
+ slingUri);
+ assertNotEquals("not equal to null", slingUri, null);
assertEquals("uris parsed from same input are expected to have the same hash code", slingUriParsedFromSameInput.hashCode(),
slingUri.hashCode());