org.eclipse.birt.data.oda.mongodb.impl.MDbConnection.java Source code

Java tutorial

Introduction

Here is the source code for org.eclipse.birt.data.oda.mongodb.impl.MDbConnection.java

Source

/*
 *************************************************************************
 * Copyright (c) 2013 Actuate Corporation.
 * All rights reserved. This program and the accompanying materials
 * are made available under the terms of the Eclipse Public License v1.0
 * which accompanies this distribution, and is available at
 * http://www.eclipse.org/legal/epl-v10.html
 *
 * Contributors:
 *  Actuate Corporation - initial API and implementation
 *  
 *************************************************************************
 */

package org.eclipse.birt.data.oda.mongodb.impl;

import java.util.Properties;

import org.eclipse.birt.data.oda.mongodb.nls.Messages;
import org.eclipse.datatools.connectivity.oda.IConnection;
import org.eclipse.datatools.connectivity.oda.IDataSetMetaData;
import org.eclipse.datatools.connectivity.oda.IQuery;
import org.eclipse.datatools.connectivity.oda.OdaException;

import com.ibm.icu.util.ULocale;
import com.mongodb.CommandResult;
import com.mongodb.DB;
import com.mongodb.Mongo;
import com.mongodb.MongoException;

/**
 * Implementation class of IConnection for the MongoDB ODA runtime driver.
 * Each connection is to a Mongo database for specific 
 * Mongo Connection URI plus additional options not definable in the URI.
 */
public class MDbConnection implements IConnection {

    private DB m_mongoDbInstance;
    private boolean m_useRequestSession = false; // default is false

    /*
     * @see org.eclipse.datatools.connectivity.oda.IConnection#open(java.util.Properties)
     */
    public void open(Properties connProperties) throws OdaException {
        if (isOpen())
            return; // already open

        DB dbInstance = getMongoDatabase(connProperties);

        // no exception thrown thus far; accept the db instance for use
        m_mongoDbInstance = dbInstance;

        // check and apply the request session property setting
        Boolean useRequestSession = MongoDBDriver.getBooleanPropValue(connProperties,
                MongoDBDriver.REQUEST_SESSION_PROP);
        m_useRequestSession = useRequestSession != null ? useRequestSession.booleanValue() : false; // reset to default
        if (m_mongoDbInstance != null) {
            // DB instance may be re-used from connection pool
            if (m_useRequestSession)
                m_mongoDbInstance.requestStart(); // starts a request session, if not already started
            else
                m_mongoDbInstance.requestDone(); // ends a request session, in case previously started but never closed
        }
    }

    public static DB getMongoDatabase(Properties connProperties) throws OdaException {
        Mongo mongoInstance = MongoDBDriver.getMongoNode(connProperties);
        if (!mongoInstance.getConnector().isOpen())
            throw new OdaException(Messages.mDbConnection_failedToOpenConn);

        // to avoid potential conflict in shared DB, ReadPreference is exposed
        // as cursorReadPreference in data set property

        String dbName = MongoDBDriver.getDatabaseName(connProperties);
        if (dbName == null || dbName.isEmpty())
            throw new OdaException(Messages.mDbConnection_missingValueDBName);

        // validate whether dbName exists
        Boolean dbExists = existsDatabase(mongoInstance, dbName, connProperties);
        if (dbExists != null && !dbExists) // does not exist for sure
        {
            // do not proceed to create new database instance
            throw new OdaException(Messages.bind(Messages.mDbConnection_invalidDatabaseName, dbName));
        }

        DB dbInstance = mongoInstance.getDB(dbName);
        authenticateDB(dbInstance, connProperties);
        return dbInstance;
    }

    /*
     * @see org.eclipse.datatools.connectivity.oda.IConnection#setAppContext(java.lang.Object)
     */
    public void setAppContext(Object context) throws OdaException {
        // do nothing; no support for pass-through context
    }

    /*
     * @see org.eclipse.datatools.connectivity.oda.IConnection#close()
     */
    public void close() throws OdaException {
        if (m_useRequestSession && m_mongoDbInstance != null)
            m_mongoDbInstance.requestDone();

        m_mongoDbInstance = null;
    }

    /*
     * @see org.eclipse.datatools.connectivity.oda.IConnection#isOpen()
     */
    public boolean isOpen() throws OdaException {
        return m_mongoDbInstance != null;
    }

    /*
     * @see org.eclipse.datatools.connectivity.oda.IConnection#getMetaData(java.lang.String)
     */
    public IDataSetMetaData getMetaData(String dataSetType) throws OdaException {
        // this driver supports only one type of data set,
        // ignores the specified dataSetType
        return new DataSetMetaData(this);
    }

    /*
     * @see org.eclipse.datatools.connectivity.oda.IConnection#newQuery(java.lang.String)
     */
    public IQuery newQuery(String dataSetType) throws OdaException {
        if (!isOpen())
            throw new OdaException(Messages.mDbConnection_noConnection);
        // this driver supports only one type of data set,
        // ignores the specified dataSetType
        return new MDbQuery(this);
    }

    /*
     * @see org.eclipse.datatools.connectivity.oda.IConnection#getMaxQueries()
     */
    public int getMaxQueries() throws OdaException {
        return 0; // no limit
    }

    /*
     * @see org.eclipse.datatools.connectivity.oda.IConnection#commit()
     */
    public void commit() throws OdaException {
        // do nothing; no transaction support needed
    }

    /*
     * @see org.eclipse.datatools.connectivity.oda.IConnection#rollback()
     */
    public void rollback() throws OdaException {
        // do nothing; no transaction support needed
    }

    /* (non-Javadoc)
     * @see org.eclipse.datatools.connectivity.oda.IConnection#setLocale(com.ibm.icu.util.ULocale)
     */
    public void setLocale(ULocale locale) throws OdaException {
        // do nothing; no locale support
    }

    DB getConnectedDB() {
        return m_mongoDbInstance;
    }

    static void authenticateDB(DB mongoDb, Properties connProps) throws OdaException {
        if (mongoDb.isAuthenticated())
            return; // already authenticated

        String username = MongoDBDriver.getUserName(connProps);
        if (username == null || username.isEmpty())
            return; // nothing to authenticate

        String passwd = MongoDBDriver.getPassword(connProps);
        char[] passwdChars = passwd != null ? passwd.toCharArray() : new char[0];

        CommandResult result = null;
        try {
            result = mongoDb.authenticateCommand(username, passwdChars);
        } catch (Exception ex) {
            OdaException odaEx = null;
            if (result != null) {
                odaEx = new OdaException(result.getErrorMessage());
                odaEx.initCause(ex);
            } else
                odaEx = new OdaException(ex);

            MongoDBDriver.getLogger()
                    .info(Messages.bind("Unable to authenticate user (${0}) in database (${1}).\n ${2}", //$NON-NLS-1$
                            new Object[] { username, mongoDb, odaEx.getCause().getMessage() }));
            throw odaEx;
        }
    }

    private static Boolean existsDatabase(Mongo mongoInstance, String dbName, Properties connProps)
            throws OdaException {
        // check if user authentication is needed
        String username = MongoDBDriver.getUserName(connProps);
        if (username != null && !username.isEmpty()) {
            DB adminDb = mongoInstance.getDB("admin"); //$NON-NLS-1$
            try {
                // login to admin db, so to get the existing database names
                authenticateDB(adminDb, connProps);
            } catch (OdaException ex) {
                // not able to determine if db exists; specified user is probably not a valid login user in admin db
                return null;
            }
        }

        try {
            return mongoInstance.getDatabaseNames().contains(dbName);
        } catch (MongoException ex) {
            throw new OdaException(ex); // unable to get db names
        }
    }

}