Many resources are needed to download a project. Please understand that we have to compensate our server costs. Thank you in advance. Project price only 1 $
You can buy this project and download/modify it how often you want.
/*
* Copyright (c) 2009. The Codehaus. All Rights Reserved.
*
* Licensed 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.codehaus.httpcache4j.uri;
import net.hamnaberg.funclite.*;
import java.net.URI;
import java.net.URISyntaxException;
import java.util.*;
import java.util.concurrent.atomic.AtomicReference;
/**
* Immutable URI builder.
* Paths in this URI builder will be UTF-8 {@link org.codehaus.httpcache4j.uri.URIEncoder URIEncoded}.
*
* All methods return a NEW instance of the URI builder, meaning you can create a ROOT uri builder and use it
* to your heart's content, as the instance will never change.
*
* @author Erlend Hamnaberg
*/
public final class URIBuilder {
public static AtomicReference schemeDefaults = new AtomicReference(new URISchemeDefaults());
private final String scheme;
private final String host;
private final int port;
private final List path;
private final String fragment;
private final QueryParams parameters;
private final boolean wasPathAbsolute;
private final boolean endsWithSlash;
private final String schemeSpecificPart;
private URIBuilder(String scheme, String schemeSpecificPart, String host, int port, List path, String fragment, QueryParams parameters, boolean wasPathAbsolute, boolean endsWithSlash) {
this.scheme = scheme;
this.schemeSpecificPart = schemeSpecificPart;
this.host = host;
this.port = port;
this.path = path;
this.fragment = fragment;
this.parameters = parameters;
this.wasPathAbsolute = wasPathAbsolute;
this.endsWithSlash = endsWithSlash;
}
public URIBuilder withHost(String host) {
return new URIBuilder(scheme, schemeSpecificPart, host, port, path, fragment, parameters, wasPathAbsolute, endsWithSlash);
}
/**
* Sets the port. This is not required to set if you are using default ports for 'http' or 'https'
* @param port the port to set
* @return a new URIBuilder with the port set
*/
public URIBuilder withPort(int port) {
Optional defaultPort = schemeDefaults.get().getPort(scheme);
if (defaultPort.isSome() && (port == defaultPort.get())) {
port = -1;
}
return new URIBuilder(scheme, schemeSpecificPart, host, port, path, fragment, parameters, wasPathAbsolute, endsWithSlash);
}
private boolean isURN() {
return scheme != null && scheme.startsWith("urn");
}
/**
* This is the scheme to use. Usually 'http' or 'https'.
* @param scheme the scheme
* @return a new URIBuilder with the new scheme set.
*/
public URIBuilder withScheme(String scheme) {
return new URIBuilder(scheme, schemeSpecificPart, host, port, path, fragment, parameters, wasPathAbsolute, endsWithSlash);
}
/**
* Adds a raw path to the URI.
* @param path a path which may contain '/'
* @return a new URI builder which contains the added path.
*/
public URIBuilder addRawPath(String path) {
boolean pathAbsolute = wasPathAbsolute || this.path.isEmpty() && path.startsWith("/");
boolean endsWithSlash = this.endsWithSlash || this.path.isEmpty() && path.endsWith("/");
List appendedPath = toPathParts(path);
ArrayList currentPath = new ArrayList();
currentPath.addAll(this.path);
currentPath.addAll(appendedPath);
return pathInternal(currentPath, pathAbsolute, endsWithSlash);
}
/**
* Appends the path part to the URI.
* We do not expect the path separator '/' to appear here, as each element will be URLEncoded.
* If the '/' character do appear it will be URLEncoded with the rest of the path.
*
* @param path path elements.
* @return a new URI builder which contains the new path.
*/
public URIBuilder addPath(List path) {
List appendedPath = CollectionOps.map(path, stringToPath);
ArrayList currentPath = new ArrayList();
currentPath.addAll(this.path);
currentPath.addAll(appendedPath);
return pathInternal(currentPath, wasPathAbsolute, false);
}
/**
* @see #addPath(java.util.List)
*
* @param path path elements
* @return a new URI builder which contains the new path.
*/
public URIBuilder addPath(String... path) {
return addPath(Arrays.asList(path));
}
/**
* @see #withPath(java.util.List)
*
* @param path path elements.
* @return a new URI builder which contains the new path.
*/
public URIBuilder withPath(String... path) {
return withPath(Arrays.asList(path));
}
/**
* Sets the path of the uri.
* We do not expect the path separator '/' to appear here, as each element will be URLEncoded.
* If the '/' character do appear it will be URLEncoded with the rest of the path.
*
* @param pathList path elements.
* @return a new URI builder which contains the new path.
*/
public URIBuilder withPath(List pathList) {
List paths = CollectionOps.map(pathList, stringToPath);
return pathInternal(paths, false, false);
}
/**
* @see #withPath(java.util.List)
*
* @param path path elements.
* @return a new URI builder which contains the new path.
*/
public URIBuilder withRawPath(String path) {
boolean pathAbsoulute = path.startsWith("/");
boolean endsWithSlash = path.endsWith("/");
List parts = toPathParts(path);
return pathInternal(parts, pathAbsoulute, endsWithSlash);
}
private URIBuilder pathInternal(List pathList, boolean pathAbsolute, boolean endsWithSlash) {
return new URIBuilder(scheme, schemeSpecificPart, host, port, pathList, fragment, parameters, pathAbsolute, endsWithSlash);
}
public URIBuilder withFragment(String fragment) {
return new URIBuilder(scheme, schemeSpecificPart, host, port, path, fragment, parameters, wasPathAbsolute, endsWithSlash);
}
/**
* Creates a new URIBuilder with no parameters, but all other values retained.
* @return new URIBuilder with no parameters.
*/
public URIBuilder noParameters() {
return withParameters(parameters.empty());
}
/**
* Sets a list of parameters. This will clear out all previously set parameters in the new instance.
* @param parameters the list of parameters
* @return new URIBuilder with parameters.
*/
public URIBuilder withParameters(Iterable parameters) {
QueryParams updated = this.parameters.set(parameters);
return withParameters(updated);
}
public URIBuilder withParameters(Map> params) {
QueryParams updated = this.parameters.set(params);
return withParameters(updated);
}
public URIBuilder withParameters(QueryParams params) {
return new URIBuilder(scheme, schemeSpecificPart, host, port, path, fragment, params, wasPathAbsolute, endsWithSlash);
}
/**
* Adds a new Parameter to the collection of parameters
* @param name the parameter name
* @param value the parameter value
* @return a new instance of the URIBuilder
*/
public URIBuilder addParameter(String name, String value) {
return addParameter(new QueryParam(name, value));
}
/**
* Adds a new Parameter to the collection of parameters
* @param parameter the parameter
* @return a new instance of the URIBuilder
*/
public URIBuilder addParameter(QueryParam parameter) {
return addParameters(Arrays.asList(parameter));
}
/**
* Adds Parameters to the collection of parameters
* @return a new instance of the URIBuilder
*/
public URIBuilder addParameters(Iterable newParams) {
if (!newParams.iterator().hasNext()) {
return this;
}
QueryParams updated = this.parameters.add(newParams);
return withParameters(updated);
}
public URIBuilder addParameters(String name, String... values) {
QueryParams updated = this.parameters.add(name, values);
return withParameters(updated);
}
public URIBuilder addParameters(Map> newParams) {
if (newParams.isEmpty()) {
return this;
}
QueryParams updated = this.parameters.add(newParams);
return withParameters(updated);
}
public URIBuilder removeParameters(String name) {
return withParameters(this.parameters.remove(name));
}
public URIBuilder replaceParameter(String name, String value) {
return withParameters(this.parameters.set(name, value));
}
private String toPath(boolean encodepath) {
if (path.isEmpty()) {
return null;
}
StringBuilder builder = new StringBuilder();
for (Path pathElement : path) {
if (builder.length() > 0) {
builder.append("/");
}
builder.append(encodepath ? pathElement.getEncodedValue() : pathElement.getValue());
}
if ((wasPathAbsolute || host != null) && builder.length() > 1) {
if (!"/".equals(builder.substring(0, 1))) {
builder.insert(0, "/");
}
}
if (endsWithSlash) {
builder.append("/");
}
return builder.toString();
}
public URI toURI() {
return toURI(true, false, false);
}
public URI toNormalizedURI(boolean encodePath) {
return toURI(encodePath, true, false).normalize();
}
public URI toNormalizedURI() {
return toNormalizedURI(true);
}
/**
* @return true if the scheme and host parts are not set.
*/
public boolean isRelative() {
return (scheme == null && host == null);
}
public URI toAbsoluteURI() {
return toURI(true, false, true);
}
private URI toURI(boolean encodePath, boolean sortQP, boolean absolutify) {
try {
if (isURN()) {
return new URI(scheme, schemeSpecificPart, fragment);
}
StringBuilder sb = new StringBuilder();
if (scheme != null) {
sb.append(scheme);
sb.append("://");
}
if (host != null) {
sb.append(host);
}
if (port > -1) {
sb.append(":").append(port);
}
if (!path.isEmpty()) {
String path = toPath(encodePath);
if (absolutify && isRelative() && !path.startsWith("/")) {
path = "/" + path;
}
sb.append(path);
}
if (!parameters.isEmpty()) {
sb.append("?");
sb.append(parameters.toQuery(sortQP));
}
if (fragment != null) {
sb.append("#");
sb.append(fragment);
}
return URI.create(sb.toString());
} catch (URISyntaxException e) {
throw new IllegalStateException(e);
}
}
public List getParametersByName(final String name) {
List params = parameters.get(name);
if (params == null) {
return Collections.emptyList();
}
return CollectionOps.map(params, new Function() {
public QueryParam apply(String s) {
return new QueryParam(name, s);
}
});
}
public String getFirstParameterValueByName(final String name) {
return parameters.getFirst(name);
}
/**
* Constructs a new URIBuilder from the given URI
* @param uri the uri to use
* @return a new URIBuilder which has the information from the URI.
*/
public static URIBuilder fromURI(URI uri) {
boolean pathAbsoluteness = uri.getPath() != null && uri.getPath().startsWith("/");
boolean endsWithSlash = uri.getPath() != null && uri.getPath().endsWith("/");
return new URIBuilder(uri.getScheme(), uri.getSchemeSpecificPart(), uri.getHost(), uri.getPort(), toPathParts(uri.getPath()), uri.getFragment(), QueryParams.parse(uri.getRawQuery()), pathAbsoluteness, endsWithSlash);
}
/**
* Creates an empty URIBuilder.
* @return an empty URIBuilder which result of {@link #toURI()} ()} will return "".
*/
public static URIBuilder empty() {
return new URIBuilder(null, "", null, -1, Collections.emptyList(), null, new QueryParams(), false, false);
}
public String getScheme() {
return scheme;
}
public String getHost() {
return host;
}
public int getPort() {
return port;
}
public List getPath() {
return CollectionOps.map(path, pathToString);
}
public List getEncodedPath() {
return CollectionOps.map(path, encodedPathToString);
}
public String getCurrentPath() {
return toPath(false);
}
public String getFragment() {
return fragment;
}
public QueryParams getParameters() {
return parameters;
}
public Map> getParametersAsMap() {
return parameters.asMap();
}
private static List toPathParts(String path) {
if (path == null) {
return Collections.emptyList();
}
if (!path.contains("/")) {
return Collections.singletonList(new Path(path));
}
else {
if (path.startsWith("/")) {
path = path.substring(1);
}
List stringList = Arrays.asList(path.split("/"));
return CollectionOps.map(stringList, stringToPath);
}
}
private static Function stringToPath = new Function() {
public Path apply(String from) {
return new Path(from);
}
};
private static Function pathToString = new Function() {
public String apply(Path from) {
return from.getValue();
}
};
private static Function encodedPathToString = new Function() {
public String apply(Path from) {
return from.getEncodedValue();
}
};
private static class Path {
private final String value;
private Path(String value) {
this.value = URIDecoder.decodeUTF8(value);
}
String getEncodedValue() {
return URIEncoder.encodeUTF8(value);
}
String getValue() {
return value;
}
@Override
public String toString() {
return value;
}
}
}