/*
* Hibernate, Relational Persistence for Idiomatic Java
*
* JBoss, Home of Professional Open Source
* Copyright 2012 Red Hat Inc. and/or its affiliates and other contributors
* as indicated by the @authors tag. All rights reserved.
* See the copyright.txt in the distribution for a
* full listing of individual contributors.
*
* This copyrighted material is made available to anyone wishing to use,
* modify, copy, or redistribute it subject to the terms and conditions
* of the GNU Lesser General Public License, v. 2.1.
* This program is distributed in the hope that it will be useful, but WITHOUT A
* WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A
* PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details.
* You should have received a copy of the GNU Lesser General Public License,
* v.2.1 along with this distribution; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
* MA 02110-1301, USA.
*/
package org.hibernate.ogm.test.utils;
import java.util.HashMap;
import java.util.Map;
import com.mongodb.MongoException;
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 com.mongodb.BasicDBObject;
import com.mongodb.DB;
import com.mongodb.DBObject;
import org.hibernate.ogm.logging.mongodb.impl.Log;
import org.hibernate.ogm.logging.mongodb.impl.LoggerFactory;
/**
* @author Guillaume Scheibel <guillaume.scheibel@gmail.com>
* @author Sanne Grinovero <sanne@hibernate.org>
*/
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 );
return result.toMap();
}
@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 {
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> envProps = new HashMap<String, String>(2);
copyFromSystemPropertiesToLocalEnvironment( Environment.MONGODB_HOST, envProps );
copyFromSystemPropertiesToLocalEnvironment( Environment.MONGODB_PORT, envProps );
copyFromSystemPropertiesToLocalEnvironment( Environment.MONGODB_USERNAME, envProps );
copyFromSystemPropertiesToLocalEnvironment( Environment.MONGODB_PASSWORD, envProps );
return envProps;
}
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 );
}
}
}