Package er.extensions.migration

Source Code of er.extensions.migration.ERXMigration

package er.extensions.migration;

import java.io.UnsupportedEncodingException;

import org.apache.log4j.Logger;

import com.webobjects.eoaccess.EOAdaptorChannel;
import com.webobjects.eoaccess.EOModel;
import com.webobjects.eocontrol.EOEditingContext;
import com.webobjects.foundation.NSArray;
import com.webobjects.foundation.NSBundle;
import com.webobjects.foundation._NSStringUtilities;

import er.extensions.foundation.ERXProperties;
import er.extensions.jdbc.ERXJDBCUtilities;

/**
* <p>Convenience superclass for Migration classes. Checks for corresponding sql files name
* "ClassnameX_Upgrade.migration" and "ClassnameX_Downgrade.migration" where
* "Classname" is the classname of the migration class. The files have to to be
* in a corresponding bundle. Implement "migrationBundleName" to return the
* correct name of the bundle.</p>
*
* <p>This makes migrations easier as you only have to create a new Java class according to the
* migration naming conventions, inherit from this class and put your SQL in a properly
* named text file (or more than one file, if you use database specific migrations).</p>
*
* <p>If you need database specific migrations use:
*
* <blockquote><code>er.extensions.migration.ERXMigration.useDatabaseSpecificMigrations=true</code></blockquote>
*
* in your Properties. The default is not to use database specific migrations. A filename
* for a database specific migration is then, for example, <code>ClassnameX_FrontBase_Upgrade.migration</code> or
* <code>ClassnameX_Postgresql_Upgrade.migration</code>.
*
* <p>For the database specific part of the filename, the databaseProductName as from the JDBC
* adaptor is used. So make sure, you're using the correct filename. The migration will throw
* an exception if the appropriate migration textfile can't be found.</p>
*
* @author cug
*/
public abstract class ERXMigration implements IERXMigration {

  /**
   * Logging support
   */
  private Logger log = Logger.getLogger(ERXMigration.class.getName());
 
  private Boolean _useDatabaseSpecificMigrations;

  /**
   * Override the global application preference on per-database migrations.
   *
   * @param useDatabaseSpecificMigrations if true, database-specific migrations will be used
   */
  public ERXMigration(boolean useDatabaseSpecificMigrations) {
    _useDatabaseSpecificMigrations = Boolean.valueOf(useDatabaseSpecificMigrations);
  }
 
  public ERXMigration() {
  }
 
  /**
   * No dependencies
   */
  public NSArray<ERXModelVersion> modelDependencies() {
    return null;
  }

  /**
   * Checks for a corresponding downgrade file which is performed as a raw SQL action
   */
  public void downgrade(EOEditingContext editingContext, EOAdaptorChannel channel, EOModel model) throws Throwable {
    String sqlString = null;
    if (useDatabaseSpecificMigrations()) {
      sqlString = getSQLForMigration(getClass().getSimpleName() + "_" + ERXJDBCUtilities.databaseProductName(channel) + "_Downgrade.migration");
    }
    else {
      sqlString = getSQLForMigration(getClass().getSimpleName() + "_Downgrade.migration");
    }

    if (sqlString != null) {
      log.info("Applying migration for: " + getClass().getName());
      ERXJDBCUtilities.executeUpdateScript(channel, sqlString);
    }
    else {
      if (useDatabaseSpecificMigrations()) {
        throw new ERXMigrationFailedException("No downgrade for migration: " + getClass().getName() + "found for database: " + ERXJDBCUtilities.databaseProductName(channel));
      }
      throw new ERXMigrationFailedException("No downgrade for migration: " + getClass().getName());
    }

  }

  /**
   * Checks for a corresponding upgrade file which is performed as a raw SQL action
   */
  public void upgrade(EOEditingContext editingContext, EOAdaptorChannel channel, EOModel model) throws Throwable {

    String sqlString = null;
    if (useDatabaseSpecificMigrations()) {
      sqlString = getSQLForMigration(getClass().getSimpleName() + "_" + ERXJDBCUtilities.databaseProductName(channel) + "_Upgrade.migration");
    }
    else {
      sqlString = getSQLForMigration(getClass().getSimpleName() + "_Upgrade.migration");
    }

    if (sqlString != null) {
      log.info("Applying migration for: " + getClass().getName());
      ERXJDBCUtilities.executeUpdateScript(channel, sqlString);
    }
    else {
      if (useDatabaseSpecificMigrations()) {
        throw new ERXMigrationFailedException("No upgrade for migration: " + getClass().getName() + " found for database: " + ERXJDBCUtilities.databaseProductName(channel));
      }
      throw new ERXMigrationFailedException("No upgrade for migration: " + getClass().getName() + " found.");
    }
  }

  /**
   * Checks in the current bundle for migration files corresponding to this classes name
   *
   * @param migrationName
   * @return SQL string
   */
  protected String getSQLForMigration(String migrationName) {
    NSBundle bundle;
    String migrationBundleName = migrationBundleName();
    if (migrationBundleName == null) {
      bundle = NSBundle.bundleForClass(getClass());
    }
    else {
      bundle = NSBundle.bundleForName(migrationBundleName());
      if (bundle == null) {
        bundle = NSBundle._appBundleForName(migrationBundleName());
      }
    }
    NSArray<String> resourcePaths = bundle.resourcePathsForResources("migration", null);

    if (resourcePaths != null) {
      for (String currentPath : resourcePaths) {
        if (currentPath.endsWith(migrationName)) {
          try {
            return new String(bundle.bytesForResourcePath(currentPath), _NSStringUtilities.UTF8_ENCODING);
          }
          catch (UnsupportedEncodingException e) {
            log.error(e, e);
          }
        }
      }
    }
    return null;
  }

  /**
   * The name to create the NSBundle for the current bundle, defaults to the
   * bundle that contains the migration class.
   *
   * @return <code>null</code>
   */
  protected String migrationBundleName() {
    return null;
  }

  protected boolean useDatabaseSpecificMigrations() {
    if (_useDatabaseSpecificMigrations == null) {
      _useDatabaseSpecificMigrations = Boolean.valueOf(
          ERXProperties.booleanForKeyWithDefault("er.extensions.migration.ERXMigration.useDatabaseSpecificMigrations", false));
    }
    return _useDatabaseSpecificMigrations.booleanValue();
  }

}
TOP

Related Classes of er.extensions.migration.ERXMigration

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.