269 lines
8.9 KiB
Java
Executable File
269 lines
8.9 KiB
Java
Executable File
/*
|
|
* Copyright (C) 2004 Red Hat Inc. All Rights Reserved.
|
|
*
|
|
* This library is free software; you can redistribute it and/or
|
|
* modify it under the terms of the GNU Lesser General Public License
|
|
* as published by the Free Software Foundation; either version 2.1 of
|
|
* the License, or (at your option) any later version.
|
|
*
|
|
* This library 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
|
|
* Lesser General Public License for more details.
|
|
*
|
|
* You should have received a copy of the GNU Lesser General Public
|
|
* License along with this library; if not, write to the Free Software
|
|
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
|
*
|
|
*/
|
|
package com.arsdigita.packaging;
|
|
|
|
import com.arsdigita.runtime.RuntimeConfig;
|
|
import com.arsdigita.runtime.SchemaLoader;
|
|
import com.arsdigita.util.Assert;
|
|
import com.arsdigita.util.Classes;
|
|
import com.arsdigita.util.StringUtils;
|
|
import com.arsdigita.util.UncheckedWrapperException;
|
|
import com.arsdigita.util.jdbc.Connections;
|
|
import com.arsdigita.xml.XML;
|
|
import java.io.InputStream;
|
|
import java.lang.reflect.InvocationTargetException;
|
|
import java.lang.reflect.Method;
|
|
import java.sql.Connection;
|
|
import java.sql.SQLException;
|
|
import java.util.ArrayList;
|
|
import java.util.Iterator;
|
|
import java.util.LinkedList;
|
|
import java.util.List;
|
|
import org.apache.commons.cli.CommandLine;
|
|
import org.apache.commons.cli.MissingOptionException;
|
|
import org.apache.commons.cli.OptionBuilder;
|
|
import org.apache.commons.cli.Options;
|
|
import org.apache.commons.cli.ParseException;
|
|
import org.apache.commons.cli.PosixParser;
|
|
import org.xml.sax.Attributes;
|
|
import org.xml.sax.helpers.DefaultHandler;
|
|
|
|
/**
|
|
* Upgrade
|
|
*
|
|
* @author Justin Ross <jross@redhat.com>
|
|
* @version $Id: Upgrade.java 736 2005-09-01 10:46:05Z sskracic $
|
|
*/
|
|
class Upgrade extends Command {
|
|
|
|
private static final Options s_options = getOptions();
|
|
|
|
private String m_from;
|
|
private String m_to;
|
|
private final List m_scripts;
|
|
|
|
static {
|
|
s_options.addOption
|
|
(OptionBuilder
|
|
.isRequired()
|
|
.hasArg()
|
|
.withLongOpt("from-version")
|
|
.withDescription("Upgrade from version VERSION")
|
|
.create());
|
|
s_options.addOption
|
|
(OptionBuilder
|
|
.isRequired()
|
|
.hasArg()
|
|
.withLongOpt("to-version")
|
|
.withDescription("Upgrade to version VERSION")
|
|
.create());
|
|
s_options.addOption
|
|
(OptionBuilder
|
|
.hasArg()
|
|
.withLongOpt("parameters")
|
|
.withDescription("Parameters to pass to upgrade scripts")
|
|
.create());
|
|
}
|
|
|
|
public Upgrade() {
|
|
super("upgrade",
|
|
"Upgrade a CCM package");
|
|
|
|
m_scripts = new ArrayList();
|
|
}
|
|
|
|
public boolean run(final String[] args) {
|
|
final CommandLine line;
|
|
|
|
if (args.length == 0) {
|
|
usage(s_options, System.err, "PACKAGE-KEY");
|
|
return false;
|
|
}
|
|
|
|
try {
|
|
line = new PosixParser().parse(s_options, args);
|
|
} catch (MissingOptionException moe) {
|
|
System.err.println("Missing option " + moe.getMessage());
|
|
usage(s_options, System.err, "PACKAGE-KEY");
|
|
return false;
|
|
} catch (ParseException e) {
|
|
System.err.println(e.getMessage());
|
|
return false;
|
|
}
|
|
|
|
if (line.hasOption("usage") || line.hasOption("help")) {
|
|
usage(s_options, System.out, "PACKAGE-KEY");
|
|
return true;
|
|
}
|
|
|
|
final String home = System.getProperty("ccm.home");
|
|
|
|
if (home == null) {
|
|
System.err.println("ccm.home system property is undefined");
|
|
return false;
|
|
}
|
|
|
|
final String[] keys = line.getArgs();
|
|
|
|
if (keys.length == 0 || keys.length > 1) {
|
|
usage(s_options, System.err, "PACKAGE-KEY");
|
|
return false;
|
|
}
|
|
|
|
final String key = keys[0];
|
|
m_from = line.getOptionValue("from-version");
|
|
m_to = line.getOptionValue("to-version");
|
|
|
|
if (m_from == null || m_to == null) {
|
|
usage(s_options, System.err, "PACKAGE-KEY");
|
|
return false;
|
|
}
|
|
|
|
final String spec = key + ".upgrade";
|
|
|
|
final InputStream in = Thread.currentThread().getContextClassLoader
|
|
().getResourceAsStream(spec);
|
|
|
|
if (in == null) {
|
|
System.err.println("Cannot find " + spec);
|
|
return false;
|
|
}
|
|
|
|
XML.parse(in, new Parser());
|
|
|
|
if (m_scripts.isEmpty()) {
|
|
System.err.println("No appropriate upgrades found; make sure " +
|
|
"that your 'to' and 'from' versions match " +
|
|
"the intended upgrade exactly");
|
|
return false;
|
|
}
|
|
|
|
Iterator iter = m_scripts.iterator();
|
|
|
|
while (iter.hasNext()) {
|
|
final String[] parts = (String[]) iter.next();
|
|
final String classname = parts[0];
|
|
final String sql = parts[1];
|
|
|
|
if (classname != null) {
|
|
final Class clacc = Classes.loadClass(classname);
|
|
|
|
System.out.println("Running Java upgrade " + clacc);
|
|
|
|
final Method method;
|
|
|
|
try {
|
|
method = clacc.getMethod
|
|
("main", new Class[] {String[].class});
|
|
} catch (NoSuchMethodException nsme) {
|
|
throw new UncheckedWrapperException(nsme);
|
|
} catch (SecurityException se) {
|
|
throw new UncheckedWrapperException(se);
|
|
}
|
|
|
|
String[] params = line.getOptionValues("parameters");
|
|
LinkedList ll = new LinkedList();
|
|
if (params != null) {
|
|
for (int i = 0; i < params.length; i++) {
|
|
String[] split = StringUtils.split(params[i],',');
|
|
for (int j = 0; j < split.length; j++) {
|
|
ll.add(split[j]);
|
|
}
|
|
}
|
|
}
|
|
try {
|
|
method.invoke(null, new Object[] {ll.toArray(new String[] {})});
|
|
} catch (IllegalAccessException iae) {
|
|
throw new UncheckedWrapperException(iae);
|
|
} catch (InvocationTargetException ite) {
|
|
throw new UncheckedWrapperException(ite);
|
|
}
|
|
} else if (sql != null) {
|
|
final SchemaLoader loader = new SchemaLoader(sql);
|
|
|
|
System.out.println("Running SQL upgrade " + loader + ", " +
|
|
"loaded from the classpath");
|
|
|
|
final Connection conn = Connections.acquire
|
|
(RuntimeConfig.getConfig().getJDBCURL());
|
|
|
|
loader.run(conn);
|
|
|
|
try {
|
|
conn.close();
|
|
} catch (SQLException e) {
|
|
throw new UncheckedWrapperException(e);
|
|
}
|
|
} else {
|
|
throw new IllegalStateException();
|
|
}
|
|
}
|
|
|
|
return true;
|
|
}
|
|
|
|
private class Parser extends DefaultHandler {
|
|
private String m_version;
|
|
|
|
public final void startElement(final String uri,
|
|
final String lname,
|
|
final String qname,
|
|
final Attributes attrs) {
|
|
if (lname.equals("version")) {
|
|
final String from = attrs.getValue(uri, "from");
|
|
final String to = attrs.getValue(uri, "to");
|
|
|
|
Assert.exists(from);
|
|
Assert.exists(to);
|
|
|
|
m_version = from + "/" + to;
|
|
}
|
|
|
|
if (lname.equals("script")) {
|
|
Assert.exists(m_version);
|
|
Assert.exists(m_from);
|
|
Assert.exists(m_to);
|
|
|
|
if (m_version.equals(m_from + "/" + m_to)) {
|
|
final String classname = attrs.getValue(uri, "class");
|
|
final String sql = attrs.getValue(uri, "sql");
|
|
|
|
if (classname == null && sql == null
|
|
|| classname != null && sql != null) {
|
|
throw new IllegalArgumentException
|
|
("The script element must have a 'class' " +
|
|
"argument or a 'sql' argument; it may not " +
|
|
"have both");
|
|
}
|
|
|
|
m_scripts.add(new String[] {classname, sql});
|
|
}
|
|
}
|
|
}
|
|
|
|
public final void endElement(final String uri,
|
|
final String lname,
|
|
final String qname) {
|
|
if (qname.equals("version")) {
|
|
m_version = null;
|
|
}
|
|
}
|
|
}
|
|
}
|