package me.prettyprint.cassandra.jndi;
import java.util.Hashtable;
import javax.naming.Context;
import javax.naming.Name;
import javax.naming.RefAddr;
import javax.naming.Reference;
import javax.naming.spi.ObjectFactory;
import me.prettyprint.cassandra.service.CassandraHostConfigurator;
import me.prettyprint.hector.api.Cluster;
import me.prettyprint.hector.api.Keyspace;
import me.prettyprint.hector.api.factory.HFactory;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
/**
* A factory for JNDI Resource managed objects. Responsible for creating a
* {@link Keyspace} references for passing to {@link HFactory}.
* A limited set of configuration parameters are supported.
* These parameters are defined in a web application's context.xml file.
* Parameter descriptions can be found in {@link CassandraHostConfigurator}
*
* <p>
* <pre>
* <Resource name="cassandra/CassandraClientFactory"
* auth="Container"
* type="me.prettyprint.cassandra.api.Keyspace"
* factory="me.prettyprint.cassandra.jndi.CassandraClientJndiResourceFactory"
* hosts="cass1:9160,cass2:9160,cass3:9160"
* keyspace="Keyspace1"
* clusterName="Test Cluster"
* maxActive="20"
* maxWaitTimeWhenExhausted="10"
* autoDiscoverHosts="true"
* runAutoDiscoveryAtStartup="true"/>
* </pre>
*
* @author Perry Hoekstra (dutchman_mn@charter.net)
* @author zznate
*
* @since 0.5.1-8
*/
public class CassandraClientJndiResourceFactory implements ObjectFactory {
private Logger log = LoggerFactory.getLogger(CassandraClientJndiResourceFactory.class);
private CassandraHostConfigurator cassandraHostConfigurator;
private Cluster cluster;
private Keyspace keyspace;
/**
* Creates an object using the location or reference information specified.
*
* @param object The possibly null object containing location or reference information that
* can be used in creating an object.
* @param jndiName The name of this object relative to nameCtx, or null if no name is
* specified.
* @param context The context relative to which the name parameter is specified, or null
* if name is relative to the default initial context.
* @param environment The possibly null environment that is used in creating the object.
*
* @return Object - The object created; null if an object cannot be created.
*
* @exception Exception - if this object factory encountered an exception while attempting
* to create an object, and no other object factories are to be tried.
*/
public Object getObjectInstance(Object object, Name jndiName, Context context,
Hashtable<?, ?> environment) throws Exception {
Reference resourceRef = null;
if (object instanceof Reference) {
resourceRef = (Reference) object;
} else {
throw new Exception("Object provided is not a javax.naming.Reference type");
}
// config CassandraHostConfigurator
if ( cluster == null ) {
configure(resourceRef);
}
return keyspace;
}
private void configure(Reference resourceRef) throws Exception {
// required
RefAddr hostsRefAddr = resourceRef.get("hosts");
RefAddr clusterNameRef = resourceRef.get("clusterName");
RefAddr keyspaceNameRef = resourceRef.get("keyspace");
// optional
RefAddr maxActiveRefAddr = resourceRef.get("maxActive");
RefAddr maxWaitTimeWhenExhausted = resourceRef.get("maxWaitTimeWhenExhausted");
RefAddr maxExhaustedTimeBeforeMarkingAsDown = resourceRef.get("maxExhaustedTimeBeforeMarkingAsDown");
RefAddr autoDiscoverHosts = resourceRef.get("autoDiscoverHosts");
RefAddr runAutoDiscoverAtStartup = resourceRef.get("runAutoDiscoveryAtStartup");
RefAddr retryDownedHostDelayInSeconds = resourceRef.get("retryDownedHostDelayInSeconds");
if ( hostsRefAddr == null || hostsRefAddr.getContent() == null) {
throw new Exception("A url and port on which Cassandra is installed and listening " +
"on must be provided as a ResourceParams in the context.xml");
}
cassandraHostConfigurator = new CassandraHostConfigurator((String)hostsRefAddr.getContent());
if ( autoDiscoverHosts != null ) {
cassandraHostConfigurator.setAutoDiscoverHosts(Boolean.parseBoolean((String)autoDiscoverHosts.getContent()));
if ( runAutoDiscoverAtStartup != null )
cassandraHostConfigurator.setRunAutoDiscoveryAtStartup(Boolean.parseBoolean((String)autoDiscoverHosts.getContent()));
}
if ( retryDownedHostDelayInSeconds != null ) {
int retryDelay = Integer.parseInt((String)retryDownedHostDelayInSeconds.getContent());
// disable retry if less than 1
if ( retryDelay < 1 )
cassandraHostConfigurator.setRetryDownedHosts(false);
cassandraHostConfigurator.setRetryDownedHostsDelayInSeconds(retryDelay);
}
if ( maxActiveRefAddr != null )
cassandraHostConfigurator.setMaxActive(Integer.parseInt((String)maxActiveRefAddr.getContent()));
if ( maxWaitTimeWhenExhausted != null )
cassandraHostConfigurator.setMaxWaitTimeWhenExhausted(Integer.parseInt((String)maxWaitTimeWhenExhausted.getContent()));
if (maxExhaustedTimeBeforeMarkingAsDown != null) {
cassandraHostConfigurator.setMaxExhaustedTimeBeforeMarkingAsDown(Integer.parseInt((String) maxExhaustedTimeBeforeMarkingAsDown.getContent()));
}
if ( log.isDebugEnabled() )
log.debug("JNDI resource created with CassandraHostConfiguration: {}", cassandraHostConfigurator.getAutoDiscoverHosts());
cluster = HFactory.getOrCreateCluster((String)clusterNameRef.getContent(), cassandraHostConfigurator);
keyspace = HFactory.createKeyspace((String)keyspaceNameRef.getContent(), cluster);
}
}