blob: c554e67967deaf2781b2888a13f9ff3c8d590295 [file] [log] [blame]
/*=============================================================================#
# Copyright (c) 2018, 2021 Stephan Wahlbrink and others.
#
# This program and the accompanying materials are made available under the
# terms of the Eclipse Public License 2.0 which is available at
# https://www.eclipse.org/legal/epl-2.0, or the Apache License, Version 2.0
# which is available at https://www.apache.org/licenses/LICENSE-2.0.
#
# SPDX-License-Identifier: EPL-2.0 OR Apache-2.0
#
# Contributors:
# Stephan Wahlbrink <sw@wahlbrink.eu> - initial API and implementation
#=============================================================================*/
package org.eclipse.statet.jcommons.io;
import java.net.URI;
import java.net.URISyntaxException;
import java.net.URL;
import org.eclipse.statet.jcommons.lang.NonNullByDefault;
import org.eclipse.statet.jcommons.lang.Nullable;
@NonNullByDefault
public class UriUtils {
public static final String HTTP_SCHEME= "http"; //$NON-NLS-1$
public static final String HTTPS_SCHEME= "https"; //$NON-NLS-1$
public static final String FILE_SCHEME= "file"; //$NON-NLS-1$
public static final String JAR_SCHEME= "jar"; //$NON-NLS-1$
public static final String JAR_SEPARATOR = "!/"; //$NON-NLS-1$
public static final URI toUri(final URL url) throws URISyntaxException {
final String s= url.toExternalForm();
final String scheme= url.getProtocol();
final String fragment= url.getRef();
final String spp= s.substring(scheme.length() + 1,
(fragment != null) ? s.length() - fragment.length() - 1 : s.length() );
return new URI(scheme, spp, fragment);
}
private static boolean isScheme(final @Nullable String scheme, final String expectedScheme) {
final int n= expectedScheme.length();
if (scheme == null || scheme.length() != n) {
return false;
}
for (int index= 0; index < n; index++) {
final char c= scheme.charAt(index);
final char cExpected= expectedScheme.charAt(index);
if (c != cExpected && Character.toLowerCase(c) != cExpected) {
return false;
}
}
return true;
}
private static boolean isSchemeUrl(final String urlString, final String expectedScheme) {
final int n= expectedScheme.length();
if (urlString.length() <= n || urlString.charAt(n) != ':') {
return false;
}
for (int index= 0; index < n; index++) {
final char c= urlString.charAt(index);
final char cExpected= expectedScheme.charAt(index);
if (c != cExpected && Character.toLowerCase(c) != cExpected) {
return false;
}
}
return true;
}
/**
* Returns if the specified URL is a file URL.
*
* <p>The function does not validate the URL.</p>
*
* @param url the URL
* @return <code>true</code> if it is a file URL, otherwise <code>false</code>
*/
public static final boolean isFileUrl(final URI url) {
return isScheme(url.getScheme(), FILE_SCHEME);
}
/**
* Returns if the specified URL is a file URL.
*
* <p>The function does not validate the URL.</p>
*
* @param urlString the URL
* @return <code>true</code> if it is a file URL, otherwise <code>false</code>
*/
public static final boolean isFileUrl(final String urlString) {
return isSchemeUrl(urlString, FILE_SCHEME);
}
/**
* Returns if the specified URL is a JAR URL.
*
* <p>The function does not validate the URL.</p>
*
* @param url the URL
* @return <code>true</code> if it is a JAR URL, otherwise <code>false</code>
*/
public static final boolean isJarUrl(final URI url) {
return isScheme(url.getScheme(), JAR_SCHEME);
}
private static URI assertJarUrlArgument(final URI url) {
if (!isJarUrl(url)) {
throw new IllegalArgumentException("no JAR url");
}
return url;
}
/**
* Returns if the specified URL is a JAR URL.
*
* <p>The function does not validate the URL.</p>
*
* @param urlString the URL
* @return <code>true</code> if it is a JAR URL, otherwise <code>false</code>
*/
public static final boolean isJarUrl(final String urlString) {
return isSchemeUrl(urlString, JAR_SCHEME);
}
/**
* Return the URL of the JAR archive file.
*
* @param url the JAR URL
* @return the URL of the archive file
* @throws IllegalArgumentException if the specified URL is not a JAR URL
* @throws URISyntaxException if the specified URL is invalid
*
* @see {@link #getJarEntryPath(URI)} for the other part of the URL
*/
public static final URI getJarFileUrl(final URI url) throws URISyntaxException {
assertJarUrlArgument(url);
final String ssp= url.getSchemeSpecificPart();
final int containerSchemeIdx= ssp.indexOf(':');
if (containerSchemeIdx <= 0) {
throw new URISyntaxException(url.toString(), "missing container scheme");
}
final int jarSepIdx= ssp.lastIndexOf(JAR_SEPARATOR);
if (jarSepIdx < containerSchemeIdx) {
throw new URISyntaxException(url.toString(), "missing JAR separator");
}
return (ssp.lastIndexOf(JAR_SEPARATOR, jarSepIdx - 1) == -1) ?
// remove jar scheme
new URI(ssp.substring(0, containerSchemeIdx),
ssp.substring(containerSchemeIdx + 1, jarSepIdx),
url.getFragment() ) :
// nested jar
new URI(url.getScheme(),
ssp.substring(0, jarSepIdx),
url.getFragment() );
}
/**
* Return the path of the entry inside the JAR archive.
*
* @param url the JAR URL
* @return the path of the entry as String (without leading slash)
* @throws IllegalArgumentException if the specified URL is not a JAR URL
* @throws URISyntaxException if the specified URL is invalid
*
* @see {@link #getJarFileUrl(URI)} for the other part of the URL
*/
public static final String getJarEntryPath(final URI url) throws URISyntaxException {
assertJarUrlArgument(url);
final String ssp= url.getSchemeSpecificPart();
final int containerSchemeIdx= ssp.indexOf(':');
if (containerSchemeIdx <= 0) {
throw new URISyntaxException(url.toString(), "missing container scheme");
}
final int jarSepIdx= ssp.lastIndexOf(JAR_SEPARATOR);
if (jarSepIdx < containerSchemeIdx) {
throw new URISyntaxException(url.toString(), "missing JAR separator");
}
return ssp.substring(jarSepIdx + 2);
}
/**
* Returns the JAR URL pointing to the root inside the specified JAR file.
*
* @param jarFileUrlString URL as String pointing to the JAR file itself
* @return the JAR URL as String
* @throws URISyntaxException
*/
public static final URI toJarUrl(final String jarFileUrlString) throws URISyntaxException {
return new URI(toJarUrlString(jarFileUrlString));
}
/**
* Returns the JAR URL as String pointing to the root inside the specified JAR file.
*
* @param jarFileUrlString URL as String pointing to the JAR file itself
* @return the JAR URL as String
* @throws URISyntaxException
*/
public static final String toJarUrlString(final String jarFileUrlString) throws URISyntaxException {
final StringBuilder sb= new StringBuilder(jarFileUrlString.length() + 6);
if (!isSchemeUrl(jarFileUrlString, JAR_SCHEME)) {
sb.append(UriUtils.JAR_SCHEME + ':');
}
sb.append(jarFileUrlString);
sb.append(UriUtils.JAR_SEPARATOR);
return sb.toString();
}
private UriUtils() {
}
}