Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,8 @@
import com.basho.riak.client.core.query.Location;
import com.basho.riak.client.core.query.Namespace;
import com.basho.riak.client.core.util.BinaryValue;
import com.basho.riak.client.core.util.DefaultCharset;

import java.nio.charset.Charset;
import java.util.ArrayList;
import java.util.List;
Expand Down Expand Up @@ -108,7 +110,7 @@ protected BinIndexQuery convertQueryInfo(SecondaryIndexQueryOperation.Query core

protected static abstract class Init<S, T extends Init<S,T>> extends SecondaryIndexQuery.Init<S,T>
{
private Charset charset = Charset.defaultCharset();
private Charset charset = DefaultCharset.get();

public Init(Namespace namespace, String indexName, S start, S end)
{
Expand Down
1 change: 0 additions & 1 deletion src/main/java/com/basho/riak/client/core/RiakCluster.java
Original file line number Diff line number Diff line change
Expand Up @@ -642,7 +642,6 @@ public static class Builder
private ScheduledExecutorService executor;
private Bootstrap bootstrap;


/**
* Instantiate a Builder containing the supplied {@link RiakNode}s
* @param riakNodes - a List of unstarted RiakNode objects
Expand Down
4 changes: 3 additions & 1 deletion src/main/java/com/basho/riak/client/core/query/Location.java
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,8 @@
package com.basho.riak.client.core.query;

import com.basho.riak.client.core.util.BinaryValue;
import com.basho.riak.client.core.util.DefaultCharset;

import java.nio.charset.Charset;

/**
Expand Down Expand Up @@ -98,7 +100,7 @@ else if (charset == null)
*/
public Location(Namespace namespace, String key)
{
this(namespace, key, Charset.defaultCharset());
this(namespace, key, DefaultCharset.get());
}

/**
Expand Down
6 changes: 4 additions & 2 deletions src/main/java/com/basho/riak/client/core/query/Namespace.java
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,8 @@
package com.basho.riak.client.core.query;

import com.basho.riak.client.core.util.BinaryValue;
import com.basho.riak.client.core.util.DefaultCharset;

import java.nio.charset.Charset;

/**
Expand Down Expand Up @@ -117,7 +119,7 @@ else if (charset == null)
*/
public Namespace(String bucketType, String bucketName)
{
this(bucketType, bucketName, Charset.defaultCharset());
this(bucketType, bucketName, DefaultCharset.get());
}

/**
Expand Down Expand Up @@ -166,7 +168,7 @@ public Namespace(String bucketName, Charset charset)
*/
public Namespace(String bucketName)
{
this(bucketName, Charset.defaultCharset());
this(bucketName, DefaultCharset.get());
}

/**
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,8 @@
package com.basho.riak.client.core.query.UserMetadata;

import com.basho.riak.client.core.util.BinaryValue;
import com.basho.riak.client.core.util.DefaultCharset;

import java.nio.charset.Charset;
import java.util.Collections;
import java.util.Map;
Expand Down Expand Up @@ -63,7 +65,7 @@ public boolean isEmpty()
*/
public boolean containsKey(String key)
{
return containsKey(key, Charset.defaultCharset());
return containsKey(key, DefaultCharset.get());
}

/**
Expand All @@ -90,7 +92,7 @@ public boolean containsKey(String key, Charset charset)
*/
public String get(String key)
{
return get(key, Charset.defaultCharset());
return get(key, DefaultCharset.get());
}

/**
Expand Down Expand Up @@ -155,7 +157,7 @@ public Set<Map.Entry<BinaryValue, BinaryValue>> getUserMetadata()
*/
public void put(String key, String value)
{
put(key, value, Charset.defaultCharset());
put(key, value, DefaultCharset.get());
}

/**
Expand Down Expand Up @@ -201,7 +203,7 @@ public void remove(String key, Charset charset)

public void remove (String key)
{
remove(key, Charset.defaultCharset());
remove(key, DefaultCharset.get());
}

// TODO: deal with charset. Should add to annotation
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,8 @@

import com.basho.riak.client.core.query.RiakObject;
import com.basho.riak.client.core.util.BinaryValue;
import com.basho.riak.client.core.util.DefaultCharset;

import java.nio.charset.Charset;

/**
Expand Down Expand Up @@ -66,7 +68,7 @@ protected String convert(BinaryValue value)

public static Name named(String name)
{
return named(name, Charset.defaultCharset());
return named(name, DefaultCharset.get());
}

public static Name named(String name, Charset charset)
Expand All @@ -88,7 +90,7 @@ public static class Name extends RiakIndex.Name<StringBinIndex>
*/
Name(String name)
{
this(name, Charset.defaultCharset());
this(name, DefaultCharset.get());
}
/**
* Constructs a RiakIndex.Name to be used with {@link RiakIndexes}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,8 @@
package com.basho.riak.client.core.query.links;

import com.basho.riak.client.core.util.BinaryValue;
import com.basho.riak.client.core.util.DefaultCharset;

import java.nio.charset.Charset;

/**
Expand Down Expand Up @@ -53,7 +55,7 @@ public class RiakLink
*/
public RiakLink(String bucket, String key, String tag)
{
this(bucket, key, tag, Charset.defaultCharset());
this(bucket, key, tag, DefaultCharset.get());
}

/**
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -75,7 +75,7 @@ public static BinaryValue create(byte[] data)
*/
public static BinaryValue create(String data)
{
return create(data, Charset.defaultCharset());
return create(data, DefaultCharset.get());
}

/**
Expand Down Expand Up @@ -185,7 +185,7 @@ public int hashCode()
@Override
public String toString()
{
return toString(Charset.defaultCharset());
return toString(DefaultCharset.get());
}

/**
Expand Down
3 changes: 2 additions & 1 deletion src/main/java/com/basho/riak/client/core/util/Constants.java
Original file line number Diff line number Diff line change
Expand Up @@ -97,5 +97,6 @@ public interface Constants {
public static final String RESPONSE_HANDLER = "responseHandler";
public static final String SSL_HANDLER = "sslHandler";
public static final String HEALTHCHECK_CODEC = "healthCheckCodec";


public static final String CLIENT_OPTION_CHARSET = "com.basho.riak.client.DefaultCharset";
}
115 changes: 115 additions & 0 deletions src/main/java/com/basho/riak/client/core/util/DefaultCharset.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,115 @@
package com.basho.riak.client.core.util;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import java.nio.charset.Charset;
import java.util.concurrent.atomic.AtomicReference;

/**
* <p>
* Holds an classloader-wide default charset, that
* is then used to encode/decode between Strings and
* Byte arrays for Riak's use (see {@link com.basho.riak.client.core.util.BinaryValue}).
* </p>
* <p/>
* <p>
* Before 2.0.3, the system used the JRE's default Charset from the
* {@link Charset#defaultCharset()} property.
* </p>
* <p/>
* <p>
* With this class you may change the Riak client to use a different default.
* You can set it at startup by providing the desired Charset name with the vm argument
* {@code -Dcom.basho.riak.client.DefaultCharset="UTF-8"}, or at runtime
* with the static method (see {@link #set(Charset)}).
* </p>
* <p/>
* <p>
* As of 2.0.3 it still defaults to the value provided by
* {@link Charset#defaultCharset()},
* but the default is planned to change to "UTF-8" with 2.1.0.
* </p>
* <p/>
* <p>
* If your JRE default charset is one of "<b>US-ASCII</b>",
* "<b>UTF-8</b>", or "<b>ISO-8859-1</b>",
* this change should <b>not</b> affect you.
* </p>
* <p/>
* <p>
* If your JRE default charset is one of "<b>UTF-16</b>",
* "<b>UTF-16BE</b>", or "<b>UTF-16LE</b>",
* <b>you will need to set that default on the command line or
* after application startup once you upgrade</b>.
* </p>
*
* @author Alex Moore <amoore AT basho dot com>
* @since 2.0.3
*/

public final class DefaultCharset
{
private static final Logger logger = LoggerFactory.getLogger(DefaultCharset.class);
private final static DefaultCharset instance = initializeDefaultCharsetSingleton();
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I don't know the specifics of JVM instantiation vs C#, but is this guaranteed to be thread safe? Do we care?

In C# I prefer the nested class approach and it appears to be a good way of doing it in Java too:

http://literatejava.com/jvm/fastest-threadsafe-singleton-jvm/

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The most simple way, but not the most obvious one, is to declare it as an enum https://dzone.com/articles/singleton-design-pattern-–

THere is also interesting academic case with hacking the Singleton... For the enum approach there is no chance to hack it with Reflection.

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

That is both interesting and gross :-)

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The static initializer should only run once, the JVM uses a lock the first time a class is loaded: http://docs.oracle.com/javase/specs/jls/se7/html/jls-12.html#jls-12.4.2. Also it should be initialized the first time the get() method is called: http://docs.oracle.com/javase/specs/jls/se7/html/jls-12.html#jls-12.4.1.

The AtomicReference should take care of any other cross-threading fun.


private final AtomicReference<Charset> currentCharset;

private DefaultCharset(Charset c)
{
logger.info("Initializing client charset to: {}", c.name());
this.currentCharset = new AtomicReference<Charset>(c);
}

private static DefaultCharset initializeDefaultCharsetSingleton()
{
Charset charset;
final Charset systemDefault = Charset.defaultCharset();
final String declaredCharsetName = System.getProperty(Constants.CLIENT_OPTION_CHARSET);

if (declaredCharsetName != null && !declaredCharsetName.isEmpty())
{
try
{
charset = Charset.forName(declaredCharsetName);
}
catch (Exception ex)
{
charset = systemDefault;
logger.warn("Requested charset '{}' is not available, the default charset '{}' will be used",
declaredCharsetName,
charset.name());
}
}
else
{
logger.info("No desired charset found in system properties, the default charset '{}' will be used",
systemDefault.name());
charset = systemDefault;
}

return new DefaultCharset(charset);
}

/**
* Get the current classloader-wide default Charset for the Riak client.
*
* @return The current classloader-wide default charset.
*/
public static Charset get()
{
return instance.currentCharset.get();
}

/**
* Set the classloader-wide default Charset for the Riak client.
*
* @param charset The charset to set the classloader-wide default to.
*/
public static void set(Charset charset)
{
final Charset current = instance.currentCharset.get();
logger.info("Setting client charset from '{}' to '{}'", current.name(), charset.name());
instance.currentCharset.set(charset);
}
}
Loading