com.aeontronix.commons.URLBuilder Maven / Gradle / Ivy
Go to download
Show more of this group Show more artifacts with this name
Show all versions of aeon-commons-core Show documentation
Show all versions of aeon-commons-core Show documentation
Various utility classes. Except for very rare exceptions (annotation-based validation) this will not
require any dependencies beyond the JRE
The newest version!
/*
* Copyright (c) 2014 Kloudtek Ltd
*/
package com.aeontronix.commons;
import java.net.MalformedURLException;
import java.net.URI;
import java.net.URISyntaxException;
import java.net.URL;
import java.util.*;
import java.util.stream.Collectors;
import static com.aeontronix.commons.StringUtils.isNotEmpty;
public class URLBuilder {
private String protocol;
private String userInfo;
private final List parameters = new ArrayList();
private String host;
private String fragment;
private int port;
private StringBuilder path;
private String ref;
public URLBuilder(String url) {
if (url == null) {
throw new IllegalArgumentException("url mustn't be null");
}
URI u = URI.create(url);
parseUri(u);
}
public URLBuilder(URI uri) {
if (uri == null) {
throw new IllegalArgumentException("uri mustn't be null");
}
parseUri(uri);
}
public URLBuilder(URL url) throws URISyntaxException {
if (url == null) {
throw new IllegalArgumentException("url mustn't be null");
}
parseUri(url.toURI());
}
private void parseUri(URI u) {
protocol = u.getScheme();
userInfo = u.getUserInfo();
host = u.getHost();
port = u.getPort();
path = new StringBuilder();
String uPath = u.getPath();
if (uPath != null) {
if (!uPath.startsWith("/")) {
path.append('/');
}
this.path.append(uPath);
}
if (isNotEmpty(u.getRawQuery())) {
parseQueryParams(u.getRawQuery());
}
ref = u.getFragment();
if (ref != null) {
int qidx = ref.indexOf("?");
if (qidx != -1) {
parseQueryParams(ref.substring(qidx + 1));
ref = ref.substring(0, qidx);
}
}
}
private void parseQueryParams(String query) {
StringTokenizer tok = new StringTokenizer(query, "&");
while (tok.hasMoreElements()) {
String[] kv = tok.nextToken().split("=");
if (kv.length > 2) {
throw new IllegalArgumentException("Invalid URL query params: " + Arrays.toString(kv));
} else if (kv.length == 1) {
parameters.add(new Param(kv[0], ""));
} else {
parameters.add(new Param(kv[0], kv[1]));
}
}
}
public URLBuilder(String baseUrl, String... path) {
this(baseUrl);
for (String p : path) {
path(p);
}
}
public URLBuilder fragment(String fragment) {
this.fragment = fragment;
return this;
}
/**
* Add a single path element which will be encoded before adding to the path
*
* @param pathElements Path element
* @return builder
*/
public URLBuilder pathEl(String... pathElements) {
if (pathElements != null) {
for (String el : pathElements) {
path(StringUtils.urlPathEncode(el));
}
}
return this;
}
/**
* Add a path to the URL. It will also parse and add any query parameters present.
*
* @param path path
* @return URLBuilder URL Building
*/
public URLBuilder path(String path) {
boolean leftHasSlash = this.path.length() > 0 && this.path.charAt(this.path.length() - 1) == '/';
int qidx = path.indexOf("?");
if (qidx != -1) {
parseQueryParams(path.substring(qidx + 1, path.length()));
path = path.substring(0, qidx);
}
boolean rightHasSlash = path.startsWith("/");
if (!leftHasSlash && !rightHasSlash) {
this.path.append('/');
}
if (leftHasSlash && rightHasSlash) {
this.path.append(path.substring(1, path.length()));
} else {
this.path.append(path);
}
return this;
}
public URLBuilder queryParam(String key, Object value) {
queryParam(StringUtils.urlEncode(key), value != null ? value.toString() : null, true, false);
return this;
}
public URLBuilder queryParam(String key, long value) {
queryParam(StringUtils.urlEncode(key), Long.toString(value), true, false);
return this;
}
public URLBuilder queryParam(String key, int value) {
queryParam(StringUtils.urlEncode(key), Integer.toString(value), true, false);
return this;
}
public URLBuilder queryParam(String key, byte value) {
queryParam(StringUtils.urlEncode(key), Byte.toString(value), true, false);
return this;
}
public URLBuilder queryParam(String key, boolean value) {
queryParam(StringUtils.urlEncode(key), Boolean.toString(value), true, false);
return this;
}
public URLBuilder queryParam(String key, String value, boolean encode, boolean append) {
final String encodedValue = encode && value != null ? StringUtils.urlEncode(value) : value;
if (append) {
if (value != null) {
parameters.add(new Param(key, encodedValue));
}
} else {
final List list = parameters.stream().filter(param -> param.key.equals(key)).collect(Collectors.toList());
if (list.isEmpty()) {
if (value != null) {
parameters.add(new Param(key, encodedValue));
}
} else {
final Param param = list.get(list.size() - 1);
if (value != null) {
param.value = encodedValue;
} else {
parameters.remove(param);
}
}
}
return this;
}
public URLBuilder setUserInfo(String userInfo) {
this.userInfo = StringUtils.urlEncode(userInfo);
return this;
}
public URLBuilder setProtocol(String protocol) {
this.protocol = protocol;
return this;
}
public URLBuilder setRef(String ref) {
this.ref = StringUtils.urlEncode(ref);
return this;
}
public URLBuilder setHost(String host) {
this.host = host;
return this;
}
public URLBuilder setPort(int port) {
this.port = port;
return this;
}
public URL toURL() {
try {
return new URL(toString());
} catch (MalformedURLException e) {
throw new IllegalArgumentException(e);
}
}
public URI toURI() {
return URI.create(toString());
}
@Override
public String toString() {
StringBuilder url = new StringBuilder();
if (isNotEmpty(protocol)) {
url.append(protocol).append("://");
}
if (isNotEmpty(userInfo)) {
url.append(StringUtils.urlEncode(userInfo)).append('@');
}
if (isNotEmpty(host)) {
url.append(host);
}
if (port != -1) {
url.append(':').append(port);
}
url.append(path.toString());
if (ref != null) {
url.append('#').append(ref);
}
if (!parameters.isEmpty()) {
url.append('?');
Iterator i = parameters.iterator();
while (i.hasNext()) {
Param p = i.next();
url.append(p.key).append("=").append(p.value);
if (i.hasNext()) {
url.append("&");
}
}
}
return url.toString();
}
public class Param {
private String key;
private String value;
public Param(String key, String value) {
this.key = key;
this.value = value;
}
}
}