* Duplicate slashes are removed. *
* The result of this method can be used in both URL-paths and URL-query-parameters. *
* For example the input "/some//ex ample///path/" becomes "some/ex%20ample/path".
* @param path the path to be encoded. Must not be null
.
* @return the encoded path. Never null
.
*/
protected String encodePath(final String path) {
requireNonNull(path, "path");
final StringBuilder sb = new StringBuilder();
final String[] segments = path.split("/");
for (final String segment : segments) {
if (segment.isEmpty())
continue;
if (sb.length() != 0)
sb.append('/');
sb.append(urlEncode(segment));
}
return sb.toString();
}
protected void assertResponseIndicatesSuccess(final Response response) {
if (400 <= response.getStatus() && response.getStatus() <= 599) {
response.bufferEntity();
if (response.hasEntity()) {
Error error = null;
try {
error = response.readEntity(Error.class);
} catch (final Exception y) {
logger.error("handleException: " + y, y);
}
if (error != null) {
throwOriginalExceptionIfPossible(error);
throw new RemoteException(error);
}
}
throw new WebApplicationException(response);
}
}
protected void throwOriginalExceptionIfPossible(final Error error) {
RemoteExceptionUtil.throwOriginalExceptionIfPossible(error);
}
}
]]>
* Important: You must {@linkplain #releaseClient() release} the client! Use a try/finally block! * @see #releaseClient() * @see #getClientOrFail() */ private synchronized void acquireClient(){ final ClientRef clientRef = clientThreadLocal.get(); if (clientRef != null) { ++clientRef.refCount; return; } Client client = clientCache.poll(); if (client == null) { ]]>
* The result of this method can be used in both URL-paths and URL-query-parameters.
* @param string the {@code String} to be encoded. Must not be null
.
* @return the encoded {@code String}.
*/
protected static String urlEncode(final String string) {
requireNonNull(string, "string");
// This UriComponent method is safe. It does not try to handle the '{' and '}'
// specially and with type PATH_SEGMENT, it encodes spaces using '%20' instead of '+'.
// It can therefore be used for *both* path segments *and* query parameters.
// return org.glassfish.jersey.uri.UriComponent.encode(string, UriComponent.Type.PATH_SEGMENT);
return UrlEncoder.encode(string);
}
/**
* Create a {@link WebTarget} from the given path segments.
*
* This method prefixes the path with the {@link #getBaseURL() base-URL} and appends * all path segments separated via slashes ('/'). *
* We do not use client.target(getBaseURL()).path("...")
, because the
* {@link WebTarget#path(String) path(...)} method does not encode curly braces
* (which might be part of a file name!).
* Instead it resolves them using {@linkplain WebTarget#matrixParam(String, Object...) matrix-parameters}.
* The matrix-parameters need to be encoded manually, too (at least I tried it and it failed, if I didn't).
* Because of these reasons and in order to make the calls more compact, we assemble the path
* ourselves here.
* @param pathSegments the parts of the path. May be null
. The path segments are
* appended to the path as they are. They are not encoded at all! If you require encoding,
* use {@link #encodePath(String)} or {@link #urlEncode(String)} before! Furthermore, all path segments
* are separated with a slash inbetween them, but not at the end. If a single path segment
* already contains a slash, duplicate slashes might occur.
* @return the target. Never null
.
*/
protected WebTarget createWebTarget(final String ... pathSegments) {
final Client client = getClientOrFail();
final StringBuilder sb = new StringBuilder();
sb.append(getBaseURL());
boolean first = true;
if (pathSegments != null && pathSegments.length != 0) {
for (final String pathSegment : pathSegments) {
if (!first) // the base-URL already ends with a slash!
sb.append('/');
first = false;
sb.append(pathSegment);
}
}
final WebTarget webTarget = client.target(URI.create(sb.toString()));
return webTarget;
}
/**
* Get the server's base-URL.
*
* This base-URL is the base of the CloudStoreREST
application. Hence all URLs
* beneath this base-URL are processed by the CloudStoreREST
application.
*
* In other words: All repository-names are located directly beneath this base-URL. The special services, too, * are located directly beneath this base-URL. *
* For example, if the server's base-URL is "https://host.domain:8443/", then the test-service is * available via "https://host.domain:8443/_test" and the repository with the alias "myrepo" is * "https://host.domain:8443/myrepo". * @return the base-URL. This URL always ends with "/". */ protected String getBaseURL() { return getCloudStoreRestClientOrFail().getBaseUrl(); ]]>