private boolean checkSchema(Connection con, String schemaKey, int requiredVersion,
            ResourceLoader resourceLoader, boolean allowRecursion) throws Exception
    {
        final int currentVersion = getCurrentVersion(con, schemaKey);

        // If already up to date, return.
        if (currentVersion >= requiredVersion) {
            return true;
        }
        // If the database schema isn't installed at all, we need to install it.
        else if (currentVersion == -1) {
            Log.info(LocaleUtils.getLocalizedString("upgrade.database.missing_schema",
                    Arrays.asList(schemaKey)));
            System.out.println(LocaleUtils.getLocalizedString("upgrade.database.missing_schema",
                    Arrays.asList(schemaKey)));
            // Resource will be like "/database/openfire_hsqldb.sql"
            String resourceName = schemaKey + "_" +
                    DbConnectionManager.getDatabaseType() + ".sql";

            try (InputStream resource = resourceLoader.loadResource(resourceName)) {
                if (resource == null) {
                    return false;
                }
                // For plugins, we will automatically convert jiveVersion to ofVersion
                executeSQLScript(con, resource, !schemaKey.equals("openfire") && !schemaKey.equals("wildfire"));
            }
            catch (Exception e) {
                Log.error(e.getMessage(), e);
                return false;
            }

            // OF-2940: If the original installation doesn't include all upgrades, the individual upgrades need to be executed, too.
            final int updatedVersion = getCurrentVersion(con, schemaKey);
            if (updatedVersion < requiredVersion && allowRecursion) {
                return checkSchema(con, schemaKey, requiredVersion, resourceLoader, false);
            }
        }
        // Must have a version of the schema that needs to be upgraded.
        else {
            // The database is an old version that needs to be upgraded.
            Log.info(LocaleUtils.getLocalizedString("upgrade.database.old_schema",
                    Arrays.asList(currentVersion, schemaKey, requiredVersion)));
            System.out.println(LocaleUtils.getLocalizedString("upgrade.database.old_schema",
                    Arrays.asList(currentVersion, schemaKey, requiredVersion)));
            // If the database type is unknown, we don't know how to upgrade it.
            if (DbConnectionManager.getDatabaseType() == DbConnectionManager.DatabaseType.unknown) {
                Log.info(LocaleUtils.getLocalizedString("upgrade.database.unknown_db"));
                System.out.println(LocaleUtils.getLocalizedString("upgrade.database.unknown_db"));
                return false;
            }
            // Upgrade scripts for interbase are not maintained.
            else if (DbConnectionManager.getDatabaseType() == DbConnectionManager.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 = currentVersion + 1; i <= requiredVersion; i++) {
                try (InputStream resource = getUpgradeResource(resourceLoader, i, schemaKey)) {
                    // apply the 'database-patches-done-in-java'
                    try {
                        if (i == 21 && schemaKey.equals("openfire")) {
                            OF33.executeFix(con);
                        }
                        if (i == 28 && schemaKey.equals("openfire")) {
                            OF1515.executeFix();
                        }
                    } catch (Exception e) {
                        Log.error(e.getMessage(), e);
                        return false;
                    }
                    if (resource == null) {
                        continue;
                    }
                    executeSQLScript(con, resource, !schemaKey.equals("openfire") && !schemaKey.equals("wildfire"));
                } catch (Exception e) {
                    Log.error(e.getMessage(), e);
                    return false;
                }
            }
        }

        // Explicitly check if the database upgrade was successful (OF-3045)
        final int finalVersion = getCurrentVersion(con, schemaKey);
        if (finalVersion >= requiredVersion) {
            Log.info(LocaleUtils.getLocalizedString("upgrade.database.success"));
            System.out.println(LocaleUtils.getLocalizedString("upgrade.database.success"));
            return true;
        } else {
            Log.error(LocaleUtils.getLocalizedString("upgrade.database.failure"));
            System.out.println(LocaleUtils.getLocalizedString("upgrade.database.failure"));
            return false;
        }
    }
Checks to see if the database needs to be upgraded. This method should be
called once every time the application starts up.

@param con the database connection to use to check the schema with.
@param schemaKey the database schema key (name).
@param requiredVersion the version that the schema should be at.
@param resourceLoader a resource loader that knows how to load schema files.
@param allowRecursion controls if the method is allowed to recursively call itself.
@throws Exception if an error occurred.
@return True if the schema update was successful.
xmppserver/src/main/java/org/jivesoftware/database/SchemaManager.java