aboutsummaryrefslogtreecommitdiffstats
path: root/sonar-core
diff options
context:
space:
mode:
authorSimon Brandhof <simon.brandhof@gmail.com>2011-10-26 11:48:24 +0200
committerSimon Brandhof <simon.brandhof@gmail.com>2011-10-26 11:49:09 +0200
commit28e68ed90ba648cd2dcd6491982a7bda227b6bbd (patch)
tree797c86b2570baa5d379ac25b3370a65976515aa6 /sonar-core
parent48563f868573a21cac93c8143b36b26200f19a6c (diff)
downloadsonarqube-28e68ed90ba648cd2dcd6491982a7bda227b6bbd.tar.gz
sonarqube-28e68ed90ba648cd2dcd6491982a7bda227b6bbd.zip
SONAR-2642 do not duplicate derby DDL files
Diffstat (limited to 'sonar-core')
-rw-r--r--sonar-core/src/main/java/org/sonar/jpa/session/AbstractDatabaseConnector.java1
-rw-r--r--sonar-core/src/main/java/org/sonar/persistence/Database.java3
-rw-r--r--sonar-core/src/main/java/org/sonar/persistence/DatabaseMigrator.java60
-rw-r--r--sonar-core/src/main/java/org/sonar/persistence/DdlUtils.java3
-rw-r--r--sonar-core/src/main/java/org/sonar/persistence/DefaultDatabase.java30
-rw-r--r--sonar-core/src/main/java/org/sonar/persistence/InMemoryDatabase.java6
-rw-r--r--sonar-core/src/main/java/org/sonar/persistence/MyBatis.java4
-rw-r--r--sonar-core/src/main/resources/org/sonar/persistence/rows-derby.sql4
-rw-r--r--sonar-core/src/main/resources/org/sonar/persistence/schema-derby.ddl2
-rw-r--r--sonar-core/src/test/java/org/sonar/persistence/DefaultDatabaseTest.java51
10 files changed, 141 insertions, 23 deletions
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 01df8825f85..1036280044f 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
@@ -82,7 +82,6 @@ public abstract class AbstractDatabaseConnector implements DatabaseConnector {
if (!started) {
String jdbcConnectionUrl = testConnection();
dialect = DialectRepository.find(configuration.getString("sonar.jdbc.dialect"), jdbcConnectionUrl);
- LoggerFactory.getLogger("org.sonar.INFO").info("Database dialect class " + dialect.getClass().getName());
started = true;
}
if (!operational) {
diff --git a/sonar-core/src/main/java/org/sonar/persistence/Database.java b/sonar-core/src/main/java/org/sonar/persistence/Database.java
index ac4fd69506d..028f8e812aa 100644
--- a/sonar-core/src/main/java/org/sonar/persistence/Database.java
+++ b/sonar-core/src/main/java/org/sonar/persistence/Database.java
@@ -19,6 +19,8 @@
*/
package org.sonar.persistence;
+import org.sonar.jpa.dialect.Dialect;
+
import javax.sql.DataSource;
/**
@@ -29,4 +31,5 @@ public interface Database {
Database start();
Database stop();
DataSource getDataSource();
+ Dialect getDialect();
}
diff --git a/sonar-core/src/main/java/org/sonar/persistence/DatabaseMigrator.java b/sonar-core/src/main/java/org/sonar/persistence/DatabaseMigrator.java
new file mode 100644
index 00000000000..6d31f295576
--- /dev/null
+++ b/sonar-core/src/main/java/org/sonar/persistence/DatabaseMigrator.java
@@ -0,0 +1,60 @@
+/*
+ * Sonar, open source software quality management tool.
+ * Copyright (C) 2008-2011 SonarSource
+ * 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.persistence;
+
+import org.apache.ibatis.session.SqlSession;
+import org.slf4j.LoggerFactory;
+import org.sonar.api.ServerComponent;
+
+import java.sql.Connection;
+
+/**
+ * Restore schema by executing DDL scripts. Only Derby database is supported. Other databases are created by Ruby on Rails migrations.
+ *
+ * @since 2.12
+ */
+public class DatabaseMigrator implements ServerComponent {
+
+ private MyBatis myBatis;
+ private Database database;
+
+ public DatabaseMigrator(MyBatis myBatis, Database database) {
+ this.myBatis = myBatis;
+ this.database = database;
+ }
+
+ /**
+ * @return true if the database has been created, false if this database is not supported
+ */
+ public boolean createDatabase() {
+ if (DdlUtils.supportsDialect(database.getDialect().getId())) {
+ LoggerFactory.getLogger(getClass()).info("Create database");
+ SqlSession session = myBatis.openSession();
+ Connection connection = session.getConnection();
+ try {
+ DdlUtils.execute(connection, database.getDialect().getId());
+ } finally {
+ session.close();
+ }
+ return true;
+ }
+ return false;
+ }
+}
diff --git a/sonar-core/src/main/java/org/sonar/persistence/DdlUtils.java b/sonar-core/src/main/java/org/sonar/persistence/DdlUtils.java
index 2b8cc3d22d7..14dd56eef2c 100644
--- a/sonar-core/src/main/java/org/sonar/persistence/DdlUtils.java
+++ b/sonar-core/src/main/java/org/sonar/persistence/DdlUtils.java
@@ -44,6 +44,9 @@ public final class DdlUtils {
return "derby".equals(dialect);
}
+ /**
+ * The connection is commited in this method but not closed.
+ */
public static void execute(Connection connection, String dialect) {
if (!supportsDialect(dialect)) {
throw new IllegalArgumentException("Unsupported dialect: " + dialect);
diff --git a/sonar-core/src/main/java/org/sonar/persistence/DefaultDatabase.java b/sonar-core/src/main/java/org/sonar/persistence/DefaultDatabase.java
index fae69d957ee..fb5eca5ccaa 100644
--- a/sonar-core/src/main/java/org/sonar/persistence/DefaultDatabase.java
+++ b/sonar-core/src/main/java/org/sonar/persistence/DefaultDatabase.java
@@ -26,6 +26,8 @@ import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.sonar.api.config.Settings;
import org.sonar.api.database.DatabaseProperties;
+import org.sonar.jpa.dialect.Dialect;
+import org.sonar.jpa.dialect.DialectRepository;
import javax.sql.DataSource;
import java.sql.SQLException;
@@ -42,6 +44,7 @@ public class DefaultDatabase implements Database {
private Settings settings;
private BasicDataSource datasource;
+ private Dialect dialect;
public DefaultDatabase(Settings settings) {
this.settings = settings;
@@ -51,8 +54,9 @@ public class DefaultDatabase implements Database {
try {
doBeforeStart();
- LOG.info("Create JDBC datasource");
- datasource = (BasicDataSource) BasicDataSourceFactory.createDataSource(getCommonsDbcpProperties());
+ Properties properties = getProperties();
+ dialect = initDialect(properties);
+ datasource = initDatasource(properties);
return this;
} catch (Exception e) {
@@ -60,6 +64,19 @@ public class DefaultDatabase implements Database {
}
}
+ BasicDataSource initDatasource(Properties properties) throws Exception {
+ LOG.info("Create JDBC datasource");
+ return (BasicDataSource) BasicDataSourceFactory.createDataSource(extractCommonsDbcpProperties(properties));
+ }
+
+ Dialect initDialect(Properties properties) {
+ Dialect result = DialectRepository.find(properties.getProperty("sonar.jdbc.dialect"), properties.getProperty("sonar.jdbc.url"));
+ if (result != null && "derby".equals(result.getId())) {
+ LoggerFactory.getLogger(getClass()).warn("Derby database should be used for evaluation purpose only");
+ }
+ return result;
+ }
+
protected void doBeforeStart() {
}
@@ -79,6 +96,10 @@ public class DefaultDatabase implements Database {
}
+ public final Dialect getDialect() {
+ return dialect;
+ }
+
public final DataSource getDataSource() {
return datasource;
}
@@ -104,10 +125,9 @@ public class DefaultDatabase implements Database {
}
}
- Properties getCommonsDbcpProperties() {
+ static Properties extractCommonsDbcpProperties(Properties properties) {
Properties result = new Properties();
- Properties props = getProperties();
- for (Map.Entry<Object, Object> entry : props.entrySet()) {
+ for (Map.Entry<Object, Object> entry : properties.entrySet()) {
String key = (String) entry.getKey();
if (StringUtils.startsWith(key, "sonar.jdbc.")) {
result.setProperty(StringUtils.removeStart(key, "sonar.jdbc."), (String) entry.getValue());
diff --git a/sonar-core/src/main/java/org/sonar/persistence/InMemoryDatabase.java b/sonar-core/src/main/java/org/sonar/persistence/InMemoryDatabase.java
index 7e54f9522a9..80cf8bb4914 100644
--- a/sonar-core/src/main/java/org/sonar/persistence/InMemoryDatabase.java
+++ b/sonar-core/src/main/java/org/sonar/persistence/InMemoryDatabase.java
@@ -21,6 +21,8 @@ package org.sonar.persistence;
import org.apache.commons.dbcp.BasicDataSource;
import org.apache.commons.dbcp.BasicDataSourceFactory;
+import org.sonar.jpa.dialect.Derby;
+import org.sonar.jpa.dialect.Dialect;
import javax.sql.DataSource;
import java.sql.Connection;
@@ -95,4 +97,8 @@ public class InMemoryDatabase implements Database {
public DataSource getDataSource() {
return datasource;
}
+
+ public Dialect getDialect() {
+ return new Derby();
+ }
}
diff --git a/sonar-core/src/main/java/org/sonar/persistence/MyBatis.java b/sonar-core/src/main/java/org/sonar/persistence/MyBatis.java
index 4a468f8f767..82e23455b70 100644
--- a/sonar-core/src/main/java/org/sonar/persistence/MyBatis.java
+++ b/sonar-core/src/main/java/org/sonar/persistence/MyBatis.java
@@ -25,6 +25,8 @@ import org.apache.ibatis.builder.xml.XMLMapperBuilder;
import org.apache.ibatis.mapping.Environment;
import org.apache.ibatis.session.*;
import org.apache.ibatis.transaction.jdbc.JdbcTransactionFactory;
+import org.sonar.api.BatchComponent;
+import org.sonar.api.ServerComponent;
import org.sonar.persistence.model.Duplication;
import org.sonar.persistence.model.DuplicationMapper;
import org.sonar.persistence.model.Rule;
@@ -33,7 +35,7 @@ import org.sonar.persistence.model.RuleMapper;
import java.io.IOException;
import java.io.InputStream;
-public class MyBatis {
+public class MyBatis implements BatchComponent, ServerComponent {
private Database database;
private SqlSessionFactory sessionFactory;
diff --git a/sonar-core/src/main/resources/org/sonar/persistence/rows-derby.sql b/sonar-core/src/main/resources/org/sonar/persistence/rows-derby.sql
index 5a8a67209a9..825db32a1a6 100644
--- a/sonar-core/src/main/resources/org/sonar/persistence/rows-derby.sql
+++ b/sonar-core/src/main/resources/org/sonar/persistence/rows-derby.sql
@@ -1,7 +1,7 @@
-- Version 2.11
-- All the rows inserted during Rails migrations. Rows inserted during server startup tasks (Java) are excluded : rules, profiles, metrics, ...
--- Note: do not split a request on multiple lines.
+-- Note: do not split a request on multiple lines and do not end with ;
INSERT INTO ACTIVE_DASHBOARDS(ID, DASHBOARD_ID, USER_ID, ORDER_INDEX) VALUES (1, 1, null, 1)
ALTER TABLE ACTIVE_DASHBOARDS ALTER COLUMN ID RESTART WITH 2
@@ -161,6 +161,8 @@ INSERT INTO SCHEMA_MIGRATIONS(VERSION) VALUES ('214')
INSERT INTO SCHEMA_MIGRATIONS(VERSION) VALUES ('215')
INSERT INTO SCHEMA_MIGRATIONS(VERSION) VALUES ('216')
INSERT INTO SCHEMA_MIGRATIONS(VERSION) VALUES ('217')
+INSERT INTO SCHEMA_MIGRATIONS(VERSION) VALUES ('220')
+INSERT INTO SCHEMA_MIGRATIONS(VERSION) VALUES ('221')
INSERT INTO USERS(ID, LOGIN, NAME, EMAIL, CRYPTED_PASSWORD, SALT, CREATED_AT, UPDATED_AT, REMEMBER_TOKEN, REMEMBER_TOKEN_EXPIRES_AT) VALUES (1, 'admin', 'Administrator', '', 'a373a0e667abb2604c1fd571eb4ad47fe8cc0878', '48bc4b0d93179b5103fd3885ea9119498e9d161b', '2011-09-26 22:27:48.0', '2011-09-26 22:27:48.0', null, null)
ALTER TABLE USERS ALTER COLUMN ID RESTART WITH 2
diff --git a/sonar-core/src/main/resources/org/sonar/persistence/schema-derby.ddl b/sonar-core/src/main/resources/org/sonar/persistence/schema-derby.ddl
index be3e9ffdb6b..df60c0d6d24 100644
--- a/sonar-core/src/main/resources/org/sonar/persistence/schema-derby.ddl
+++ b/sonar-core/src/main/resources/org/sonar/persistence/schema-derby.ddl
@@ -41,7 +41,7 @@ CREATE TABLE "RULES" ("ID" INTEGER NOT NULL GENERATED BY DEFAULT AS IDENTITY (ST
CREATE TABLE "WIDGET_PROPERTIES" ("ID" INTEGER NOT NULL GENERATED BY DEFAULT AS IDENTITY (START WITH 1, INCREMENT BY 1), "WIDGET_ID" INTEGER NOT NULL, "KEE" VARCHAR(100), "TEXT_VALUE" VARCHAR(4000), "VALUE_TYPE" VARCHAR(20))
-CREATE TABLE "EVENTS" ("ID" INTEGER NOT NULL GENERATED BY DEFAULT AS IDENTITY (START WITH 1, INCREMENT BY 1), "NAME" VARCHAR(50), "RESOURCE_ID" INTEGER, "SNAPSHOT_ID" INTEGER, "CATEGORY" VARCHAR(50), "EVENT_DATE" TIMESTAMP, "CREATED_AT" TIMESTAMP, "DESCRIPTION" VARCHAR(3072), "DATA" VARCHAR(4000))
+CREATE TABLE "EVENTS" ("ID" INTEGER NOT NULL GENERATED BY DEFAULT AS IDENTITY (START WITH 1, INCREMENT BY 1), "NAME" VARCHAR(400), "RESOURCE_ID" INTEGER, "SNAPSHOT_ID" INTEGER, "CATEGORY" VARCHAR(50), "EVENT_DATE" TIMESTAMP, "CREATED_AT" TIMESTAMP, "DESCRIPTION" VARCHAR(4000))
CREATE TABLE "ALERTS" ("ID" INTEGER NOT NULL GENERATED BY DEFAULT AS IDENTITY (START WITH 1, INCREMENT BY 1), "PROFILE_ID" INTEGER, "METRIC_ID" INTEGER, "OPERATOR" VARCHAR(3), "VALUE_ERROR" VARCHAR(64), "VALUE_WARNING" VARCHAR(64))
diff --git a/sonar-core/src/test/java/org/sonar/persistence/DefaultDatabaseTest.java b/sonar-core/src/test/java/org/sonar/persistence/DefaultDatabaseTest.java
index 94361873195..05922626fae 100644
--- a/sonar-core/src/test/java/org/sonar/persistence/DefaultDatabaseTest.java
+++ b/sonar-core/src/test/java/org/sonar/persistence/DefaultDatabaseTest.java
@@ -19,10 +19,13 @@
*/
package org.sonar.persistence;
+import org.apache.commons.dbcp.BasicDataSource;
import org.hamcrest.core.Is;
import org.junit.Test;
import org.sonar.api.config.Settings;
+import java.sql.DriverManager;
+import java.sql.SQLException;
import java.util.Properties;
import static org.junit.Assert.assertThat;
@@ -52,28 +55,24 @@ public class DefaultDatabaseTest {
}
@Test
- public void shouldGetCommonsDbcpProperties() {
- Settings settings = new Settings();
- settings.setProperty("sonar.jdbc.driverClassName", "my.Driver");
- settings.setProperty("sonar.jdbc.username", "me");
- settings.setProperty("sonar.jdbc.maxActive", "5");
-
- DefaultDatabase db = new DefaultDatabase(settings);
- Properties props = db.getCommonsDbcpProperties();
+ public void shouldExtractCommonsDbcpProperties() {
+ Properties props = new Properties();
+ props.setProperty("sonar.jdbc.driverClassName", "my.Driver");
+ props.setProperty("sonar.jdbc.username", "me");
+ props.setProperty("sonar.jdbc.maxActive", "5");
- assertThat(props.getProperty("username"), Is.is("me"));
- assertThat(props.getProperty("driverClassName"), Is.is("my.Driver"));
- assertThat(props.getProperty("maxActive"), Is.is("5"));
+ Properties commonsDbcpProps = DefaultDatabase.extractCommonsDbcpProperties(props);
- // default value
- assertThat(props.getProperty("password"), Is.is("sonar"));
+ assertThat(commonsDbcpProps.getProperty("username"), Is.is("me"));
+ assertThat(commonsDbcpProps.getProperty("driverClassName"), Is.is("my.Driver"));
+ assertThat(commonsDbcpProps.getProperty("maxActive"), Is.is("5"));
}
@Test
public void shouldCompleteProperties() {
Settings settings = new Settings();
- DefaultDatabase db = new DefaultDatabase(settings){
+ DefaultDatabase db = new DefaultDatabase(settings) {
@Override
protected void doCompleteProperties(Properties properties) {
properties.setProperty("sonar.jdbc.maxActive", "2");
@@ -84,4 +83,28 @@ public class DefaultDatabaseTest {
assertThat(props.getProperty("sonar.jdbc.maxActive"), Is.is("2"));
}
+
+ @Test
+ public void shouldStart() throws SQLException {
+ Settings settings = new Settings();
+ settings.setProperty("sonar.jdbc.url", "jdbc:derby:memory:sonar;create=true;user=sonar;password=sonar");
+ settings.setProperty("sonar.jdbc.driverClassName", "org.apache.derby.jdbc.EmbeddedDriver");
+ settings.setProperty("sonar.jdbc.username", "sonar");
+ settings.setProperty("sonar.jdbc.password", "sonar");
+ settings.setProperty("sonar.jdbc.maxActive", "1");
+
+ try {
+ DefaultDatabase db = new DefaultDatabase(settings);
+ db.start();
+
+ assertThat(db.getDialect().getId(), Is.is("derby"));
+ assertThat(((BasicDataSource) db.getDataSource()).getMaxActive(), Is.is(1));
+ } finally {
+ try {
+ DriverManager.getConnection("jdbc:derby:memory:sonar;drop=true");
+ } catch (Exception e) {
+ // silently ignore
+ }
+ }
+ }
}