Commit e4a70aae authored by Matt Tucker's avatar Matt Tucker Committed by matt

Added support for plugin db schema support (JM-673).

git-svn-id: http://svn.igniterealtime.org/svn/repos/wildfire/trunk@3878 b35dd754-fafc-0310-a699-88a17e54d16e
parent e90508d2
......@@ -105,10 +105,10 @@ file might look like the following:
<li>databaseVersion -- the database schema version (if a database schema is defined). New plugins
with a database schema should start at version 0. If future versions of the plugin
require updates to the schema, those updates can be defined by creating sub-directories
in the <tt>database</tt> directory for each version number. For example, the directories
<tt>database/1</tt> and <tt>database/2</tt> would contain scripts such as "foo_mysql.sql"
and "foo_oracle.sql" that contain the relevant database changes for each version. Each
script should update version information in the jiveVersion table, e.g.:<br><br>
in the <tt>database/upgrade</tt> directory for each version number. For example, the directories
<tt>database/upgrade/1</tt> and <tt>database/upgrade/2</tt> would contain scripts such as
"foo_mysql.sql" and "foo_oracle.sql" that contain the relevant database changes for each
version. Each script should update version information in the jiveVersion table, e.g.:<br><br>
<tt>UPDATE jiveVersion set version=1 where name='foo';</tt><br><br>
......
......@@ -1503,12 +1503,13 @@ system.cache.total=Celkem:
system.cache.clear-selected=Vy\u010disti vybran\u00e9
# Upgrade process
upgrade.database.old_schema=Nalezena star\u00e1 verze datab\u00e1ze. Aktualizuji...
upgrade.database.missing_schema=Missing database schema for {0}. Attempting to install...
upgrade.database.old_schema=Found old database version {0} for {1}. Upgrading to version {2}...
upgrade.database.unknown_db=Varov\u00e1n\u00ed: nezn\u00e1m\u00fd typ datab\u00e1ze. Datab\u00e1zi mus\u00edte aktualizovat manu\u00e1ln\u011b.
upgrade.database.interbase_db=Varov\u00e1n\u00ed: automatick\u00e9 aktualizace Interbase nejsou podporov\u00e1ny. \
Datab\u00e1zi mus\u00edte aktualizovat manu\u00e1ln\u011b.
upgrade.database.success=Datab\u00e1ze \u00fasp\u011b\u0161n\u011b upgradov\u00e1na.
upgrade.database.failure=Aktualizace datab\u00e1ze selhala. Pros\u00edm aktualizujte datab\u00e1zi manu\u00e1ln\u011b.
upgrade.database.success=Database update successful.
upgrade.database.failure=Database update failed. Please manually upgrade your database.
# Publish-Subscribe
......
......@@ -1500,12 +1500,13 @@ system.cache.desc.effectiveness=* Effectiveness measures how well your cache is
system.cache.total=Total:
system.cache.clear-selected=Clear Selected
database.upgrade.old_schema=Found old database version. Upgrading...
upgrade.database.missing_schema=Missing database schema for {0}. Attempting to install...
upgrade.database.old_schema=Found old database version {0} for {1}. Upgrading to version {2}...
database.upgrade.unknown_db=Warning: database type unknown. You must manually upgrade your database.
database.upgrade.interbase_db=Warning: automatic upgrades of Interbase are not supported. You \
must manually upgrade your database.
upgrade.database.success=Database upgraded successfully.
upgrade.database.failure=Database upgrade failed. Please manually upgrade your database.
upgrade.database.success=Database update successful.
upgrade.database.failure=Database update failed. Please manually upgrade your database.
# Publish-Subscribe
......
......@@ -170,6 +170,10 @@
## 3.0.0
## Added key: 'startup.multiplexer'
## Added section: 'muc.stats..*'
## Added key: 'upgrade.database.missing_schema'
## Updated key: 'upgrade.database.old_schema'
## Updated key: 'upgrade.database.success'
# Updated key: 'upgrade.database.failure'
# Wildfire
......@@ -1683,12 +1687,13 @@ system.cache.total=Total:
system.cache.clear-selected=Clear Selected
# Upgrade process
upgrade.database.old_schema=Found old database version. Upgrading...
upgrade.database.missing_schema=Missing database schema for {0}. Attempting to install...
upgrade.database.old_schema=Found old database version {0} for {1}. Upgrading to version {2}...
upgrade.database.unknown_db=Warning: database type unknown. You must manually upgrade your database.
upgrade.database.interbase_db=Warning: automatic upgrades of Interbase are not supported. You \
must manually upgrade your database.
upgrade.database.success=Database upgraded successfully.
upgrade.database.failure=Database upgrade failed. Please manually upgrade your database.
upgrade.database.success=Database update successful.
upgrade.database.failure=Database update failed. Please manually upgrade your database.
# Publish-Subscribe
......
......@@ -1376,14 +1376,14 @@ system.cache.total=Total:
system.cache.clear-selected=Limpiar Seleccionados
# Upgrade process
upgrade.database.old_schema=Se ha encontrado una versi\u00f3n vieja de base de datos. Actualizando...
upgrade.database.missing_schema=Missing database schema for {0}. Attempting to install...
upgrade.database.old_schema=Found old database version {0} for {1}. Upgrading to version {2}...
upgrade.database.unknown_db=Atenci\u00f3n: tipo de base de datos desconocida. Actualice \
la base de datos manualmente.
upgrade.database.interbase_db=Atenci\u00f3n: actualizaci\u00f3n autom\u00e1tica de Interbase no \
soportada. Actualice la base de datos manualmente.
upgrade.database.success=Base de datos actualizada con \u00e9xito.
upgrade.database.failure=Ha habido un fallo en la actualizaci\u00f3n de la base de datos. Actualice \
la base de datos manualmente.
upgrade.database.success=Database update successful.
upgrade.database.failure=Database update failed. Please manually upgrade your database.
# Publish-Subscribe
......
......@@ -1616,12 +1616,13 @@ system.cache.total=Total:
system.cache.clear-selected=Vider les caches selectionn\u00e9s
# Upgrade process
upgrade.database.old_schema=Ancienne base de donn\u00e9es trouv\u00e9e. Mise \u00e0 jour...
upgrade.database.missing_schema=Missing database schema for {0}. Attempting to install...
upgrade.database.old_schema=Found old database version {0} for {1}. Upgrading to version {2}...
upgrade.database.unknown_db=Attention : type de base de donn\u00e9es inconnu. Vous devez mettre \u00e0 jour votre base de donn\u00e9es manuellement.
upgrade.database.interbase_db=Attention : les mises \u00e0 jour automatiques d'Interbase ne sont pas prisent en charge. \
Vous devez mettre \u00e0 jour votre base de donn\u00e9es manuellement.
upgrade.database.success=Base de donn\u00e9es mise \u00e0 jour avec succ\u00e8s.
upgrade.database.failure=Echec de la mise \u00e0 jour de la base de donn\u00e9es. Veuillez mettre \u00e0 jour votre base de donn\u00e9es manuellement.
upgrade.database.success=Database update successful.
upgrade.database.failure=Database update failed. Please manually upgrade your database.
# Publish-Subscribe
......
......@@ -1503,12 +1503,13 @@ system.cache.desc.effectiveness=* Effectiveness measures how well your cache is
system.cache.total=Total:
system.cache.clear-selected=Clear Selected
database.upgrade.old_schema=Found old database version. Upgrading...
database.upgrade.unknown_db=Warning: database type unknown. You must manually upgrade your database.
database.upgrade.interbase_db=Warning: automatic upgrades of Interbase are not supported. You \
upgrade.database.missing_schema=Missing database schema for {0}. Attempting to install...
upgrade.database.old_schema=Found old database version {0} for {1}. Upgrading to version {2}...
upgrade.database.unknown_db=Warning: database type unknown. You must manually upgrade your database.
upgrade.database.interbase_db=Warning: automatic upgrades of Interbase are not supported. You \
must manually upgrade your database.
upgrade.database.success=Database upgraded successfully.
upgrade.database.failure=Database upgrade failed. Please manually upgrade your database.
upgrade.database.success=Database update successful.
upgrade.database.failure=Database update failed. Please manually upgrade your database.
# Publish-Subscribe
......
......@@ -1477,11 +1477,13 @@ system.cache.total=Og\u00f3\u0142em:
system.cache.clear-selected=Wyczy\u015b\u0107 zaznaczone
# Upgrade process
upgrade.database.old_schema=Znaleziono star\u0105 wersj\u0119 bazy danych. Aktualizacja...
upgrade.database.missing_schema=Missing database schema for {0}. Attempting to install...
upgrade.database.old_schema=Found old database version {0} for {1}. Upgrading to version {2}...
upgrade.database.unknown_db=Ostrze\u017cenie: nieznany typ bazy danych. Musisz r\u0119cznie zaktualizowa\u0107 baz\u0119 danych.
upgrade.database.interbase_db=Ostrze\u017cenie: aktualizacje automatyczne dla bazy Interbase nie s\u0105 obs\u0142ugiwane. Musisz \
r\u0119cznie zaktualizowa\u0107 baz\u0119 danych.
upgrade.database.done=Aktualizacja bazy danych zako\u0144czona.
upgrade.database.success=Database update successful.
upgrade.database.failure=Database update failed. Please manually upgrade your database.
# Publish-Subscribe
......
......@@ -1504,12 +1504,13 @@ system.cache.total=Total:
system.cache.clear-selected=Limpar Selecionados
# Upgrade process
upgrade.database.old_schema=Encontrado uma vers\u00e3o antiga do banco de dados. Atualizando...
upgrade.database.missing_schema=Missing database schema for {0}. Attempting to install...
upgrade.database.old_schema=Found old database version {0} for {1}. Upgrading to version {2}...
upgrade.database.unknown_db=Aviso: o tipo do banco de dados \u00e9 desconhecido. Voc\u00ea deve atualizar manualmente seu banco de dados.
upgrade.database.interbase_db=Aviso: atualiza\u00e7\u00e3o autom\u00e1tica do Interbase n\u00e3o \u00e9 suportada. Voc\u00ea \
deve atualizar seu banco de dados manualmente.
upgrade.database.success=Banco de dados atualizado com sucesso.
upgrade.database.failure=Atualiza\u00e7\u00e3o do banco de dados falhou. Favor atualizar sem banco de dados manualmente.
upgrade.database.success=Database update successful.
upgrade.database.failure=Database update failed. Please manually upgrade your database.
# Publish-Subscribe
......
......@@ -1372,11 +1372,12 @@ system.cache.total=\u5408\u8ba1:
system.cache.clear-selected=\u6e05\u9664\u5df2\u9009\u9879\u76ee
# Upgrade process
upgrade.database.old_schema=\u53d1\u73b0\u65e7\u7684\u6570\u636e\u5e93\u7248\u672c\u3002\u5347\u7ea7\u4e2d...
upgrade.database.missing_schema=Missing database schema for {0}. Attempting to install...
upgrade.database.old_schema=Found old database version {0} for {1}. Upgrading to version {2}...
upgrade.database.unknown_db=\u8b66\u544a\uff1a\u6570\u636e\u5e93\u7c7b\u578b\u672a\u77e5\u3002\u60a8\u5fc5\u987b\u624b\u52a8\u5347\u7ea7\u60a8\u7684\u6570\u636e\u5e93\u3002
upgrade.database.interbase_db=\u8b66\u544a\uff1a\u4e0d\u652f\u6301\u81ea\u52a8\u5347\u7ea7Interbase\u6570\u636e\u5e93\u3002\u60a8\u5fc5\u987b\u624b\u52a8\u5347\u7ea7\u60a8\u7684\u6570\u636e\u5e93\u3002
upgrade.database.success=\u6570\u636e\u5e93\u5347\u7ea7\u6210\u529f\u3002
upgrade.database.failure=\u6570\u636e\u5e93\u5347\u7ea7\u5931\u8d25\u3002\u8bf7\u624b\u52a8\u5347\u7ea7\u60a8\u7684\u6570\u636e\u5e93\u3002
upgrade.database.success=Database update successful.
upgrade.database.failure=Database update failed. Please manually upgrade your database.
# Publish-Subscribe
......
......@@ -9,12 +9,10 @@
* a copy of which is included in this distribution.
*/
package org.jivesoftware.database;
import org.jivesoftware.util.ClassUtils;
import org.jivesoftware.util.JiveGlobals;
import org.jivesoftware.util.LocaleUtils;
import org.jivesoftware.util.Log;
import java.io.*;
......@@ -33,17 +31,6 @@ import java.sql.*;
*/
public class DbConnectionManager {
private static final String CHECK_VERSION_OLD =
"SELECT minorVersion FROM jiveVersion";
private static final String CHECK_VERSION =
"SELECT version FROM jiveVersion WHERE name=?";
/**
* Database schema version.
*/
private static final int DATABASE_VERSION = 9;
private static ConnectionProvider connectionProvider;
private static final Object providerLock = new Object();
......@@ -67,6 +54,8 @@ public class DbConnectionManager {
private static DatabaseType databaseType = DatabaseType.unknown;
private static SchemaManager schemaManager = new SchemaManager();
/**
* Returns a database connection from the currently active connection
* provider. (auto commit is set to true).
......@@ -438,13 +427,7 @@ public class DbConnectionManager {
setMetaData(con);
// Check to see if the database schema needs to be upgraded.
try {
upgradeDatabase(con);
}
catch (Exception e) {
Log.error(LocaleUtils.getLocalizedString("upgrade.database.failure"), e);
System.out.println(LocaleUtils.getLocalizedString("upgrade.database.failure"));
}
schemaManager.checkWildfireSchema(con);
}
catch (Exception e) {
Log.error(e);
......@@ -606,6 +589,16 @@ public class DbConnectionManager {
}
}
/**
* Returns a SchemaManager instance, which can be used to manage the database
* schema information for Wildfire and plugins.
*
* @return a SchemaManager instance.
*/
public static SchemaManager getSchemaManager() {
return schemaManager;
}
/**
* Uses a connection from the database to set meta data information about
* what different JDBC drivers and databases support.
......@@ -784,144 +777,6 @@ public class DbConnectionManager {
unknown
}
/**
* Checks to see if the database needs to be upgraded. This method should be
* called once every time the application starts up.
*
* @throws SQLException if an error occured.
*/
private static boolean upgradeDatabase(Connection con) throws Exception {
int version = 0;
PreparedStatement pstmt = null;
try {
pstmt = con.prepareStatement(CHECK_VERSION);
pstmt.setString(1, "wildfire");
ResultSet rs = pstmt.executeQuery();
rs.next();
version = rs.getInt(1);
rs.close();
}
catch (SQLException sqle) {
// Releases of Wildfire before 2.6.0 stored a major and minor version
// number so the normal check for version can fail. Check for the
// version using the old format in that case.
try {
if (pstmt != null) {
pstmt.close();
}
pstmt = con.prepareStatement(CHECK_VERSION_OLD);
ResultSet rs = pstmt.executeQuery();
rs.next();
version = rs.getInt(1);
rs.close();
}
catch (SQLException sqle2) {
// Must be database version 0.
}
}
finally {
try {
if (pstmt != null) {
pstmt.close();
}
}
catch (Exception e) {
Log.error(e);
}
}
if (version == DATABASE_VERSION) {
return false;
}
// The database is an old version that needs to be upgraded.
Log.info(LocaleUtils.getLocalizedString("upgrade.database.old_schema"));
System.out.println(LocaleUtils.getLocalizedString("upgrade.database.old_schema"));
if (databaseType == DatabaseType.unknown) {
Log.info(LocaleUtils.getLocalizedString("upgrade.database.unknown_db"));
System.out.println(LocaleUtils.getLocalizedString("upgrade.database.unknown_db"));
return false;
}
else if (databaseType == DatabaseType.interbase) {
Log.info(LocaleUtils.getLocalizedString("upgrade.database.interbase_db"));
System.out.println(LocaleUtils.getLocalizedString("upgrade.database.interbase_db"));
return false;
}
// Run all upgrade scripts until we're up to the latest schema.
for (int i = version+1; i <= DATABASE_VERSION; i++) {
BufferedReader in = null;
Statement stmt;
try {
// Resource will be like "/database/upgrade/6/wildfire_hsqldb.sql"
String resourceName = "/database/upgrade/" + i + "/wildfire_" +
databaseType + ".sql";
InputStream resource = DbConnectionManager.class.getResourceAsStream(resourceName);
if (resource == null) {
// If the resource is null, the specific upgrade number is not available.
continue;
}
in = new BufferedReader(new InputStreamReader(resource));
boolean done = false;
while (!done) {
StringBuilder command = new StringBuilder();
while (true) {
String line = in.readLine();
if (line == null) {
done = true;
break;
}
// Ignore comments and blank lines.
if (isSQLCommandPart(line)) {
command.append(line);
}
if (line.endsWith(";")) {
break;
}
}
// Send command to database.
if (!done && command != null) {
stmt = con.createStatement();
stmt.execute(command.toString());
stmt.close();
}
}
}
finally {
if (in != null) {
try {
in.close();
}
catch (Exception e) {
// Ignore.
}
}
}
}
Log.info(LocaleUtils.getLocalizedString("upgrade.database.success"));
System.out.println(LocaleUtils.getLocalizedString("upgrade.database.success"));
return true;
}
/**
* Returns true if a line from a SQL schema is a valid command part.
*
* @param line the line of the schema.
* @return true if a valid command part.
*/
public static boolean isSQLCommandPart(String line) {
line = line.trim();
if (line.equals("")) {
return false;
}
// Check to see if the line is a comment. Valid comment types:
// "//" is HSQLDB
// "--" is DB2 and Postgres
// "#" is MySQL
// "REM" is Oracle
// "/*" is SQLServer
return !(line.startsWith("//") || line.startsWith("--") || line.startsWith("#") ||
line.startsWith("REM") || line.startsWith("/*") || line.startsWith("*"));
}
private DbConnectionManager() {
// Not instantiable.
}
......
......@@ -14,10 +14,8 @@ package org.jivesoftware.database;
import org.jivesoftware.util.JiveGlobals;
import org.jivesoftware.util.Log;
import java.io.BufferedReader;
import java.io.File;
import java.io.IOException;
import java.io.InputStreamReader;
import java.sql.Connection;
import java.sql.SQLException;
import java.sql.Statement;
......@@ -80,7 +78,8 @@ public class EmbeddedConnectionProvider implements ConnectionProvider {
minConnections, maxConnections, connectionTimeout, false);
// Create initial tables if they don't already exist.
if (initData) {
initializeDatabase();
// TODO
// initializeDatabase();
}
}
catch (IOException ioe) {
......@@ -130,6 +129,9 @@ public class EmbeddedConnectionProvider implements ConnectionProvider {
destroy();
}
// TODO
/*
private void initializeDatabase() {
BufferedReader in = null;
Connection con = null;
......@@ -172,5 +174,5 @@ public class EmbeddedConnectionProvider implements ConnectionProvider {
try { if (con != null) { con.close(); } }
catch (Exception e) { Log.error(e); }
}
}
} */
}
\ No newline at end of file
......@@ -428,7 +428,7 @@ public class LocaleUtils {
final XMPPServer xmppServer = XMPPServer.getInstance();
PluginManager pluginManager = xmppServer.getPluginManager();
Plugin plugin = pluginManager.getPlugin(pluginName);
if(plugin == null){
if (plugin == null){
throw new NullPointerException("Plugin could not be located.");
}
......
......@@ -53,7 +53,8 @@ public class PluginClassLoader {
* after adding the directory to make the change take effect.
*
* @param directory the directory.
* @param developmentMode true if the plugin is running in development mode. This resolves classloader conflicts between the deployed plugin
* @param developmentMode true if the plugin is running in development mode. This
* resolves classloader conflicts between the deployed plugin
* and development classes.
*/
public void addDirectory(File directory, boolean developmentMode) {
......@@ -64,6 +65,12 @@ public class PluginClassLoader {
list.add(classesDir.toURL());
}
// Add i18n directory to classpath.
File databaseDir = new File(directory, "database");
if(databaseDir.exists()){
list.add(databaseDir.toURL());
}
// Add i18n directory to classpath.
File i18nDir = new File(directory, "i18n");
if(i18nDir.exists()){
......@@ -173,9 +180,10 @@ public class PluginClassLoader {
/**
* Returns the URLClassloader used.
*
* @return the URLClassLoader used.
*/
public ClassLoader getClassLoader(){
public ClassLoader getClassLoader() {
return classLoader;
}
}
......@@ -19,6 +19,7 @@ import org.jivesoftware.admin.AdminConsole;
import org.jivesoftware.util.Log;
import org.jivesoftware.util.Version;
import org.jivesoftware.wildfire.XMPPServer;
import org.jivesoftware.database.DbConnectionManager;
import java.io.File;
import java.io.FileFilter;
......@@ -212,8 +213,6 @@ public class PluginManager {
compilationClassesDir.deleteOnExit();
}
if (parentPluginNode != null) {
String parentPlugin = parentPluginNode.getTextTrim();
// See if the parent is already loaded.
......@@ -351,6 +350,9 @@ public class PluginManager {
pluginDevelopment.put(plugin, dev);
}
// Check the plugin's database schema (if it requires one).
DbConnectionManager.getSchemaManager().checkPluginSchema(plugin);
// If there a <adminconsole> section defined, register it.
Element adminElement = (Element)pluginXML.selectSingleNode("/plugin/adminconsole");
if (adminElement != null) {
......@@ -528,6 +530,39 @@ public class PluginManager {
return getElementValue(plugin, "/plugin/version");
}
/**
* Returns the database schema key of a plugin, if it exists. The value is retrieved
* from the plugin.xml file of the plugin. If the value could not be found, <tt>null</tt>
* will be returned.
*
* @param plugin the plugin.
* @return the plugin's database schema key or <tt>null</tt> if it doesn't exist.
*/
public String getDatabaseKey(Plugin plugin) {
return getElementValue(plugin, "/plugin/databaseKey");
}
/**
* Returns the database schema version of a plugin, if it exists. The value is retrieved
* from the plugin.xml file of the plugin. If the value could not be found, <tt>-1</tt>
* will be returned.
*
* @param plugin the plugin.
* @return the plugin's database schema version or <tt>-1</tt> if it doesn't exist.
*/
public int getDatabaseVersion(Plugin plugin) {
String versionString = getElementValue(plugin, "/plugin/databaseVersion");
if (versionString != null) {
try {
return Integer.parseInt(versionString.trim());
}
catch (NumberFormatException nfe) {
Log.error(nfe);
}
}
return -1;
}
/**
* Returns the classloader of a plugin.
*
......
......@@ -58,7 +58,6 @@
}
catch (SQLException sqle) {
success = false;
sqle.printStackTrace();
errors.put("general","The Wildfire database schema does not "
+ "appear to be installed. Follow the installation guide to "
+ "fix this error.");
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment