diff --git a/server/src/com/cloud/upgrade/dao/VersionDao.java b/server/src/com/cloud/upgrade/dao/VersionDao.java new file mode 100644 index 00000000000..5db926eda7d --- /dev/null +++ b/server/src/com/cloud/upgrade/dao/VersionDao.java @@ -0,0 +1,24 @@ +/** + * Copyright (C) 2010 Cloud.com, Inc. All rights reserved. + * + * This software is licensed under the GNU General Public License v3 or later. + * + * It 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, either version 3 of the License, or any later version. + * 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, see . + * + */ +package com.cloud.upgrade.dao; + +import com.cloud.utils.db.GenericDao; + +public interface VersionDao extends GenericDao { + +} diff --git a/server/src/com/cloud/upgrade/dao/VersionDaoImpl.java b/server/src/com/cloud/upgrade/dao/VersionDaoImpl.java new file mode 100644 index 00000000000..67bfe8b9e90 --- /dev/null +++ b/server/src/com/cloud/upgrade/dao/VersionDaoImpl.java @@ -0,0 +1,86 @@ +/** + * Copyright (C) 2010 Cloud.com, Inc. All rights reserved. + * + * This software is licensed under the GNU General Public License v3 or later. + * + * It 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, either version 3 of the License, or any later version. + * 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, see . + * + */ +package com.cloud.upgrade.dao; + +import java.sql.Connection; +import java.sql.PreparedStatement; +import java.sql.ResultSet; +import java.sql.SQLException; +import java.util.List; +import java.util.Map; + +import javax.ejb.Local; +import javax.naming.ConfigurationException; + +import com.cloud.upgrade.dao.VersionVO.Step; +import com.cloud.utils.db.DB; +import com.cloud.utils.db.Filter; +import com.cloud.utils.db.GenericDaoBase; +import com.cloud.utils.db.GenericSearchBuilder; +import com.cloud.utils.db.SearchCriteria; +import com.cloud.utils.db.SearchCriteria.Func; +import com.cloud.utils.db.SearchCriteria.Op; +import com.cloud.utils.db.Transaction; +import com.cloud.utils.exception.CloudRuntimeException; + +@Local(value=VersionDao.class) +public class VersionDaoImpl extends GenericDaoBase implements VersionDao { + final GenericSearchBuilder CurrentVersionSearch; + protected VersionDaoImpl() { + super(); + + CurrentVersionSearch = createSearchBuilder(String.class); + CurrentVersionSearch.select(null, Func.FIRST, CurrentVersionSearch.entity().getVersion()); + CurrentVersionSearch.and("step", CurrentVersionSearch.entity().getStep(), Op.EQ); + + } + + @DB + protected String getCurrentVersion() { + Transaction txn = Transaction.currentTxn(); + try { + Connection conn = txn.getConnection(); + + PreparedStatement pstmt = conn.prepareStatement("SHOW TABLES LIKE 'VERSION'"); + ResultSet rs = pstmt.executeQuery(); + if (rs.getRow() == 0) { + return "2.1.7"; + } + pstmt.close(); + rs.close(); + } catch (SQLException e) { + throw new CloudRuntimeException("Unable to get the current version", e); + } + SearchCriteria sc = CurrentVersionSearch.create(); + + sc.setParameters("step", Step.Complete); + Filter filter = new Filter(VersionVO.class, "updated", true, 0l, 1l); + + List vers = customSearch(sc, filter); + return vers.get(0); + } + + + @Override + public boolean configure(String name, Map params) throws ConfigurationException { + super.configure(name, params); + + + return true; + } +} diff --git a/server/src/com/cloud/upgrade/dao/VersionVO.java b/server/src/com/cloud/upgrade/dao/VersionVO.java new file mode 100644 index 00000000000..ebfd2431cd6 --- /dev/null +++ b/server/src/com/cloud/upgrade/dao/VersionVO.java @@ -0,0 +1,81 @@ +/** + * Copyright (C) 2010 Cloud.com, Inc. All rights reserved. + * + * This software is licensed under the GNU General Public License v3 or later. + * + * It 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, either version 3 of the License, or any later version. + * 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, see . + * + */ +package com.cloud.upgrade.dao; + +import java.util.Date; + +import javax.persistence.Column; +import javax.persistence.Entity; +import javax.persistence.EnumType; +import javax.persistence.Enumerated; +import javax.persistence.Table; +import javax.persistence.Temporal; +import javax.persistence.TemporalType; + +import com.cloud.utils.component.ComponentLocator; +import com.cloud.utils.exception.CloudRuntimeException; + +@Entity +@Table(name="version") +public class VersionVO { + public enum Step { + Dump, + Upgrade, + Cleanup, + Complete + }; + + @Column(name="id") + long id; + + @Column(name="version") + String version; + + @Temporal(TemporalType.TIMESTAMP) + @Column(name="updated") + Date updated; + + @Enumerated(value=EnumType.STRING) + @Column(name="") + Step step; + + public VersionVO() { + version = ComponentLocator.class.getPackage().getImplementationVersion(); + if (version == null) { + throw new CloudRuntimeException("Uanble to get the implementation version of the package"); + } + updated = new Date(); + } + + public long getId() { + return id; + } + + public String getVersion() { + return version; + } + + public Date getUpdated() { + return updated; + } + + public Step getStep() { + return step; + } + +} diff --git a/server/test/com/cloud/upgrade/dao/VersionDaoImplTest.java b/server/test/com/cloud/upgrade/dao/VersionDaoImplTest.java new file mode 100644 index 00000000000..884e433558b --- /dev/null +++ b/server/test/com/cloud/upgrade/dao/VersionDaoImplTest.java @@ -0,0 +1,54 @@ +/** + * Copyright (C) 2010 Cloud.com, Inc. All rights reserved. + * + * This software is licensed under the GNU General Public License v3 or later. + * + * It 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, either version 3 of the License, or any later version. + * 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, see . + * + */ +package com.cloud.upgrade.dao; + + +import junit.framework.TestCase; + +import org.junit.After; +import org.junit.Before; + +import com.cloud.utils.component.ComponentLocator; + +public class VersionDaoImplTest extends TestCase { + + VersionDaoImpl _dao; + + /** + * @throws java.lang.Exception + */ + @Before + public void setUp() throws Exception { + _dao = ComponentLocator.inject(VersionDaoImpl.class); + } + + /** + * @throws java.lang.Exception + */ + @After + public void tearDown() throws Exception { + _dao = null; + } + + public void testGetCurrentVersion() { + String version = _dao.getCurrentVersion(); + + assert (version.equals("2.1.7")); + } + +} diff --git a/tools/junit/junit-4.8.1.jar b/tools/junit/junit-4.8.1.jar new file mode 100644 index 00000000000..524cd65ce5f Binary files /dev/null and b/tools/junit/junit-4.8.1.jar differ diff --git a/utils/src/com/cloud/utils/db/ScriptRunner.java b/utils/src/com/cloud/utils/db/ScriptRunner.java new file mode 100644 index 00000000000..c7191dc8eb5 --- /dev/null +++ b/utils/src/com/cloud/utils/db/ScriptRunner.java @@ -0,0 +1,243 @@ +/* + * Slightly modified version of the com.ibatis.common.jdbc.ScriptRunner class + * from the iBATIS Apache project. Only removed dependency on Resource class + * and a constructor + */ +/* + * Copyright 2004 Clinton Begin + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package com.cloud.utils.db; + +import java.io.IOException; +import java.io.LineNumberReader; +import java.io.PrintWriter; +import java.io.Reader; +import java.sql.Connection; +import java.sql.ResultSet; +import java.sql.ResultSetMetaData; +import java.sql.SQLException; +import java.sql.Statement; + +/** + * Tool to run database scripts + */ +public class ScriptRunner { + + private static final String DEFAULT_DELIMITER = ";"; + + private Connection connection; + + private boolean stopOnError; + private boolean autoCommit; + + private PrintWriter logWriter = new PrintWriter(System.out); + private PrintWriter errorLogWriter = new PrintWriter(System.err); + + private String delimiter = DEFAULT_DELIMITER; + private boolean fullLineDelimiter = false; + + /** + * Default constructor + */ + public ScriptRunner(Connection connection, boolean autoCommit, boolean stopOnError) { + this.connection = connection; + this.autoCommit = autoCommit; + this.stopOnError = stopOnError; + } + + public void setDelimiter(String delimiter, boolean fullLineDelimiter) { + this.delimiter = delimiter; + this.fullLineDelimiter = fullLineDelimiter; + } + + /** + * Setter for logWriter property + * + * @param logWriter + * - the new value of the logWriter property + */ + public void setLogWriter(PrintWriter logWriter) { + this.logWriter = logWriter; + } + + /** + * Setter for errorLogWriter property + * + * @param errorLogWriter + * - the new value of the errorLogWriter property + */ + public void setErrorLogWriter(PrintWriter errorLogWriter) { + this.errorLogWriter = errorLogWriter; + } + + /** + * Runs an SQL script (read in using the Reader parameter) + * + * @param reader + * - the source of the script + */ + public void runScript(Reader reader) throws IOException, SQLException { + try { + boolean originalAutoCommit = connection.getAutoCommit(); + try { + if (originalAutoCommit != this.autoCommit) { + connection.setAutoCommit(this.autoCommit); + } + runScript(connection, reader); + } finally { + connection.setAutoCommit(originalAutoCommit); + } + } catch (IOException e) { + throw e; + } catch (SQLException e) { + throw e; + } catch (Exception e) { + throw new RuntimeException("Error running script. Cause: " + e, e); + } + } + + /** + * Runs an SQL script (read in using the Reader parameter) using the + * connection passed in + * + * @param conn + * - the connection to use for the script + * @param reader + * - the source of the script + * @throws SQLException + * if any SQL errors occur + * @throws IOException + * if there is an error reading from the Reader + */ + private void runScript(Connection conn, Reader reader) throws IOException, SQLException { + StringBuffer command = null; + try { + LineNumberReader lineReader = new LineNumberReader(reader); + String line = null; + while ((line = lineReader.readLine()) != null) { + if (command == null) { + command = new StringBuffer(); + } + String trimmedLine = line.trim(); + if (trimmedLine.startsWith("--")) { + println(trimmedLine); + } else if (trimmedLine.length() < 1 || trimmedLine.startsWith("//")) { + // Do nothing + } else if (trimmedLine.length() < 1 || trimmedLine.startsWith("--")) { + // Do nothing + } else if (!fullLineDelimiter && trimmedLine.endsWith(getDelimiter()) || fullLineDelimiter && trimmedLine.equals(getDelimiter())) { + command.append(line.substring(0, line.lastIndexOf(getDelimiter()))); + command.append(" "); + Statement statement = conn.createStatement(); + + println(command); + + boolean hasResults = false; + if (stopOnError) { + hasResults = statement.execute(command.toString()); + } else { + try { + statement.execute(command.toString()); + } catch (SQLException e) { + e.fillInStackTrace(); + printlnError("Error executing: " + command); + printlnError(e); + } + } + + if (autoCommit && !conn.getAutoCommit()) { + conn.commit(); + } + + ResultSet rs = statement.getResultSet(); + if (hasResults && rs != null) { + ResultSetMetaData md = rs.getMetaData(); + int cols = md.getColumnCount(); + for (int i = 0; i < cols; i++) { + String name = md.getColumnLabel(i); + print(name + "\t"); + } + println(""); + while (rs.next()) { + for (int i = 0; i < cols; i++) { + String value = rs.getString(i); + print(value + "\t"); + } + println(""); + } + } + + command = null; + try { + statement.close(); + } catch (Exception e) { + // Ignore to workaround a bug in Jakarta DBCP + } + Thread.yield(); + } else { + command.append(line); + command.append(" "); + } + } + if (!autoCommit) { + conn.commit(); + } + } catch (SQLException e) { + e.fillInStackTrace(); + printlnError("Error executing: " + command); + printlnError(e); + throw e; + } catch (IOException e) { + e.fillInStackTrace(); + printlnError("Error executing: " + command); + printlnError(e); + throw e; + } finally { + conn.rollback(); + flush(); + } + } + + private String getDelimiter() { + return delimiter; + } + + private void print(Object o) { + if (logWriter != null) { + System.out.print(o); + } + } + + private void println(Object o) { + if (logWriter != null) { + logWriter.println(o); + } + } + + private void printlnError(Object o) { + if (errorLogWriter != null) { + errorLogWriter.println(o); + } + } + + private void flush() { + if (logWriter != null) { + logWriter.flush(); + } + if (errorLogWriter != null) { + errorLogWriter.flush(); + } + } +} \ No newline at end of file