/*
* RHQ Management Platform
* Copyright (C) 2005-2008 Red Hat, Inc.
* All rights reserved.
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation version 2 of the License.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
*/
package org.rhq.core.db.ant.dbupgrade;
import java.sql.Connection;
import java.sql.SQLException;
import java.util.ArrayList;
import java.util.List;
import mazz.i18n.Msg;
import org.apache.tools.ant.BuildException;
import org.apache.tools.ant.Task;
import org.apache.tools.ant.TaskContainer;
import org.apache.tools.ant.UnknownElement;
import org.rhq.core.db.ant.DbAntI18NFactory;
import org.rhq.core.db.ant.DbAntI18NResourceKeys;
/**
* An ANT task that defines a single, specific upgrade step that upgrades the schema to a particular
* {@link SchemaVersion version}. Each {@link SchemaSpec} contains child {@link SchemaSpecTask tasks} that define the
* actual work that needs to get done to perform this upgrade step.
*/
public class SchemaSpec extends Task implements TaskContainer, Comparable {
private static final Msg MSG = DbAntI18NFactory.getMsg();
private String versionString = null;
private SchemaVersion version = null;
private List<SchemaSpecTask> schemaSpecTasks = new ArrayList<SchemaSpecTask>();
private Connection conn = null;
private DBUpgrader upgrader = null;
/**
* Creates a new {@link SchemaSpec} object.
*
* @param parent
*/
public SchemaSpec(DBUpgrader parent) {
}
/**
* This is the version to which this upgrade step takes the schema to. After this object's child tasks are run, the
* schema is considered to be at this version.
*
* @param version
*/
public void setVersion(String version) {
versionString = version;
}
/**
* Returns the schema version of this object. This is the version to which this upgrade step takes the schema to.
* After this object's child tasks are run, the schema is considered to be at this version.
*
* @return the version
*
* @throws BuildException if the version string was invalid
*/
public SchemaVersion getVersion() throws BuildException {
if (version == null) {
if (versionString == null) {
throw new BuildException(MSG.getMsg(DbAntI18NResourceKeys.MISSING_SCHEMA_SPEC_VERSION));
}
try {
version = new SchemaVersion(versionString);
} catch (IllegalArgumentException e) {
throw new BuildException(e.getMessage(), e);
}
}
return version;
}
/**
* Initializes this object with a database connection and a DBUpgrade task object.
*
* @param db_conn
* @param db_upgrader
*/
public void initialize(Connection db_conn, DBUpgrader db_upgrader) {
this.conn = db_conn;
this.upgrader = db_upgrader;
}
/**
* Adds the given child task to the list of tasks. The task must be of type {@link SchemaSpecTask}.
*
* @param schema_spec_task
*
* @throws BuildException if the task is not of the expected type
*/
public void addTask(Task schema_spec_task) {
if (schema_spec_task instanceof SchemaSpecTask) {
schemaSpecTasks.add((SchemaSpecTask) schema_spec_task);
} else if (schema_spec_task instanceof UnknownElement) {
((UnknownElement) schema_spec_task).maybeConfigure();
schema_spec_task = ((UnknownElement) schema_spec_task).getTask();
if ((schema_spec_task != null) && (schema_spec_task instanceof SchemaSpecTask)) {
schemaSpecTasks.add((SchemaSpecTask) schema_spec_task);
} else {
throw new BuildException(MSG.getMsg(DbAntI18NResourceKeys.CANNOT_ADD_SCHEMA_SPEC_TASK, schema_spec_task
.getTaskName(), SchemaSpecTask.class));
}
}
}
/**
* Executes each task defined in this schema spec.
*
* @throws BuildException
*/
public void execute() throws BuildException {
validateAttributes();
for (SchemaSpecTask sst : schemaSpecTasks) {
try {
log(MSG.getMsg(DbAntI18NResourceKeys.EXECUTING_SCHEMA_SPEC_TASK, sst.getClass(), getVersion()));
sst.initialize(conn, upgrader);
// to be able to ignore a failed ddl update we need to execute that
// update in its own trans, because the failure may mark the trans
// for rollback. So, commit ant transaction in progress.
if (sst.isIgnoreError()) {
try {
conn.commit();
} catch (SQLException e) {
log("commit() exception: " + e.toString());
}
}
sst.execute();
} catch (Exception e) {
String msg = MSG.getMsg(DbAntI18NResourceKeys.ERROR_EXECUTING_SCHEMA_SPEC_TASK, sst.getClass()
.getName(), getVersion(), e);
if (!sst.isIgnoreError()) {
throw new BuildException(msg, e);
} else {
// rollback the trans so the next statement starts a new trans
try {
conn.rollback();
} catch (SQLException e2) {
log("rollback() exception: " + e2.toString());
}
log(msg);
}
}
}
}
/**
* Makes sure the schema spec version string is valid.
*
* @throws BuildException
*/
private void validateAttributes() throws BuildException {
getVersion();
}
/**
* @see java.lang.Object#toString()
*/
public String toString() {
return "SchemaSpec[" + getVersion() + "]";
}
/**
* Compares the versions.
*
* @see java.lang.Comparable#compareTo(java.lang.Object)
*/
public int compareTo(Object o) {
if (o instanceof SchemaSpec) {
SchemaSpec ss = (SchemaSpec) o;
return getVersion().compareTo(ss.getVersion());
}
throw new IllegalArgumentException(MSG.getMsg(DbAntI18NResourceKeys.CANNOT_COMPARE_NON_SCHEMA_SPEC, o));
}
}