uk.ac.soton.itinnovation.sad.coordinator.Coordinator.java Source code

Java tutorial

Introduction

Here is the source code for uk.ac.soton.itinnovation.sad.coordinator.Coordinator.java

Source

/////////////////////////////////////////////////////////////////////////
//
//  University of Southampton IT Innovation Centre, 2013
//
// Copyright in this library belongs to the University of Southampton
// IT Innovation Centre of Gamma House, Enterprise Road,
// Chilworth Science Park, Southampton, SO16 7NS, UK.
//
// This software may not be used, sold, licensed, transferred, copied
// or reproduced in whole or in part in any manner or form or in or
// on any media by any person other than in accordance with the terms
// of the Licence Agreement supplied with the software, or otherwise
// without the prior written consent of the copyright owners.
//
// This software is distributed WITHOUT ANY WARRANTY, without even the
// implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
// PURPOSE, except where stated in the Licence Agreement supplied with
// the software.
//
//   Created By :         Sleiman Jneidi, Maxim Bashevoy
//   Created Date :         2013-08-13
//   Created for Project :           Experimedia
//
/////////////////////////////////////////////////////////////////////////
package uk.ac.soton.itinnovation.sad.coordinator;

import com.google.code.morphia.Datastore;
import com.google.code.morphia.Key;
import com.google.code.morphia.Morphia;
import com.google.code.morphia.logging.MorphiaLoggerFactory;
import com.google.code.morphia.query.Query;
import com.mongodb.DBCollection;
import com.mongodb.Mongo;
import java.io.Closeable;
import java.io.File;
import java.io.FileNotFoundException;
import java.io.IOException;
import java.net.UnknownHostException;
import java.util.Scanner;
import net.sf.json.JSONArray;
import net.sf.json.JSONObject;
import org.slf4j.LoggerFactory;

/**
 * Database access class for SAD.
 */
public class Coordinator implements Closeable {

    private final org.slf4j.Logger logger = LoggerFactory.getLogger(getClass());

    private static final String lineSeparator = System.getProperty("line.separator");
    private JSONObject configuration;
    private JSONArray configurationPojoPackages;

    private Mongo mongo;
    private Datastore datastore;

    private String configurationDatabaseName, configurationDatabaseMongoServerHost;
    private int configurationDatabaseMongoServerPort;

    private boolean databaseInitialised = false;

    /**
     * Requires valid path to configuration file.
     *
     * @param pathToConfigurationFile
     */
    public Coordinator(String pathToConfigurationFile) {

        logger.debug("New SAD coordinator initialising with the following path: " + pathToConfigurationFile);

        if (pathToConfigurationFile == null) {
            throw new RuntimeException("SAD coordinator configuration path can not be null");
        }

        if (pathToConfigurationFile.length() < 1) {
            throw new RuntimeException("SAD coordinator configuration path can not be empty");
        }

        File configurationFile = new File(pathToConfigurationFile);

        if (!configurationFile.exists()) {
            throw new RuntimeException("SAD coordinator configuration file does not exist on the following path: "
                    + pathToConfigurationFile);
        }

        if (!configurationFile.isFile()) {
            throw new RuntimeException(
                    "SAD coordinator configuration file is not a file: " + pathToConfigurationFile);
        }

        String absPathToConfigurationFile;
        try {
            absPathToConfigurationFile = configurationFile.getCanonicalPath();
        } catch (IOException ex) {
            throw new RuntimeException("Failed to resolve absolute path to Coordinator configuration file", ex);
        }

        logger.debug("Resolved SAD coordinator file path to: " + absPathToConfigurationFile);

        StringBuilder fileContents = new StringBuilder((int) configurationFile.length());
        Scanner scanner;
        try {
            scanner = new Scanner(configurationFile);
        } catch (FileNotFoundException ex) {
            throw new RuntimeException("Coordinator configuration file not found", ex);
        }
        while (scanner.hasNextLine()) {
            fileContents.append(scanner.nextLine());
            fileContents.append(lineSeparator);
        }
        scanner.close();

        String configAsString = fileContents.toString();

        if (configAsString.length() < 1) {
            throw new RuntimeException(
                    "SAD coordinator configuration file can not be empty: " + absPathToConfigurationFile);
        }

        logger.debug("Loading SAD coordinator configuration: " + configAsString);

        configuration = JSONObject.fromObject(configAsString);

        if (!configuration.containsKey("database")) {
            throw new RuntimeException("SAD coordinator configuration file \'" + pathToConfigurationFile
                    + "\' must contain field \'database\'");
        }

        if (!configuration.containsKey("pojo_packages")) {
            throw new RuntimeException("SAD coordinator configuration file \'" + pathToConfigurationFile
                    + "\' must contain field \'pojo_packages\'");
        }

        JSONObject configurationDatabase = configuration.getJSONObject("database");

        if (!configurationDatabase.containsKey("mongo_server")) {
            throw new RuntimeException("SAD coordinator configuration file \'" + pathToConfigurationFile
                    + "\' must contain field \'database/mongo_server\'");
        }
        if (!configurationDatabase.containsKey("name")) {
            throw new RuntimeException("SAD coordinator configuration file \'" + pathToConfigurationFile
                    + "\' must contain field \'database/name\'");
        }

        JSONObject configurationDatabaseMongoServer = configurationDatabase.getJSONObject("mongo_server");

        if (!configurationDatabaseMongoServer.containsKey("host")) {
            throw new RuntimeException("SAD coordinator configuration file \'" + pathToConfigurationFile
                    + "\' must contain field \'database/mongo_server/host\'");
        }
        if (!configurationDatabaseMongoServer.containsKey("port")) {
            throw new RuntimeException("SAD coordinator configuration file \'" + pathToConfigurationFile
                    + "\' must contain field \'database/mongo_server/port\'");
        }

        configurationDatabaseMongoServerHost = configurationDatabaseMongoServer.getString("host");
        configurationDatabaseMongoServerPort = configurationDatabaseMongoServer.getInt("port");
        configurationDatabaseName = configurationDatabase.getString("name");

        configurationPojoPackages = configuration.getJSONArray("pojo_packages");

        if (configurationPojoPackages.isEmpty()) {
            logger.warn("No POJO package names detected");
        }

        logger.debug("Testing database connection");

        // connect to Mongo
        try {
            mongo = new Mongo(configurationDatabaseMongoServerHost, configurationDatabaseMongoServerPort);
        } catch (UnknownHostException ex) {
            throw new RuntimeException("Failed to connect to Mongo server, unknown host", ex);
        }

        logger.debug("Coordinator initialized successfully, call setupDatabase() or deleteDatabase() next");
    }

    /**
     * Sets up SAD database, this method has to be called for the Coordinator to
     * be usable (apart from deleteDatabase() method).
     */
    public void setupDatabase() {
        logger.debug("Setting up Mongo database \'" + configurationDatabaseName + "\' on server \'"
                + configurationDatabaseMongoServerHost + ":" + configurationDatabaseMongoServerPort + "\'");

        // Initialise Morphia
        MorphiaLoggerFactory.reset(); // TODO: look into this, only a temp fix
        MorphiaLoggerFactory.registerLogger(com.google.code.morphia.logging.slf4j.SLF4JLogrImplFactory.class);
        Morphia morphia = new Morphia();
        int numPackages = configurationPojoPackages.size();
        String packageName;

        for (int i = 0; i < numPackages; i++) {
            packageName = configurationPojoPackages.getJSONObject(i).getString("name");
            if (packageName != null) {
                logger.debug("Adding package: " + packageName + " to Morphia");
                morphia = morphia.mapPackage(packageName);
            }
        }

        datastore = morphia.createDatastore(mongo, configurationDatabaseName);
        databaseInitialised = true;

    }

    public <T> Query<T> createQuery(Class<T> type) {
        if (null == this.datastore) {
            setupDatabase();
        }
        Query<T> query = this.datastore.createQuery(type);
        return query;
    }

    /*
     * Saves object and updates @Id
     */
    public <T> Key<T> saveObject(T object) {
        if (null == this.datastore) {
            setupDatabase();
        }
        Key<T> key = this.datastore.save(object);
        return key;
    }

    public Datastore getDatastore() {
        if (null == this.datastore) {
            setupDatabase();
        }
        return this.datastore;
    }

    public DBCollection getDBCollection(SADCollections collection) {
        DBCollection coll = getDatastore().getDB().getCollection(collection.getName());
        return coll;
    }

    public DBCollection getDBCollection(String name) {
        DBCollection coll = getDatastore().getDB().getCollection(name);
        return coll;
    }

    public void closeMongo() {
        if (mongo != null) {
            logger.debug("Closing mongo connection");
            databaseInitialised = false;
            mongo.close();
            mongo.getConnector().close();
            logger.debug("Mongo connector isOpen: " + mongo.getConnector().isOpen());
        } else {
            logger.error("FAILED to close mongo connection because mongo=NULL");
        }
    }

    /**
     * DELETES main SAD database, can be called before setupDatabase() method.
     */
    public void deleteDatabase() {
        logger.warn(
                "Database \'" + configurationDatabaseName + "\' on server \'" + configurationDatabaseMongoServerHost
                        + ":" + configurationDatabaseMongoServerPort + "\' will be deleted now");
        mongo.dropDatabase(configurationDatabaseName);
    }

    /**
     * Indicates if setupDatabase() was ever called successfully.
     *
     * @return true if the database is initialised.
     */
    public boolean isDatabaseInitialised() {
        return databaseInitialised;
    }

    @Override
    public void close() throws IOException {
        closeMongo();
    }
}