diff --git a/src/main/java/com/orbitz/consul/KeyValueClient.java b/src/main/java/com/orbitz/consul/KeyValueClient.java index 609ad9fa..b40c1b2d 100644 --- a/src/main/java/com/orbitz/consul/KeyValueClient.java +++ b/src/main/java/com/orbitz/consul/KeyValueClient.java @@ -1,6 +1,8 @@ package com.orbitz.consul; import com.fasterxml.jackson.core.JsonProcessingException; + +import java.nio.charset.Charset; import java.util.Optional; import com.google.common.collect.ImmutableMap; import com.google.common.primitives.UnsignedLongs; @@ -262,8 +264,22 @@ public void getValues(String key, QueryOptions queryOptions, ConsulResponseCallb * {@link Optional#empty()} */ public Optional getValueAsString(String key) { + return getValueAsString(key, Charset.defaultCharset()); + } + + /** + * Retrieves a string value for a specific key from the key/value store. + * + * GET /v1/kv/{key} + * + * @param key The key to retrieve. + * @param charset The charset of the value + * @return An {@link Optional} containing the value as a string or + * {@link Optional#empty()} + */ + public Optional getValueAsString(String key, Charset charset) { for (Value v: getValue(key).map(Collections::singleton).orElse(Collections.emptySet())) { - return v.getValueAsString(); + return v.getValueAsString(charset); } return Optional.empty(); } @@ -278,11 +294,25 @@ public Optional getValueAsString(String key) { * @return A list of zero to many string values. */ public List getValuesAsString(String key) { + return getValuesAsString(key, Charset.defaultCharset()); + } + + /** + * Retrieves a list of string values for a specific key from the key/value + * store. + * + * GET /v1/kv/{key}?recurse + * + * @param key The key to retrieve. + * @param charset The charset of the value + * @return A list of zero to many string values. + */ + public List getValuesAsString(String key, Charset charset) { List result = new ArrayList(); for(Value value : getValues(key)) { - if (value.getValueAsString().isPresent()) { - result.add(value.getValueAsString().get()); + if (value.getValueAsString(charset).isPresent()) { + result.add(value.getValueAsString(charset).get()); } } @@ -310,6 +340,17 @@ public boolean putValue(String key, String value) { return putValue(key, value, 0L, PutOptions.BLANK); } + /** + * Puts a value into the key/value store. + * + * @param key The key to use as index. + * @param value The value to index. + * @return true if the value was successfully indexed. + */ + public boolean putValue(String key, String value, Charset charset) { + return putValue(key, value, 0L, PutOptions.BLANK, charset); + } + /** * Puts a value into the key/value store. * @@ -322,6 +363,18 @@ public boolean putValue(String key, String value, long flags) { return putValue(key, value, flags, PutOptions.BLANK); } + /** + * Puts a value into the key/value store. + * + * @param key The key to use as index. + * @param value The value to index. + * @param flags The flags for this key. + * @return true if the value was successfully indexed. + */ + public boolean putValue(String key, String value, long flags, Charset charset) { + return putValue(key, value, flags, PutOptions.BLANK, charset); + } + /** * Puts a value into the key/value store. * @@ -331,6 +384,18 @@ public boolean putValue(String key, String value, long flags) { * @return true if the value was successfully indexed. */ public boolean putValue(String key, String value, long flags, PutOptions putOptions) { + return putValue(key, value, flags, putOptions, Charset.defaultCharset()); + } + + /** + * Puts a value into the key/value store. + * + * @param key The key to use as index. + * @param value The value to index. + * @param putOptions PUT options (e.g. wait, acquire). + * @return true if the value was successfully indexed. + */ + public boolean putValue(String key, String value, long flags, PutOptions putOptions, Charset charset) { checkArgument(StringUtils.isNotEmpty(key), "Key must be defined"); Map query = putOptions.toQuery(); @@ -344,7 +409,7 @@ public boolean putValue(String key, String value, long flags, PutOptions putOpti query)); } else { return extract(api.putValue(trimLeadingSlash(key), - RequestBody.create(MediaType.parse("text/plain"), value), query)); + RequestBody.create(MediaType.parse("text/plain; charset=" + charset.name()), value), query)); } } diff --git a/src/main/java/com/orbitz/consul/model/kv/Value.java b/src/main/java/com/orbitz/consul/model/kv/Value.java index f8852bd7..084f3621 100644 --- a/src/main/java/com/orbitz/consul/model/kv/Value.java +++ b/src/main/java/com/orbitz/consul/model/kv/Value.java @@ -5,10 +5,12 @@ import com.fasterxml.jackson.annotation.JsonProperty; import com.fasterxml.jackson.databind.annotation.JsonDeserialize; import com.fasterxml.jackson.databind.annotation.JsonSerialize; -import java.util.Optional; import com.google.common.io.BaseEncoding; import com.orbitz.consul.util.UnsignedLongDeserializer; +import java.nio.charset.Charset; +import java.util.Optional; + @org.immutables.value.Value.Immutable @JsonDeserialize(as = ImmutableValue.class) @JsonSerialize(as = ImmutableValue.class) @@ -40,10 +42,16 @@ public abstract class Value { @JsonIgnore @org.immutables.value.Value.Lazy public Optional getValueAsString() { + return getValueAsString(Charset.defaultCharset()); + } + + @JsonIgnore + @org.immutables.value.Value.Lazy + public Optional getValueAsString(Charset charset) { if (getValue().isPresent()) { return Optional.of( - new String(BaseEncoding.base64().decode(getValue().get())) + new String(BaseEncoding.base64().decode(getValue().get()), charset) ); } else { return Optional.empty(); diff --git a/src/test/java/com/orbitz/consul/KeyValueTests.java b/src/test/java/com/orbitz/consul/KeyValueTests.java index 39629317..c7338bd7 100644 --- a/src/test/java/com/orbitz/consul/KeyValueTests.java +++ b/src/test/java/com/orbitz/consul/KeyValueTests.java @@ -1,5 +1,6 @@ package com.orbitz.consul; +import java.nio.charset.Charset; import java.util.Optional; import com.orbitz.consul.async.ConsulResponseCallback; import com.orbitz.consul.model.ConsulResponse; @@ -11,6 +12,7 @@ import com.orbitz.consul.model.session.SessionCreatedResponse; import com.orbitz.consul.option.ImmutableDeleteOptions; import com.orbitz.consul.option.ImmutableDeleteOptions.Builder; +import com.orbitz.consul.option.PutOptions; import com.orbitz.consul.option.QueryOptions; import org.apache.commons.codec.binary.Base64; import org.apache.commons.lang3.RandomStringUtils; @@ -32,6 +34,7 @@ import static org.junit.Assert.fail; public class KeyValueTests extends BaseIntegrationTest { + private static final Charset TEST_CHARSET = Charset.forName("IBM297"); @Test public void shouldPutAndReceiveString() throws UnknownHostException { @@ -43,6 +46,16 @@ public void shouldPutAndReceiveString() throws UnknownHostException { assertEquals(value, keyValueClient.getValueAsString(key).get()); } + @Test + public void shouldPutAndReceiveStringWithAnotherCharset() throws UnknownHostException { + KeyValueClient keyValueClient = client.keyValueClient(); + String key = UUID.randomUUID().toString(); + String value = UUID.randomUUID().toString(); + + assertTrue(keyValueClient.putValue(key, value, TEST_CHARSET)); + assertEquals(value, keyValueClient.getValueAsString(key, TEST_CHARSET).get()); + } + @Test public void shouldPutAndReceiveValue() throws UnknownHostException { KeyValueClient keyValueClient = client.keyValueClient(); @@ -56,6 +69,19 @@ public void shouldPutAndReceiveValue() throws UnknownHostException { } + @Test + public void shouldPutAndReceiveValueWithAnotherCharset() throws UnknownHostException { + KeyValueClient keyValueClient = client.keyValueClient(); + String key = UUID.randomUUID().toString(); + String value = UUID.randomUUID().toString(); + + assertTrue(keyValueClient.putValue(key, value, TEST_CHARSET)); + Value received = keyValueClient.getValue(key).get(); + assertEquals(value, received.getValueAsString(TEST_CHARSET).get()); + assertEquals(0L, received.getFlags()); + + } + @Test public void shouldPutAndReceiveWithFlags() throws UnknownHostException { KeyValueClient keyValueClient = client.keyValueClient(); @@ -70,6 +96,20 @@ public void shouldPutAndReceiveWithFlags() throws UnknownHostException { } + @Test + public void shouldPutAndReceiveWithFlagsAndCharset() throws UnknownHostException { + KeyValueClient keyValueClient = client.keyValueClient(); + String key = UUID.randomUUID().toString(); + String value = UUID.randomUUID().toString(); + long flags = UUID.randomUUID().getMostSignificantBits(); + + assertTrue(keyValueClient.putValue(key, value, flags, TEST_CHARSET)); + Value received = keyValueClient.getValue(key).get(); + assertEquals(value, received.getValueAsString(TEST_CHARSET).get()); + assertEquals(flags, received.getFlags()); + + } + @Test public void putNullValue() { @@ -82,6 +122,18 @@ public void putNullValue() { assertFalse(received.getValue().isPresent()); } + @Test + public void putNullValueWithAnotherCharset() { + + KeyValueClient keyValueClient = client.keyValueClient(); + String key = UUID.randomUUID().toString(); + + assertTrue(keyValueClient.putValue(key, null, 0, PutOptions.BLANK, TEST_CHARSET)); + + Value received = keyValueClient.getValue(key).get(); + assertFalse(received.getValue().isPresent()); + } + @Test public void shouldPutAndReceiveStrings() throws UnknownHostException { KeyValueClient keyValueClient = client.keyValueClient(); @@ -100,6 +152,24 @@ public void shouldPutAndReceiveStrings() throws UnknownHostException { }, new HashSet(keyValueClient.getValuesAsString(key))); } + @Test + public void shouldPutAndReceiveStringsWithAnotherCharset() throws UnknownHostException { + KeyValueClient keyValueClient = client.keyValueClient(); + String key = UUID.randomUUID().toString(); + String key2 = key + "/" + UUID.randomUUID().toString(); + final String value = UUID.randomUUID().toString(); + final String value2 = UUID.randomUUID().toString(); + + assertTrue(keyValueClient.putValue(key, value, TEST_CHARSET)); + assertTrue(keyValueClient.putValue(key2, value2, TEST_CHARSET)); + assertEquals(new HashSet() { + { + add(value); + add(value2); + } + }, new HashSet(keyValueClient.getValuesAsString(key, TEST_CHARSET))); + } + @Test public void shouldDelete() throws Exception { KeyValueClient keyValueClient = client.keyValueClient();