package kr.debop4j.data.mongodb.test.utils; import com.mongodb.BasicDBObject; import com.mongodb.DB; import com.mongodb.DBObject; import com.mongodb.MongoException; import kr.debop4j.data.ogm.test.utils.TestableGridDialect; import org.hibernate.SessionFactory; import org.hibernate.annotations.common.AssertionFailure; import org.hibernate.engine.spi.SessionFactoryImplementor; import org.hibernate.ogm.datastore.mongodb.AssociationStorage; import org.hibernate.ogm.datastore.mongodb.Environment; import org.hibernate.ogm.datastore.mongodb.impl.MongoDBDatastoreProvider; import org.hibernate.ogm.datastore.spi.DatastoreProvider; import org.hibernate.ogm.dialect.mongodb.MongoDBDialect; import org.hibernate.ogm.grid.EntityKey; import org.hibernate.ogm.logging.mongodb.impl.Log; import org.hibernate.ogm.logging.mongodb.impl.LoggerFactory; import java.util.HashMap; import java.util.Map; /** * kr.debop4j.data.mongodb.test.utils.MongoDBTestHelper * * @author 배성혁 ( sunghyouk.bae@gmail.com ) * @since 13. 4. 10. 오후 9:50 */ public class MongoDBTestHelper implements TestableGridDialect { private static final Log log = LoggerFactory.getLogger(); static { // Read host and port from environment variable // Maven's surefire plugin set it to the string 'null' String mongoHostName = System.getenv("MONGODB_HOSTNAME"); if (isNotNull(mongoHostName)) { System.getProperties().setProperty(Environment.MONGODB_HOST, mongoHostName); } String mongoPort = System.getenv("MONGODB_PORT"); if (isNotNull(mongoPort)) { System.getProperties().setProperty(Environment.MONGODB_PORT, mongoPort); } } private static boolean isNotNull(String mongoHostName) { return mongoHostName != null && mongoHostName.length() > 0 && !"null".equals(mongoHostName); } @Override public boolean assertNumberOfEntities(int numberOfEntities, SessionFactory sessionFactory) { MongoDBDatastoreProvider provider = MongoDBTestHelper.getProvider(sessionFactory); AssociationStorage storage = provider.getAssociationStorage(); DB db = provider.getDatabase(); int count = 0; for (String collectionName : db.getCollectionNames()) { if (collectionName.startsWith("system.")) continue; if (storage == AssociationStorage.GLOBAL_COLLECTION && collectionName.equals(Environment.MONGODB_DEFAULT_ASSOCIATION_STORE)) continue; if (storage == AssociationStorage.COLLECTION && collectionName.startsWith(MongoDBDialect.ASSOCIATIONS_COLLECTION_PREFIX)) continue; count += db.getCollection(collectionName).count(); } return count == numberOfEntities; } @Override public boolean assertNumberOfAssociations(int numberOfAssociations, SessionFactory sessionFactory) { MongoDBDatastoreProvider provider = MongoDBTestHelper.getProvider(sessionFactory); AssociationStorage assocStorage = provider.getAssociationStorage(); DB db = provider.getDatabase(); if (assocStorage == AssociationStorage.IN_ENTITY) { return true; //FIXME find a way to test that, maybe with some map reduce magic? } else if (assocStorage == AssociationStorage.GLOBAL_COLLECTION) { return db.getCollection(Environment.MONGODB_DEFAULT_ASSOCIATION_STORE).count() == numberOfAssociations; } else if (assocStorage == AssociationStorage.COLLECTION) { int count = 0; for (String collectionName : db.getCollectionNames()) { if (assocStorage == AssociationStorage.COLLECTION && collectionName.startsWith(MongoDBDialect.ASSOCIATIONS_COLLECTION_PREFIX)) { count += db.getCollection(collectionName).count(); } } return count == numberOfAssociations; } else { throw new AssertionFailure("Unknown AssociationStorage approach: " + assocStorage); } } @Override public Map<String, Object> extractEntityTuple(SessionFactory sessionFactory, EntityKey key) { MongoDBDatastoreProvider provider = MongoDBTestHelper.getProvider(sessionFactory); DBObject finder = new BasicDBObject(MongoDBDialect.ID_FIELDNAME, key.getColumnValues()[0]); DBObject result = provider.getDatabase().getCollection(key.getTable()).findOne(finder); replaceIdentifierColumnName(result, key); return result.toMap(); } /** * The MongoDB dialect replaces the name of the column identifier, so when the tuple is extracted from the db * we replace the column name of the identifier with the original one. * We are assuming the identifier is not embedded and is a single property. */ private void replaceIdentifierColumnName(DBObject result, EntityKey key) { Object idValue = result.get(MongoDBDialect.ID_FIELDNAME); result.removeField(MongoDBDialect.ID_FIELDNAME); result.put(key.getColumnNames()[0], idValue); } @Override public boolean backendSupportsTransactions() { return false; } private static MongoDBDatastoreProvider getProvider(SessionFactory sessionFactory) { DatastoreProvider provider = ((SessionFactoryImplementor) sessionFactory).getServiceRegistry().getService( DatastoreProvider.class); if (!(MongoDBDatastoreProvider.class.isInstance(provider))) { throw new RuntimeException("Not testing with MongoDB, cannot extract underlying cache"); } return MongoDBDatastoreProvider.class.cast(provider); } @Override public void dropSchemaAndDatabase(SessionFactory sessionFactory) { MongoDBDatastoreProvider provider = getProvider(sessionFactory); try { log.info("MongoDB의 provider를 얻어 database를 삭제합니다..."); provider.getDatabase().dropDatabase(); } catch (MongoException ex) { throw log.unableToDropDatabase(ex, provider.getDatabase().getName()); } } @Override public Map<String, String> getEnvironmentProperties() { //read variables from the System properties set in the static initializer Map<String, String> props = new HashMap<String, String>(2); copyFromSystemPropertiesToLocalEnvironment(Environment.MONGODB_HOST, props); copyFromSystemPropertiesToLocalEnvironment(Environment.MONGODB_PORT, props); copyFromSystemPropertiesToLocalEnvironment(Environment.MONGODB_USERNAME, props); copyFromSystemPropertiesToLocalEnvironment(Environment.MONGODB_PASSWORD, props); // hibernate-search 환경설정 props.put("hibernate.search.default.indexmanager", "near-real-time"); props.put("hibernate.search.default.directory_provider", "filesystem"); props.put("hibernate.search.default.indexBase", ".lucene/indexes"); props.put("hibernate.search.default.locking_strategy", "simple"); // hibernate-search index worker settings props.put("hibernate.search.worker.execution", "async"); props.put("hibernate.search.worker.thread_pool.size", "8"); props.put("hibernate.search.worker.buffer_queue.max", "1000000"); // hibernate-search performance settings props.put("hibernate.search.default.indexwriter.max_buffered_doc", "true"); props.put("hibernate.search.default.indexwriter.max_merge_docs", "100"); props.put("hibernate.search.default.indexwriter.merge_factor", "20"); props.put("hibernate.search.default.indexwriter.term_index_interval", "default"); props.put("hibernate.search.default.indexwriter.ram_buffer_size", "2048"); props.put("hibernate.search.default.exclusive_index_use", "true"); return props; } private void copyFromSystemPropertiesToLocalEnvironment(String environmentVariableName, Map<String, String> envProps) { String value = System.getProperties().getProperty(environmentVariableName); if (value != null && value.length() > 0) { envProps.put(environmentVariableName, value); } } }