Package com.dotmarketing.startup

Source Code of com.dotmarketing.startup.StartupTasksExecutor

package com.dotmarketing.startup;

import java.sql.Connection;
import java.sql.Date;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.sql.Statement;
import java.util.Calendar;
import java.util.Comparator;
import java.util.List;

import com.dotmarketing.common.reindex.ReindexThread;
import com.dotmarketing.db.DbConnectionFactory;
import com.dotmarketing.db.HibernateUtil;
import com.dotmarketing.exception.DotDataException;
import com.dotmarketing.exception.DotRuntimeException;
import com.dotmarketing.util.Config;
import com.dotmarketing.util.Logger;
import com.dotmarketing.util.TaskLocatorUtil;

import com.dotcms.repackage.edu.emory.mathcs.backport.java.util.Collections;

public class StartupTasksExecutor {

 
  private static StartupTasksExecutor executor;

  private String pgLock = "lock table db_version;";
  private String myLock = "lock table db_version write;";
  private String oraLock = "LOCK TABLE DB_VERSION IN EXCLUSIVE MODE";
  private String msLock = "SELECT * FROM db_version WITH (XLOCK)";
  private String h2Lock = "SELECT * FROM db_version FOR UPDATE";

  private String pgCommit = "commit;";
  private String myCommit = "unlock tables";
  private String oraCommit = "COMMIT";
  private String msCommit = "COMMIT";
  private String h2Commit = "COMMIT";

  private String pgCreate = "CREATE TABLE db_version (db_version integer NOT NULL, date_update timestamp with time zone NOT NULL, CONSTRAINT db_version_pkey PRIMARY KEY (db_version));";
  private String myCreate = "CREATE TABLE `db_version` (`db_version` INTEGER UNSIGNED NOT NULL,`date_update` DATETIME NOT NULL, PRIMARY KEY (`db_version`))";
  private String oraCreate = "CREATE TABLE \"DB_VERSION\" ( \"DB_VERSION\" INTEGER NOT NULL , \"DATE_UPDATE\" TIMESTAMP NOT NULL, PRIMARY KEY (\"DB_VERSION\") )";
  private String msCreate ="CREATE TABLE db_version (  db_version int NOT NULL , date_update datetime NOT NULL, PRIMARY KEY (db_version) )";
  private String h2Create = "CREATE TABLE db_version (db_version integer NOT NULL, date_update timestamp NOT NULL, CONSTRAINT db_version_pkey PRIMARY KEY (db_version))";
 
  private String pgSelect = "SELECT max(db_version) AS db_version FROM db_version";
  private String mySelect = "SELECT max(db_version) AS db_version FROM db_version";
  private String oraSelect = "SELECT max(db_version) AS db_version FROM db_version";
  private String msSelect = "SELECT max(db_version) AS db_version FROM db_version";
  private String h2Select = "SELECT max(db_version) AS db_version FROM db_version";

//  private String pgSelect = "SELECT * FROM db_version ORDER BY db_version DESC LIMIT 1;";
//  private String mySelect = "SELECT * FROM db_version ORDER BY db_version DESC LIMIT 1;";
//  private String oraSelect = "SELECT * FROM db_version WHERE rownum<=1 ORDER BY db_version DESC";
 
  private String lock;
  private String commit;
  private String create;
  private String select;


 
 
  private StartupTasksExecutor() {

  }

  public static StartupTasksExecutor getInstance() {
    if (executor == null)
      executor = new StartupTasksExecutor();
    return executor;
  }

  /**
   * Check which database we're using, and select the apropiate SQL. In a
   * different method to avoid further clutter
   */
  private void setupSQL() {
    if (DbConnectionFactory.isPostgres()) {
      lock = pgLock;
      commit = pgCommit;
      create = pgCreate;
      select = pgSelect;
    }
    else if (DbConnectionFactory.isMySql()) {
      lock = myLock.toLowerCase();
      commit = myCommit.toLowerCase();
      create = myCreate.toLowerCase();
      select = mySelect.toLowerCase();
    }
   
    else if (DbConnectionFactory.isOracle()) {
      lock = oraLock;
      commit = oraCommit;
      create = oraCreate;
      select = oraSelect;
    }
   
    else if (DbConnectionFactory.isMsSql()) {
      lock = msLock;
      commit = msCommit;
      create = msCreate;
      select = msSelect;
    }
   
    else if(DbConnectionFactory.isH2()) {
        lock = h2Lock;
        commit = h2Commit;
        create = h2Create;
        select = h2Select;
    }

  }

  public void executeUpgrades(String appLocation) throws DotDataException, DotRuntimeException {

    List<Class<?>> runOnce;
    List<Class<?>> runAlways;
    Comparator<Class<?>> comparator = new Comparator<Class<?>>() {
      public int compare(Class<?> o1, Class<?> o2) {
        return o1.getName().compareTo(o2.getName());
      }
    };
    try {
      runOnce = TaskLocatorUtil.getStartupRunOnceTaskClasses();
      runAlways = TaskLocatorUtil.getStartupRunAlwaysTaskClasses();
    } catch (Exception e) {
      throw new DotRuntimeException(e.getMessage(), e);
    }
    Collections.sort(runOnce, comparator);
    Collections.sort(runAlways, comparator);
    Logger.debug(this.getClass(), "Locking db_version table");
    setupSQL();
    //Integer currentVersion = null;
    PreparedStatement update = null;
    Statement s = null;
    ResultSet rs = null;
    Connection conn = null;
    try {
      conn = DbConnectionFactory.getDataSource().getConnection();

      conn.setAutoCommit(false);
      s = conn.createStatement();
      update = conn
          .prepareStatement("INSERT INTO db_version (db_version,date_update) VALUES (?,?)");
      s.execute(lock);
      rs = s
          .executeQuery(select);
      rs.next();
      Config.DB_VERSION = rs.getInt("db_version");
    } catch (SQLException e) {
      // Maybe the table doesn't exist?
      Logger.debug(this.getClass(), "Trying to create db_version table");
      try {
        conn.rollback();
        if(DbConnectionFactory.isMySql()){
          s.execute("SET storage_engine=INNODB");
        }
        s.execute(create);
        if(update==null) {
            // looks like H2 do an early table name check
            update = conn.prepareStatement("INSERT INTO db_version (db_version,date_update) VALUES (?,?)");
        }
        update.setInt(1, 0);
        Date date = new Date(Calendar.getInstance().getTimeInMillis());
        update.setDate(2, date);
        update.execute();
        conn.commit();

        Logger
            .debug(this.getClass(),
                "Table db_version created.  Trying to lock db_table again.");
        s.execute(lock);
        rs = s
            .executeQuery(select);

        rs.next();
        Config.DB_VERSION = rs.getInt("db_version");

      } catch (SQLException e2) {
        Logger.fatal(this.getClass(),
            "Locking of db_version table failed: "
                + e2.getMessage());
        throw new DotRuntimeException(
            "Locking of db_version table failed: "
                + e2.getMessage(), e2);
      }

    }
    Logger.debug(this.getClass(), "Locking db_version succeeded");

    boolean firstTimeStart = false;
    String name = null;
    try {
      Logger.info(this, "Starting startup tasks.");
      HibernateUtil.startTransaction();

      for (Class<?> c : runAlways) {
        name = c.getCanonicalName();
        name = name.substring(name.lastIndexOf(".") + 1);
        if (StartupTask.class.isAssignableFrom(c)) {
          StartupTask task;
          try {
            task = (StartupTask) c.newInstance();
          } catch (Exception e) {
            throw new DotRuntimeException(e.getMessage(), e);
          }
          HibernateUtil.startTransaction();
          if (task.forceRun()) {
            HibernateUtil.commitTransaction();
            HibernateUtil.startTransaction();
            Logger.info(this, "Running: " + name);
            task.executeUpgrade();
            if(name.equals("Task00001LoadSchema")){
              firstTimeStart = true;
            }
          } else {
            Logger.info(this, "Not running: " + name);
          }
          HibernateUtil.commitTransaction();
        }
      }
      Logger.info(this, "Finishing startup tasks.");
    } catch (Exception e) {
      HibernateUtil.rollbackTransaction();
      Logger.fatal(this, "Unable to execute the upgrade task : " + name, e);
    } finally {
      // This will commit the changes and close the connection
      HibernateUtil.closeSession();
      try {
          update.close();
//          conn.close();
      } catch(Exception exx) { /* Ignore this */ }
    }

    Logger.info(this, "Starting upgrade tasks.");

    Logger.info(this, "Database version: " + Config.DB_VERSION);

    name = null;
    //HibernateUtil.startTransaction();
    try {
      if(runOnce.size() > 0)
        ReindexThread.stopThread();
      for (Class<?> c : runOnce) {
        name = c.getCanonicalName();
        name = name.substring(name.lastIndexOf(".") + 1);
        String id = name.substring(4, 9);
        try {
          int taskId = Integer.parseInt(id);
          if (StartupTask.class.isAssignableFrom(c)
              && taskId > Config.DB_VERSION) {
            StartupTask task;
            try {
              task = (StartupTask) c.newInstance();
            } catch (Exception e) {
              throw new DotRuntimeException(e.getMessage(), e);
            }
            //HibernateUtil.startTransaction();

            if (!firstTimeStart && task.forceRun()) {
              HibernateUtil.commitTransaction();
              HibernateUtil.startTransaction();
              Logger.info(this, "Running: " + name);
              if(name.equals("Task00250UpdateMysqlTablesToINNODB")){
                s = conn.createStatement();
                s.execute(commit);
                task.executeUpgrade();
                s = conn.createStatement();
                s.execute(lock);
              }else{
                task.executeUpgrade();
              }
            }
            // Nothing to execute, or the task ran ok so bump
            // the db version.
            try {
//                conn = DbConnectionFactory.getDataSource().getConnection();
                conn.setAutoCommit(true);
                update = conn.prepareStatement("INSERT INTO db_version (db_version,date_update) VALUES (?,?)");
                update.setInt(1, taskId);
                Date date = new Date(Calendar.getInstance().getTimeInMillis());
                update.setDate(2, date);
                update.execute();
            }
            finally {
//              s.execute(commit);
                update.close();
//                conn.close();
            }

            Logger.info(this, "Database upgraded to version: "
                + taskId);
            HibernateUtil.commitTransaction();

          }
        } catch (NumberFormatException e) {
          Logger
              .error(
                  this,
                  "Class "
                      + name
                      + " has invalid name or shouldn't be in the tasks package.");

        }
      }
      //if(runOnce.size() > 0)
        //ReindexThread.startThread(Config.getIntProperty("REINDEX_THREAD_SLEEP", 500), Config.getIntProperty("REINDEX_THREAD_INIT_DELAY", 5000));
     
    } catch (Exception e) {
      HibernateUtil.rollbackTransaction();
      Logger.fatal(this, "Unable to execute the upgrade task : " + name, e);
      throw new DotDataException("Unable to execute startup task : ",e);
    } finally {
      // This will commit the changes and close the connection
      HibernateUtil.closeSession();
     
      // DOTCMS-4352
      try {
        if(conn != null && !conn.isClosed()){
          Statement s1 = conn.createStatement();
          if(DbConnectionFactory.isMySql()){
            s1.execute(commit);
          }
          if(!conn.getAutoCommit()){
            conn.commit();
          }
          conn.close();
        }
      } catch (Exception e) {
        Logger.debug(StartupTasksExecutor.class, "Exception: "
            + e.getMessage(), e);
        throw new DotDataException(
            "Exception finishing upgrade tasks: " + e.getMessage(),
            e);
      }
      Logger.info(this, "Finishing upgrade tasks.");
    }

  }



}
TOP

Related Classes of com.dotmarketing.startup.StartupTasksExecutor

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.