package com.alvazan.orm.impl.bindings; import java.util.Map; import com.alvazan.orm.api.base.Bootstrap; import com.alvazan.orm.api.base.DbTypeEnum; import com.alvazan.orm.api.base.NoSqlEntityManagerFactory; import com.alvazan.orm.api.z8spi.NoSqlRawSession; import com.alvazan.orm.api.z8spi.conv.Converter; import com.alvazan.orm.layer0.base.BaseEntityManagerFactoryImpl; import com.google.inject.Guice; import com.google.inject.Injector; import com.google.inject.Key; import com.google.inject.name.Named; import com.google.inject.name.Names; import com.netflix.astyanax.AstyanaxContext; import com.netflix.astyanax.AstyanaxContext.Builder; import com.netflix.astyanax.clock.MicrosecondsAsyncClock; import com.netflix.astyanax.connectionpool.NodeDiscoveryType; import com.netflix.astyanax.connectionpool.impl.ConnectionPoolConfigurationImpl; import com.netflix.astyanax.connectionpool.impl.ConnectionPoolType; import com.netflix.astyanax.connectionpool.impl.CountingConnectionPoolMonitor; import com.netflix.astyanax.connectionpool.impl.FixedRetryBackoffStrategy; import com.netflix.astyanax.connectionpool.impl.SimpleAuthenticationCredentials; import com.netflix.astyanax.impl.AstyanaxConfigurationImpl; import com.netflix.astyanax.model.ConsistencyLevel; public class BootstrapImpl extends Bootstrap { @SuppressWarnings("rawtypes") @Override public NoSqlEntityManagerFactory createInstance(DbTypeEnum type, Map<String, Object> properties, Map<Class, Converter> converters, ClassLoader cl2) { ClassLoader previous = Thread.currentThread().getContextClassLoader(); try { //Javassit uses the thread's context classloader so we need to set that for javassist then //we reset it back in case some other framework relies on it... ClassLoader playOrmCl = BootstrapImpl.class.getClassLoader(); Thread.currentThread().setContextClassLoader(playOrmCl); return createInstanceImpl(type, properties, converters, cl2); } finally { Thread.currentThread().setContextClassLoader(previous); } } private NoSqlEntityManagerFactory createInstanceImpl(DbTypeEnum type, Map<String, Object> properties, Map<Class, Converter> converters, ClassLoader cl2) { Object spiImpl = properties.get(Bootstrap.SPI_IMPL); NoSqlRawSession temp = null; if(spiImpl != null && spiImpl instanceof NoSqlRawSession) { temp = (NoSqlRawSession) spiImpl; } Injector injector = Guice.createInjector(new ProductionBindings(type, temp)); NoSqlEntityManagerFactory factory = injector.getInstance(NoSqlEntityManagerFactory.class); Named named = Names.named("logger"); Key<NoSqlRawSession> key = Key.get(NoSqlRawSession.class, named); NoSqlRawSession inst = injector.getInstance(key); inst.start(properties); //why not just add setInjector() and setup() in NoSqlEntityManagerFactory BaseEntityManagerFactoryImpl impl = (BaseEntityManagerFactoryImpl)factory; impl.setInjector(injector); ClassLoader cl = cl2; if(cl == null) cl = BootstrapImpl.class.getClassLoader(); //The expensive scan all entities occurs here... impl.setup(properties, converters, cl); return impl; } @Override protected void createBestCassandraConfig(Map<String, Object> properties, String clusterName, String keyspace2, String seeds2) { ConnectionPoolConfigurationImpl poolConfig = new ConnectionPoolConfigurationImpl("MyConnectionPool") .setMaxConnsPerHost(20) .setInitConnsPerHost(2) .setSeeds(seeds2) .setConnectTimeout(10000) .setRetryBackoffStrategy(new FixedRetryBackoffStrategy(5000, 30000)); Object username = properties.get(Bootstrap.CASSANDRA_USERNAME); Object password = properties.get(Bootstrap.CASSANDRA_PASSWORD); if (username != null && password != null) { poolConfig.setAuthenticationCredentials(new SimpleAuthenticationCredentials(""+username, ""+password)); } Object port = properties.get(Bootstrap.CASSANDRA_THRIFT_PORT); if(port != null) { int portVal = 9160; if(port instanceof Integer) portVal = (Integer) port; else if(port instanceof String) portVal = Integer.valueOf((String) port); else throw new RuntimeException(Bootstrap.CASSANDRA_THRIFT_PORT+" key in map has a value of type="+port.getClass()+" but that must be a String or Integer"); poolConfig.setPort(portVal); } Builder builder = new AstyanaxContext.Builder() .forCluster(clusterName) .forKeyspace(keyspace2) .withAstyanaxConfiguration(new AstyanaxConfigurationImpl() .setDiscoveryType(NodeDiscoveryType.RING_DESCRIBE) .setConnectionPoolType(ConnectionPoolType.TOKEN_AWARE) .setClock(new MicrosecondsAsyncClock()) ) .withConnectionPoolConfiguration(poolConfig) .withConnectionPoolMonitor(new CountingConnectionPoolMonitor()); String clStr = (String) properties.get(Bootstrap.CASSANDRA_DEFAULT_CONSISTENCY_LEVEL); if(clStr != null) { ConsistencyLevel cl = null; for(ConsistencyLevel l : ConsistencyLevel.values()) { if(l.toString().equals(clStr)) { cl = l; break; } } if(cl == null) throw new IllegalArgumentException("Consistency level must be one of the strings mathcin astyanax ConsistencyLevel.XXXX"); AstyanaxConfigurationImpl config = new AstyanaxConfigurationImpl(); config.setDefaultWriteConsistencyLevel(cl); config.setDefaultReadConsistencyLevel(cl); builder = builder.withAstyanaxConfiguration(config); } else if(seeds2.contains(",")) { //for a multi-node cluster, we want the test suite using quorum on writes and //reads so we have no issues... AstyanaxConfigurationImpl config = new AstyanaxConfigurationImpl(); config.setDefaultWriteConsistencyLevel(ConsistencyLevel.CL_QUORUM); config.setDefaultReadConsistencyLevel(ConsistencyLevel.CL_QUORUM); builder = builder.withAstyanaxConfiguration(config); } properties.put(Bootstrap.CASSANDRA_BUILDER, builder); } @Override protected void createBestMongoDbConfig(Map<String, Object> properties, String clusterName, String keyspace2, String seeds2) { properties.put(Bootstrap.MONGODB_CLUSTERNAME, clusterName); properties.put(Bootstrap.MONGODB_KEYSPACE, keyspace2); properties.put(Bootstrap.MONGODB_SEEDS, seeds2); } @Override protected void createBestHBaseConfig(Map<String, Object> properties, String clusterName, String keyspace2, String seeds2) { properties.put(Bootstrap.HBASE_CLUSTERNAME, clusterName); properties.put(Bootstrap.HBASE_KEYSPACE, keyspace2); properties.put(Bootstrap.HBASE_SEEDS, seeds2); } @Override protected void createBestCqlConfig(Map<String, Object> properties, String clusterName, String keyspace2, String seeds2) { properties.put(Bootstrap.CQL_CLUSTERNAME, clusterName); properties.put(Bootstrap.CQL_KEYSPACE, keyspace2); properties.put(Bootstrap.CQL_SEEDS, seeds2); } }