From e8fdc7a09f6356dbcec4a8fd1ab157b0e2097c39 Mon Sep 17 00:00:00 2001 From: simonbrandhof Date: Wed, 22 Dec 2010 19:12:57 +0000 Subject: [PATCH] add the server-side component ServerUpgradeStatus to know the database version before starting the server --- .../session/AbstractDatabaseConnector.java | 8 +-- .../sonar/jpa/session/DatabaseConnector.java | 2 + .../api/platform/ServerUpgradeStatus.java | 44 ++++++++++++ .../platform/DefaultServerUpgradeStatus.java | 60 ++++++++++++++++ .../org/sonar/server/platform/Platform.java | 6 +- .../DefaultServerUpgradeStatusTest.java | 71 +++++++++++++++++++ 6 files changed, 185 insertions(+), 6 deletions(-) create mode 100644 sonar-plugin-api/src/main/java/org/sonar/api/platform/ServerUpgradeStatus.java create mode 100644 sonar-server/src/main/java/org/sonar/server/platform/DefaultServerUpgradeStatus.java create mode 100644 sonar-server/src/test/java/org/sonar/server/platform/DefaultServerUpgradeStatusTest.java diff --git a/sonar-core/src/main/java/org/sonar/jpa/session/AbstractDatabaseConnector.java b/sonar-core/src/main/java/org/sonar/jpa/session/AbstractDatabaseConnector.java index ac778560a18..9ea59cd7b89 100644 --- a/sonar-core/src/main/java/org/sonar/jpa/session/AbstractDatabaseConnector.java +++ b/sonar-core/src/main/java/org/sonar/jpa/session/AbstractDatabaseConnector.java @@ -88,7 +88,7 @@ public abstract class AbstractDatabaseConnector implements DatabaseConnector { * * @return JDBC transaction isolation */ - public Integer getTransactionIsolation() { + public final Integer getTransactionIsolation() { return transactionIsolation; } @@ -222,15 +222,15 @@ public abstract class AbstractDatabaseConnector implements DatabaseConnector { return databaseVersion == SchemaMigration.LAST_VERSION; } - protected int getDatabaseVersion() { + public final int getDatabaseVersion() { return databaseVersion; } - public Dialect getDialect() { + public final Dialect getDialect() { return dialect; } - public String getDialectClass() { + public final String getDialectClass() { String dialectClass = configuration.getString(DatabaseProperties.PROP_DIALECT_CLASS); if (dialectClass == null && dialect != null) { dialectClass = dialect.getHibernateDialectClass().getName(); diff --git a/sonar-core/src/main/java/org/sonar/jpa/session/DatabaseConnector.java b/sonar-core/src/main/java/org/sonar/jpa/session/DatabaseConnector.java index 952c2529a33..93aa1191504 100644 --- a/sonar-core/src/main/java/org/sonar/jpa/session/DatabaseConnector.java +++ b/sonar-core/src/main/java/org/sonar/jpa/session/DatabaseConnector.java @@ -36,4 +36,6 @@ public interface DatabaseConnector { EntityManager createEntityManager(); + int getDatabaseVersion(); + } diff --git a/sonar-plugin-api/src/main/java/org/sonar/api/platform/ServerUpgradeStatus.java b/sonar-plugin-api/src/main/java/org/sonar/api/platform/ServerUpgradeStatus.java new file mode 100644 index 00000000000..68f5c2bab6d --- /dev/null +++ b/sonar-plugin-api/src/main/java/org/sonar/api/platform/ServerUpgradeStatus.java @@ -0,0 +1,44 @@ +/* + * Sonar, open source software quality management tool. + * Copyright (C) 2009 SonarSource SA + * mailto:contact AT sonarsource DOT com + * + * Sonar 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 3 of the License, or (at your option) any later version. + * + * Sonar 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 Sonar; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02 + */ +package org.sonar.api.platform; + +import org.sonar.api.ServerComponent; + +/** + * @since 2.5 + */ +public interface ServerUpgradeStatus extends ServerComponent { + + /** + * Has the database been upgraded during the current startup ? Return false if isInstalledFromScratch() is true. + */ + boolean isUpgraded(); + + /** + * Has the database been created during the current startup ? + */ + boolean isInstalledFromScratch(); + + /** + * The database version before the server startup. Returns <=0 if db created from scratch. + */ + int getInitialDbVersion(); + +} diff --git a/sonar-server/src/main/java/org/sonar/server/platform/DefaultServerUpgradeStatus.java b/sonar-server/src/main/java/org/sonar/server/platform/DefaultServerUpgradeStatus.java new file mode 100644 index 00000000000..545f2c336f7 --- /dev/null +++ b/sonar-server/src/main/java/org/sonar/server/platform/DefaultServerUpgradeStatus.java @@ -0,0 +1,60 @@ +/* + * Sonar, open source software quality management tool. + * Copyright (C) 2009 SonarSource SA + * mailto:contact AT sonarsource DOT com + * + * Sonar 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 3 of the License, or (at your option) any later version. + * + * Sonar 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 Sonar; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02 + */ +package org.sonar.server.platform; + +import org.apache.commons.lang.builder.ReflectionToStringBuilder; +import org.apache.commons.lang.builder.ToStringStyle; +import org.sonar.api.platform.ServerUpgradeStatus; +import org.sonar.jpa.entity.SchemaMigration; +import org.sonar.jpa.session.DatabaseConnector; + +/** + * @since 2.5 + */ +public final class DefaultServerUpgradeStatus implements ServerUpgradeStatus { + + private int initialDbVersion; + private DatabaseConnector dbConnector; + + public DefaultServerUpgradeStatus(DatabaseConnector dbConnector) { + this.dbConnector = dbConnector; + } + + public void start() { + this.initialDbVersion = dbConnector.getDatabaseVersion(); + } + + public boolean isUpgraded() { + return !isInstalledFromScratch() &&(initialDbVersion < SchemaMigration.LAST_VERSION); + } + + public boolean isInstalledFromScratch() { + return initialDbVersion <= 0; + } + + public int getInitialDbVersion() { + return initialDbVersion; + } + + @Override + public String toString() { + return new ReflectionToStringBuilder(this, ToStringStyle.SHORT_PREFIX_STYLE).toString(); + } +} diff --git a/sonar-server/src/main/java/org/sonar/server/platform/Platform.java b/sonar-server/src/main/java/org/sonar/server/platform/Platform.java index bd25a77c12a..302ff2a2fc7 100644 --- a/sonar-server/src/main/java/org/sonar/server/platform/Platform.java +++ b/sonar-server/src/main/java/org/sonar/server/platform/Platform.java @@ -28,6 +28,7 @@ import org.sonar.api.Plugins; import org.sonar.api.database.configuration.DatabaseConfiguration; import org.sonar.api.platform.Environment; import org.sonar.api.platform.Server; +import org.sonar.api.platform.ServerUpgradeStatus; import org.sonar.api.profiles.AnnotationProfileParser; import org.sonar.api.profiles.XMLProfileParser; import org.sonar.api.profiles.XMLProfileSerializer; @@ -96,7 +97,7 @@ public final class Platform { } public void start() { - if (!started && isConnectedToDatabase()) { + if (!started && isUpToDateDatabase()) { TimeProfiler profiler = new TimeProfiler().start("Start services"); startCoreComponents(); startServiceComponents(); @@ -113,12 +114,13 @@ public final class Platform { rootContainer.as(Characteristics.CACHE).addComponent(configuration); rootContainer.as(Characteristics.CACHE).addComponent(EmbeddedDatabaseFactory.class); rootContainer.as(Characteristics.CACHE).addComponent(JndiDatabaseConnector.class); + rootContainer.as(Characteristics.CACHE).addComponent(DefaultServerUpgradeStatus.class); rootContainer.start(); // Platform is already starting, so it's registered after the container startup } - private boolean isConnectedToDatabase() { + private boolean isUpToDateDatabase() { JndiDatabaseConnector databaseConnector = getContainer().getComponent(JndiDatabaseConnector.class); return databaseConnector.isOperational(); } diff --git a/sonar-server/src/test/java/org/sonar/server/platform/DefaultServerUpgradeStatusTest.java b/sonar-server/src/test/java/org/sonar/server/platform/DefaultServerUpgradeStatusTest.java new file mode 100644 index 00000000000..be801d2ac83 --- /dev/null +++ b/sonar-server/src/test/java/org/sonar/server/platform/DefaultServerUpgradeStatusTest.java @@ -0,0 +1,71 @@ +/* + * Sonar, open source software quality management tool. + * Copyright (C) 2009 SonarSource SA + * mailto:contact AT sonarsource DOT com + * + * Sonar 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 3 of the License, or (at your option) any later version. + * + * Sonar 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 Sonar; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02 + */ +package org.sonar.server.platform; + +import org.junit.Test; +import org.sonar.jpa.entity.SchemaMigration; +import org.sonar.jpa.session.DatabaseConnector; + +import static org.hamcrest.core.Is.is; +import static org.junit.Assert.assertThat; +import static org.mockito.Mockito.mock; +import static org.mockito.Mockito.when; + +public class DefaultServerUpgradeStatusTest { + + @Test + public void shouldBeInstalledFromScratch() { + DatabaseConnector connector = mock(DatabaseConnector.class); + when(connector.getDatabaseVersion()).thenReturn(-1); + + DefaultServerUpgradeStatus status = new DefaultServerUpgradeStatus(connector); + status.start(); + + assertThat(status.isInstalledFromScratch(), is(true)); + assertThat(status.isUpgraded(), is(false)); + assertThat(status.getInitialDbVersion(), is(-1)); + } + + @Test + public void shouldBeUpgraded() { + DatabaseConnector connector = mock(DatabaseConnector.class); + when(connector.getDatabaseVersion()).thenReturn(50); + + DefaultServerUpgradeStatus status = new DefaultServerUpgradeStatus(connector); + status.start(); + + assertThat(status.isInstalledFromScratch(), is(false)); + assertThat(status.isUpgraded(), is(true)); + assertThat(status.getInitialDbVersion(), is(50)); + } + + @Test + public void shouldNotBeUpgraded() { + DatabaseConnector connector = mock(DatabaseConnector.class); + when(connector.getDatabaseVersion()).thenReturn(SchemaMigration.LAST_VERSION); + + DefaultServerUpgradeStatus status = new DefaultServerUpgradeStatus(connector); + status.start(); + + assertThat(status.isInstalledFromScratch(), is(false)); + assertThat(status.isUpgraded(), is(false)); + assertThat(status.getInitialDbVersion(), is(SchemaMigration.LAST_VERSION)); + } +} -- 2.39.5