package org.hivedb.hibernate.simplified.session; import org.apache.commons.logging.Log; import org.apache.commons.logging.LogFactory; import org.hibernate.cfg.Configuration; import org.hibernate.shards.ShardId; import org.hibernate.shards.ShardedConfiguration; import org.hibernate.shards.cfg.ShardConfiguration; import org.hibernate.shards.session.ShardedSessionFactory; import org.hibernate.shards.strategy.ShardStrategy; import org.hibernate.shards.strategy.ShardStrategyFactory; import org.hibernate.shards.strategy.ShardStrategyImpl; import org.hibernate.shards.strategy.access.ShardAccessStrategy; import org.hivedb.Hive; import org.hivedb.configuration.EntityHiveConfig; import org.hivedb.hibernate.ConfigurationReader; import org.hivedb.hibernate.HiveShardResolver; import org.hivedb.hibernate.HiveShardSelector; import org.hivedb.hibernate.simplified.session.configuration.NodeConfiguration; import org.hivedb.meta.Node; import org.hivedb.util.Lists; import org.hivedb.util.functional.Atom; import org.hivedb.util.functional.Transform; import org.hivedb.util.functional.Unary; import java.util.*; public class SingletonHiveSessionFactoryBuilder implements HiveSessionFactoryBuilder, Observer { private final static Log log = LogFactory.getLog(SingletonHiveSessionFactoryBuilder.class); private HiveSessionFactory factory = null; private Hive hive; private List<Class<?>> persistableClasses; private Properties overrides; private ShardAccessStrategy accessStrategy; private EntityHiveConfig hiveConfig; public SingletonHiveSessionFactoryBuilder(Hive hive, List<Class<?>> persistableClasses, ShardAccessStrategy accessStrategy) { this(hive, persistableClasses, accessStrategy, new Properties()); } public SingletonHiveSessionFactoryBuilder(Hive hive, List<Class<?>> persistableClasses, ShardAccessStrategy accessStrategy, Properties overrides) { this.hive = hive; this.persistableClasses = persistableClasses; this.overrides = overrides; this.accessStrategy = accessStrategy; this.hiveConfig = new ConfigurationReader(this.persistableClasses).getHiveConfiguration(); } public HiveSessionFactory getSessionFactory() { if(factory == null) factory = buildSessionFactory(); return factory; } private HiveSessionFactory buildSessionFactory() { log.info("Building HiveSessionFactory"); Collection<NodeConfiguration> nodeConfigs = getNodeConfigurations(); Collection<ShardConfiguration> shardConfigs = Transform.map(new Unary<NodeConfiguration, ShardConfiguration>(){ public ShardConfiguration f(NodeConfiguration item) { log.info("Adding node: " + item.getNode().getUri()); return item.toShardConfig(); } },nodeConfigs); ShardedSessionFactory shardedFactory = new ShardedConfiguration( buildPrototypeConfiguration(Atom.getFirstOrThrow(nodeConfigs)), Lists.newList(shardConfigs), buildShardStrategyFactory()).buildShardedSessionFactory(); logIterable("Adding class:", persistableClasses); logMap("Overriding: ", overrides); return new HiveSessionFactoryImpl(shardedFactory, hive, hiveConfig); } private ShardStrategyFactory buildShardStrategyFactory() { return new ShardStrategyFactory() { public ShardStrategy newShardStrategy(List<ShardId> shardIds) { return new ShardStrategyImpl( new HiveShardSelector(hiveConfig,hive), new HiveShardResolver(hiveConfig,hive), accessStrategy); } }; } private Configuration buildPrototypeConfiguration(Configuration config) { for(Class clazz : persistableClasses) config.addClass(clazz); config.setProperty("hibernate.session_factory_name", "factory:prototype"); return config; } private Collection<NodeConfiguration> getNodeConfigurations() { return Transform.map(new Unary<Node,NodeConfiguration>(){ public NodeConfiguration f(Node item) { return (NodeConfiguration) new NodeConfiguration(item, overrides).configure(); } }, hive.getNodes()); } public void update(Observable o, Object arg) { log.info("Update received"); HiveSessionFactory newFactory = buildSessionFactory(); synchronized(this) { this.factory = newFactory; } } private void logIterable(String prefix, Iterable<?> iterable) { for(Object o : iterable) { log.info(String.format("%s %s", prefix, o)); } } private void logMap(String prefix, Map<?,?> map) { for(Map.Entry e : map.entrySet()) { log.info(String.format("%s %s => %s", prefix, e.getKey(), e.getValue())); } } public Hive getHive() { return hive; } public Properties getOverrides() { return overrides; } public List<Class<?>> getPersistableClasses() { return persistableClasses; } }