Package com.sun.messaging.jmq.jmsserver.persist.jdbc

Source Code of com.sun.messaging.jmq.jmsserver.persist.jdbc.DBTool

/*
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER.
*
* Copyright (c) 2000-2010 Oracle and/or its affiliates. All rights reserved.
*
* The contents of this file are subject to the terms of either the GNU
* General Public License Version 2 only ("GPL") or the Common Development
* and Distribution License("CDDL") (collectively, the "License").  You
* may not use this file except in compliance with the License.  You can
* obtain a copy of the License at
* https://glassfish.dev.java.net/public/CDDL+GPL_1_1.html
* or packager/legal/LICENSE.txt.  See the License for the specific
* language governing permissions and limitations under the License.
*
* When distributing the software, include this License Header Notice in each
* file and include the License file at packager/legal/LICENSE.txt.
*
* GPL Classpath Exception:
* Oracle designates this particular file as subject to the "Classpath"
* exception as provided by Oracle in the GPL Version 2 section of the License
* file that accompanied this code.
*
* Modifications:
* If applicable, add the following below the License Header, with the fields
* enclosed by brackets [] replaced by your own identifying information:
* "Portions Copyright [year] [name of copyright owner]"
*
* Contributor(s):
* If you wish your version of this file to be governed by only the CDDL or
* only the GPL Version 2, indicate your decision by adding "[Contributor]
* elects to include this software in this distribution under the [CDDL or GPL
* Version 2] license."  If you don't indicate a single choice of license, a
* recipient has the option to distribute your version of this file under
* either the CDDL, the GPL Version 2 or to extend the choice of license to
* its licensees as provided above.  However, if you add GPL Version 2 code
* and therefore, elected the GPL Version 2 license, then the option applies
* only if the new code is made subject to such option by the copyright
* holder.
*/

/*
* @(#)DBTool.java  1.108 06/29/07
*/

package com.sun.messaging.jmq.jmsserver.persist.jdbc;

import com.sun.messaging.jmq.Version;
import com.sun.messaging.jmq.io.Status;
import com.sun.messaging.jmq.jmsserver.config.*;
import com.sun.messaging.jmq.jmsserver.util.*;
import com.sun.messaging.jmq.jmsserver.*;
import com.sun.messaging.jmq.jmsserver.cluster.BrokerState;
import com.sun.messaging.jmq.jmsserver.resources.*;
import com.sun.messaging.jmq.util.log.Logger;
import com.sun.messaging.jmq.util.StringUtil;
import com.sun.messaging.jmq.util.UID;

import com.sun.messaging.jmq.jmsserver.persist.StoreManager;
import com.sun.messaging.jmq.jmsserver.persist.HABrokerInfo;
import com.sun.messaging.jmq.jmsserver.persist.TransactionInfo;
import com.sun.messaging.jmq.jmsserver.persist.ChangeRecordInfo;
import com.sun.messaging.jmq.jmsserver.persist.file.FileStore;
import com.sun.messaging.jmq.jmsserver.persist.sharecc.ShareConfigChangeStore;
import com.sun.messaging.jmq.jmsserver.persist.jdbc.sharecc.ShareConfigChangeDBManager;
import com.sun.messaging.jmq.jmsserver.persist.jdbc.sharecc.JDBCShareConfigChangeStore;
import com.sun.messaging.jmq.jmsserver.persist.jdbc.sharecc.ShareConfigRecordDAO;
import com.sun.messaging.jmq.jmsserver.persist.jdbc.sharecc.ShareConfigRecordDAOImpl;
import com.sun.messaging.jmq.jmsserver.persist.jdbc.comm.BaseDAO;
import com.sun.messaging.jmq.jmsserver.persist.jdbc.comm.CommDBManager;
import com.sun.messaging.jmq.jmsserver.persist.jdbc.comm.DBConnectionPool;
import com.sun.messaging.jmq.jmsserver.persist.jdbc.comm.TableSchema;
import com.sun.messaging.jmq.jmsserver.multibroker.ChangeRecord;
import com.sun.messaging.jmq.jmsserver.core.Destination;
import com.sun.messaging.jmq.jmsserver.core.DestinationUID;
import com.sun.messaging.jmq.jmsserver.core.Consumer;
import com.sun.messaging.jmq.jmsserver.core.ConsumerUID;
import com.sun.messaging.jmq.jmsserver.data.TransactionUID;
import com.sun.messaging.jmq.jmsserver.data.TransactionAcknowledgement;
import com.sun.messaging.jmq.io.Packet;
import com.sun.messaging.jmq.io.SysMessageID;
import com.sun.messaging.bridge.BridgeServiceManager;
import com.sun.messaging.bridge.service.JMSBridgeStore;

import java.io.*;
import java.sql.*;
import java.util.*;

/**
* This class is used to create, delete, and recreate database tables.
* It may also be used to create a database.
* All database specific information is obtained from property file,
* except for username and password which may also be specified as command
* line arguments.
*/
public class DBTool implements DBConstants {

    static final String SQLFILEDIR_PROP =
    DBManager.JDBC_PROP_PREFIX + "sqlfile.dirpath";

    static final String SQLFILENAME_PROP =
    DBManager.JDBC_PROP_PREFIX + "sqlfile.name";

    /*
     * All internal properties must start with "imq."
     */
    static final String STORE_PROPERTY_HABROKERS = "imq.cluster.haBrokers";
    static final String STORE_PROPERTY_SUPPORT_JMSBRIDGE = "imq.bridge.jmsbridge.tables";

    // parser exception reasons
    private static int EXTRA_CMD_SPECIFIED  = 0;
    private static int BAD_CMD_ARG    = 1;
    private static int BAD_OPT      = 2;
    private static int BAD_OPT_ARG    = 3;
    private static int MISSING_OPT_ARG    = 4;
    private static int MISSING_CMD_ARG    = 5;
    private static int MISSING_OPT          = 6;

    private static String CMD_NAME    = "dbmgrcmd";
    private static String CREATE_ALL_CMD  = "createall";
    private static String CREATE_TBL_CMD  = "createtbl";
    private static String CREATE_SHARECCTBL_CMD  = "create sharecc_tbl";
    private static String DELETE_TBL_CMD  = "deletetbl";
    private static String DELETE_SHARECCTBL_CMD  = "delete sharecc_tbl";
    private static String RECREATE_TBL_CMD  = "recreatetbl";
    private static String RECREATE_SHARECCTBL_CMD = "recreate sharecc_tbl";
    private static String REMOVE_BKR_CMD  = "removebkr";
    private static String REMOVE_JMSBRIDGE_CMD = "removejmsbridge";
    private static String DUMP_CMD    = "dump";
    private static String DUMP_SHARECCTBL_CMD   = "dump sharecc_tbl";
    private static String DROPTBL_CMD          = "droptbl";
    private static String RESET_CMD    = "reset";
    private static String BACKUP_CMD            = "backup";
    private static String BACKUP_SHARECCTBL_CMD            = "backup sharecc_tbl";
    private static String RESTORE_CMD           = "restore";
    private static String RESTORE_SHARECCTBL_CMD = "restore sharecc_tbl";
    private static String UPGRADE_STORE_CMD     = "upgradestore";
    private static String UPGRADE_HASTORE_CMD   = "upgradehastore";
    private static String QUERY_CMD             = "query";

    private static String ARG_NAME    = "dbmgrarg";

    private static String CREATE_CMD_STR = "create";
    private static String DELETE_CMD_STR = "delete";
    private static String RECREATE_CMD_STR = "recreate";
    private static String REMOVE_CMD_STR = "remove";
    private static String UPGRADE_CMD_STR = "upgrade";
    private static String ARGU_ALL = "all";
    private static String ARGU_TBL = "tbl";
    private static String ARGU_SHARECCTBL = "sharecc_tbl";
    private static String ARGU_BKR = "bkr";
    private static String ARGU_JMSBRIDGE = "jmsbridge";
    private static String ARGU_OLDTBL = "oldtbl";
    private static String ARGU_LCK = "lck";
    private static String ARGU_STORE = "store";
    private static String ARGU_HASTORE = "hastore";
    private static String OPT_H = "-h";
    private static String OPT_LH = "-help";
    private static String OPT_V = "-v";
    private static String OPT_LV = "-version";
    private static String OPT_B = "-b";
    private static String OPT_N = "-n";
    private static String OPT_U = "-u";
    private static String OPT_P = "-p";
    private static String OPT_PW = "-pw";
    private static String OPT_PASSFILE = "-passfile";
    private static String OPT_D = "-D";
    private static String OPT_VARHOME = "-varhome";
    private static String OPT_VERBOSE = "-verbose";
    private static String OPT_DEBUG = "-debug";
    private static String OPT_DIR = "-dir";
    private static String OPT_FILE = "-file";
    private static String OPT_FORCE = "-f";
    private static String JMSBRIDGE_NAME_PROPERTY = "jmsbridge.name";

    private static BrokerResources br = Globals.getBrokerResources();
    private static BrokerConfig config;
    private static Logger logger;

    private Version version;
    private DBManager dbmgr = null;
    private boolean standalone = true;
    private boolean cliPasswdSpecified = false;
    private boolean debugSpecified = false;
    private boolean forceSpecified = false;

    DBTool(boolean standalone) {
  this.version = new Version();
  this.standalone = standalone;
    }

    private void doCreate(boolean createdb)
  throws BrokerException {
        doCreate(createdb, null);
    }

    private void doCreate(boolean createdb, CommDBManager mgrArg)
  throws BrokerException {

    CommDBManager mgr = (mgrArg == null ? dbmgr:mgrArg);
  Connection conn = null;
  try {
            if (createdb) {
                conn = mgr.connectToCreate();
                conn.setAutoCommit( true );
            } else {
                conn = mgr.newConnection( true ); // set autoCommit to true
            }

            // Check if store exist
            boolean continueOnError = false;
            int status = mgr.checkStoreExists( conn );
            if (status > 0) {
                if (!(mgr instanceof ShareConfigChangeDBManager)) {
                // All tables have already been created
                throw new BrokerException(br.getKString(
                    BrokerResources.E_DATABASE_TABLE_ALREADY_CREATED));
                } else {
                throw new BrokerException(br.getKString(
                    BrokerResources.E_SHARECC_TABLE_ALREADY_CREATED,
                    Globals.getClusterID()));
                }
            } else if (status < 0) {
                // Some tables are missings so try to create the tables
                // but ignore error if table already exists
                continueOnError = true;
            }

            createTables( conn, continueOnError, mgr );

      if (standalone) {
                if ( Globals.getHAEnabled() ) {
                    System.out.println( br.getString(
                        BrokerResources.I_DATABASE_TABLE_HA_CREATED,
                        Globals.getClusterID() ) );
                } else if (mgr instanceof ShareConfigChangeDBManager) {
                    System.out.println( br.getString(
                        BrokerResources.I_SHARECC_DATABASE_TABLE_CREATED,
                        Globals.getClusterID() ) );
                } else {
                    System.out.println(
                        br.getString(BrokerResources.I_DATABASE_TABLE_CREATED));
                }
      }
  } catch (Throwable t) {
      String url;
      if (createdb)
    url = mgr.getCreateDBURL();
      else
    url = mgr.getOpenDBURL();

      throw new BrokerException(br.getKString(
                BrokerResources.E_CREATE_DATABASE_TABLE_FAILED, url), t);
  } finally {
            if ( createdb && conn != null ) {
                // Since the connection is not from the pool; we've to close it
                try {
                    conn.close();
                } catch (SQLException e) {
                    throw new BrokerException(
                        Globals.getBrokerResources().getKString(
                            BrokerResources.E_INTERNAL_BROKER_ERROR,
                            "Unable to close JDBC resources", e ) );
                }
            }
  }
    }

    // create database tables used in the current version of persistent store
    static void createTables( Connection conn ) throws BrokerException {
        createTables( conn, false );
    }

    static void createTables( Connection conn, boolean continueOnError )
        throws BrokerException {
        createTables(conn, continueOnError, null, null);
    }

    public static void createTables( Connection conn,
                                     boolean continueOnError,
                                     CommDBManager mgrArg )
        throws BrokerException {
        createTables(conn, continueOnError, null, mgrArg);
    }

    static void createTables( Connection conn, boolean continueOnError,
                              ArrayList tableDAOs)
        throws BrokerException {
        createTables(conn, continueOnError, tableDAOs, null);
    }

    //if tableDAOs != null, only create these tables
    //else create current version of persist store
    static void createTables( Connection conn, boolean continueOnError,
                              ArrayList tableDAOs, CommDBManager mgrArg)
        throws BrokerException {

        CommDBManager mgr = mgrArg;
        if (mgr == null) {
            mgr = DBManager.getDBManager();
        }
        Iterator itr = null;
        if (tableDAOs != null) {
            itr = tableDAOs.iterator();
        } else {
            itr = mgr.allDAOIterator();
        }
        while ( itr.hasNext() ) {
            BaseDAO dao = (BaseDAO)itr.next();
            try {
                Util.RetryStrategy retry = null;
                do {
                    try {
                        dao.createTable( conn );
                        break; // table created so break from retry loop
                    } catch ( Exception e ) {
                        // Exception will be log & re-throw if operation cannot be retry
                        if ( retry == null ) {
                            retry = new Util.RetryStrategy(mgr);
                        }
                        retry.assertShouldRetry( e );
                    }
                } while ( true );
            } catch (BrokerException be) {
                if ( Globals.getHAEnabled() ||
                     (mgr instanceof ShareConfigChangeDBManager) ) {
                    // Paused for a few secs to prevent race condition when two
                    // or more brokers try to create the tables at the same time
                    try {
                        Thread.sleep(5000);
                    } catch (InterruptedException e) {}
                }

                // Verify if the store has already been created
                if ( mgr.checkStoreExists( conn ) > 0 ) {
                    if (tableDAOs == null) {
                    Globals.getLogger().log(Logger.WARNING,
                        BrokerResources.E_CREATE_DATABASE_TABLE_FAILED,
                        Globals.getBrokerResources().getString(
                            BrokerResources.E_DATABASE_TABLE_ALREADY_CREATED));
                    continueOnError = true;
                    } else {
                    Globals.getLogger().log(Logger.WARNING,
                        BrokerResources.E_CREATE_DATABASE_TABLE_FAILED,
                        Globals.getBrokerResources().getString(
                            BrokerResources.E_THE_DATABASE_TABLE_ALREADY_CREATED, dao.getTableName()));
                    }
                    break;
                } else if (continueOnError) {
                    // Just log msg and continue
                    Globals.getLogger().log(Logger.WARNING, be.toString(), be.getCause());
                } else {
                    throw be;
                }
            }
        }

        if ( tableDAOs != null || !(mgr instanceof DBManager) ) {
            return;
        }

        DAOFactory daoFactory = ((DBManager)mgr).getDAOFactory();

      // Insert version info in the version table
        VersionDAO versionDAO = daoFactory.getVersionDAO();
        try {
            if ( continueOnError ) {
                // Do this only if version is missing from version table
                int storeVersion = versionDAO.getStoreVersion( conn );
                if ( storeVersion != JDBCStore.STORE_VERSION ) {
                    versionDAO.insert( conn, JDBCStore.STORE_VERSION );
                }
            } else {
                versionDAO.insert( conn, JDBCStore.STORE_VERSION );
            }
        } catch (BrokerException be) {
            if ( Globals.getHAEnabled() ) {
                // Re-check if version info has been added by another broker
                int storeVersion = versionDAO.getStoreVersion( conn );
                if ( storeVersion != JDBCStore.STORE_VERSION ) {
                    throw be; // Re-throw the exception
                }
            } else {
                throw be; // Re-throw the exception
            }
        }

        // Insert a unique store session for the stand-alone broker
        if ( !Globals.getHAEnabled() ) {
            // Do this only if store session is missing from session table
            String brokerID = Globals.getBrokerID();
            StoreSessionDAO sessionDAO = daoFactory.getStoreSessionDAO();
            if ( sessionDAO.getStoreSession( conn, brokerID ) <= 0 ) {
                sessionDAO.insert( conn, brokerID, new UID().longValue(), true );
            }
        }

        PropertyDAO dao = daoFactory.getPropertyDAO();
        dao.update( conn, STORE_PROPERTY_SUPPORT_JMSBRIDGE, Boolean.valueOf(true));
    }

    static void updateStoreVersion410IfNecessary(Connection conn)
        throws BrokerException {

        try {
            if (!Globals.getHAEnabled()) {
               DBManager.lockTables(conn, true);
            }
            DBManager dbMgr = DBManager.getDBManager();
            DAOFactory daoFactory = dbMgr.getDAOFactory();
            VersionDAO versionDAO  = daoFactory.getVersionDAO();
            int storeVersion = versionDAO.getStoreVersion(conn);

            if (storeVersion != JDBCStore.STORE_VERSION) {
                throw new BrokerException(br.getKString(
                          BrokerResources.E_BAD_STORE_VERSION,
                          String.valueOf(storeVersion),
                          String.valueOf(JDBCStore.STORE_VERSION)));
            }
            PropertyDAO dao = daoFactory.getPropertyDAO();
            if (!dao.hasProperty(conn, STORE_PROPERTY_SUPPORT_JMSBRIDGE)) {
                ArrayList daos = new ArrayList();
                daos.add(daoFactory.getTMLogRecordDAOJMSBG());
                daos.add(daoFactory. getJMSBGDAO());
                createTables(conn, false, daos);

                dao.update( conn, STORE_PROPERTY_SUPPORT_JMSBRIDGE, Boolean.valueOf(true));
            }

        } finally {
            if (!Globals.getHAEnabled()) {
                DBManager.lockTables(conn, false);
            }
        }
    }

    private void doReset() throws BrokerException {

  Connection conn = null;
    Exception myex = null;
  try {
            conn = dbmgr.getConnection(true);

            // unlock the tables
      DBManager.lockTables(conn, false); // false = unlock
    } catch (BrokerException e) {
        myex = e;
        throw e;
  } finally {
        Util.close( null, null, conn, myex );
  }
    }

    private void doDelete(String arg) throws BrokerException {
        doDelete(arg, null);
    }
    private void doDelete(String arg, CommDBManager mgrArg) throws BrokerException {

    CommDBManager mgr = (mgrArg == null ? dbmgr:mgrArg);
  boolean deleted = false;
    Connection conn = null;
    Exception myex = null;
  try {
            conn = mgr.getConnection(true);

      if (arg == null || arg.length() == 0) {
                // Check if store exist
                boolean continueOnError = false;
                int status = mgr.checkStoreExists( conn );
                if (status > 0 && !(mgr instanceof ShareConfigChangeDBManager)) {
                    // Verify cluster is not active in HA mode
                    if (!forceSpecified && Globals.getHAEnabled() &&
                        ((DBManager)mgr).isHAClusterActive(conn)) {
                        throw new BrokerException(br.getKString(
                            BrokerResources.E_HA_CLUSTER_STILL_ACTIVE, dbmgr.getClusterID()));
                    }

                    try {
                        // lock the tables first (implemented since version 350);
                        // note that we don't need to unlock the tables since
                        // the tables will be dropped when we are done
                        if (!forceSpecified) {
                            ((DBManager)mgr).lockTables(conn, true); // true = lock
                        }
                    } catch ( BrokerException e ) {
                        if ( e.getStatusCode() == Status.NOT_FOUND ) {
                            // For some reason if version table doesn't exist or
                            // version data is not found we can just ignore the error!
                            continueOnError = true;
                        } else {
                            throw e;
                        }
                    }
                } else if (status > 0 && (mgr instanceof ShareConfigChangeDBManager)) {
                    try {
                        if (!forceSpecified) {
                            ((ShareConfigChangeDBManager)mgr).lockTable(conn, true);
                        }
                    } catch ( BrokerException e ) {
                        if ( e.getStatusCode() == Status.NOT_FOUND ) {
                            continueOnError = true;
                        } else {
                            throw e;
                        }
                    }

                } else if (status < 0) {
                    // Some tables are missings so try to delete the rest
                    // but ignore error if table does not exists
                    continueOnError = true;
                } else {
                    if (!(mgr instanceof ShareConfigChangeDBManager)) {
                    // All tables have already been deleted
                    throw new BrokerException(br.getKString(
                        BrokerResources.E_DATABASE_TABLE_ALREADY_DELETED));
                    } else {
                    throw new BrokerException(br.getKString(
                        BrokerResources.E_SHARECC_TABLE_ALREADY_DELETED,
                        Globals.getClusterID()));
                    }
                }

    deleted = dropTables(conn, null, continueOnError, mgrArg);
      } else if (arg.equals(ARGU_OLDTBL)) {
                int oldStoreVersion = -1;
                if ( checkVersion( conn,
                    VERSION_TBL_37 + dbmgr.getBrokerID() ) ) {
                    oldStoreVersion = JDBCStore.OLD_STORE_VERSION_370;
                } else if ( checkVersion( conn,
                    VERSION_TBL_35 + dbmgr.getBrokerID() ) ) {
                    oldStoreVersion = JDBCStore.OLD_STORE_VERSION_350;
                } else {
                    throw new BrokerException("Old persistent store (version " +
                        JDBCStore.OLD_STORE_VERSION_370 + ") not found");
                }

                deleted = dropTables(conn, dbmgr.getTableNames(oldStoreVersion));
      } else {
    // not possible since argument is checked already
      }

      if (standalone && deleted) {
                if ( Globals.getHAEnabled() ) {
                    System.out.println( br.getString(
                        BrokerResources.I_DATABASE_TABLE_HA_DELETED,
                        Globals.getClusterID() ) );
                } else if (mgr instanceof ShareConfigChangeDBManager) {
                    System.out.println( br.getString(
                        BrokerResources.I_SHARECC_DATABASE_TABLE_DELETED,
                        Globals.getClusterID() ) );
                } else {
                    System.out.println(br.getString(BrokerResources.I_DATABASE_TABLE_DELETED));
                }
      }
  } catch (Exception e) {
        myex = e;
        if (debugSpecified) {
            e.printStackTrace();
        }
        if (!(mgr instanceof ShareConfigChangeDBManager)) {
      throw new BrokerException(
                br.getKString(BrokerResources.E_DELETE_DATABASE_TABLE_FAILED,
                    mgr.getOpenDBURL()), e);
        } else {
      throw new BrokerException(
                br.getKString(BrokerResources.E_SHARECC_FAIL_DELETE_TABLE,
                Globals.getClusterID(), mgr.getOpenDBURL()), e);
        }
  } finally {
        Util.close( null, null, conn, myex, mgrArg );
  }
    }

    static boolean dropTables(Connection conn, String names[])
        throws SQLException, BrokerException {
        return dropTables(conn, names, false);
    }

    static boolean dropTables(Connection conn, String names[],
                              boolean continueOnError)
                              throws SQLException, BrokerException {
        return dropTables(conn, names, continueOnError, null);
    }

    static boolean dropTables(Connection conn, String names[],
                              boolean continueOnError, CommDBManager mgrArg)
                              throws SQLException, BrokerException {

        CommDBManager mgr = (mgrArg == null ? DBManager.getDBManager():mgrArg);
        boolean deleted = false;
        Exception myex = null;
        try {
            if ( names != null && names.length > 0 ) {
                // Removing old tables, i.e. 3.5
                Statement stmt = null;
                try {
                    stmt = conn.createStatement();
                    for ( int i = 0, len = names.length; i < len; i++ ) {
                        String oldTableName = names[i];
                        Globals.getLogger().logToAll( Logger.INFO,
                            br.getString( BrokerResources.I_DROP_TABLE,
                                oldTableName ) );
                        stmt.executeUpdate( "DROP TABLE " + oldTableName );

                        if ( mgr.hasSupplementForCreateDrop(oldTableName) ) {
                             TableSchema schema = mgr.getTableSchema(oldTableName);
                             mgr.dropTableSupplement(stmt, schema, oldTableName, true);
                        }
                    }
                } catch (SQLException e) {
                    myex = e;
                    throw e;
                } finally {
                    Util.close( null, stmt, null, myex, mgr );
                }
            } else {
                Iterator itr = mgr.allDAOIterator();
                while ( itr.hasNext() ) {
                    BaseDAO dao = (BaseDAO)itr.next();
                    try {
                        Util.RetryStrategy retry = null;
                        do {
                            try {
                                dao.dropTable( conn );
                                break; // table dropped so break from retry loop
                            } catch ( Exception e ) {
                                // Exception will be log & re-throw if operation cannot be retry
                                if ( retry == null ) {
                                    retry = new Util.RetryStrategy(mgr);
                                }
                                retry.assertShouldRetry( e );
                            }
                        } while ( true );
                    } catch (BrokerException be) {
                        if (continueOnError) {
                            // Just log msg and continue
                            Globals.getLogger().log(Logger.WARNING, be.toString(), be.getCause());
                        } else {
                            throw be;
                        }
                    }
                }
            }
            deleted = true;
        } catch ( Exception e ) {
            if (!(mgr instanceof ShareConfigChangeDBManager)) {
            Globals.getLogger().log(Logger.ERROR,
                BrokerResources.E_DELETE_DATABASE_TABLE_FAILED,
                e.toString(), e);
            } else {
            Globals.getLogger().log(Logger.ERROR,
                BrokerResources.E_SHARECC_FAIL_DELETE_TABLE,
                Globals.getClusterID(), e.toString(), e);
            }
            if (e instanceof SQLException) {
                throw (SQLException)e;
            }
            if (e instanceof BrokerException) {
                throw (BrokerException)e;
            }
            throw new BrokerException(e.getMessage(), e);
        }

  return deleted;
    }

    static boolean checkVersion(Connection conn, String vtable)
        throws BrokerException {

        // get version from table
        String selectSQL = "SELECT * FROM " + vtable;

        Statement stmt = null;
        ResultSet rs = null;
        Exception myex = null;
        try {
            stmt = conn.createStatement();
            rs = stmt.executeQuery(selectSQL);
        } catch (SQLException e) {
            myex = e;
            // assume that the table does not exist
            return false;
        } finally {
            Util.close(rs, stmt, null, myex);
        }

        return true;
    }

    private void doRecreate() throws BrokerException {
        doRecreate(null);
    }

    private void doRecreate(CommDBManager mgrArg) throws BrokerException {

    CommDBManager mgr = (mgrArg == null ? dbmgr : mgrArg)
  Connection conn = null;
    Throwable myex = null;
  try {
            conn = mgr.getConnection(true);

            boolean deleted = false;
            boolean continueOnError = false;
            int status = mgr.checkStoreExists( conn );
            if (status > 0 && !(mgr instanceof ShareConfigChangeDBManager)) {
                // Verify cluster is not active in HA mode
                if (!forceSpecified && Globals.getHAEnabled() &&
                    ((DBManager)mgr).isHAClusterActive(conn)) {
                    throw new BrokerException(br.getKString(
                        BrokerResources.E_HA_CLUSTER_STILL_ACTIVE, dbmgr.getClusterID()));
                }

                try {
                    // lock the tables first (implemented since version 350);
                    // note that we don't need to unlock the tables since
                    // the tables will be recreated when we are done
                    if (!forceSpecified) {
                        ((DBManager)mgr).lockTables(conn, true); // true = lock
                    }
                } catch (BrokerException e) {
                    if ( e.getStatusCode() == Status.NOT_FOUND ) {
                        // For some reason if version table doesn't exist or
                        // version data is not found we can just ignore the error!
                        continueOnError = true;
                    } else {
                        // unable to get the lock
                        throw e;
                    }
                }
            } else if (status > 0 && (mgr instanceof ShareConfigChangeDBManager)) {
                try {
                    if (!forceSpecified) {
                        ((ShareConfigChangeDBManager)mgr).lockTable(conn, true);
                    }
                } catch (BrokerException e) {
                    if ( e.getStatusCode() == Status.NOT_FOUND ) {
                        continueOnError = true;
                    } else {
                        throw e;
                    }
                }
            } else if (status < 0) {
                // Some tables are missings so try to delete the rest
                // but ignore error if table does not exists
                continueOnError = true;
            } else {
                deleted = true;
            }

            if ( !deleted ) {
                dropTables( conn, null, continueOnError, mgrArg );
            }

      createTables( conn, false, mgrArg );

      if (standalone) {
                if ( Globals.getHAEnabled() ) {
                    System.out.println( br.getString(
                        BrokerResources.I_DATABASE_TABLE_HA_CREATED,
                        Globals.getClusterID() ) );

                } else if (mgr instanceof ShareConfigChangeDBManager) {
                    System.out.println( br.getString(
                        BrokerResources.I_SHARECC_DATABASE_TABLE_CREATED,
                        Globals.getClusterID() ) );
                } else {
                    System.out.println(
                        br.getString(BrokerResources.I_DATABASE_TABLE_CREATED) );
                }
      }
  } catch (Throwable t) {
        myex = t;
        if (!(mgr instanceof ShareConfigChangeDBManager)) {
      throw new BrokerException(
                br.getKString(BrokerResources.E_RECREATE_DATABASE_TABLE_FAILED,
                    mgr.getOpenDBURL()), t);
        } else {
      throw new BrokerException(
                br.getKString(BrokerResources.E_SHARECC_FAIL_RECREATE_TABLE,
                    Globals.getClusterID(), mgr.getOpenDBURL()), t);
        }
  } finally {
            Util.close( null, null, conn, myex, mgrArg );
  }
    }

    private void doRemoveBkr() throws BrokerException {

        String brokerID = Globals.getBrokerID();
  Connection conn = null;
    String errorMsg = null;
    Exception myex = null;
  try {
            conn = dbmgr.getConnection(true);

            // try to lock the tables first
            DBManager.lockTables(conn, true); // true = lock

            try {
                DAOFactory daoFactory = dbmgr.getDAOFactory();
                BrokerDAO brokerDAO = daoFactory.getBrokerDAO();
                BrokerState state = brokerDAO.getState(conn, brokerID);
                if ( !state.isActiveState() ) {
                    try {
                        // Remove broker's and its data
                        conn.setAutoCommit(false); // do this in 1 txn
                        daoFactory.getConsumerStateDAO().deleteAll(conn);
                        daoFactory.getMessageDAO().deleteAll(conn);
                        daoFactory.getDestinationDAO().deleteAll(conn);
                        daoFactory.getTransactionDAO().deleteAll(conn);
                        daoFactory.getStoreSessionDAO().deleteByBrokerID(conn, brokerID);
                        brokerDAO.delete(conn, brokerID);
                        daoFactory.getTMLogRecordDAOJMSBG().deleteAll(conn);
                        daoFactory.getJMSBGDAO().deleteAll(conn);
                        conn.commit(); // commit changes
                    } finally {
                        conn.setAutoCommit(true);
                    }
                } else {
                    errorMsg = br.getString(
                        BrokerResources.E_REMOVE_BROKER_FAILED,
                        brokerID, "broker is still active - " + state );
                }
            } finally {
                // remove the lock
                DBManager.lockTables(conn, false); // false = unlock
            }
  } catch (Exception e) {
        myex = e;
      throw new BrokerException(
    br.getKString( BrokerResources.E_REMOVE_BROKER_2_FAILED,
                    brokerID ), e );
  } finally {
        Util.close( null, null, conn, myex );
  }

        if ( standalone ) {
            if ( errorMsg == null ) {
                System.out.println(
                    br.getString( BrokerResources.I_BROKER_REMOVE, brokerID ) );
            } else {
                System.out.println(errorMsg);
            }
        }
    }

    private void doRemoveJMSBridge(String bname) throws BrokerException {

        if (bname == null) {
            try {
            checkArg(null, null, OPT_N, 0, 0);
            } catch (ParserException e) {
            handleParserException(e);
            exit(1);
            }
        }

        String brokerID = Globals.getBrokerID();
        Connection conn = null;
        String errorMsg = null;
        Exception myex = null;
        try {

            if (!askConfirmation("Removing JMS Bridge "+bname+".")) {
                return;
            }

            conn = dbmgr.getConnection(true);

            DBManager.lockTables(conn, true); // true = lock

            try {
                DAOFactory daoFactory = dbmgr.getDAOFactory();
                BrokerDAO brokerDAO = daoFactory.getBrokerDAO();
                BrokerState state = brokerDAO.getState(conn, brokerID);
                if ( !state.isActiveState() ) {
                    try {
                        conn.setAutoCommit(false);
                        daoFactory.getJMSBGDAO().delete(conn, bname, null);
                        daoFactory.getTMLogRecordDAOJMSBG().deleteAllByName(conn, bname, null);
                        conn.commit();
                    } finally {
                        conn.setAutoCommit(true);
                    }
                } else {
                    errorMsg = br.getString(BrokerResources.E_BROKER_STILL_ACTIVE);
                }
            } finally {
                DBManager.lockTables(conn, false);
            }
      } catch (Exception e) {
            myex = e;
            throw new BrokerException(br.getString(
            br.E_REMOVE_JMSBRIDGE_FAILED, bname, e.getMessage()), e);
      } finally {
            Util.close( null, null, conn, myex );
      }

        if ( standalone ) {
            if ( errorMsg == null ) {
                System.out.println(br.getString(
                BrokerResources.I_JMSBRIDGE_REMOVED_FROM_HA_STORE, bname ));
            } else {
                System.out.println(errorMsg);
            }
        }
    }

    private void doUpgrade(boolean haStore)
  throws BrokerException {

  Connection conn = null;
    BrokerException myex = null;
  try {
            conn = dbmgr.getConnection(true);

            if ( haStore ) {
                new UpgradeHAStore().upgradeStore( conn );
            } else {
                JDBCStore store = (JDBCStore)StoreManager.getStore();
                int oldStoreVersion = -1;
                if ( store.checkOldStoreVersion( conn,
                    dbmgr.getTableName(VersionDAO.TABLE + DBConstants.SCHEMA_VERSION_40),
                    VersionDAO.STORE_VERSION_COLUMN,
                    JDBCStore.OLD_STORE_VERSION_400 ) ) {
                    oldStoreVersion = JDBCStore.OLD_STORE_VERSION_400;
                } else if ( store.checkOldStoreVersion( conn,
                    VERSION_TBL_37 + dbmgr.getBrokerID(), TVERSION_CVERSION,
                    JDBCStore.OLD_STORE_VERSION_370 ) ) {
                    oldStoreVersion = JDBCStore.OLD_STORE_VERSION_370;
                } else if ( store.checkOldStoreVersion( conn,
                    VERSION_TBL_35 + dbmgr.getBrokerID(), TVERSION_CVERSION,
                    JDBCStore.OLD_STORE_VERSION_350 ) ) {
                    oldStoreVersion = JDBCStore.OLD_STORE_VERSION_350;
                } else {
                    throw new BrokerException("Old persistent store (version " +
                        JDBCStore.OLD_STORE_VERSION_400 + ") not found");
                }

                new UpgradeStore(store, oldStoreVersion).upgradeStore(conn);
            }
    } catch (BrokerException e) {
        myex = e;
        throw e;
  } finally {
        Util.close( null, null, conn, myex );
  }
    }

    /**
     * dump info about the database.
     * for debugging purpose
     */
    private void doDump(String arg, CommDBManager mgrArg)
    throws SQLException, BrokerException {

    CommDBManager mgr = (mgrArg == null ? dbmgr:mgrArg);

    String names[] = null;

    if (!(mgr instanceof ShareConfigChangeDBManager)) {
        int storeVersion = JDBCStore.STORE_VERSION;
      if (arg != null) {
          try {
                storeVersion = Integer.parseInt(arg);
          } catch (NumberFormatException e) {
            storeVersion = 0;
          }
      }

        if ( storeVersion != JDBCStore.STORE_VERSION ) {
            // Old store
            names = mgr.getTableNames(storeVersion);
            if (names == null || names.length == 0) {
                throw new BrokerException("version " + arg + " not supported");
            }
        }
    }

        Connection conn = null;
        Exception myex = null;
        try {
            conn = mgr.getConnection(true);
            doDump(conn, names, mgr);
        } catch (SQLException e) {
            myex = e;
            throw e;
        } catch (BrokerException e) {
            myex = e;
            throw e;
        } finally {
            Util.close( null, null, conn, myex, mgr );
        }
    }

    static void doDump(Connection dbconn, String tables[],
                       CommDBManager mgrArg)
                       throws BrokerException, SQLException {

        CommDBManager mgr = mgrArg;

        if ( tables != null && tables.length > 0 ) {
            Statement stmt = null;
            Exception myex = null;
            try {
                stmt = dbconn.createStatement();
                for (int i = 0; i < tables.length; i++) {
                    ResultSet r = null;
                    String tname = tables[i];
                    String sql = "SELECT COUNT(*) FROM " + tname;
                    try {
                        r = stmt.executeQuery(sql);
                        if (r.next()) {
                            System.out.println(tname + ": number of row="
                                                + r.getInt(1));
                        }
                        r.close();
                    } catch (SQLException e) {
                        SQLException ex = mgr.wrapSQLException(
                                                        "[" + sql + "]", e);
                        logger.log(Logger.ERROR, "failed to dump tables", ex);
                    }
                }
            } catch (SQLException e) {
                myex = e;
                throw e;
            } finally {
                Util.close( null, stmt, null, myex, mgr );
            }
        } else {
            // Starting in 4.0, use info from BaseDAO.getDebugInfo()
            Iterator itr = mgr.allDAOIterator();
            while ( itr.hasNext() ) {
                BaseDAO dao = (BaseDAO)itr.next();
                System.out.println( dao.getDebugInfo( dbconn ).toString() );

            }
        }
    }

    /**
     * drop tables that start with mq and match the specified table name pattern.
     * for internal use!!!
     */
    private void doDropTablesByPattern(String arg) throws BrokerException {

        Connection conn = null;
        Exception myex = null;
        try {
            conn = dbmgr.getConnection(true);
            Map map = dbmgr.getTableNamesFromDB(conn, arg, false);
            String[] names = (String[])map.values().toArray(new String[0] );

            if ( names == null || names.length == 0 ) {
                System.out.println(
                    "There were no tables that match the name pattern 'MQ*" +
                    arg + "'.");
                return;
            }

            // List all tables that match the name pattern
            System.out.println(
                "Tables matching the name pattern 'MQ*" + arg + "':");

            for (int i = 0, len = names.length; i < len; i++) {
                System.out.println("\t" + names[i]);
            }

            if (!askConfirmation("Remove all tables that match 'MQ*"+ arg +"'.")) {
                // if not positive confirmation, do nothing!
                return;
            }

            dropTables(conn, names, true);
        } catch (Exception e) {
            myex = e;
            System.err.println(
                "Failed to drop tables by name pattern: " + e.getMessage());
            throw new BrokerException(
                br.getKString(BrokerResources.E_DELETE_DATABASE_TABLE_FAILED,
                    "table name pattern '" + arg + "'"), e);
        } finally {
            Util.close( null, null, conn, myex );
        }
    }


    private boolean askConfirmation(String prompt) throws IOException {
        // Ask for confirmation only if force option is not specified
        if (forceSpecified) return true;

        System.out.println(prompt+"\nDo you wish to proceed? [y/n] ");
        System.out.flush();

        String val = (new BufferedReader(new InputStreamReader(System.in))).readLine();

        if (!"y".equalsIgnoreCase(val) && !"yes".equalsIgnoreCase(val)) {
            return false;
        }
        return true;
    }


    /**
     * Backup the JDBC store to filebased backup files.
     */
    private void doBackup() throws BrokerException {

        if (!Globals.getHAEnabled()) {
            throw new BrokerException(br.getKString(BrokerResources.I_HA_NOT_ENABLE,
                dbmgr.getBrokerID()));
        }

        // instantiate the file store.
        Properties props = System.getProperties();
        String clusterID = Globals.getClusterID();
        String backupDir = (String)props.get(Globals.IMQ + ".backupdir") +
            File.separator + clusterID;

        logger.logToAll(Logger.INFO,
            "Backup persistent store for HA cluster " + clusterID);

        FileStore fileStore = new FileStore(backupDir, false);

        // for backup, need to clear the store before storing anything.
        fileStore.clearAll(false);

        JDBCStore jdbcStore = null;
        try {
            jdbcStore = (JDBCStore)StoreManager.getStore();

            /*
             * For data that are not broker specific, i.e. properties, change
             * records, consumers, brokers, and sessions, we will store
             * those data on the top level directory (a.k.a cluster filestore).
             */

            // Properties table
            Properties properties = jdbcStore.getAllProperties();
            Iterator propItr = properties.entrySet().iterator();
            while (propItr.hasNext()) {
                Map.Entry entry = (Map.Entry)propItr.next();
                fileStore.updateProperty(
                    (String)entry.getKey(), entry.getValue(), false);

            }
            propItr = null; properties = null;

            // Configuration Change Record table
            List<ChangeRecordInfo> records = jdbcStore.getAllConfigRecords();
            for (int i = 0, len = records.size(); i < len; i++) {
                fileStore.storeConfigChangeRecord(
                    records.get(i).getTimestamp(),
                    (byte[])records.get(i).getRecord(), false);
            }
            records = null;

            // Consumer table
            Consumer[] consumerArray = jdbcStore.getAllInterests();
            for (int i = 0; i < consumerArray.length; i++) {
                fileStore.storeInterest(consumerArray[i], false);
            }
            consumerArray = null;

            // Broker & Session table - store all HABrokerInfo as a property
            HashMap bkrMap = jdbcStore.getAllBrokerInfos(true);
            List haBrokers = new ArrayList(bkrMap.values());
            fileStore.updateProperty(STORE_PROPERTY_HABROKERS, haBrokers, true);

            /*
             * For each broker in the cluster, we will store broker specific
             * data, destinations, messages, transactions, acknowledgements
             * in their own filestore (a.k.a broker filestore).
             */
            Iterator bkrItr = haBrokers.iterator();
            while (bkrItr.hasNext()) {
                // Backup data for each broker
                HABrokerInfo bkrInfo = (HABrokerInfo)bkrItr.next();
                String brokerID = bkrInfo.getId();

                logger.logToAll(Logger.INFO,
                    "Backup persistent data for broker " + brokerID);

                FileStore bkrFS = null;
                JMSBridgeStore jmsbridgeStore = null;
                try {
                    String instanceRootDir = backupDir + File.separator + brokerID;
                    bkrFS = new FileStore(instanceRootDir, false);
                    bkrFS.clearAll(false);

                    // Destination table.
                    Destination[] dstArray = jdbcStore.getAllDestinations(brokerID);
                    for (int i = 0, len = dstArray.length; i < len; i++) {
                        DestinationUID did = dstArray[i].getDestinationUID();
                        Destination dst = bkrFS.getDestination(did);
                        if (dst == null) {
                            // Store the destination if not found
                            bkrFS.storeDestination(dstArray[i]false);
                        }
                    }

                    // Storing messages for each destination.
                    for (int i = 0, len = dstArray.length; i < len; i++) {
                        Enumeration e = jdbcStore.messageEnumeration(dstArray[i]);
                        try {
                        for (; e.hasMoreElements();) {
                            DestinationUID did = dstArray[i].getDestinationUID();
                            Packet message = (Packet)e.nextElement();
                            SysMessageID mid = message.getSysMessageID();

                            // Get interest states for the message; Consumer State table
                            HashMap stateMap = jdbcStore.getInterestStates(did, mid);
                            if (stateMap == null || stateMap.isEmpty()) {
                                bkrFS.storeMessage(did, message, false);
                            } else {
                                int size = stateMap.size();
                                ConsumerUID[] iids = new ConsumerUID[size];
                                int[] states  = new int[size];
                                Iterator stateItr = stateMap.entrySet().iterator();
                                int j = 0;
                                while (stateItr.hasNext()) {
                                    Map.Entry entry = (Map.Entry)stateItr.next();
                                    iids[j] = (ConsumerUID)entry.getKey();
                                    states[j] = ((Integer)entry.getValue()).intValue();
                                    j++;
                                }
                                bkrFS.storeMessage(did, message, iids, states, false);
                            }

                        }

                        } finally {
                        jdbcStore.closeEnumeration(e);
                        }
                    }

                    // Transaction table
                    Collection txnList = jdbcStore.getTransactions(brokerID);
                    Iterator txnItr = txnList.iterator();
                    while (txnItr.hasNext()) {
                        TransactionUID tid = (TransactionUID)txnItr.next();
                        TransactionInfo txnInfo = jdbcStore.getTransactionInfo(tid);
                        TransactionAcknowledgement txnAck[] =
                            jdbcStore.getTransactionAcks(tid);
                        bkrFS.storeTransaction(tid, txnInfo, false);
                        for (int i = 0, len = txnAck.length; i < len; i++) {
                            bkrFS.storeTransactionAck(tid, txnAck[i], false);
                        }
                    }

                    /**************************************************
                     * JMSBridge
                     **************************************************/

                    Properties bp = new Properties();
                    bp.setProperty("instanceRootDir", instanceRootDir);
                    bp.setProperty("reset", "true");
                    bp.setProperty("logdomain", "imqdbmgr");
                    bp.setProperty("identityName", Globals.getIdentityName());


                    BridgeServiceManager.getExportedService(
                        "com.sun.messaging.bridge.service.JMSBridgeStore", "JMS", bp);

                    List bnames = jdbcStore.getJMSBridgesByBroker(brokerID, null);
                    Collections.sort(bnames);

                    String bname = null;
                    String currbname = null;
                    Iterator itr = bnames.iterator();
                    while (itr.hasNext()) {
                        bname = (String)itr.next();
                        if (currbname == null || !currbname.equals(bname)) {
                            currbname = bname;
                            bp.setProperty("jmsbridge", bname);
                            if (jmsbridgeStore != null) {
                                jmsbridgeStore.closeJMSBridgeStore();
                                jmsbridgeStore = null;
                            }
                            logger.logToAll(logger.INFO, "Backup JMS bridge "+bname);
                            jmsbridgeStore = (JMSBridgeStore)BridgeServiceManager.getExportedService(
                                             "com.sun.messaging.bridge.service.JMSBridgeStore", "JMS", bp);
                            List lrs = jdbcStore.getLogRecordsByNameByBroker(bname, brokerID, null);
                            logger.logToAll(logger.INFO, "\tBackup JMS bridge "+bname+" with "+lrs.size()+" TM log records");
                            byte[] lr = null;
                            Iterator itr1 = lrs.iterator();
                            while (itr1.hasNext()) {
                                lr = (byte[])itr1.next();
                                jmsbridgeStore.storeTMLogRecord(null, lr, currbname, true, null);
                            }
                         }
                    }

                } finally {
                    bkrFS.close();
                    if (jmsbridgeStore != null) jmsbridgeStore.closeJMSBridgeStore();
                }
            }

            logger.logToAll(Logger.INFO, "Backup persistent store complete.");
        } catch(Throwable ex){
            ex.printStackTrace();
            throw new BrokerException(ex.getMessage());
        } finally {
            if (fileStore != null) {
                try {
                    fileStore.close();
                } catch(Exception e) {
                    e.printStackTrace();
                }
            }

            StoreManager.releaseStore(true);
        }
    }

    /*
     * Restore the JDBC store from filebased backup files.
     */
    private void doRestore() throws BrokerException {

        if (!Globals.getHAEnabled()) {
            throw new BrokerException(br.getKString(BrokerResources.I_HA_NOT_ENABLE,
                dbmgr.getBrokerID()));
        }

        // instantiate the file store.
        Properties props = System.getProperties();
        String clusterID = Globals.getClusterID();
        String backupDir = (String)props.get(Globals.IMQ + ".backupdir") +
            File.separator + clusterID;

        logger.logToAll(Logger.INFO,
            "Restore persistent store for HA cluster " + clusterID + " from backup dir: " + backupDir);

        FileStore fileStore = new FileStore(backupDir, false);

        // Brokers table.
        JDBCStore jdbcStore = null;
        try {
            // Re-create the jdbc store
            doRecreate();

            jdbcStore = (JDBCStore)StoreManager.getStore();

            /*
             * For data that are not broker specific, i.e. properties, change
             * records, consumers, brokers, and sessions, we will retrieve
             * those data from the top level directory (a.k.a cluster filestore).
             */

            // Properties table
            List haBrokers = null;
            Properties properties = fileStore.getAllProperties();
            Iterator propItr = properties.entrySet().iterator();
            while (propItr.hasNext()) {
                Map.Entry entry = (Map.Entry)propItr.next();
                String name = (String)entry.getKey();
                if (name.equals(STORE_PROPERTY_HABROKERS)) {
                    // Retrieve all HABrokerInfo from a property
                    haBrokers = (List)entry.getValue();
                } else {
                    jdbcStore.updateProperty(name, entry.getValue(), false);
                }
            }
            propItr = null; properties = null;

            if (haBrokers == null || haBrokers.isEmpty()) {
                throw new BrokerException(br.getKString(
                    BrokerResources.X_LOAD_ALL_BROKERINFO_FAILED));
            }

            // Configuration Change Record table
            List<ChangeRecordInfo> records = fileStore.getAllConfigRecords();
            for (int i = 0, len = records.size(); i < len; i++) {
                jdbcStore.storeConfigChangeRecord(
                    records.get(i).getTimestamp(),
                    records.get(i).getRecord(), false);
            }
            records = null;

            // Consumer table
            Consumer[] consumerArray = fileStore.getAllInterests();
            for (int i = 0; i < consumerArray.length; i++) {
                jdbcStore.storeInterest(consumerArray[i], false);
            }
            consumerArray = null;

            // Broker & Session table.
            Iterator bkrItr = haBrokers.iterator();
            while (bkrItr.hasNext()) {
                HABrokerInfo bkrInfo = (HABrokerInfo)bkrItr.next();
                jdbcStore.addBrokerInfo(bkrInfo, false);
            }

            /*
             * For each broker in the cluster, we will retrieve broker specific
             * data, destinations, messages, transactions, acknowledgements
             * from their own filestore (a.k.a broker filestore).
             */
            bkrItr = haBrokers.iterator();
            while (bkrItr.hasNext()) {
                // Backup data for each broker
                HABrokerInfo bkrInfo = (HABrokerInfo)bkrItr.next();
                String brokerID = bkrInfo.getId();
                long sessionID = bkrInfo.getSessionID();

                logger.logToAll(Logger.INFO,
                    "Restore persistent data for broker " + brokerID);

                FileStore bkrFS = null;
                JMSBridgeStore jmsbridgeStore = null;
                try {
                    String instanceRootDir = backupDir + File.separator + brokerID;
                    bkrFS = new FileStore(instanceRootDir, false);

                    // Destination table.
                    Destination[] dstArray = bkrFS.getAllDestinations();
                    for (int i = 0, len = dstArray.length; i < len; i++) {
                        DestinationUID did = dstArray[i].getDestinationUID();
                        Destination dst = jdbcStore.getDestination(did);
                        if (dst == null) {
                            // Store the destination if not found
                            jdbcStore.storeDestination(dstArray[i], sessionID);
                        }
                    }

                    // Retrieve messages for each destination.
                    for (int i = 0, len = dstArray.length; i < len; i++) {
                        for (Enumeration e = bkrFS.messageEnumeration(dstArray[i]);
                            e.hasMoreElements();) {
                            DestinationUID did = dstArray[i].getDestinationUID();
                            Packet message = (Packet)e.nextElement();
                            SysMessageID mid = message.getSysMessageID();

                            // Get interest states for the message; Consumer State table
                            HashMap stateMap = bkrFS.getInterestStates(did, mid);
                            if (stateMap == null || stateMap.isEmpty()) {
                                jdbcStore.storeMessage(
                                    did, message, null, null, sessionID, false);
                            } else {
                                int size = stateMap.size();
                                ConsumerUID[] iids = new ConsumerUID[size];
                                int[] states  = new int[size];
                                Iterator stateItr = stateMap.entrySet().iterator();
                                int j = 0;
                                while (stateItr.hasNext()) {
                                    Map.Entry entry = (Map.Entry)stateItr.next();
                                    iids[j] = (ConsumerUID)entry.getKey();
                                    states[j] = ((Integer)entry.getValue()).intValue();
                                    j++;
                                }
                                jdbcStore.storeMessage(
                                    did, message, iids, states, sessionID, false);
                            }
                        }
                    }

                    // Transaction table
                    Collection txnList = bkrFS.getTransactions(brokerID);
                    Iterator txnItr = txnList.iterator();
                    while (txnItr.hasNext()) {
                        TransactionUID tid = (TransactionUID)txnItr.next();
                        TransactionInfo txnInfo = bkrFS.getTransactionInfo(tid);
                        TransactionAcknowledgement txnAck[] =
                            bkrFS.getTransactionAcks(tid);
                        jdbcStore.storeTransaction(tid, txnInfo, sessionID);
                        for (int i = 0, len = txnAck.length; i < len; i++) {
                            jdbcStore.storeTransactionAck(tid, txnAck[i], false);
                        }
                    }

                    /**************************************************
                     * JMSBridge
                     **************************************************/

                    Properties bp = new Properties();
                    bp.setProperty("instanceRootDir", instanceRootDir);
                    bp.setProperty("reset", "false");
                    bp.setProperty("logdomain", "imqdbmgr");

                    jmsbridgeStore = (JMSBridgeStore)BridgeServiceManager.getExportedService(
                                     "com.sun.messaging.bridge.service.JMSBridgeStore", "JMS", bp);

                    if (jmsbridgeStore != null) {

                    List bnames = jmsbridgeStore.getJMSBridges(null);
                    String bname = null;
                    Iterator itr = bnames.iterator();
                    while (itr.hasNext()) {
                        bname = (String)itr.next();
                        jdbcStore.addJMSBridge(bname, true, null);
                    }
                    jmsbridgeStore.closeJMSBridgeStore();
                    jmsbridgeStore = null;

                    bname = null;
                    itr = bnames.iterator();
                    while (itr.hasNext()) {
                        bname = (String)itr.next();
                        bp.setProperty("jmsbridge", bname);
                        if (jmsbridgeStore != null) {
                            jmsbridgeStore.closeJMSBridgeStore();
                            jmsbridgeStore = null;
                        }
                        logger.logToAll(logger.INFO, "Restore JMS bridge "+bname);
                        jmsbridgeStore = (JMSBridgeStore)BridgeServiceManager.getExportedService(
                                         "com.sun.messaging.bridge.service.JMSBridgeStore", "JMS", bp);
                        List xids = jmsbridgeStore.getTMLogRecordKeysByName(bname, null);

                        logger.logToAll(logger.INFO, "\tRestore JMS bridge "+bname+" with "+xids.size()+" TM log records");

                        String xid = null;
                        byte[] lr = null;
                        Iterator itr1 = xids.iterator();
                        while (itr1.hasNext()) {
                            xid = (String)itr1.next();
                            lr = jmsbridgeStore.getTMLogRecord(xid, bname, null);
                            if (lr == null) {
                                logger.logToAll(Logger.INFO,
                                        "JMSBridge TM log record not found for "+xid);
                                continue;
                           
                            jdbcStore.storeTMLogRecord(xid, lr, bname, true, null);  
                         }
                    }
                    }

                } finally {
                    bkrFS.close();
                    if (jmsbridgeStore != null) jmsbridgeStore.closeJMSBridgeStore();
                }
            }

            logger.logToAll(Logger.INFO, "Restore persistent store complete.");
        } catch (Throwable ex){
            ex.printStackTrace();
            throw new BrokerException(ex.getMessage());
        } finally {
            if (fileStore != null) {
                try {
                    fileStore.close();
                } catch(Exception e) {
                    e.printStackTrace();
                }
            }

            StoreManager.releaseStore(true);
        }
    }

    /**
     * Backup the shared table for cluster config change record to a file
     */
    private void doBackupSharecc() throws BrokerException {
        Properties props = System.getProperties();
        String clusterID = Globals.getClusterID();
        String backupfile = (String)props.get(
            ShareConfigChangeStore.CLUSTER_SHARECC_PROP_PREFIX+".backupfile");

        logger.logToAll(Logger.INFO, br.getKString(br.I_SHARECC_BACKUP,
                                                   clusterID, backupfile));

        ShareConfigChangeDBManager mgr = ShareConfigChangeDBManager.getDBManager();
        ShareConfigRecordDAO dao = mgr.getDAOFactory().getShareConfigRecordDAO();
        try {
            List<ChangeRecordInfo> records = null;

            Util.RetryStrategy retry = null;
            do {
                try {
                    records = dao.getAllRecords( null );
                    break;
                } catch ( Exception e ) {
                    if ( retry == null ) {
                         retry = new Util.RetryStrategy(mgr);
                    }
                    retry.assertShouldRetry( e );
                }
            } while ( true );

            Globals.getLogger().logToAll(Logger.INFO, br.getKString(
                                         br.I_SHARECC_BACKUP_RECORDS,
                                         String.valueOf(records.size()),
                                         dao.getTableName()));

            ChangeRecord.backupRecords(records, backupfile, true);

            Globals.getLogger().logToAll(Logger.INFO,
                                         br.getKString(br.I_SHARECC_BACKUP_RECORDS_SUCCESS,
                                         Globals.getClusterID(), backupfile));
        } catch (BrokerException e) {
            String emsg =  br.getKString(br.E_SHARECC_BACKUP_RECORDS_FAIL, e.getMessage());
            Globals.getLogger().logToAll(Logger.ERROR, emsg, e);
            throw e;
        }
    }

    /**
     * Restore the shared table for cluster config change record from a file
     */
    private void doRestoreSharecc() throws BrokerException {

        Properties props = System.getProperties();
        String clusterID = Globals.getClusterID();
        String backupfile = (String)props.get(
            ShareConfigChangeStore.CLUSTER_SHARECC_PROP_PREFIX+".backupfile");

        logger.logToAll(Logger.INFO, br.getKString(br.I_SHARECC_RESTORE,
                                                   clusterID, backupfile));

        ShareConfigChangeDBManager mgr = ShareConfigChangeDBManager.getDBManager();

        Connection conn = null;
        Exception myex = null;
        try {
            List<ChangeRecordInfo> records = ChangeRecord.prepareRestoreRecords(backupfile);

            ShareConfigRecordDAO dao = mgr.getDAOFactory().getShareConfigRecordDAO();

            Globals.getLogger().logToAll(Logger.INFO, br.getKString(
                                         br.I_SHARECC_RESTORE_RECORDS,
                                         String.valueOf(records.size()),
                                         backupfile));

            conn = mgr.getConnection( false );

            Util.RetryStrategy retry = null;
            do {
                try {
                    ChangeRecordInfo resetcri = ChangeRecord.makeResetRecord( true );
                    dao.insertResetRecord( conn, resetcri, false);
                    Iterator itr = records.iterator();
                    ChangeRecordInfo cri = null;
                    while (itr.hasNext()) {
                        cri = (ChangeRecordInfo)itr.next();
                        if (cri.getType() == ChangeRecordInfo.TYPE_RESET_PERSISTENCE) {
                            itr.remove();
                            continue;
                        }
                        cri.setResetUUID(resetcri.getUUID());
                        cri.setTimestamp(System.currentTimeMillis());
                        ((ShareConfigRecordDAOImpl)dao).insert( conn, cri, false );
                    }
                    ((ShareConfigRecordDAOImpl)dao).setResetRecordFLAGNULL( conn );

                    conn.commit();
                    break;
                } catch ( Exception e ) {
                    if ( retry == null ) {
                         retry = new Util.RetryStrategy(mgr);
                    }
                    retry.assertShouldRetry( e );
                }
            } while ( true );

            Globals.getLogger().logToAll(Logger.INFO,
                                         br.getKString(br.I_SHARECC_RESTORE_RECORDS_SUCCESS,
                                         Globals.getClusterID(), backupfile));
        } catch (Exception e) {
            myex = e;
            String emsg =  br.getKString(br.E_SHARECC_RESTORE_RECORDS_FAIL, e.getMessage());
            Globals.getLogger().logToAll(Logger.ERROR, emsg, e);
            if (e instanceof BrokerException) {
                throw (BrokerException)e;
            }
            throw new BrokerException(emsg, e);
        } finally {
            Util.close( null, null, conn, myex, mgr );
        }
    }

    /*
     * Check persistence store.
     */
    private void doQuery() throws BrokerException {

        Connection conn = null;
        Exception myex = null;
        try {
            conn = dbmgr.getConnection(true);

            if ( Globals.getHAEnabled() ) {
                System.out.println( br.getString(
                    BrokerResources.I_RUNNING_IN_HA,
                    Globals.getBrokerID(), Globals.getClusterID() ) );
            } else {
                System.out.println( br.getString(
                    BrokerResources.I_STANDALONE_INITIALIZED ) );
            }

            updateStoreVersion410IfNecessary( conn );
            int status = dbmgr.checkStoreExists( conn );
            if ( status == 0 ) {
                System.out.println( br.getString(
                    BrokerResources.E_NO_DATABASE_TABLES ) );
            } else if (status > 0) {
                // All tables have already been created
                System.out.println( br.getString(
                    BrokerResources.E_DATABASE_TABLE_ALREADY_CREATED ) );
            } else {
                // Some tables are missings
                System.out.println( br.getString(
                    BrokerResources.E_BAD_STORE_MISSING_TABLES ) );
            }
        } catch (BrokerException e) {
            myex = e;
            throw e;
        } finally {
            Util.close( null, null, conn, myex );
        }
    }

    private boolean printHelp(String[] args) {
  for (int i = 0; i < args.length; i++) {
      if (args[i].equals(OPT_H) || args[i].equals(OPT_LH)) {
    return true;
      }
  }
  return false;
    }

    private boolean printVersion(String[] args) {
  for (int i = 0; i < args.length; i++) {
      if (args[i].equals(OPT_V) || args[i].equals(OPT_LV)) {
    return true;
      }
  }
  return false;
    }

    // throw exception if argument is missing
    private void checkArg(String cmd, String opt, int next, int total)
  throws ParserException {
        checkArg(cmd, opt, null, next, total);
    }

    private void checkArg(String cmd, String opt, String missopt, int next, int total)
  throws ParserException {

  if (next >= total) {
      ParserException pe;
      if (cmd != null) {
    pe = new ParserException(MISSING_CMD_ARG);
    pe.cmd = cmd;
        } else if(missopt != null) {
    pe = new ParserException(MISSING_OPT);
    pe.opt = missopt;
      } else {
    pe = new ParserException(MISSING_OPT_ARG);
    pe.opt = opt;
      }

      throw pe;
  }
    }

    private void throwParserException(int reason, String cmd, String cmdarg,
  String opt, String optarg) throws ParserException {
        throwParserException(reason, cmd, cmdarg, opt, optarg, null);
    }
    private void throwParserException(int reason, String cmd, String cmdarg,
  String opt, String optarg, Throwable cause) throws ParserException {

  ParserException pe = new ParserException(reason, cause);
  pe.cmd = cmd;
  pe.cmdarg = cmdarg;
  pe.opt = opt;
  pe.optarg = optarg;
  throw pe;
    }

    private void handleParserException(ParserException e) {
  if (e.reason == MISSING_CMD_ARG) {
      System.out.println(br.getString(
      BrokerResources.E_MISSING_DBMGR_CMD_ARG, e.cmd));
  } else if (e.reason == MISSING_OPT_ARG) {
      System.out.println(br.getString(
      BrokerResources.E_MISSING_DBMGR_OPT_ARG, e.opt));
  } else if (e.reason == MISSING_OPT) {
      System.out.println(br.getString(
      BrokerResources.E_MISSING_DBMGR_OPT, e.opt));
  } else if (e.reason == BAD_CMD_ARG) {
      System.out.println(br.getString(
      BrokerResources.E_INVALID_DBMGR_CMD_ARG, e.cmd, e.cmdarg));
  } else if (e.reason == BAD_OPT) {
      if (e.opt.equals(OPT_P)) {
          System.out.println(br.getString(BrokerResources.E_PASSWD_OPTION_NOT_SUPPORTED, e.opt));
      } else {
          System.out.println(br.getString(BrokerResources.E_INVALID_DBMGR_OPT, e.opt));
      }
  } else if (e.reason == BAD_OPT_ARG) {
      System.out.println(br.getString(
      BrokerResources.E_INVALID_DBMGR_OPT_ARG, e.opt, e.optarg));
  } else if (e.reason == EXTRA_CMD_SPECIFIED) {
      System.out.println(br.getString(
      BrokerResources.E_EXTRA_DBMGR_CMD, e.cmd));
  }
    }

    private Properties parseArgs(String[] args) throws ParserException {

  Properties props = System.getProperties();
  boolean gotcmd = false;

  // check cmd and options: -b, -p, -u (-h and -v checked already)
  for (int i = 0; i < args.length; i++) {
      if (args[i].equals(CREATE_CMD_STR)) {
    if (gotcmd) {
        throwParserException(EXTRA_CMD_SPECIFIED, args[i], null,
          null, null);
    } else {
        gotcmd = true;
    }

    checkArg(args[i], null, ++i, args.length);

    // find argument
    if (args[i].equals(ARGU_ALL)) {
        props.put(CMD_NAME, CREATE_ALL_CMD);
    } else if (args[i].equals(ARGU_TBL)) {
        props.put(CMD_NAME, CREATE_TBL_CMD);
    } else if (args[i].equals(ARGU_SHARECCTBL)) {
        props.put(CMD_NAME, CREATE_SHARECCTBL_CMD);
    } else {
        throwParserException(BAD_CMD_ARG, CREATE_CMD_STR,
          args[i], null, null);
    }
      } else if (args[i].equals(DELETE_CMD_STR)) {
    if (gotcmd) {
        throwParserException(EXTRA_CMD_SPECIFIED, args[i],
          null, null, null);
    } else {
        gotcmd = true;
    }

    checkArg(args[i], null, ++i, args.length);

    // find argument
    if (args[i].equals(ARGU_TBL)) {
        props.put(CMD_NAME, DELETE_TBL_CMD);
    } else if (args[i].equals(ARGU_SHARECCTBL)) {
        props.put(CMD_NAME, DELETE_SHARECCTBL_CMD);
    } else if (args[i].equals(ARGU_OLDTBL)) {
        props.put(CMD_NAME, DELETE_TBL_CMD);
        props.put(ARG_NAME, ARGU_OLDTBL);
    } else {
        throwParserException(BAD_CMD_ARG, DELETE_CMD_STR,
          args[i], null, null);
    }
      } else if (args[i].equals(RECREATE_CMD_STR)) {
    if (gotcmd) {
        throwParserException(EXTRA_CMD_SPECIFIED, args[i],
          null, null, null);
    } else {
        gotcmd = true;
    }

    checkArg(args[i], null, ++i, args.length);

    // find argument
    if (args[i].equals(ARGU_TBL)) {
        props.put(CMD_NAME, RECREATE_TBL_CMD);
    } else if (args[i].equals(ARGU_SHARECCTBL)) {
        props.put(CMD_NAME, RECREATE_SHARECCTBL_CMD);
    } else {
        throwParserException(BAD_CMD_ARG, RECREATE_CMD_STR,
          args[i], null, null);
    }
      } else if (args[i].equals(REMOVE_CMD_STR)) {
    if (gotcmd) {
        throwParserException(EXTRA_CMD_SPECIFIED, args[i],
          null, null, null);
    } else {
        gotcmd = true;
    }

    checkArg(args[i], null, ++i, args.length);

    // find argument
    if (args[i].equals(ARGU_BKR)) {
        props.put(CMD_NAME, REMOVE_BKR_CMD);
    } else if (args[i].equals(ARGU_JMSBRIDGE)) {
        props.put(CMD_NAME, REMOVE_JMSBRIDGE_CMD);
    } else {
        throwParserException(BAD_CMD_ARG, REMOVE_CMD_STR,
          args[i], null, null);
    }

        } else if (args[i].equals(DUMP_CMD)) {
    // private command for debug purpose only
    if (gotcmd) {
        throwParserException(EXTRA_CMD_SPECIFIED, args[i],
          null, null, null);
    } else {
        gotcmd = true;
    }

    checkArg(args[i], null, ++i, args.length);

        if (args[i].equals(ARGU_SHARECCTBL)) {
            props.put(CMD_NAME, DUMP_SHARECCTBL_CMD);
        } else {
            try {
                Integer.parseInt(args[i]);
            } catch (Exception e) {
                throwParserException(BAD_CMD_ARG, DUMP_CMD,
                args[i], null, null, e);    
            }
            props.put(CMD_NAME, DUMP_CMD);
            props.put(ARG_NAME, args[i]);
        }

        } else if (args[i].equals(DROPTBL_CMD)) {
    // private command to drop tables that match the specified
                // table name pattern for internal use only!!!
    if (gotcmd) {
        throwParserException(EXTRA_CMD_SPECIFIED, args[i],
          null, null, null);
    } else {
        gotcmd = true;
    }

    checkArg(args[i], null, ++i, args.length);

    props.put(CMD_NAME, DROPTBL_CMD);
    props.put(ARG_NAME, args[i]);
      } else if (args[i].equals(RESET_CMD)) {
    // command for resetting the table lock
    if (gotcmd) {
        throwParserException(EXTRA_CMD_SPECIFIED, args[i],
          null, null, null);
    } else {
        gotcmd = true;
    }

    checkArg(args[i], null, ++i, args.length);

    // find argument
    if (args[i].equals(ARGU_LCK)) {
        props.put(CMD_NAME, RESET_CMD);
    } else {
        throwParserException(BAD_CMD_ARG, RESET_CMD,
          args[i], null, null);
    }
            } else if (args[i].equals(BACKUP_CMD)) {
                // command for backing up the jdbc store
                if (gotcmd) {
                    throwParserException(EXTRA_CMD_SPECIFIED, args[i],
                    null, null, null);
                } else {
                    gotcmd = true;
                }

                checkArg(args[i], null, ++i, args.length);

                // find argument
                if (args[i].equals(OPT_DIR)) {
                    props.put(CMD_NAME, BACKUP_CMD);
                    checkArg(args[i], null, ++i, args.length);
                    props.put(Globals.IMQ + ".backupdir", args[i]);
                } else if (args[i].equals(ARGU_SHARECCTBL)) {
                    props.put(CMD_NAME, BACKUP_SHARECCTBL_CMD);
                    checkArg(null, null, OPT_FILE, ++i, args.length);
                    if (args[i].equals(OPT_FILE)) {
                        checkArg(null, args[i], null, ++i, args.length);
                        props.put(ShareConfigChangeStore.CLUSTER_SHARECC_PROP_PREFIX+
                                  ".backupfile", args[i]);
                    } else {
                        throwParserException(BAD_CMD_ARG, BACKUP_SHARECCTBL_CMD,
                            args[i], null, null);
                    }
                } else {
                    throwParserException(BAD_CMD_ARG, BACKUP_CMD,
                    args[i], null, null);
                }
            } else if (args[i].equals(RESTORE_CMD)) {
                // command for backing up the jdbc store
                if (gotcmd) {
                    throwParserException(EXTRA_CMD_SPECIFIED, args[i],
                    null, null, null);
                } else {
                    gotcmd = true;
                }

                checkArg(args[i], null, ++i, args.length);

                // find argument
                if (args[i].equals(OPT_DIR)) {
                    props.put(CMD_NAME, RESTORE_CMD);
                    checkArg(args[i], null, ++i, args.length);
                    props.put(Globals.IMQ + ".backupdir", args[i]);
                } else if (args[i].equals(ARGU_SHARECCTBL)) {
                    props.put(CMD_NAME, RESTORE_SHARECCTBL_CMD);
                    checkArg(null, null, OPT_FILE, ++i, args.length);
                    if (args[i].equals(OPT_FILE)) {
                        checkArg(null, args[i], null, ++i, args.length);
                        props.put(ShareConfigChangeStore.CLUSTER_SHARECC_PROP_PREFIX+
                                  ".backupfile", args[i]);
                    } else {
                        throwParserException(BAD_CMD_ARG, RESTORE_SHARECCTBL_CMD,
                            args[i], null, null);
                    }
                } else {
                    throwParserException(BAD_CMD_ARG, RESTORE_CMD,
                    args[i], null, null);
                }
            } else if (args[i].equals(UPGRADE_CMD_STR)) {
                if (gotcmd) {
                    throwParserException(EXTRA_CMD_SPECIFIED, args[i],
                                        null, null, null);
                } else {
                    gotcmd = true;
                }

                checkArg(args[i], null, ++i, args.length);

                // find argument
                if (args[i].equals(ARGU_STORE)) {
                    props.put(CMD_NAME, UPGRADE_STORE_CMD);
                } else if (args[i].equals(ARGU_HASTORE)) {
                    props.put(CMD_NAME, UPGRADE_HASTORE_CMD);
                } else {
                    throwParserException(BAD_CMD_ARG, UPGRADE_CMD_STR,
                                        args[i], null, null);
                }
            } else if (args[i].equals(QUERY_CMD)) {
                if (gotcmd) {
                    throwParserException(EXTRA_CMD_SPECIFIED, args[i],
                                        null, null, null);
                } else {
                    gotcmd = true;
                }
                props.put(CMD_NAME, QUERY_CMD);
            } else if (args[i].equals(OPT_B)) {

                checkArg(null, OPT_B, ++i, args.length);
                props.put(Globals.IMQ + ".instancename", args[i]);

            } else if (args[i].equals(OPT_N)) {

                checkArg(null, OPT_N, ++i, args.length);
                props.put(Globals.BROKERID_PROPERTY, args[i]);
                props.put(JMSBRIDGE_NAME_PROPERTY, args[i]);

      } else if (args[i].equals(OPT_U)) {

    checkArg(null, OPT_U, ++i, args.length);
    props.put(DBManager.FALLBACK_USER_PROP, args[i]);

      } else if (args[i].equals(OPT_PW)) {

    checkArg(null, OPT_PW, ++i, args.length);
    props.put(DBManager.FALLBACK_PWD_PROP, args[i]);
    cliPasswdSpecified = true;

      } else if (args[i].equals(OPT_PASSFILE)) {

    checkArg(null, OPT_PASSFILE, ++i, args.length);

    File passfile = null;
    try {
        passfile = (new File(args[i])).getCanonicalFile();
    } catch (Exception e) {
        throwParserException(BAD_OPT, null, null, args[i], null);
    }
    props.put(Globals.KEYSTORE_USE_PASSFILE_PROP, "true");
    props.put(Globals.KEYSTORE_PASSDIR_PROP,
          passfile.getParent());
    props.put(Globals.KEYSTORE_PASSFILE_PROP,
          passfile.getName());

            } else if (args[i].equals(OPT_VERBOSE)) {
                // Handled by wrapper script
                ;
            } else if (args[i].equals(OPT_DEBUG)) {
                debugSpecified = true;
            } else if (args[i].equals(OPT_FORCE)) {
                forceSpecified = true;
            } else if (args[i].equals(OPT_VARHOME)) {
                // Handled by wrapper script
                i++;
      } else if (args[i].startsWith(OPT_D)) {
    int value_index = 0;
    String prop_name = null, prop_value = "";

    value_index = args[i].indexOf('=');
    if (args[i].length() <= 2) {
        // -D
        continue;
    } else if (value_index < 0) {
        // -Dfoo
        prop_name = args[i].substring(2);
    } else if (value_index == args[i].length() - 1) {
        // -Dfoo=
        prop_name = args[i].substring(2, value_index);
                } else {
        // -Dfoo=bar
        prop_name = args[i].substring(2, value_index);
        prop_value = args[i].substring(value_index + 1);
                }

    props.put(prop_name, prop_value);
      } else {
    throwParserException(BAD_OPT, null, null, args[i], null);
      }
        if (props.getProperty(REMOVE_JMSBRIDGE_CMD) != null &&
            props.getProperty(JMSBRIDGE_NAME_PROPERTY) == null) {
            checkArg(null, null, OPT_N, 0, 0);
        }
  }

  return props;
    }

    /*
     * Read/parse the passfile if it is specified.
     *
     * The objective is to obtain the database password.
     * It can be specified directly via the -p option
     * or via a passfile, specified using the -passfile option.
     *
     * This method is called to to see if a passfile is specified.
     * If it was, it is read and parsed.
     *
     * Matters are complicated by the fact that imqdbmgr reads
     * the broker's configuration files. This means that
     * A password or passfile can be specified either via
     * the broker's config.properties file or imqdbmgr's
     * -p/-passfile command line options.
     *
     * A slightly less frequent use case to consider is the one
     * where the user (intentionally or not) specifies a password
     * as well as a passfile. In this case, the password takes
     * precedence over the passfile.
     *
     * Summary of behavior:
     *  - Values specified on the command line (-p, -passfile) override
     *    config.properties (imq.persist.jdbc.password, imq.passfile.*).
     *
     *  - The passwd obtained from a 'password' configuration (-p or
     *    imq.persist.jdbc.password in config.properties) will override
     *    passwords obtained from a 'passfile' configuration (-passfile
     *    or imq.passfile.* properties in config.properties). This means
     *    -p overrides -passfile.
     *
     *  - A password obtained from -passfile will override a value for
     *    imq.persist.jdbc.password in config.properties.
     */
    private void parsePassfile()
        throws FileNotFoundException
    {
        String  pf_value = null,
          pf_dir = null,
    usePassfile = null;

  /*
   * This method checks if a passfile was specified and merges
   * it's contents (it should contain imq.persist.jdbc.password)
   * with the broker configuration.
   */

  /*
   * Return if a passfile was not specified on the cmdline or via
   * the broker configuration file.
   */
        usePassfile = config.getProperty(Globals.KEYSTORE_USE_PASSFILE_PROP);
        if ((usePassfile == null) ||
      !usePassfile.equalsIgnoreCase(Boolean.TRUE.toString())) {
      return;
  }

  // get passfile location
        if ((pf_value = config.getProperty(Globals.KEYSTORE_PASSDIR_PROP))
                                                                != null) {
      pf_value = StringUtil.expandVariables(pf_value, config);
      pf_dir = pf_value;
  } else {
      pf_dir = config.getProperty(Globals.IMQ + ".etchome")
          +File.separator + "security";
  }

  String passfile_location = pf_dir  +File.separator +
                    config.getProperty(Globals.KEYSTORE_PASSFILE_PROP);

  // Check if the passfile exists else throw exception
  File pf = new File(passfile_location);
  if (pf.exists()) {
      Properties props = new Properties();
      // read password from passfile
            //
      try {
          FileInputStream fis = new FileInputStream(
                passfile_location);
                props.load(fis);
      } catch (IOException ioex) {
          logger.log(Logger.ERROR,
        br.getKString(BrokerResources.X_READ_PASSFILE), ioex);
      }
            config.putAll(props);
        } else {
      throw new FileNotFoundException(
                br.getKString(BrokerResources.E_GET_PASSFILE,
                    passfile_location));
  }
    }


    private void exit(int status) {
    if (standalone) {
      System.exit(status);
    }
    }

    void doCommand(String[] args) throws SQLException,
      BrokerException, FileNotFoundException {

  // print all
  if (args.length == 0) {
      System.out.println(version.getBanner(true));
      System.out.println(br.getString(BrokerResources.M_DBMGR_USAGE));
      exit(0);
  }

  // print help
  if (printHelp(args)) {
      System.out.println(br.getString(BrokerResources.M_DBMGR_USAGE));
      exit(0);
  }

  // print version
  if (printVersion(args)) {
      System.out.println(version.getBanner(true));
      System.out.println(br.getString(BrokerResources.I_JAVA_VERSION) +
    System.getProperty("java.version") + " " +
    System.getProperty("java.vendor") + " " +
    System.getProperty("java.home"));
      System.out.println(br.getString(BrokerResources.I_JAVA_CLASSPATH) +
    System.getProperty("java.class.path"));
      exit(0);
  }

  Properties props = null;

  try {
            props = parseArgs(args);
  } catch (ParserException e) {
      handleParserException(e);
      exit(1);
  }

    props.getProperty(DBManager.JDBC_PROP_PREFIX+
                      DBConnectionPool.NUM_CONN_PROP_SUFFIX, "2");

  if (cliPasswdSpecified)  {
            System.err.println(br.getString(BrokerResources.W_PASSWD_OPTION_DEPRECATED, OPT_PW));
            System.err.println("");
  }

        // 1st check existence of broker instance because Globals.init()
        // method will create an instance if it does not exist!
        String configName = (String)props.getProperty(Globals.IMQ + ".instancename");
        if (configName != null && configName.length() > 0) {
            Globals.pathinit(null);
            String topname =
                Globals.JMQ_INSTANCES_HOME + File.separator + configName;

            if (!(new File(topname)).exists()) {
                System.err.println(br.getString(
                    BrokerResources.E_INSTANCE_NOT_EXIST, configName));
                System.exit(1);
            }
        }

  Globals.init(props, false, false);
        config = Globals.getConfig();
  logger = Globals.getLogger();

        // Password in passfile override broker's properties object
        parsePassfile();

        // User/Password passed in from command line option take precedence.
        // Inorder to override the User/Password we need to construct the
        // correct property based on the dbVendor value; we do this after
        // calling Globals.init() so we can determine the dbVendor value.
        String dbVendor = config.getProperty(DBManager.JDBC_PROP_PREFIX + ".dbVendor");
        String vendorPropPrefix = DBManager.JDBC_PROP_PREFIX + "." + dbVendor;
        String user = props.getProperty(DBManager.FALLBACK_USER_PROP);
        if (user != null && user.length() > 0) {
            config.put(vendorPropPrefix + ".user", user);
        }

        String pwd = props.getProperty(DBManager.FALLBACK_PWD_PROP);
        if (pwd != null && pwd.length() > 0) {
            config.put(vendorPropPrefix + ".password", pwd);
        }

  String cmd = props.getProperty(CMD_NAME);

    CommDBManager mgr = null;

  if (DELETE_SHARECCTBL_CMD.equals(cmd) ||
        RECREATE_SHARECCTBL_CMD.equals(cmd) ||
        CREATE_SHARECCTBL_CMD.equals(cmd) ||
        DUMP_SHARECCTBL_CMD.equals(cmd) ||
        BACKUP_SHARECCTBL_CMD.equals(cmd) ||
        RESTORE_SHARECCTBL_CMD.equals(cmd)) {
        if (debugSpecified) {
            System.out.println("cmd="+cmd+", use sharecc");
        }
        if (!Globals.useSharedConfigRecord()) {
            if (Globals.getHAEnabled()) {
            logger.logToAll(Logger.ERROR,
                br.getKString(BrokerResources.E_CONFIGURED_HA_MODE));
            } else {
            logger.logToAll(Logger.ERROR,
                br.getKString(BrokerResources.E_NOT_CONFIGURED_USE_SHARECC,
                Globals.NO_MASTERBROKER_PROP));
            }
            exit(1);
        }
        mgr = ShareConfigChangeDBManager.getDBManager();
    } else {
      dbmgr = DBManager.getDBManager();
        mgr = dbmgr;
    }

  // print out info messages
  String brokerid = null;
    if (mgr instanceof DBManager) {
      brokerid = ((DBManager)mgr).getBrokerID();
    }
        String url;
        if (CREATE_ALL_CMD.equals(cmd)) {
            url = mgr.getCreateDBURL();
        } else {
            url = mgr.getOpenDBURL();
        }
        if ( url == null ) {
            url = "not specified";
        }
        user = mgr.getUser();
        if ( user == null ) {
            user = "not specified";
        }

        if (!(mgr instanceof ShareConfigChangeDBManager)) {
           String msgArgs[] = { String.valueOf(JDBCStore.STORE_VERSION), brokerid,
                                url, user };
           logger.logToAll(Logger.INFO,
                           br.getString(BrokerResources.I_JDBC_STORE_INFO, msgArgs));
       } else {
           String msgArgs[] = { "",  String.valueOf(JDBCShareConfigChangeStore.SCHEMA_VERSION),
                                Globals.getClusterID(), url, user };
           logger.logToAll(Logger.INFO, br.getKString(
                           BrokerResources.I_SHARECC_JDBCSTORE_INFO, msgArgs));
       }

    if (debugSpecified) {
        System.out.println("cmd="+cmd);
    }
  if (CREATE_ALL_CMD.equals(cmd)) {
      doCreate(true); // create database as well
  } else if (CREATE_TBL_CMD.equals(cmd)) {
      doCreate(false); // just tables
  } else if (CREATE_SHARECCTBL_CMD.equals(cmd)) {
      doCreate(false, ShareConfigChangeDBManager.getDBManager());
  } else if (DELETE_TBL_CMD.equals(cmd)) {
      doDelete(props.getProperty(ARG_NAME), null);
  } else if (DELETE_SHARECCTBL_CMD.equals(cmd)) {
      doDelete(props.getProperty(ARG_NAME), ShareConfigChangeDBManager.getDBManager());
        } else if (RECREATE_TBL_CMD.equals(cmd)) {
            doRecreate();
        } else if (RECREATE_SHARECCTBL_CMD.equals(cmd)) {
            doRecreate(ShareConfigChangeDBManager.getDBManager());
        } else if (REMOVE_BKR_CMD.equals(cmd)) {
            doRemoveBkr();
        } else if (REMOVE_JMSBRIDGE_CMD.equals(cmd)) {
            doRemoveJMSBridge(props.getProperty(JMSBRIDGE_NAME_PROPERTY));
        } else if (DUMP_CMD.equals(cmd)) {
            String arg = props.getProperty(ARG_NAME);
            doDump(arg, null);
        } else if (DUMP_SHARECCTBL_CMD.equals(cmd)) {
            doDump(null, ShareConfigChangeDBManager.getDBManager());
        } else if (DROPTBL_CMD.equals(cmd)) {
            String arg = props.getProperty(ARG_NAME);
            doDropTablesByPattern(arg);
  } else if (RESET_CMD.equals(cmd)) {
      doReset();
        } else if(BACKUP_CMD.equals(cmd)) {
            doBackup();
        } else if(BACKUP_SHARECCTBL_CMD.equals(cmd)) {
            doBackupSharecc();
        } else if(RESTORE_CMD.equals(cmd)) {
            doRestore();
        } else if(RESTORE_SHARECCTBL_CMD.equals(cmd)) {
            doRestoreSharecc();
        } else if(UPGRADE_STORE_CMD.equals(cmd)) {
            doUpgrade(false);
        } else if(UPGRADE_HASTORE_CMD.equals(cmd)) {
            doUpgrade(true);
        } else if(QUERY_CMD.equals(cmd)) {
            doQuery();
  } else if (cmd == null) {
      System.out.println(br.getString(BrokerResources.E_MISSING_DBMGR_CMD));
  } else {
      System.out.println(br.getString(BrokerResources.E_INVALID_DBMGR_CMD, cmd));
  }
    }

    private static class ParserException extends Exception {
  String cmd;
  String cmdarg;
  String opt;
  String optarg;
  int reason;

  ParserException(int reason) {
        this(reason, null);
    }

  ParserException(int reason, Throwable cause) {
        super(cause);
      this.reason = reason;
  }
    }

    public static void main(String[] args) {

        int exitCode = 0;
        DBTool tool = new DBTool(true); // standalone;
  try {
      tool.doCommand(args);
  } catch (Exception e) {
            if (e instanceof BrokerException) {
                logger.logStack(Logger.ERROR, e.getMessage(), e);
            } else {
                logger.logStack(Logger.ERROR, e.getMessage(), e);
            }

            if (tool.debugSpecified) {
                e.printStackTrace();
            }
      exitCode = 1;
  } finally {
            if (tool.dbmgr != null) {
                tool.dbmgr.close(); // Free connection from connection pool
            }
        }

        System.exit(exitCode);
    }
}
TOP

Related Classes of com.sun.messaging.jmq.jmsserver.persist.jdbc.DBTool

TOP
Copyright © 2018 www.massapi.com. All rights reserved.
All source code are property of their respective owners. Java is a trademark of Sun Microsystems, Inc and owned by ORACLE Inc. Contact coftware#gmail.com.