diff --git a/pom.xml b/pom.xml index b688454..6a2de32 100644 --- a/pom.xml +++ b/pom.xml @@ -3,7 +3,7 @@ org.lightcouch lightcouch - 0.2.1-SNAPSHOT + 0.2.4 jar LightCouch CouchDB Java API @@ -35,9 +35,10 @@ UTF-8 - 4.5.3 - 2.8.2 - 4.8.2 + 4.5.13 + 2.11.0 + 4.13.2 + 23.0.0 @@ -59,6 +60,13 @@ ${junit.version} test + + + org.jetbrains + annotations + ${jb-annotations.version} + provided + @@ -67,8 +75,8 @@ maven-compiler-plugin 3.1 - 1.5 - 1.5 + 11 + 11 diff --git a/src/main/java/org/lightcouch/Changes.java b/src/main/java/org/lightcouch/Changes.java index a544d46..cad26a4 100644 --- a/src/main/java/org/lightcouch/Changes.java +++ b/src/main/java/org/lightcouch/Changes.java @@ -75,7 +75,7 @@ public class Changes { Changes(CouchDbClientBase dbc) { this.dbc = dbc; this.gson = dbc.getGson(); - this.uriBuilder = URIBuilder.buildUri(dbc.getDBUri()).path("_changes"); + this.uriBuilder = dbc.getDBURIBuilder().pathSegment("_changes"); } /** @@ -152,7 +152,7 @@ public Changes filter(String filter) { } public Changes includeDocs(boolean includeDocs) { - uriBuilder.query("include_docs", includeDocs); + uriBuilder.query(CouchConstants.PARAM_INCLUDE_DOCS, includeDocs); return this; } diff --git a/src/main/java/org/lightcouch/CouchConstants.java b/src/main/java/org/lightcouch/CouchConstants.java new file mode 100644 index 0000000..d3f2cb1 --- /dev/null +++ b/src/main/java/org/lightcouch/CouchConstants.java @@ -0,0 +1,25 @@ +/* + * Copyright (C) 2011 lightcouch.org + * + * 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.lightcouch; + +final class CouchConstants { + static final String PARAM_REVISION = "rev"; + static final String PARAM_INCLUDE_DOCS = "include_docs"; + + private CouchConstants() { + // No instances for you! + } +} diff --git a/src/main/java/org/lightcouch/CouchDbClientBase.java b/src/main/java/org/lightcouch/CouchDbClientBase.java index 956eb85..5da4242 100644 --- a/src/main/java/org/lightcouch/CouchDbClientBase.java +++ b/src/main/java/org/lightcouch/CouchDbClientBase.java @@ -23,7 +23,6 @@ import static org.lightcouch.CouchDbUtil.getAsString; import static org.lightcouch.CouchDbUtil.getStream; import static org.lightcouch.CouchDbUtil.streamToString; -import static org.lightcouch.URIBuilder.buildUri; import java.io.IOException; import java.io.InputStream; @@ -34,6 +33,7 @@ import java.net.URI; import java.util.ArrayList; import java.util.List; +import java.util.Map; import org.apache.commons.codec.Charsets; import org.apache.commons.logging.Log; @@ -66,6 +66,8 @@ import com.google.gson.JsonSerializationContext; import com.google.gson.JsonSerializer; import com.google.gson.reflect.TypeToken; +import org.jetbrains.annotations.NotNull; +import org.jetbrains.annotations.Nullable; /** * Contains a client Public API implementation. @@ -77,29 +79,27 @@ public abstract class CouchDbClientBase { static final Log log = LogFactory.getLog(CouchDbClient.class); + private final CouchDbProperties props; + @Nullable private URI baseURI; + @Nullable private URI dbURI; - private Gson gson; + private Gson gson; private CouchDbContext context; private CouchDbDesign design; final HttpClient httpClient; final HttpHost host; - + CouchDbClientBase() { this(new CouchDbConfig()); } CouchDbClientBase(CouchDbConfig config) { - final CouchDbProperties props = config.getProperties(); + props = config.getProperties(); this.httpClient = createHttpClient(props); this.gson = initGson(new GsonBuilder()); this.host = new HttpHost(props.getHost(), props.getPort(), props.getProtocol()); - - final String path = props.getPath() != null ? props.getPath() : ""; - this.baseURI = buildUri().scheme(props.getProtocol()).host(props.getHost()).port(props.getPort()).path("/").path(path).build(); - this.dbURI = buildUri(baseURI).path(props.getDbName()).path("/").build(); - - this.context = new CouchDbContext(this, props); + this.context = new CouchDbContext(this, props); this.design = new CouchDbDesign(this); } @@ -180,10 +180,7 @@ public Changes changes() { * @throws NoDocumentException If the document is not found in the database. */ public T find(Class classType, String id) { - assertNotEmpty(classType, "Class"); - assertNotEmpty(id, "id"); - final URI uri = buildUri(getDBUri()).pathEncoded(id).build(); - return get(uri, classType); + return find(classType, id, Map.of()); } /** @@ -195,10 +192,26 @@ public T find(Class classType, String id) { * @return An object of type T. * @throws NoDocumentException If the document is not found in the database. */ + @Deprecated public T find(Class classType, String id, Params params) { + return find(classType, id, params.getParamMap()); + } + + /** + * Finds an Object of the specified type. + * + * @param Object type. + * @param classType The class of type T. + * @param id The document id. + * @param params Extra parameters to append. + * @return An object of type T. + * @throws NoDocumentException If the document is not found in the database. + */ + public T find(Class classType, String id, Map params) { assertNotEmpty(classType, "Class"); assertNotEmpty(id, "id"); - final URI uri = buildUri(getDBUri()).pathEncoded(id).query(params).build(); + + URI uri = getDBURIBuilder().pathSegment(id).query(params).build(); return get(uri, classType); } @@ -214,8 +227,8 @@ public T find(Class classType, String id, Params params) { public T find(Class classType, String id, String rev) { assertNotEmpty(classType, "Class"); assertNotEmpty(id, "id"); - assertNotEmpty(id, "rev"); - final URI uri = buildUri(getDBUri()).pathEncoded(id).query("rev", rev).build(); + assertNotEmpty(rev, CouchConstants.PARAM_REVISION); + URI uri = getDBURIBuilder().pathSegment(id).query(CouchConstants.PARAM_REVISION, rev).build(); return get(uri, classType); } @@ -243,7 +256,7 @@ public T findAny(Class classType, String uri) { */ public InputStream find(String id) { assertNotEmpty(id, "id"); - return get(buildUri(getDBUri()).path(id).build()); + return get(getDBURIBuilder().pathSegment(id).build()); } /** @@ -256,8 +269,8 @@ public InputStream find(String id) { */ public InputStream find(String id, String rev) { assertNotEmpty(id, "id"); - assertNotEmpty(rev, "rev"); - final URI uri = buildUri(getDBUri()).path(id).query("rev", rev).build(); + assertNotEmpty(rev, CouchConstants.PARAM_REVISION); + final URI uri = getDBURIBuilder().pathSegment(id).query(CouchConstants.PARAM_REVISION, rev).build(); return get(uri); } @@ -273,8 +286,8 @@ public List findDocs(String jsonQuery, Class classOfT) { assertNotEmpty(jsonQuery, "jsonQuery"); HttpResponse response = null; try { - response = post(buildUri(getDBUri()).path("_find").build(), jsonQuery); - Reader reader = new InputStreamReader(getStream(response), Charsets.UTF_8); + response = post(getDBURIBuilder().pathSegment("_find").build(), jsonQuery); + Reader reader = new InputStreamReader(getStream(response), Charsets.UTF_8); // FIXME close this reader JsonArray jsonArray = new JsonParser().parse(reader) .getAsJsonObject().getAsJsonArray("docs"); List list = new ArrayList(); @@ -298,7 +311,7 @@ public boolean contains(String id) { assertNotEmpty(id, "id"); HttpResponse response = null; try { - response = head(buildUri(getDBUri()).pathEncoded(id).build()); + response = head(getDBURIBuilder().pathSegment(id).build()); } catch (NoDocumentException e) { return false; } finally { @@ -315,7 +328,7 @@ public boolean contains(String id) { * @return {@link Response} */ public Response save(Object object) { - return put(getDBUri(), object, true); + return put(getDBURIBuilder(), object, true); } /** @@ -327,9 +340,8 @@ public Response save(Object object) { public Response post(Object object) { assertNotEmpty(object, "object"); HttpResponse response = null; - try { - URI uri = buildUri(getDBUri()).build(); - response = post(uri, getGson().toJson(object)); + try { + response = post(getDBUri(), gson.toJson(object)); return getResponse(response); } finally { close(response); @@ -344,7 +356,7 @@ public void batch(Object object) { assertNotEmpty(object, "object"); HttpResponse response = null; try { - URI uri = buildUri(getDBUri()).query("batch", "ok").build(); + URI uri = getDBURIBuilder().query("batch", "ok").build(); response = post(uri, getGson().toJson(object)); } finally { close(response); @@ -358,7 +370,7 @@ public void batch(Object object) { * @return {@link Response} */ public Response update(Object object) { - return put(getDBUri(), object, false); + return put(getDBURIBuilder(), object, false); } /** @@ -385,8 +397,8 @@ public Response remove(Object object) { */ public Response remove(String id, String rev) { assertNotEmpty(id, "id"); - assertNotEmpty(rev, "rev"); - final URI uri = buildUri(getDBUri()).pathEncoded(id).query("rev", rev).build(); + assertNotEmpty(rev, CouchConstants.PARAM_REVISION); + URI uri = getDBURIBuilder().pathSegment(id).query(CouchConstants.PARAM_REVISION, rev).build(); return delete(uri); } @@ -402,7 +414,7 @@ public List bulk(List objects, boolean newEdits) { try { final String newEditsVal = newEdits ? "\"new_edits\": true, " : "\"new_edits\": false, "; final String json = String.format("{%s%s%s}", newEditsVal, "\"docs\": ", getGson().toJson(objects)); - final URI uri = buildUri(getDBUri()).path("_bulk_docs").build(); + final URI uri = getDBURIBuilder().pathSegment("_bulk_docs").build(); response = post(uri, json); return getResponseList(response); } finally { @@ -422,7 +434,10 @@ public Response saveAttachment(InputStream in, String name, String contentType) assertNotEmpty(in, "in"); assertNotEmpty(name, "name"); assertNotEmpty(contentType, "ContentType"); - final URI uri = buildUri(getDBUri()).path(generateUUID()).path("/").path(name).build(); + URI uri = getDBURIBuilder() + .pathSegment(generateUUID()) + .pathSegment(name) + .build(); return put(uri, in, contentType); } @@ -442,7 +457,11 @@ public Response saveAttachment(InputStream in, String name, String contentType, assertNotEmpty(name, "name"); assertNotEmpty(contentType, "ContentType"); assertNotEmpty(docId, "docId"); - final URI uri = buildUri(getDBUri()).pathEncoded(docId).path("/").path(name).query("rev", docRev).build(); + URI uri = getDBURIBuilder() + .pathSegment(docId) + .pathSegment(name) + .query(CouchConstants.PARAM_REVISION, docRev) + .build(); return put(uri, in, contentType); } @@ -459,12 +478,36 @@ public Response saveAttachment(InputStream in, String name, String contentType, * @param params The query parameters as {@link Params}. * @return The output of the request. */ + @Deprecated public String invokeUpdateHandler(String updateHandlerUri, String docId, Params params) { + return invokeUpdateHandler(updateHandlerUri, docId, params.getParamMap()); + } + + /** + * Invokes an Update Handler. + *
+	 * Params params = new Params()
+	 *	.addParam("field", "foo")
+	 *	.addParam("value", "bar");
+	 * String output = dbClient.invokeUpdateHandler("designDoc/update1", "docId", params);
+	 * 
+ * @param updateHandlerUri The Update Handler URI, in the format: designDoc/update1 + * @param docId The document id to update. + * @param params The query parameters as {@link Params}. + * @return The output of the request. + */ + public String invokeUpdateHandler(String updateHandlerUri, String docId, Map params) { assertNotEmpty(updateHandlerUri, "uri"); assertNotEmpty(docId, "docId"); final String[] v = updateHandlerUri.split("/"); - final String path = String.format("_design/%s/_update/%s/", v[0], v[1]); - final URI uri = buildUri(getDBUri()).path(path).path(docId).query(params).build(); + URI uri = getDBURIBuilder() + .pathSegment("_design") + .pathSegment(v[0]) + .pathSegment("_update") + .pathSegment(v[1]) + .pathSegment(docId) + .query(params) + .build(); final HttpResponse response = executeRequest(new HttpPut(uri)); return streamToString(getStream(response)); } @@ -503,17 +546,40 @@ public void setGsonBuilder(GsonBuilder gsonBuilder) { /** * @return The base URI. */ + @NotNull public URI getBaseUri() { + if (baseURI == null) { + baseURI = getBaseURIBuilder().build(); + } return baseURI; } + + URIBuilder getBaseURIBuilder() { + URIBuilder builder = new URIBuilder() + .scheme(props.getProtocol()) + .host(props.getHost()) + .port(props.getPort()); + if (props.getPath() != null) { + builder.pathSegment(props.getPath()); + } + return builder; + } /** * @return The database URI. */ + @NotNull public URI getDBUri() { + if (dbURI == null) { + dbURI = getDBURIBuilder().build(); + } return dbURI; } - + + URIBuilder getDBURIBuilder() { + return getBaseURIBuilder().pathSegment(props.getDbName()); + } + /** * @return The Gson instance. */ @@ -570,7 +636,7 @@ HttpResponse head(URI uri) { * Performs a HTTP PUT request, saves or updates a document. * @return {@link Response} */ - Response put(URI uri, Object object, boolean newEntity) { + Response put(URIBuilder uriBuilder, Object object, boolean newEntity) { assertNotEmpty(object, "object"); HttpResponse response = null; try { @@ -578,13 +644,13 @@ Response put(URI uri, Object object, boolean newEntity) { String id = getAsString(json, "_id"); String rev = getAsString(json, "_rev"); if(newEntity) { // save - assertNull(rev, "rev"); + assertNull(rev, CouchConstants.PARAM_REVISION); id = (id == null) ? generateUUID() : id; } else { // update assertNotEmpty(id, "id"); - assertNotEmpty(rev, "rev"); + assertNotEmpty(rev, CouchConstants.PARAM_REVISION); } - final HttpPut put = new HttpPut(buildUri(uri).pathEncoded(id).build()); + HttpPut put = new HttpPut(uriBuilder.pathSegment(id).build()); setEntity(put, json.toString()); response = executeRequest(put); return getResponse(response); @@ -696,7 +762,8 @@ private void setEntity(HttpEntityEnclosingRequestBase httpRequest, String json) * @return {@link Gson} instance */ private Gson initGson(GsonBuilder gsonBuilder) { - gsonBuilder.registerTypeAdapter(JsonObject.class, new JsonDeserializer() { + // Fix of https://github.com/lightcouch/LightCouch/issues/82 +/* gsonBuilder.registerTypeAdapter(JsonObject.class, new JsonDeserializer() { public JsonObject deserialize(JsonElement json, Type typeOfT, JsonDeserializationContext context) throws JsonParseException { @@ -709,7 +776,7 @@ public JsonElement serialize(JsonObject src, Type typeOfSrc, return src.getAsJsonObject(); } - }); + });*/ return gsonBuilder.create(); } } diff --git a/src/main/java/org/lightcouch/CouchDbContext.java b/src/main/java/org/lightcouch/CouchDbContext.java index f0b4949..c0101d8 100644 --- a/src/main/java/org/lightcouch/CouchDbContext.java +++ b/src/main/java/org/lightcouch/CouchDbContext.java @@ -17,7 +17,6 @@ package org.lightcouch; import static org.lightcouch.CouchDbUtil.*; -import static org.lightcouch.URIBuilder.*; import java.io.InputStream; import java.io.InputStreamReader; @@ -44,8 +43,7 @@ * @author Ahmed Yehia */ public class CouchDbContext { - - private static final Log log = LogFactory.getLog(CouchDbClient.class); + private static final Log log = LogFactory.getLog(CouchDbContext.class); private CouchDbClientBase dbc; @@ -67,7 +65,7 @@ public void deleteDB(String dbName, String confirm) { assertNotEmpty(dbName, "dbName"); if(!"delete database".equals(confirm)) throw new IllegalArgumentException("Invalid confirm!"); - dbc.delete(buildUri(dbc.getBaseUri()).path(dbName).build()); + dbc.delete(dbc.getBaseURIBuilder().pathSegment(dbName).build()); } /** @@ -78,7 +76,7 @@ public void createDB(String dbName) { assertNotEmpty(dbName, "dbName"); InputStream getresp = null; HttpResponse putresp = null; - final URI uri = buildUri(dbc.getBaseUri()).path(dbName).build(); + URI uri = dbc.getBaseURIBuilder().pathSegment(dbName).build(); try { getresp = dbc.get(uri); } catch (NoDocumentException e) { // db doesn't exist @@ -98,8 +96,8 @@ public List getAllDbs() { InputStream instream = null; try { Type typeOfList = new TypeToken>() {}.getType(); - instream = dbc.get(buildUri(dbc.getBaseUri()).path("_all_dbs").build()); - Reader reader = new InputStreamReader(instream, Charsets.UTF_8); + instream = dbc.get(dbc.getBaseURIBuilder().pathSegment("_all_dbs").build()); + Reader reader = new InputStreamReader(instream, Charsets.UTF_8); // FIXME close this reader return dbc.getGson().fromJson(reader, typeOfList); } finally { close(instream); @@ -110,7 +108,7 @@ public List getAllDbs() { * @return {@link CouchDbInfo} Containing the DB server info. */ public CouchDbInfo info() { - return dbc.get(buildUri(dbc.getDBUri()).build(), CouchDbInfo.class); + return dbc.get(dbc.getDBUri(), CouchDbInfo.class); } /** @@ -119,8 +117,8 @@ public CouchDbInfo info() { public String serverVersion() { InputStream instream = null; try { - instream = dbc.get(buildUri(dbc.getBaseUri()).build()); - Reader reader = new InputStreamReader(instream, Charsets.UTF_8); + instream = dbc.get(dbc.getBaseUri()); + Reader reader = new InputStreamReader(instream, Charsets.UTF_8); // FIXME close this reader return getAsString(new JsonParser().parse(reader).getAsJsonObject(), "version"); } finally { close(instream); @@ -133,7 +131,7 @@ public String serverVersion() { public void compact() { HttpResponse response = null; try { - response = dbc.post(buildUri(dbc.getDBUri()).path("_compact").build(), ""); + response = dbc.post(dbc.getDBURIBuilder().pathSegment("_compact").build(), ""); } finally { close(response); } @@ -145,7 +143,7 @@ public void compact() { public void ensureFullCommit() { HttpResponse response = null; try { - response = dbc.post(buildUri(dbc.getDBUri()).path("_ensure_full_commit").build(), ""); + response = dbc.post(dbc.getDBURIBuilder().pathSegment("_ensure_full_commit").build(), ""); } finally { close(response); } diff --git a/src/main/java/org/lightcouch/CouchDbDesign.java b/src/main/java/org/lightcouch/CouchDbDesign.java index 33da85a..5eb7327 100644 --- a/src/main/java/org/lightcouch/CouchDbDesign.java +++ b/src/main/java/org/lightcouch/CouchDbDesign.java @@ -21,7 +21,6 @@ import static org.lightcouch.CouchDbUtil.listResources; import static org.lightcouch.CouchDbUtil.readFile; import static org.lightcouch.CouchDbUtil.removeExtension; -import static org.lightcouch.URIBuilder.buildUri; import java.net.URI; import java.util.ArrayList; @@ -122,7 +121,7 @@ public void synchronizeAllWithDb() { */ public DesignDocument getFromDb(String id) { assertNotEmpty(id, "id"); - final URI uri = buildUri(dbc.getDBUri()).path(id).build(); + URI uri = dbc.getDBURIBuilder().pathSegment(id).build(); return dbc.get(uri, DesignDocument.class); } @@ -134,8 +133,8 @@ public DesignDocument getFromDb(String id) { */ public DesignDocument getFromDb(String id, String rev) { assertNotEmpty(id, "id"); - assertNotEmpty(id, "rev"); - final URI uri = buildUri(dbc.getDBUri()).path(id).query("rev", rev).build(); + assertNotEmpty(id, CouchConstants.PARAM_REVISION); + URI uri = dbc.getDBURIBuilder().pathSegment(id).query(CouchConstants.PARAM_REVISION, rev).build(); return dbc.get(uri, DesignDocument.class); } diff --git a/src/main/java/org/lightcouch/CouchDbInfo.java b/src/main/java/org/lightcouch/CouchDbInfo.java index caaa70f..deaa2c8 100644 --- a/src/main/java/org/lightcouch/CouchDbInfo.java +++ b/src/main/java/org/lightcouch/CouchDbInfo.java @@ -33,7 +33,7 @@ public class CouchDbInfo { @SerializedName("update_seq") private String updateSeq; @SerializedName("purge_seq") - private long purgeSeq; + private Object purgeSeq; @SerializedName("compact_running") private boolean compactRunning; @SerializedName("disk_size") @@ -59,7 +59,7 @@ public String getUpdateSeq() { return updateSeq; } - public long getPurgeSeq() { + public Object getPurgeSeq() { return purgeSeq; } diff --git a/src/main/java/org/lightcouch/Params.java b/src/main/java/org/lightcouch/Params.java index bffa1a9..fb93b7b 100644 --- a/src/main/java/org/lightcouch/Params.java +++ b/src/main/java/org/lightcouch/Params.java @@ -16,10 +16,11 @@ package org.lightcouch; -import java.io.UnsupportedEncodingException; +import org.jetbrains.annotations.Nullable; + import java.net.URLEncoder; -import java.util.ArrayList; -import java.util.List; +import java.nio.charset.StandardCharsets; +import java.util.*; /** * Query parameters to append to find requests. @@ -30,54 +31,60 @@ * @see CouchDbClientBase#find(Class, String, Params) * @since 0.0.6 * @author Ahmed Yehia - * + * */ +@Deprecated public class Params { + private final Map paramMap = new LinkedHashMap<>(); + + public Params revsInfo() { + return addTrueFlag("revs_info"); + } - private List params = new ArrayList(); + public Params attachments() { + return addTrueFlag("attachments"); + } - public Params revsInfo() { - params.add("revs_info=true"); - return this; - } + public Params revisions() { + return addTrueFlag("revs"); + } - public Params attachments() { - params.add("attachments=true"); - return this; - } + public Params rev(String rev) { + return addParam(CouchConstants.PARAM_REVISION, rev); + } - public Params revisions() { - params.add("revs=true"); - return this; - } + public Params conflicts() { + return addTrueFlag("conflicts"); + } - public Params rev(String rev) { - params.add(String.format("rev=%s", rev)); - return this; - } + public Params localSeq() { + return addTrueFlag("local_seq"); + } - public Params conflicts() { - params.add("conflicts=true"); - return this; - } + private Params addTrueFlag(String paramName) { + return addParam(paramName, "true"); + } - public Params localSeq() { - params.add("local_seq=true"); - return this; - } + public Params addParam(String name, String value) { + paramMap.put(name, value); + return this; + } - public Params addParam(String name, String value) { - try { - name = URLEncoder.encode(name, "UTF-8"); - value = URLEncoder.encode(value, "UTF-8"); - params.add(String.format("%s=%s", name, value)); - } catch (UnsupportedEncodingException e) { - throw new IllegalArgumentException(e); - } - return this; - } + @Nullable + public List getParams() { + if (paramMap.isEmpty()) { + return null; + } + List list = new ArrayList<>(); + for (var entry : paramMap.entrySet()) { + String encodedName = URLEncoder.encode(entry.getKey(), StandardCharsets.UTF_8); + String encodedValue = URLEncoder.encode(entry.getValue(), StandardCharsets.UTF_8); + list.add(encodedName + '=' + encodedValue); + } + return list; + } - public List getParams() { - return params.isEmpty() ? null : params; - } + Map getParamMap() { + return Collections.unmodifiableMap(paramMap); + } } diff --git a/src/main/java/org/lightcouch/Replication.java b/src/main/java/org/lightcouch/Replication.java index a98de51..f00a0f2 100644 --- a/src/main/java/org/lightcouch/Replication.java +++ b/src/main/java/org/lightcouch/Replication.java @@ -19,7 +19,6 @@ import static org.lightcouch.CouchDbUtil.assertNotEmpty; import static org.lightcouch.CouchDbUtil.close; import static org.lightcouch.CouchDbUtil.getStream; -import static org.lightcouch.URIBuilder.buildUri; import java.io.InputStreamReader; import java.net.URI; @@ -100,7 +99,7 @@ public ReplicationResult trigger() { if(log.isDebugEnabled()) { log.debug(json); } - final URI uri = buildUri(dbc.getBaseUri()).path("_replicate").build(); + URI uri = dbc.getBaseURIBuilder().pathSegment("_replicate").build(); response = dbc.post(uri, json.toString()); final InputStreamReader reader = new InputStreamReader(getStream(response), Charsets.UTF_8); return dbc.getGson().fromJson(reader, ReplicationResult.class); diff --git a/src/main/java/org/lightcouch/Replicator.java b/src/main/java/org/lightcouch/Replicator.java index 73b9069..676a16f 100644 --- a/src/main/java/org/lightcouch/Replicator.java +++ b/src/main/java/org/lightcouch/Replicator.java @@ -17,7 +17,6 @@ package org.lightcouch; import static org.lightcouch.CouchDbUtil.*; -import static org.lightcouch.URIBuilder.buildUri; import java.io.InputStream; import java.io.InputStreamReader; @@ -80,16 +79,17 @@ public class Replicator { private CouchDbClientBase dbc; private ReplicatorDocument replicatorDoc; - private URI dbURI; public Replicator(CouchDbClientBase dbc) { this.dbc = dbc; replicatorDoc = new ReplicatorDocument(); replicatorDB = "_replicator"; // default replicator db userCtxRoles = new String[0]; // default roles - dbURI = buildUri(dbc.getBaseUri()).path(replicatorDB).path("/").build(); } + private URIBuilder getURIBuilder() { + return dbc.getBaseURIBuilder().pathSegment(replicatorDB); + } /** * Adds a new document to the replicator database. @@ -104,7 +104,7 @@ public Response save() { ctx.setRoles(userCtxRoles); replicatorDoc.setUserCtx(ctx); } - return dbc.put(dbURI, replicatorDoc, true); + return dbc.put(getURIBuilder(), replicatorDoc, true); } /** @@ -113,7 +113,10 @@ public Response save() { */ public ReplicatorDocument find() { assertNotEmpty(replicatorDoc.getId(), "Doc id"); - final URI uri = buildUri(dbURI).path(replicatorDoc.getId()).query("rev", replicatorDoc.getRevision()).build(); + URI uri = getURIBuilder() + .pathSegment(replicatorDoc.getId()) + .query(CouchConstants.PARAM_REVISION, replicatorDoc.getRevision()) + .build(); return dbc.get(uri, ReplicatorDocument.class); } @@ -123,8 +126,8 @@ public ReplicatorDocument find() { */ public List findAll() { InputStream instream = null; - try { - final URI uri = buildUri(dbURI).path("_all_docs").query("include_docs", "true").build(); + try { + URI uri = getURIBuilder().pathSegment("_all_docs").query(CouchConstants.PARAM_INCLUDE_DOCS, true).build(); final Reader reader = new InputStreamReader(instream = dbc.get(uri), Charsets.UTF_8); final JsonArray jsonArray = new JsonParser().parse(reader) .getAsJsonObject().getAsJsonArray("rows"); @@ -149,7 +152,10 @@ public List findAll() { public Response remove() { assertNotEmpty(replicatorDoc.getId(), "Doc id"); assertNotEmpty(replicatorDoc.getRevision(), "Doc rev"); - final URI uri = buildUri(dbURI).path(replicatorDoc.getId()).query("rev", replicatorDoc.getRevision()).build(); + URI uri = getURIBuilder() + .pathSegment(replicatorDoc.getId()) + .query(CouchConstants.PARAM_REVISION, replicatorDoc.getRevision()) + .build(); return dbc.delete(uri); } @@ -202,7 +208,6 @@ public Replicator createTarget(Boolean createTarget) { public Replicator replicatorDB(String replicatorDB) { this.replicatorDB = replicatorDB; - dbURI = buildUri(dbc.getBaseUri()).path(replicatorDB).path("/").build(); return this; } diff --git a/src/main/java/org/lightcouch/URIBuilder.java b/src/main/java/org/lightcouch/URIBuilder.java index 8bc6d81..7bae6f9 100644 --- a/src/main/java/org/lightcouch/URIBuilder.java +++ b/src/main/java/org/lightcouch/URIBuilder.java @@ -16,35 +16,34 @@ package org.lightcouch; -import java.io.UnsupportedEncodingException; +import org.apache.http.NameValuePair; +import org.apache.http.client.utils.URLEncodedUtils; +import org.jetbrains.annotations.NotNull; +import org.jetbrains.annotations.Nullable; + import java.net.URI; import java.net.URISyntaxException; -import java.net.URLEncoder; -import java.util.ArrayList; -import java.util.List; +import java.nio.charset.StandardCharsets; +import java.util.*; +import java.util.stream.Collectors; /** * Helper class for construction of HTTP request URIs. * @since 0.0.2 * @author Ahmed Yehia - * + * */ class URIBuilder { + @Nullable private String scheme; + @Nullable private String host; - private int port; - private String path = ""; - private final List params = new ArrayList(); - - public static URIBuilder buildUri() { - return new URIBuilder(); - } - - public static URIBuilder buildUri(URI uri) { - URIBuilder builder = URIBuilder.buildUri().scheme(uri.getScheme()). - host(uri.getHost()).port(uri.getPort()).path(uri.getPath()); - return builder; - } + @Nullable + private Integer port; + @Nullable + private Collection pathSegments; + @Nullable + private Map queryParams; public URIBuilder scheme(String scheme) { this.scheme = scheme; @@ -60,57 +59,84 @@ public URIBuilder port(int port) { this.port = port; return this; } - - public URIBuilder path(String path) { - this.path += path; - return this; - } - public URIBuilder pathEncoded(String path) { - try { - this.path += URLEncoder.encode(path, "UTF-8"); - } catch (UnsupportedEncodingException e) { - throw new IllegalArgumentException(e); + URIBuilder pathSegment(String pathSegment) { + if (pathSegments == null) { + pathSegments = new ArrayList<>(); } + pathSegments.add(pathSegment); return this; } public URIBuilder query(String name, Object value) { - if (name != null && value != null) { - try { - name = URLEncoder.encode(name, "UTF-8"); - value = URLEncoder.encode(String.valueOf(value), "UTF-8"); - this.params.add(String.format("%s=%s", name, value)); - } catch (UnsupportedEncodingException e) { - throw new IllegalArgumentException(e); - } - } + safeQueryParams().put(name, value); return this; } - public URIBuilder query(Params params) { - if (params.getParams() != null) - this.params.addAll(params.getParams()); + URIBuilder query(Map params) { + safeQueryParams().putAll(params); return this; } + @NotNull + private Map safeQueryParams() { + if (queryParams == null) { + queryParams = new LinkedHashMap<>(); + } + return queryParams; + } + public URI build() { - final StringBuilder query = new StringBuilder(); - - for (int i = 0; i < params.size(); i++) { - String amp = (i != params.size() - 1) ? "&" : ""; - query.append(params.get(i) + amp); + assert scheme != null; // mandated by RFC 3986 + + StringBuilder builder = new StringBuilder(scheme); + builder.append(':'); + if (host != null || port != null) { + builder.append("//"); } - - String q = (query.length() == 0) ? "" : "?" + query; - String uri = String.format("%s://%s:%s%s%s", new Object[] { scheme, host, port, path, q }); - + if (host != null) { + builder.append(host); + } + if (port != null) { + builder.append(':').append(port); + } + if (pathSegments != null) { + String path = URLEncodedUtils.formatSegments(pathSegments, StandardCharsets.UTF_8); + builder.append(path); + } + if (queryParams != null) { + builder.append('?'); + Iterable nameValuePairs = queryParams.entrySet().stream() + .map(entry -> new QueryParameter(entry.getKey(), String.valueOf(entry.getValue()))) + .collect(Collectors.toList()); + String query = URLEncodedUtils.format(nameValuePairs, StandardCharsets.UTF_8); + builder.append(query); + } + try { - return new URI(uri); + return new URI(builder.toString()); } catch (URISyntaxException e) { - throw new IllegalArgumentException(e); + throw new IllegalStateException(e); } - } + private static final class QueryParameter implements NameValuePair { + private final String name; + private final String value; + + private QueryParameter(String name, String value) { + this.name = name; + this.value = value; + } + + @Override + public String getName() { + return name; + } + + @Override + public String getValue() { + return value; + } + } } diff --git a/src/main/java/org/lightcouch/View.java b/src/main/java/org/lightcouch/View.java index 1802e63..63ca98d 100644 --- a/src/main/java/org/lightcouch/View.java +++ b/src/main/java/org/lightcouch/View.java @@ -111,7 +111,7 @@ public class View { String[] v = viewId.split("/"); view = String.format("_design/%s/_view/%s", v[0], v[1]); } - this.uriBuilder = URIBuilder.buildUri(dbc.getDBUri()).path(view); + this.uriBuilder = dbc.getDBURIBuilder().pathSegment(view); } // Query options @@ -535,7 +535,7 @@ public View reduce(Boolean reduce) { */ public View includeDocs(Boolean includeDocs) { this.includeDocs = includeDocs; - uriBuilder.query("include_docs", this.includeDocs); + uriBuilder.query(CouchConstants.PARAM_INCLUDE_DOCS, this.includeDocs); return this; } diff --git a/src/test/java/org/lightcouch/tests/AttachmentsTest.java b/src/test/java/org/lightcouch/AttachmentsTest.java similarity index 96% rename from src/test/java/org/lightcouch/tests/AttachmentsTest.java rename to src/test/java/org/lightcouch/AttachmentsTest.java index d56a42b..4142aaa 100644 --- a/src/test/java/org/lightcouch/tests/AttachmentsTest.java +++ b/src/test/java/org/lightcouch/AttachmentsTest.java @@ -14,7 +14,7 @@ * limitations under the License. */ -package org.lightcouch.tests; +package org.lightcouch; import static org.junit.Assert.assertArrayEquals; import static org.junit.Assert.assertNotNull; @@ -28,12 +28,10 @@ import org.apache.commons.codec.binary.Base64; import org.junit.AfterClass; import org.junit.BeforeClass; +import org.junit.Ignore; import org.junit.Test; -import org.lightcouch.Attachment; -import org.lightcouch.CouchDbClient; -import org.lightcouch.Params; -import org.lightcouch.Response; +@Ignore("Not a unit test! Runs agains a live database") public class AttachmentsTest { private static CouchDbClient dbClient; diff --git a/src/test/java/org/lightcouch/tests/Bar.java b/src/test/java/org/lightcouch/Bar.java similarity index 83% rename from src/test/java/org/lightcouch/tests/Bar.java rename to src/test/java/org/lightcouch/Bar.java index 4391174..cf5f4cf 100644 --- a/src/test/java/org/lightcouch/tests/Bar.java +++ b/src/test/java/org/lightcouch/Bar.java @@ -1,6 +1,4 @@ -package org.lightcouch.tests; - -import org.lightcouch.Document; +package org.lightcouch; public class Bar extends Document { private String bar; diff --git a/src/test/java/org/lightcouch/tests/BulkDocumentTest.java b/src/test/java/org/lightcouch/BulkDocumentTest.java similarity index 94% rename from src/test/java/org/lightcouch/tests/BulkDocumentTest.java rename to src/test/java/org/lightcouch/BulkDocumentTest.java index 4d40083..1880bf6 100644 --- a/src/test/java/org/lightcouch/tests/BulkDocumentTest.java +++ b/src/test/java/org/lightcouch/BulkDocumentTest.java @@ -14,7 +14,7 @@ * limitations under the License. */ -package org.lightcouch.tests; +package org.lightcouch; import static org.hamcrest.CoreMatchers.is; import static org.junit.Assert.assertThat; @@ -25,12 +25,12 @@ import org.junit.AfterClass; import org.junit.BeforeClass; +import org.junit.Ignore; import org.junit.Test; -import org.lightcouch.CouchDbClient; -import org.lightcouch.Response; import com.google.gson.JsonObject; +@Ignore("Not a unit test! Runs agains a live database") public class BulkDocumentTest { private static CouchDbClient dbClient; diff --git a/src/test/java/org/lightcouch/tests/ChangeNotificationsTest.java b/src/test/java/org/lightcouch/ChangeNotificationsTest.java similarity index 91% rename from src/test/java/org/lightcouch/tests/ChangeNotificationsTest.java rename to src/test/java/org/lightcouch/ChangeNotificationsTest.java index 66e1704..753eebe 100644 --- a/src/test/java/org/lightcouch/tests/ChangeNotificationsTest.java +++ b/src/test/java/org/lightcouch/ChangeNotificationsTest.java @@ -14,7 +14,7 @@ * limitations under the License. */ -package org.lightcouch.tests; +package org.lightcouch; import static org.hamcrest.CoreMatchers.is; import static org.junit.Assert.assertEquals; @@ -25,16 +25,13 @@ import org.junit.AfterClass; import org.junit.BeforeClass; +import org.junit.Ignore; import org.junit.Test; -import org.lightcouch.Changes; -import org.lightcouch.ChangesResult; import org.lightcouch.ChangesResult.Row; -import org.lightcouch.CouchDbClient; -import org.lightcouch.CouchDbInfo; -import org.lightcouch.Response; import com.google.gson.JsonObject; +@Ignore("Not a unit test! Runs agains a live database") public class ChangeNotificationsTest { private static CouchDbClient dbClient; diff --git a/src/test/java/org/lightcouch/tests/CouchDbClientLoadTest.java b/src/test/java/org/lightcouch/CouchDbClientLoadTest.java similarity index 96% rename from src/test/java/org/lightcouch/tests/CouchDbClientLoadTest.java rename to src/test/java/org/lightcouch/CouchDbClientLoadTest.java index 292c6c3..a960c51 100644 --- a/src/test/java/org/lightcouch/tests/CouchDbClientLoadTest.java +++ b/src/test/java/org/lightcouch/CouchDbClientLoadTest.java @@ -14,7 +14,7 @@ * limitations under the License. */ -package org.lightcouch.tests; +package org.lightcouch; import java.util.concurrent.ExecutorService; import java.util.concurrent.Executors; @@ -23,8 +23,6 @@ import org.junit.BeforeClass; import org.junit.Ignore; import org.junit.Test; -import org.lightcouch.CouchDbClient; -import org.lightcouch.CouchDbProperties; /** * {@link CouchDbClient} load test. @@ -125,6 +123,4 @@ public static long stop() { return value; } } - } - diff --git a/src/test/java/org/lightcouch/tests/DBServerTest.java b/src/test/java/org/lightcouch/DBServerTest.java similarity index 94% rename from src/test/java/org/lightcouch/tests/DBServerTest.java rename to src/test/java/org/lightcouch/DBServerTest.java index f174bc9..28ab941 100644 --- a/src/test/java/org/lightcouch/tests/DBServerTest.java +++ b/src/test/java/org/lightcouch/DBServerTest.java @@ -14,7 +14,7 @@ * limitations under the License. */ -package org.lightcouch.tests; +package org.lightcouch; import static org.hamcrest.CoreMatchers.is; import static org.hamcrest.CoreMatchers.not; @@ -25,10 +25,10 @@ import org.junit.AfterClass; import org.junit.BeforeClass; +import org.junit.Ignore; import org.junit.Test; -import org.lightcouch.CouchDbClient; -import org.lightcouch.CouchDbInfo; +@Ignore("Not a unit test! Runs agains a live database") public class DBServerTest { private static CouchDbClient dbClient; diff --git a/src/test/java/org/lightcouch/tests/DesignDocumentsTest.java b/src/test/java/org/lightcouch/DesignDocumentsTest.java similarity index 94% rename from src/test/java/org/lightcouch/tests/DesignDocumentsTest.java rename to src/test/java/org/lightcouch/DesignDocumentsTest.java index 0e6061f..03f2357 100644 --- a/src/test/java/org/lightcouch/tests/DesignDocumentsTest.java +++ b/src/test/java/org/lightcouch/DesignDocumentsTest.java @@ -14,7 +14,7 @@ * limitations under the License. */ -package org.lightcouch.tests; +package org.lightcouch; import static org.hamcrest.CoreMatchers.not; import static org.junit.Assert.assertThat; @@ -24,10 +24,10 @@ import org.junit.AfterClass; import org.junit.BeforeClass; +import org.junit.Ignore; import org.junit.Test; -import org.lightcouch.CouchDbClient; -import org.lightcouch.DesignDocument; +@Ignore("Not a unit test! Runs agains a live database") public class DesignDocumentsTest { private static CouchDbClient dbClient; @@ -65,5 +65,4 @@ public void designDocs() { assertThat(designDocs.size(), not(0)); } - } diff --git a/src/test/java/org/lightcouch/tests/DocumentsCRUDTest.java b/src/test/java/org/lightcouch/DocumentsCRUDTest.java similarity index 96% rename from src/test/java/org/lightcouch/tests/DocumentsCRUDTest.java rename to src/test/java/org/lightcouch/DocumentsCRUDTest.java index c25e8f3..88c3783 100644 --- a/src/test/java/org/lightcouch/tests/DocumentsCRUDTest.java +++ b/src/test/java/org/lightcouch/DocumentsCRUDTest.java @@ -14,7 +14,7 @@ * limitations under the License. */ -package org.lightcouch.tests; +package org.lightcouch; import static org.junit.Assert.assertEquals; import static org.junit.Assert.assertFalse; @@ -29,16 +29,13 @@ import org.junit.AfterClass; import org.junit.BeforeClass; +import org.junit.Ignore; import org.junit.Test; -import org.lightcouch.CouchDbClient; -import org.lightcouch.DocumentConflictException; -import org.lightcouch.NoDocumentException; -import org.lightcouch.Params; -import org.lightcouch.Response; import com.google.gson.JsonArray; import com.google.gson.JsonObject; +@Ignore("Not a unit test! Runs agains a live database") public class DocumentsCRUDTest { private static CouchDbClient dbClient; diff --git a/src/test/java/org/lightcouch/tests/Foo.java b/src/test/java/org/lightcouch/Foo.java similarity index 97% rename from src/test/java/org/lightcouch/tests/Foo.java rename to src/test/java/org/lightcouch/Foo.java index e7d4105..92c891a 100644 --- a/src/test/java/org/lightcouch/tests/Foo.java +++ b/src/test/java/org/lightcouch/Foo.java @@ -1,4 +1,4 @@ -package org.lightcouch.tests; +package org.lightcouch; import java.util.Arrays; import java.util.Date; @@ -6,8 +6,6 @@ import java.util.Map; import java.util.Set; -import org.lightcouch.Attachment; - public class Foo { @SuppressWarnings("unused") diff --git a/src/test/java/org/lightcouch/tests/MangoTest.java b/src/test/java/org/lightcouch/MangoTest.java similarity index 92% rename from src/test/java/org/lightcouch/tests/MangoTest.java rename to src/test/java/org/lightcouch/MangoTest.java index d6742c0..64c6138 100644 --- a/src/test/java/org/lightcouch/tests/MangoTest.java +++ b/src/test/java/org/lightcouch/MangoTest.java @@ -14,7 +14,7 @@ * limitations under the License. */ -package org.lightcouch.tests; +package org.lightcouch; import static org.hamcrest.CoreMatchers.not; import static org.junit.Assert.assertThat; @@ -23,9 +23,10 @@ import org.junit.AfterClass; import org.junit.BeforeClass; +import org.junit.Ignore; import org.junit.Test; -import org.lightcouch.CouchDbClient; +@Ignore("Not a unit test! Runs agains a live database") public class MangoTest { private static CouchDbClient dbClient; diff --git a/src/test/java/org/lightcouch/tests/ReplicationTest.java b/src/test/java/org/lightcouch/ReplicationTest.java similarity index 94% rename from src/test/java/org/lightcouch/tests/ReplicationTest.java rename to src/test/java/org/lightcouch/ReplicationTest.java index e77b4e2..b1cfb52 100644 --- a/src/test/java/org/lightcouch/tests/ReplicationTest.java +++ b/src/test/java/org/lightcouch/ReplicationTest.java @@ -14,7 +14,7 @@ * limitations under the License. */ -package org.lightcouch.tests; +package org.lightcouch; import static org.hamcrest.CoreMatchers.is; import static org.hamcrest.CoreMatchers.not; @@ -29,11 +29,6 @@ import org.junit.BeforeClass; import org.junit.Ignore; import org.junit.Test; -import org.lightcouch.CouchDbClient; -import org.lightcouch.ReplicationResult; -import org.lightcouch.ReplicatorDocument; -import org.lightcouch.Response; -import org.lightcouch.ViewResult; import org.lightcouch.ReplicationResult.ReplicationHistory; @Ignore diff --git a/src/test/java/org/lightcouch/URIBuilderTest.java b/src/test/java/org/lightcouch/URIBuilderTest.java new file mode 100644 index 0000000..9d162e3 --- /dev/null +++ b/src/test/java/org/lightcouch/URIBuilderTest.java @@ -0,0 +1,147 @@ +/* + * Copyright (C) 2011 lightcouch.org + * + * 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.lightcouch; + +import org.junit.Test; + +import java.net.URI; + +import static org.junit.Assert.assertEquals; + +public class URIBuilderTest { + private static final String SCHEME = "http"; + private static final String HOST = "1.1.1.1"; + private static final int PORT = 5984; + + private static final String STRING_WITH_SLASH = "light/couch"; + private static final String STRING_WITH_HYPHEN = "light-couch"; + private static final String STRING_WITH_PLUS = "light+couch"; + private static final String STRING_WITH_AMPERSAND = "light&couch"; + + private static final String STRING_WITH_SLASH_ENCODED = "light%2Fcouch"; + private static final String STRING_WITH_PLUS_ENCODED_FOR_QUERY = "light%2Bcouch"; + private static final String STRING_WITH_AMPERSAND_ENCODED_FOR_QUERY = "light%26couch"; + + @Test + public void schemeAndHostTest() { + URI uri = new URIBuilder() + .scheme(SCHEME) + .host(HOST) + .build(); + assertEquals(SCHEME + "://" + HOST, uri.toString()); + } + + @Test + public void schemeHostAndPortTest() { + URI uri = new URIBuilder() + .scheme(SCHEME) + .host(HOST) + .port(PORT) + .build(); + assertEquals(SCHEME + "://" + HOST + ":" + PORT, uri.toString()); + } + + @Test + public void schemeAuthorityAndSimplePathTest() { + URI uri = new URIBuilder() + .scheme(SCHEME) + .host(HOST) + .port(PORT) + .pathSegment(STRING_WITH_HYPHEN) + .build(); + assertEquals(SCHEME + "://" + HOST + ":" + PORT + "/" + STRING_WITH_HYPHEN, uri.toString()); + } + + @Test + public void schemeAuthorityAndCompoundPathTest() { + URI uri = new URIBuilder() + .scheme(SCHEME) + .host(HOST) + .port(PORT) + .pathSegment(STRING_WITH_HYPHEN) + .pathSegment(STRING_WITH_PLUS) + .pathSegment(STRING_WITH_SLASH) + .build(); + String expected = SCHEME + "://" + HOST + ":" + PORT + + "/" + STRING_WITH_HYPHEN + + "/" + STRING_WITH_PLUS + + "/" + STRING_WITH_SLASH_ENCODED; + assertEquals(expected, uri.toString()); + } + + @Test + public void schemeAuthorityPathAndSingleParamQueryTest() { + URI uri = new URIBuilder() + .scheme(SCHEME) + .host(HOST) + .port(PORT) + .pathSegment(STRING_WITH_HYPHEN) + .pathSegment(STRING_WITH_PLUS) + .pathSegment(STRING_WITH_SLASH) + .query(STRING_WITH_HYPHEN, STRING_WITH_PLUS) + .build(); + String expected = SCHEME + "://" + HOST + ":" + PORT + + "/" + STRING_WITH_HYPHEN + + "/" + STRING_WITH_PLUS + + "/" + STRING_WITH_SLASH_ENCODED + + "?" + STRING_WITH_HYPHEN + "=" + STRING_WITH_PLUS_ENCODED_FOR_QUERY; + assertEquals(expected, uri.toString()); + } + + @Test + public void schemeAuthorityPathAndCompoundParamQueryTest() { + URI uri = new URIBuilder() + .scheme(SCHEME) + .host(HOST) + .port(PORT) + .pathSegment(STRING_WITH_HYPHEN) + .pathSegment(STRING_WITH_PLUS) + .pathSegment(STRING_WITH_SLASH) + .query(STRING_WITH_HYPHEN, STRING_WITH_PLUS) + .query(STRING_WITH_SLASH, STRING_WITH_AMPERSAND) + .build(); + String expected = SCHEME + "://" + HOST + ":" + PORT + + "/" + STRING_WITH_HYPHEN + + "/" + STRING_WITH_PLUS + + "/" + STRING_WITH_SLASH_ENCODED + + "?" + STRING_WITH_HYPHEN + "=" + STRING_WITH_PLUS_ENCODED_FOR_QUERY + + "&" + STRING_WITH_SLASH_ENCODED + "=" + STRING_WITH_AMPERSAND_ENCODED_FOR_QUERY; + assertEquals(expected, uri.toString()); + } + + @Test + public void schemeAuthorityPathAndCompoundParamQueryViaParamsTest() { + Params params = new Params() + .addParam(STRING_WITH_HYPHEN, STRING_WITH_PLUS) + .addParam(STRING_WITH_SLASH, STRING_WITH_AMPERSAND); + URI uri = new URIBuilder() + .scheme(SCHEME) + .host(HOST) + .port(PORT) + .pathSegment(STRING_WITH_HYPHEN) + .pathSegment(STRING_WITH_PLUS) + .pathSegment(STRING_WITH_SLASH) + .query(params.getParamMap()) + .build(); + String expected = SCHEME + "://" + HOST + ":" + PORT + + "/" + STRING_WITH_HYPHEN + + "/" + STRING_WITH_PLUS + + "/" + STRING_WITH_SLASH_ENCODED + + "?" + STRING_WITH_HYPHEN + "=" + STRING_WITH_PLUS_ENCODED_FOR_QUERY + + "&" + STRING_WITH_SLASH_ENCODED + "=" + STRING_WITH_AMPERSAND_ENCODED_FOR_QUERY; + assertEquals(expected, uri.toString()); + } +} diff --git a/src/test/java/org/lightcouch/tests/UpdateHandlerTest.java b/src/test/java/org/lightcouch/UpdateHandlerTest.java similarity index 92% rename from src/test/java/org/lightcouch/tests/UpdateHandlerTest.java rename to src/test/java/org/lightcouch/UpdateHandlerTest.java index bbc2be2..4467f05 100644 --- a/src/test/java/org/lightcouch/tests/UpdateHandlerTest.java +++ b/src/test/java/org/lightcouch/UpdateHandlerTest.java @@ -14,18 +14,17 @@ * limitations under the License. */ -package org.lightcouch.tests; +package org.lightcouch; import static org.junit.Assert.assertEquals; import static org.junit.Assert.assertNotNull; import org.junit.AfterClass; import org.junit.BeforeClass; +import org.junit.Ignore; import org.junit.Test; -import org.lightcouch.CouchDbClient; -import org.lightcouch.Params; -import org.lightcouch.Response; +@Ignore("Not a unit test! Runs agains a live database") public class UpdateHandlerTest { private static CouchDbClient dbClient; diff --git a/src/test/java/org/lightcouch/tests/ViewsTest.java b/src/test/java/org/lightcouch/ViewsTest.java similarity index 96% rename from src/test/java/org/lightcouch/tests/ViewsTest.java rename to src/test/java/org/lightcouch/ViewsTest.java index c9d8e86..9219381 100644 --- a/src/test/java/org/lightcouch/tests/ViewsTest.java +++ b/src/test/java/org/lightcouch/ViewsTest.java @@ -14,7 +14,7 @@ * limitations under the License. */ -package org.lightcouch.tests; +package org.lightcouch; import static org.hamcrest.CoreMatchers.is; import static org.hamcrest.CoreMatchers.not; @@ -29,16 +29,12 @@ import org.junit.AfterClass; import org.junit.BeforeClass; +import org.junit.Ignore; import org.junit.Test; -import org.lightcouch.CouchDbClient; -import org.lightcouch.Document; -import org.lightcouch.DocumentConflictException; -import org.lightcouch.NoDocumentException; -import org.lightcouch.Page; -import org.lightcouch.ViewResult; import com.google.gson.JsonObject; +@Ignore("Not a unit test! Runs agains a live database") public class ViewsTest { private static CouchDbClient dbClient;