Parcourir la source

Replacing Derby with H2

tags/3.2
David Gageot il y a 12 ans
Parent
révision
25e954167d
37 fichiers modifiés avec 298 ajouts et 816 suppressions
  1. 4
    20
      pom.xml
  2. 3
    3
      sonar-application/assembly.xml
  3. 2
    2
      sonar-application/pom.xml
  4. 7
    10
      sonar-application/src/main/assembly/conf/sonar.properties
  5. 5
    12
      sonar-core/pom.xml
  6. 1
    1
      sonar-core/src/main/java/org/sonar/core/persistence/DatabaseMigrator.java
  7. 1
    1
      sonar-core/src/main/java/org/sonar/core/persistence/DdlUtils.java
  8. 9
    4
      sonar-core/src/main/java/org/sonar/core/persistence/DefaultDatabase.java
  9. 1
    1
      sonar-core/src/main/java/org/sonar/core/persistence/dialect/DialectUtils.java
  10. 7
    41
      sonar-core/src/main/java/org/sonar/core/persistence/dialect/H2.java
  11. 0
    0
      sonar-core/src/main/resources/org/sonar/core/persistence/rows-h2.sql
  12. 23
    206
      sonar-core/src/main/resources/org/sonar/core/persistence/schema-h2.ddl
  13. 2
    2
      sonar-core/src/test/java/org/sonar/core/config/ConfigurationUtilsTest.java
  14. 14
    10
      sonar-core/src/test/java/org/sonar/core/persistence/DaoTestCase.java
  15. 10
    7
      sonar-core/src/test/java/org/sonar/core/persistence/DatabaseCommands.java
  16. 22
    25
      sonar-core/src/test/java/org/sonar/core/persistence/DdlUtilsTest.java
  17. 8
    16
      sonar-core/src/test/java/org/sonar/core/persistence/DefaultDatabaseTest.java
  18. 0
    52
      sonar-core/src/test/java/org/sonar/core/persistence/DerbyUtils.java
  19. 15
    60
      sonar-core/src/test/java/org/sonar/core/persistence/H2Database.java
  20. 3
    7
      sonar-core/src/test/java/org/sonar/core/persistence/H2DatabaseTest.java
  21. 2
    6
      sonar-core/src/test/java/org/sonar/core/persistence/MyBatisTest.java
  22. 6
    6
      sonar-core/src/test/java/org/sonar/core/persistence/dialect/H2Test.java
  23. 11
    35
      sonar-core/src/test/java/org/sonar/jpa/test/AbstractDbUnitTestCase.java
  24. 12
    3
      sonar-plugin-api/src/main/java/org/sonar/api/database/DatabaseProperties.java
  25. 1
    1
      sonar-server/h2-start.bat
  26. 1
    1
      sonar-server/h2-start.sh
  27. 10
    20
      sonar-server/pom.xml
  28. 0
    0
      sonar-server/src/dev/h2/conf/logback.xml
  29. 5
    5
      sonar-server/src/dev/h2/conf/sonar.properties
  30. 38
    123
      sonar-server/src/main/java/org/sonar/server/database/EmbeddedDatabase.java
  31. 10
    5
      sonar-server/src/main/java/org/sonar/server/database/EmbeddedDatabaseFactory.java
  32. 1
    1
      sonar-server/src/main/java/org/sonar/server/plugins/BatchResourcesServlet.java
  33. 19
    94
      sonar-server/src/test/java/org/sonar/server/database/EmbeddedDatabaseTest.java
  34. 30
    31
      sonar-server/src/test/java/org/sonar/server/filters/FilterExecutorTest.java
  35. 1
    3
      sonar-server/src/test/java/org/sonar/server/plugins/BatchResourcesServletTest.java
  36. 2
    2
      sonar-testing-harness/pom.xml
  37. 12
    0
      sonar-web-test/pom.xml

+ 4
- 20
pom.xml Voir le fichier

@@ -81,13 +81,7 @@
</prerequisites>

<properties>
<!--
Warning before upgrading Derby to 10.8 : new conversion from BOOLEAN to CHAR.
"If you use setBoolean() or setObject() with a CHAR(1) datatype you must change your code and use setInt() or Derby will try to store "true" or
"false" strings."
-->
<derby.version>10.7.1.1</derby.version>

<h2.version>1.3.167</h2.version>
<jetty.version>6.1.25</jetty.version>
<sonar.skippedModules>sonar-gwt-api,sonar-core-gwt</sonar.skippedModules>
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
@@ -792,19 +786,9 @@
<version>0.9.30</version>
</dependency>
<dependency>
<groupId>org.apache.derby</groupId>
<artifactId>derbyclient</artifactId>
<version>${derby.version}</version>
</dependency>
<dependency>
<groupId>org.apache.derby</groupId>
<artifactId>derby</artifactId>
<version>${derby.version}</version>
</dependency>
<dependency>
<groupId>org.apache.derby</groupId>
<artifactId>derbynet</artifactId>
<version>${derby.version}</version>
<groupId>com.h2database</groupId>
<artifactId>h2</artifactId>
<version>${h2.version}</version>
</dependency>
<dependency>
<!--

+ 3
- 3
sonar-application/assembly.xml Voir le fichier

@@ -13,7 +13,7 @@
<excludes>
<exclude>org.codehaus.sonar:sonar-server</exclude>
<exclude>mysql:mysql-connector-java</exclude>
<exclude>org.apache.derby:derbyclient</exclude>
<exclude>com.h2database:h2</exclude>
<exclude>postgresql:postgresql</exclude>
<exclude>net.sourceforge.jtds:jtds</exclude>
<exclude>org.codehaus.sonar.plugins:*</exclude>
@@ -45,9 +45,9 @@
<scope>runtime</scope>
</dependencySet>
<dependencySet>
<outputDirectory>extensions/jdbc-driver/derby/</outputDirectory>
<outputDirectory>extensions/jdbc-driver/h2/</outputDirectory>
<includes>
<include>org.apache.derby:derbyclient</include>
<include>com.h2database:h2</include>
</includes>
<unpack>false</unpack>
<scope>runtime</scope>

+ 2
- 2
sonar-application/pom.xml Voir le fichier

@@ -93,8 +93,8 @@
<scope>runtime</scope>
</dependency>
<dependency>
<groupId>org.apache.derby</groupId>
<artifactId>derbyclient</artifactId>
<groupId>com.h2database</groupId>
<artifactId>h2</artifactId>
<scope>runtime</scope>
</dependency>
<dependency>

+ 7
- 10
sonar-application/src/main/assembly/conf/sonar.properties Voir le fichier

@@ -26,7 +26,7 @@
#-----------------------------------------------------------------------
# DATABASE
#
# IMPORTANT : the embedded database Derby is used by default.
# IMPORTANT : the embedded database H2 is used by default.
# It is recommended for tests only. Please use an external database
# for production environment (MySQL, Oracle, Postgresql, SQLServer)
#
@@ -38,22 +38,19 @@
sonar.jdbc.username: sonar
sonar.jdbc.password: sonar

#----- Embedded database Derby
#----- Embedded database H2
# Note : it does not accept connections from remote hosts, so the
# sonar server and the maven plugin must be executed on the same host.
# Comment the following line to deactivate the default embedded database.
sonar.jdbc.url: jdbc:derby://localhost:1527/sonar;create=true
#sonar.jdbc.driverClassName: org.apache.derby.jdbc.ClientDriver
sonar.jdbc.url: jdbc:h2:tcp://localhost:9092/sonar
#sonar.jdbc.driverClassName: org.h2.Driver
#sonar.jdbc.validationQuery: values(1)

# directory containing Derby database files. By default it's the /data directory in the sonar installation.
# directory containing H2 database files. By default it's the /data directory in the sonar installation.
#sonar.embeddedDatabase.dataDir:
# derby embedded database server listening port, defaults to 1527
#sonar.derby.drda.portNumber: 1527

# uncomment to accept connections from remote hosts. Ba default it only accepts localhost connections.
#sonar.derby.drda.host: 0.0.0.0
# H2 embedded database server listening port, defaults to 9092
#sonar.embeddedDatabase.port: 9092


#----- MySQL 5.x/6.x

+ 5
- 12
sonar-core/pom.xml Voir le fichier

@@ -41,18 +41,6 @@
<groupId>org.mybatis</groupId>
<artifactId>mybatis</artifactId>
</dependency>
<dependency>
<groupId>org.apache.derby</groupId>
<artifactId>derby</artifactId>
</dependency>
<dependency>
<groupId>org.apache.derby</groupId>
<artifactId>derbyclient</artifactId>
</dependency>
<dependency>
<groupId>org.apache.derby</groupId>
<artifactId>derbynet</artifactId>
</dependency>
<dependency>
<groupId>org.codehaus.sonar</groupId>
<artifactId>sonar-update-center-common</artifactId>
@@ -160,6 +148,11 @@
<artifactId>jtds</artifactId>
<scope>test</scope>
</dependency>
<dependency>
<groupId>com.h2database</groupId>
<artifactId>h2</artifactId>
<scope>test</scope>
</dependency>
</dependencies>

<profiles>

+ 1
- 1
sonar-core/src/main/java/org/sonar/core/persistence/DatabaseMigrator.java Voir le fichier

@@ -26,7 +26,7 @@ import org.sonar.api.ServerComponent;
import java.sql.Connection;

/**
* Restore schema by executing DDL scripts. Only Derby database is supported.
* Restore schema by executing DDL scripts. Only H2 database is supported.
* Other databases are created by Ruby on Rails migrations.
*
* @since 2.12

+ 1
- 1
sonar-core/src/main/java/org/sonar/core/persistence/DdlUtils.java Voir le fichier

@@ -37,7 +37,7 @@ public final class DdlUtils {
}

public static boolean supportsDialect(String dialect) {
return "derby".equals(dialect);
return "h2".equals(dialect);
}

/**

+ 9
- 4
sonar-core/src/main/java/org/sonar/core/persistence/DefaultDatabase.java Voir le fichier

@@ -27,10 +27,15 @@ import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.sonar.api.config.Settings;
import org.sonar.api.database.DatabaseProperties;
import org.sonar.core.persistence.dialect.*;
import org.sonar.core.persistence.dialect.Dialect;
import org.sonar.core.persistence.dialect.DialectUtils;
import org.sonar.core.persistence.dialect.H2;
import org.sonar.core.persistence.dialect.Oracle;
import org.sonar.core.persistence.dialect.PostgreSql;
import org.sonar.jpa.session.CustomHibernateConnectionProvider;

import javax.sql.DataSource;

import java.sql.SQLException;
import java.util.Arrays;
import java.util.List;
@@ -84,8 +89,8 @@ public class DefaultDatabase implements Database {
if (dialect == null) {
throw new IllegalStateException("Can not guess the JDBC dialect. Please check the property sonar.jdbc.url.");
}
if (Derby.ID.equals(dialect.getId())) {
LoggerFactory.getLogger(DefaultDatabase.class).warn("Derby database should be used for evaluation purpose only");
if (H2.ID.equals(dialect.getId())) {
LoggerFactory.getLogger(DefaultDatabase.class).warn("H2 database should be used for evaluation purpose only");
}
if (!properties.containsKey("sonar.jdbc.driverClassName")) {
properties.setProperty("sonar.jdbc.driverClassName", dialect.getDefaultDriverClassName());
@@ -107,7 +112,7 @@ public class DefaultDatabase implements Database {
}
}

private void initDatasource() throws Exception {//NOSONAR this exception is thrown by BasicDataSourceFactory
private void initDatasource() throws Exception {// NOSONAR this exception is thrown by BasicDataSourceFactory
// but it's correctly caught by start()

LOG.info("Create JDBC datasource");

+ 1
- 1
sonar-core/src/main/java/org/sonar/core/persistence/dialect/DialectUtils.java Voir le fichier

@@ -32,7 +32,7 @@ public final class DialectUtils {
private DialectUtils() {
}

private static final Dialect[] DIALECTS = new Dialect[]{new Derby(), new MySql(), new Oracle(), new PostgreSql(), new MsSql()};
private static final Dialect[] DIALECTS = new Dialect[] {new H2(), new MySql(), new Oracle(), new PostgreSql(), new MsSql()};

public static Dialect find(final String dialectId, final String jdbcConnectionUrl) {
Dialect match = StringUtils.isNotBlank(dialectId) ? findById(dialectId) : findByJdbcUrl(jdbcConnectionUrl);

sonar-core/src/main/java/org/sonar/core/persistence/dialect/Derby.java → sonar-core/src/main/java/org/sonar/core/persistence/dialect/H2.java Voir le fichier

@@ -20,25 +20,21 @@
package org.sonar.core.persistence.dialect;

import org.apache.commons.lang.StringUtils;
import org.hibernate.dialect.DerbyDialect;
import org.hibernate.id.IdentityGenerator;
import org.sonar.api.database.DatabaseProperties;

import java.sql.Types;
import org.hibernate.dialect.H2Dialect;

/**
* @since 1.12
*/
public class Derby implements Dialect {
public class H2 implements Dialect {

public static final String ID = "derby";
public static final String ID = "h2";

public String getId() {
return ID;
}

public String getActiveRecordDialectCode() {
return "derby";
return "h2";
}

public String getActiveRecordJdbcAdapter() {
@@ -46,51 +42,21 @@ public class Derby implements Dialect {
}

public Class<? extends org.hibernate.dialect.Dialect> getHibernateDialectClass() {
return DerbyWithDecimalDialect.class;
return H2Dialect.class;
}

public boolean matchesJdbcURL(String jdbcConnectionURL) {
return StringUtils.startsWithIgnoreCase(jdbcConnectionURL, "jdbc:derby:");
return StringUtils.startsWithIgnoreCase(jdbcConnectionURL, "jdbc:h2:");
}

public String getDefaultDriverClassName() {
return "org.apache.derby.jdbc.ClientDriver";
return "org.h2.Driver";
}

public String getConnectionInitStatement(String schema) {
return null;
}

public static class DerbyWithDecimalDialect extends DerbyDialect {
public DerbyWithDecimalDialect() {
super();
registerColumnType(Types.DOUBLE, "decimal");
registerColumnType(Types.VARCHAR, DatabaseProperties.MAX_TEXT_SIZE, "clob");
registerColumnType(Types.VARBINARY, "blob");

// Not possible to do alter column types in Derby
registerColumnType(Types.BIGINT, "integer");

registerColumnType(Types.BIT, "boolean");
}

@Override
public String toBooleanValueString(boolean bool) {
return bool ? "true" : "false";
}

/**
* To be compliant with Oracle, we define on each model (ch.hortis.sonar.model classes)
* a sequence generator. It works on mySQL because strategy = GenerationType.AUTO, so
* it equals GenerationType.IDENTITY.
* But on derby, AUTO becomes TABLE instead of IDENTITY. So we explicitly change this behavior.
*/
@Override
public Class getNativeIdentifierGeneratorClass() {
return IdentityGenerator.class;
}
}

public String getTrueSqlValue() {
return "true";
}

sonar-core/src/main/resources/org/sonar/core/persistence/rows-derby.sql → sonar-core/src/main/resources/org/sonar/core/persistence/rows-h2.sql Voir le fichier


sonar-core/src/main/resources/org/sonar/core/persistence/schema-derby.ddl → sonar-core/src/main/resources/org/sonar/core/persistence/schema-h2.ddl Voir le fichier

@@ -1,6 +1,6 @@
-- Structure of Sonar Database

-- Initially this file has been generated from existing H2 DB
-- Should be updated manually, during addition of new migrations

CREATE TABLE "QUALITY_MODELS" (
@@ -24,13 +24,13 @@ CREATE TABLE "CRITERIA" (
"FAMILY" VARCHAR(100),
"KEE" VARCHAR(100),
"OPERATOR" VARCHAR(20),
"VALUE" DECIMAL(30,20),
"VALUE" DOUBLE,
"TEXT_VALUE" VARCHAR(256),
"VARIATION" BOOLEAN
);

CREATE TABLE "DEPENDENCIES" (
"ID" INTEGER NOT NULL GENERATED BY DEFAULT AS IDENTITY (START WITH 1, INCREMENT BY 1),
"ID" BIGINT NOT NULL GENERATED BY DEFAULT AS IDENTITY (START WITH 1, INCREMENT BY 1),
"FROM_SNAPSHOT_ID" INTEGER,
"FROM_RESOURCE_ID" INTEGER,
"TO_SNAPSHOT_ID" INTEGER,
@@ -102,9 +102,9 @@ CREATE TABLE "FILTER_COLUMNS" (

CREATE TABLE "MEASURE_DATA" (
"ID" INTEGER NOT NULL GENERATED BY DEFAULT AS IDENTITY (START WITH 1, INCREMENT BY 1),
"MEASURE_ID" INTEGER,
"MEASURE_ID" BIGINT,
"SNAPSHOT_ID" INTEGER,
"DATA" BLOB(2147483647)
"DATA" BINARY(167772150)
);

CREATE TABLE "GROUPS" (
@@ -171,7 +171,7 @@ CREATE TABLE "RULES" (
"ID" INTEGER NOT NULL GENERATED BY DEFAULT AS IDENTITY (START WITH 1, INCREMENT BY 1),
"PLUGIN_RULE_KEY" VARCHAR(200) NOT NULL,
"PLUGIN_NAME" VARCHAR(255) NOT NULL,
"DESCRIPTION" CLOB(2147483647),
"DESCRIPTION" VARCHAR(16777215),
"PRIORITY" INTEGER,
"ENABLED" BOOLEAN,
"CARDINALITY" VARCHAR(10),
@@ -238,7 +238,7 @@ CREATE TABLE "REVIEW_COMMENTS" (
"UPDATED_AT" TIMESTAMP,
"REVIEW_ID" INTEGER,
"USER_ID" INTEGER,
"REVIEW_TEXT" CLOB(2147483647)
"REVIEW_TEXT" VARCHAR(16777215)
);

CREATE TABLE "ACTIVE_RULE_CHANGES" (
@@ -254,8 +254,8 @@ CREATE TABLE "ACTIVE_RULE_CHANGES" (
);

CREATE TABLE "PROJECT_MEASURES" (
"ID" INTEGER NOT NULL GENERATED BY DEFAULT AS IDENTITY (START WITH 1, INCREMENT BY 1),
"VALUE" DECIMAL(30,20),
"ID" BIGINT NOT NULL GENERATED BY DEFAULT AS IDENTITY (START WITH 1, INCREMENT BY 1),
"VALUE" DOUBLE,
"METRIC_ID" INTEGER NOT NULL,
"SNAPSHOT_ID" INTEGER,
"RULE_ID" INTEGER,
@@ -271,11 +271,11 @@ CREATE TABLE "PROJECT_MEASURES" (
"RULE_PRIORITY" INTEGER,
"CHARACTERISTIC_ID" INTEGER,
"PERSON_ID" INTEGER,
"VARIATION_VALUE_1" DECIMAL(30,20),
"VARIATION_VALUE_2" DECIMAL(30,20),
"VARIATION_VALUE_3" DECIMAL(30,20),
"VARIATION_VALUE_4" DECIMAL(30,20),
"VARIATION_VALUE_5" DECIMAL(30,20)
"VARIATION_VALUE_1" DOUBLE,
"VARIATION_VALUE_2" DOUBLE,
"VARIATION_VALUE_3" DOUBLE,
"VARIATION_VALUE_4" DOUBLE,
"VARIATION_VALUE_5" DOUBLE
);

CREATE TABLE "SNAPSHOT_SOURCES" (
@@ -321,10 +321,10 @@ CREATE TABLE "REVIEWS" (
);

CREATE TABLE "MANUAL_MEASURES" (
"ID" INTEGER NOT NULL GENERATED BY DEFAULT AS IDENTITY (START WITH 1, INCREMENT BY 1),
"ID" BIGINT NOT NULL GENERATED BY DEFAULT AS IDENTITY (START WITH 1, INCREMENT BY 1),
"METRIC_ID" INTEGER NOT NULL,
"RESOURCE_ID" INTEGER,
"VALUE" DECIMAL(30,20),
"VALUE" DOUBLE,
"TEXT_VALUE" VARCHAR(4000),
"USER_LOGIN" VARCHAR(40),
"DESCRIPTION" VARCHAR(4000),
@@ -343,7 +343,7 @@ CREATE TABLE "ACTIVE_RULES" (
CREATE TABLE "NOTIFICATIONS" (
"ID" INTEGER NOT NULL GENERATED BY DEFAULT AS IDENTITY (START WITH 1, INCREMENT BY 1),
"CREATED_AT" TIMESTAMP,
"DATA" BLOB(2147483647)
"DATA" BINARY(167772150)
);

CREATE TABLE "USER_ROLES" (
@@ -371,7 +371,7 @@ CREATE TABLE "CHARACTERISTIC_PROPERTIES" (
"ID" INTEGER NOT NULL GENERATED BY DEFAULT AS IDENTITY (START WITH 1, INCREMENT BY 1),
"CHARACTERISTIC_ID" INTEGER,
"KEE" VARCHAR(100),
"VALUE" DECIMAL(30,20),
"VALUE" DOUBLE,
"TEXT_VALUE" VARCHAR(4000)
);

@@ -421,7 +421,7 @@ CREATE TABLE "RULE_FAILURES" (
"FAILURE_LEVEL" INTEGER NOT NULL,
"MESSAGE" VARCHAR(4000),
"LINE" INTEGER,
"COST" DECIMAL(30,20),
"COST" DOUBLE,
"CREATED_AT" TIMESTAMP,
"CHECKSUM" VARCHAR(1000),
"PERMANENT_ID" INTEGER,
@@ -441,8 +441,8 @@ CREATE TABLE "METRICS" (
"USER_MANAGED" BOOLEAN DEFAULT FALSE,
"ENABLED" BOOLEAN DEFAULT TRUE,
"ORIGIN" VARCHAR(3),
"WORST_VALUE" DECIMAL(30,20),
"BEST_VALUE" DECIMAL(30,20),
"WORST_VALUE" DOUBLE,
"BEST_VALUE" DOUBLE,
"OPTIMIZED_BEST_VALUE" BOOLEAN,
"HIDDEN" BOOLEAN,
"DELETE_HISTORICAL_DATA" BOOLEAN
@@ -486,7 +486,7 @@ CREATE TABLE "ACTIVE_RULE_NOTES" (
"ID" INTEGER NOT NULL GENERATED BY DEFAULT AS IDENTITY (START WITH 1, INCREMENT BY 1),
"ACTIVE_RULE_ID" INTEGER,
"USER_LOGIN" VARCHAR(40),
"DATA" BLOB(2147483647),
"DATA" BINARY(167772150),
"CREATED_AT" TIMESTAMP,
"UPDATED_AT" TIMESTAMP
);
@@ -495,7 +495,7 @@ CREATE TABLE "RULE_NOTES" (
"ID" INTEGER NOT NULL GENERATED BY DEFAULT AS IDENTITY (START WITH 1, INCREMENT BY 1),
"RULE_ID" INTEGER,
"USER_LOGIN" VARCHAR(40),
"DATA" BLOB(2147483647),
"DATA" BINARY(167772150),
"CREATED_AT" TIMESTAMP,
"UPDATED_AT" TIMESTAMP
);
@@ -507,194 +507,3 @@ CREATE TABLE "AUTHORS" (
"CREATED_AT" TIMESTAMP,
"UPDATED_AT" TIMESTAMP
);



CREATE INDEX "GROUP_ROLES_RESOURCE" ON "GROUP_ROLES" ("RESOURCE_ID");

CREATE INDEX "GROUP_ROLES_GROUP" ON "GROUP_ROLES" ("GROUP_ID");

CREATE INDEX "USER_ROLES_RESOURCE" ON "USER_ROLES" ("RESOURCE_ID");

CREATE INDEX "USER_ROLES_USER" ON "USER_ROLES" ("USER_ID");

CREATE INDEX "DUPLICATIONS_INDEX_HASH" ON "DUPLICATIONS_INDEX" ("HASH");

CREATE INDEX "DUPLICATIONS_INDEX_SID" ON "DUPLICATIONS_INDEX" ("SNAPSHOT_ID");

CREATE INDEX "DUPLICATIONS_INDEX_PSID" ON "DUPLICATIONS_INDEX" ("PROJECT_SNAPSHOT_ID");

CREATE INDEX "SNAP_SOURCES_SNAPSHOT_ID" ON "SNAPSHOT_SOURCES" ("SNAPSHOT_ID");

CREATE INDEX "INDEX_GROUPS_USERS_ON_GROUP_ID" ON "GROUPS_USERS" ("GROUP_ID");

CREATE INDEX "INDEX_GROUPS_USERS_ON_USER_ID" ON "GROUPS_USERS" ("USER_ID");

CREATE INDEX "DEPS_TO_SID" ON "DEPENDENCIES" ("TO_SNAPSHOT_ID");

CREATE INDEX "DEPS_FROM_SID" ON "DEPENDENCIES" ("FROM_SNAPSHOT_ID");

CREATE INDEX "DEPS_PRJ_SID" ON "DEPENDENCIES" ("PROJECT_SNAPSHOT_ID");

CREATE INDEX "MEASURES_SID_METRIC" ON "PROJECT_MEASURES" ("SNAPSHOT_ID", "METRIC_ID");

CREATE INDEX "ACTIVE_RULE_CHANGES_PID" ON "ACTIVE_RULE_CHANGES" ("PROFILE_ID");

CREATE INDEX "CHARACTERISTIC_PROPERTIES_CID" ON "CHARACTERISTIC_PROPERTIES" ("CHARACTERISTIC_ID");

CREATE UNIQUE INDEX "METRICS_UNIQUE_NAME" ON "METRICS" ("NAME");

CREATE INDEX "ACTIVE_RULE_PARAM_CHANGES_CID" ON "ACTIVE_RULE_PARAM_CHANGES" ("ACTIVE_RULE_CHANGE_ID");

CREATE INDEX "M_DATA_SID" ON "MEASURE_DATA" ("SNAPSHOT_ID");

CREATE INDEX "MEASURE_DATA_MEASURE_ID" ON "MEASURE_DATA" ("MEASURE_ID");

CREATE INDEX "RF_PERMANENT_ID" ON "RULE_FAILURES" ("PERMANENT_ID");

CREATE INDEX "RULE_FAILURE_RULE_ID" ON "RULE_FAILURES" ("RULE_ID");

CREATE INDEX "RULE_FAILURE_SNAPSHOT_ID" ON "RULE_FAILURES" ("SNAPSHOT_ID");

CREATE INDEX "EVENTS_SNAPSHOT_ID" ON "EVENTS" ("SNAPSHOT_ID");

CREATE INDEX "EVENTS_RESOURCE_ID" ON "EVENTS" ("RESOURCE_ID");

CREATE INDEX "WIDGETS_WIDGETKEY" ON "WIDGETS" ("WIDGET_KEY");

CREATE INDEX "WIDGETS_DASHBOARDS" ON "WIDGETS" ("DASHBOARD_ID");

CREATE INDEX "SNAPSHOTS_QUALIFIER" ON "SNAPSHOTS" ("QUALIFIER");

CREATE INDEX "SNAPSHOTS_ROOT" ON "SNAPSHOTS" ("ROOT_SNAPSHOT_ID");

CREATE INDEX "SNAPSHOTS_PARENT" ON "SNAPSHOTS" ("PARENT_SNAPSHOT_ID");

CREATE INDEX "SNAPSHOT_PROJECT_ID" ON "SNAPSHOTS" ("PROJECT_ID");

CREATE INDEX "RULES_PARAMETERS_RULE_ID" ON "RULES_PARAMETERS" ("RULE_ID");

CREATE INDEX "ACTIVE_DASHBOARDS_DASHBOARDID" ON "ACTIVE_DASHBOARDS" ("DASHBOARD_ID");

CREATE INDEX "ACTIVE_DASHBOARDS_USERID" ON "ACTIVE_DASHBOARDS" ("USER_ID");

CREATE UNIQUE INDEX "UNIQUE_SCHEMA_MIGRATIONS" ON "SCHEMA_MIGRATIONS" ("VERSION");

CREATE INDEX "WIDGET_PROPERTIES_WIDGETS" ON "WIDGET_PROPERTIES" ("WIDGET_ID");

CREATE INDEX "PROPERTIES_KEY" ON "PROPERTIES" ("PROP_KEY");

CREATE INDEX "MANUAL_MEASURES_RESOURCE_ID" ON "MANUAL_MEASURES" ("RESOURCE_ID");

CREATE INDEX "PROJECTS_KEE" ON "PROJECTS" ("KEE");

CREATE INDEX "RESOURCE_INDEX_KEE" ON "RESOURCE_INDEX" ("KEE");

CREATE INDEX "RESOURCE_INDEX_RID" ON "RESOURCE_INDEX" ("RESOURCE_ID");

CREATE INDEX "INDEX_ACTION_PLANS_ON_PROJET_ID" ON "ACTION_PLANS" ("PROJECT_ID");

CREATE INDEX "INDEX_ACTION_PLANS_REVIEWS_ON_ACTION_PLAN_ID" ON "ACTION_PLANS_REVIEWS" ("ACTION_PLAN_ID");

CREATE INDEX "INDEX_ACTION_PLANS_REVIEWS_ON_REVIEW_ID" ON "ACTION_PLANS_REVIEWS" ("REVIEW_ID");

CREATE INDEX "INDEX_ACTIVE_RULE_NOTES_ON_ACTIVE_RULE_ID" ON "ACTIVE_RULE_NOTES" ("ACTIVE_RULE_ID");

CREATE INDEX "INDEX_RULE_NOTES_ON_ACTIVE_RULE_ID" ON "RULE_NOTES" ("RULE_ID");

CREATE INDEX "REVIEWS_RID" ON "REVIEWS" ("RESOURCE_ID");



ALTER TABLE "GROUP_ROLES" ADD CONSTRAINT "SQL110927104437910" PRIMARY KEY ("ID");

ALTER TABLE "REVIEWS" ADD CONSTRAINT "SQL110927104440700" PRIMARY KEY ("ID");

ALTER TABLE "RULES" ADD CONSTRAINT "SQL110927104437080" PRIMARY KEY ("ID");

ALTER TABLE "USER_ROLES" ADD CONSTRAINT "SQL110927104437940" PRIMARY KEY ("ID");

ALTER TABLE "SNAPSHOT_SOURCES" ADD CONSTRAINT "SQL110927104437590" PRIMARY KEY ("ID");

ALTER TABLE "NOTIFICATIONS" ADD CONSTRAINT "SQL110927104441030" PRIMARY KEY ("ID");

ALTER TABLE "DEPENDENCIES" ADD CONSTRAINT "SQL110927104438330" PRIMARY KEY ("ID");

ALTER TABLE "PROJECT_MEASURES" ADD CONSTRAINT "SQL110927104437040" PRIMARY KEY ("ID");

ALTER TABLE "ACTIVE_RULE_CHANGES" ADD CONSTRAINT "SQL110927104440770" PRIMARY KEY ("ID");

ALTER TABLE "CHARACTERISTIC_PROPERTIES" ADD CONSTRAINT "SQL110927104439660" PRIMARY KEY ("ID");

ALTER TABLE "QUALITY_MODELS" ADD CONSTRAINT "SQL110927104439440" PRIMARY KEY ("ID");

ALTER TABLE "USERS" ADD CONSTRAINT "SQL110927104437310" PRIMARY KEY ("ID");

ALTER TABLE "CRITERIA" ADD CONSTRAINT "SQL110927104438720" PRIMARY KEY ("ID");

ALTER TABLE "METRICS" ADD CONSTRAINT "SQL110927104436990" PRIMARY KEY ("ID");

ALTER TABLE "ACTIVE_RULE_PARAM_CHANGES" ADD CONSTRAINT "SQL110927104440790" PRIMARY KEY ("ID");

ALTER TABLE "MEASURE_DATA" ADD CONSTRAINT "SQL110927104437810" PRIMARY KEY ("ID");

ALTER TABLE "RULE_FAILURES" ADD CONSTRAINT "SQL110927104437100" PRIMARY KEY ("ID");

ALTER TABLE "EVENTS" ADD CONSTRAINT "SQL110927104437690" PRIMARY KEY ("ID");

ALTER TABLE "WIDGETS" ADD CONSTRAINT "SQL110927104439750" PRIMARY KEY ("ID");

ALTER TABLE "SNAPSHOTS" ADD CONSTRAINT "SQL110927104436960" PRIMARY KEY ("ID");

ALTER TABLE "ACTIVE_RULES" ADD CONSTRAINT "SQL110927104437550" PRIMARY KEY ("ID");

ALTER TABLE "CHARACTERISTICS" ADD CONSTRAINT "SQL110927104439450" PRIMARY KEY ("ID");

ALTER TABLE "RULES_PARAMETERS" ADD CONSTRAINT "SQL110927104437130" PRIMARY KEY ("ID");

ALTER TABLE "ACTIVE_DASHBOARDS" ADD CONSTRAINT "SQL110927104439710" PRIMARY KEY ("ID");

ALTER TABLE "FILTER_COLUMNS" ADD CONSTRAINT "SQL110927104438710" PRIMARY KEY ("ID");

ALTER TABLE "REVIEW_COMMENTS" ADD CONSTRAINT "SQL110927104440710" PRIMARY KEY ("ID");

ALTER TABLE "WIDGET_PROPERTIES" ADD CONSTRAINT "SQL110927104439770" PRIMARY KEY ("ID");

ALTER TABLE "PROPERTIES" ADD CONSTRAINT "SQL110927104437750" PRIMARY KEY ("ID");

ALTER TABLE "DASHBOARDS" ADD CONSTRAINT "SQL110927104439740" PRIMARY KEY ("ID");

ALTER TABLE "GROUPS" ADD CONSTRAINT "SQL110927104437850" PRIMARY KEY ("ID");

ALTER TABLE "PROJECT_LINKS" ADD CONSTRAINT "SQL110927104437150" PRIMARY KEY ("ID");

ALTER TABLE "FILTERS" ADD CONSTRAINT "SQL110927104438690" PRIMARY KEY ("ID");

ALTER TABLE "MANUAL_MEASURES" ADD CONSTRAINT "SQL110927104440930" PRIMARY KEY ("ID");

ALTER TABLE "ALERTS" ADD CONSTRAINT "SQL110927104437730" PRIMARY KEY ("ID");

ALTER TABLE "PROJECTS" ADD CONSTRAINT "SQL110927104436930" PRIMARY KEY ("ID");

ALTER TABLE "RULES_PROFILES" ADD CONSTRAINT "SQL110927104437540" PRIMARY KEY ("ID");

ALTER TABLE "ACTIVE_RULE_PARAMETERS" ADD CONSTRAINT "SQL110927104437560" PRIMARY KEY ("ID");

ALTER TABLE "LOADED_TEMPLATES" ADD CONSTRAINT "SQL110927104437650" PRIMARY KEY ("ID");

ALTER TABLE "ACTION_PLANS" ADD CONSTRAINT "SQL110927104447650" PRIMARY KEY ("ID");

ALTER TABLE "ACTIVE_RULE_NOTES" ADD CONSTRAINT "SQL110927104847650" PRIMARY KEY ("ID");

ALTER TABLE "RULE_NOTES" ADD PRIMARY KEY ("ID");

ALTER TABLE "AUTHORS" ADD PRIMARY KEY ("ID");

ALTER TABLE "RESOURCE_INDEX" ADD PRIMARY KEY ("ID");

+ 2
- 2
sonar-core/src/test/java/org/sonar/core/config/ConfigurationUtilsTest.java Voir le fichier

@@ -36,13 +36,13 @@ public class ConfigurationUtilsTest {
input.setProperty("url", "${env:SONAR_JDBC_URL}");
input.setProperty("do_not_change", "${SONAR_JDBC_URL}");
Map<String, String> variables = Maps.newHashMap();
variables.put("SONAR_JDBC_URL", "jdbc:derby:mem");
variables.put("SONAR_JDBC_URL", "jdbc:h2:mem");

Properties output = ConfigurationUtils.interpolateVariables(input, variables);

assertThat(output.size(), is(3));
assertThat(output.getProperty("hello"), is("world"));
assertThat(output.getProperty("url"), is("jdbc:derby:mem"));
assertThat(output.getProperty("url"), is("jdbc:h2:mem"));
assertThat(output.getProperty("do_not_change"), is("${SONAR_JDBC_URL}"));

// input is not changed

+ 14
- 10
sonar-core/src/test/java/org/sonar/core/persistence/DaoTestCase.java Voir le fichier

@@ -60,17 +60,21 @@ public abstract class DaoTestCase {
public static void startDatabase() throws Exception {
Settings settings = new Settings();
settings.setProperties(Maps.fromProperties(System.getProperties()));
if (settings.hasKey("sonar.jdbc.dialect")) {
database = new DefaultDatabase(settings);
} else {
database = new InMemoryDatabase();
}
database.start();
boolean hasDialect = settings.hasKey("sonar.jdbc.dialect");

if ((null == database) || (hasDialect)) { // Create database only once per vm (Only for in mempry database)
if (hasDialect) {
database = new DefaultDatabase(settings);
} else {
database = new H2Database();
}
database.start();

myBatis = new MyBatis(database);
myBatis.start();
myBatis = new MyBatis(database);
myBatis.start();

databaseCommands = DatabaseCommands.forDialect(database.getDialect());
databaseCommands = DatabaseCommands.forDialect(database.getDialect());
}
}

@Before
@@ -145,7 +149,7 @@ public abstract class DaoTestCase {
}

protected final void checkTables(String testName, String... tables) {
checkTables(testName, new String[]{}, tables);
checkTables(testName, new String[] {}, tables);
}

protected final void checkTables(String testName, String[] excludedColumnNames, String... tables) {

+ 10
- 7
sonar-core/src/test/java/org/sonar/core/persistence/DatabaseCommands.java Voir le fichier

@@ -20,15 +20,19 @@
package org.sonar.core.persistence;

import org.apache.commons.lang.StringUtils;
import org.dbunit.dataset.datatype.DefaultDataTypeFactory;
import org.dbunit.dataset.datatype.IDataTypeFactory;
import org.dbunit.ext.h2.H2DataTypeFactory;
import org.dbunit.ext.mssql.InsertIdentityOperation;
import org.dbunit.ext.mssql.MsSqlDataTypeFactory;
import org.dbunit.ext.mysql.MySqlDataTypeFactory;
import org.dbunit.ext.oracle.Oracle10DataTypeFactory;
import org.dbunit.ext.postgresql.PostgresqlDataTypeFactory;
import org.dbunit.operation.DatabaseOperation;
import org.sonar.core.persistence.dialect.*;
import org.sonar.core.persistence.dialect.Dialect;
import org.sonar.core.persistence.dialect.MsSql;
import org.sonar.core.persistence.dialect.MySql;
import org.sonar.core.persistence.dialect.Oracle;
import org.sonar.core.persistence.dialect.PostgreSql;

import java.sql.Connection;
import java.sql.SQLException;
@@ -64,7 +68,7 @@ public abstract class DatabaseCommands {
return DatabaseOperation.CLEAN_INSERT;
}

static final DatabaseCommands DERBY = new DatabaseCommands(new DefaultDataTypeFactory()) {
static final DatabaseCommands H2 = new DatabaseCommands(new H2DataTypeFactory()) {
@Override
public String truncate(String table) {
return "TRUNCATE TABLE " + table;
@@ -117,7 +121,7 @@ public abstract class DatabaseCommands {
return Arrays.asList(
"DROP SEQUENCE " + sequence,
"CREATE SEQUENCE " + sequence + " INCREMENT BY 1 MINVALUE 1 START WITH 1"
);
);
}

@Override
@@ -143,10 +147,9 @@ public abstract class DatabaseCommands {
}
};


public static DatabaseCommands forDialect(Dialect dialect) {
if (Derby.ID.equals(dialect.getId())) {
return DERBY;
if (org.sonar.core.persistence.dialect.H2.ID.equals(dialect.getId())) {
return H2;
}
if (MsSql.ID.equals(dialect.getId())) {
return MSSQL;

+ 22
- 25
sonar-core/src/test/java/org/sonar/core/persistence/DdlUtilsTest.java Voir le fichier

@@ -19,8 +19,7 @@
*/
package org.sonar.core.persistence;

import org.apache.derby.jdbc.EmbeddedDriver;
import org.hamcrest.core.Is;
import org.h2.Driver;
import org.junit.Test;

import java.sql.Connection;
@@ -28,39 +27,37 @@ import java.sql.DriverManager;
import java.sql.ResultSet;
import java.sql.SQLException;

import static org.hamcrest.Matchers.greaterThan;
import static org.junit.Assert.assertThat;
import static org.fest.assertions.Assertions.assertThat;

public class DdlUtilsTest {

static {
DerbyUtils.fixDerbyLogs();
}

@Test
public void shouldSupportOnlyDerby() {
assertThat(DdlUtils.supportsDialect("derby"), Is.is(true));
assertThat(DdlUtils.supportsDialect("mysql"), Is.is(false));
assertThat(DdlUtils.supportsDialect("oracle"), Is.is(false));
assertThat(DdlUtils.supportsDialect("mssql"), Is.is(false));
public void shouldSupportOnlyH2() {
assertThat(DdlUtils.supportsDialect("h2")).isTrue();
assertThat(DdlUtils.supportsDialect("mysql")).isFalse();
assertThat(DdlUtils.supportsDialect("oracle")).isFalse();
assertThat(DdlUtils.supportsDialect("mssql")).isFalse();
}

@Test
public void shouldCreateDerbySchema() throws SQLException {
int tables = 0;
DriverManager.registerDriver(new EmbeddedDriver());
Connection connection = DriverManager.getConnection("jdbc:derby:memory:sonar;create=true");
DdlUtils.createSchema(connection, "derby");
public void shouldCreateSchema() throws SQLException {
DriverManager.registerDriver(new Driver());
Connection connection = DriverManager.getConnection("jdbc:h2:mem:sonar_test");
DdlUtils.createSchema(connection, "h2");

int tables = countTables(connection);

connection.close();
assertThat(tables).isGreaterThan(30);
}

ResultSet resultSet = connection.getMetaData().getTables("", null, null, new String[]{"TABLE"});
private int countTables(Connection connection) throws SQLException {
int count = 0;
ResultSet resultSet = connection.getMetaData().getTables(null, null, null, new String[] {"TABLE"});
while (resultSet.next()) {
tables++;
count++;
}
resultSet.close();
connection.commit();
connection.close();
assertThat(tables, greaterThan(30));

DerbyUtils.dropInMemoryDatabase();
return count;
}
}

+ 8
- 16
sonar-core/src/test/java/org/sonar/core/persistence/DefaultDatabaseTest.java Voir le fichier

@@ -33,10 +33,6 @@ import static org.junit.Assert.assertThat;

public class DefaultDatabaseTest {

static {
DerbyUtils.fixDerbyLogs();
}

@Test
public void shouldLoadDefaultValues() {
DefaultDatabase db = new DefaultDatabase(new Settings());
@@ -45,8 +41,8 @@ public class DefaultDatabaseTest {
Properties props = db.getProperties();
assertThat(props.getProperty("sonar.jdbc.username"), Is.is("sonar"));
assertThat(props.getProperty("sonar.jdbc.password"), Is.is("sonar"));
assertThat(props.getProperty("sonar.jdbc.url"), Is.is("jdbc:derby://localhost:1527/sonar"));
assertThat(props.getProperty("sonar.jdbc.driverClassName"), Is.is("org.apache.derby.jdbc.ClientDriver"));
assertThat(props.getProperty("sonar.jdbc.url"), Is.is("jdbc:h2:tcp://localhost/sonar"));
assertThat(props.getProperty("sonar.jdbc.driverClassName"), Is.is("org.h2.Driver"));
}

@Test
@@ -97,21 +93,17 @@ public class DefaultDatabaseTest {
@Test
public void shouldStart() {
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.url", "jdbc:h2:mem:sonar");
settings.setProperty("sonar.jdbc.driverClassName", "org.h2.Driver");
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();
DefaultDatabase db = new DefaultDatabase(settings);
db.start();

assertThat(db.getDialect().getId(), Is.is("derby"));
assertThat(((BasicDataSource) db.getDataSource()).getMaxActive(), Is.is(1));
} finally {
DerbyUtils.dropInMemoryDatabase();
}
assertThat(db.getDialect().getId(), Is.is("h2"));
assertThat(((BasicDataSource) db.getDataSource()).getMaxActive(), Is.is(1));
}

@Test

+ 0
- 52
sonar-core/src/test/java/org/sonar/core/persistence/DerbyUtils.java Voir le fichier

@@ -1,52 +0,0 @@
/*
* Sonar, open source software quality management tool.
* Copyright (C) 2008-2012 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.core.persistence;

import java.io.OutputStream;
import java.sql.DriverManager;

public final class DerbyUtils {

private DerbyUtils() {
}

public static final OutputStream DEV_NULL = new OutputStream() {
@Override
public void write(int b) {
}
};

/**
* Disables Derby log.
* Note: in order to work properly this method should be called before Derby boot.
* See http://db.apache.org/derby/docs/10.7/ref/rrefproper33027.html
*/
public static void fixDerbyLogs() {
System.setProperty("derby.stream.error.field", "org.sonar.core.persistence.DerbyUtils.DEV_NULL");
}

public static void dropInMemoryDatabase() {
try {
DriverManager.getConnection("jdbc:derby:memory:sonar;drop=true");
} catch (Exception e) {
// silently ignore
}
}
}

sonar-core/src/test/java/org/sonar/core/persistence/InMemoryDatabase.java → sonar-core/src/test/java/org/sonar/core/persistence/H2Database.java Voir le fichier

@@ -22,33 +22,29 @@ package org.sonar.core.persistence;
import org.apache.commons.dbcp.BasicDataSource;
import org.apache.commons.dbcp.BasicDataSourceFactory;
import org.hibernate.cfg.Environment;
import org.sonar.core.persistence.dialect.Derby;
import org.sonar.core.persistence.dialect.Dialect;
import org.sonar.core.persistence.dialect.H2;
import org.sonar.jpa.session.CustomHibernateConnectionProvider;

import javax.sql.DataSource;
import java.sql.*;

import java.sql.Connection;
import java.sql.SQLException;
import java.util.Properties;

/**
* Derby in-memory database, used for unit tests only.
* H2 in-memory database, used for unit tests only.
*
* @since 2.12
* @since 3.2
*/
public class InMemoryDatabase implements Database {

static {
DerbyUtils.fixDerbyLogs();
}

public class H2Database implements Database {
private static BasicDataSource datasource;

public InMemoryDatabase start() {
public H2Database start() {
if (datasource == null) {
startDatabase();
createSchema();
}
truncateTables();
return this;
}

@@ -58,10 +54,10 @@ public class InMemoryDatabase implements Database {
void startDatabase() {
try {
Properties properties = new Properties();
properties.put("driverClassName", "org.apache.derby.jdbc.EmbeddedDriver");
properties.put("driverClassName", "org.h2.Driver");
properties.put("username", "sonar");
properties.put("password", "sonar");
properties.put("url", "jdbc:derby:memory:sonar2;create=true;user=sonar;password=sonar");
properties.put("url", "jdbc:h2:mem:sonar2");

// limit to 2 because of Hibernate and MyBatis
properties.put("maxActive", "2");
@@ -69,7 +65,7 @@ public class InMemoryDatabase implements Database {
datasource = (BasicDataSource) BasicDataSourceFactory.createDataSource(properties);

} catch (Exception e) {
throw new IllegalStateException("Fail to start Derby", e);
throw new IllegalStateException("Fail to start H2", e);
}
}

@@ -77,67 +73,26 @@ public class InMemoryDatabase implements Database {
Connection connection = null;
try {
connection = datasource.getConnection();
DdlUtils.createSchema(connection, "derby");

DdlUtils.createSchema(connection, "h2");
} catch (SQLException e) {
throw new IllegalStateException("Fail to create schema", e);

} finally {
closeQuietly(connection);
}
}

private void truncateTables() {
Connection connection = null;
try {
connection = datasource.getConnection();

DatabaseMetaData meta = connection.getMetaData();
Statement statement = connection.createStatement();

ResultSet res = meta.getTables(null, null, null, new String[]{"TABLE"});
while (res.next()) {
String tableName = res.getString("TABLE_NAME");
statement.executeUpdate("TRUNCATE TABLE " + tableName);
}
res.close();

// See https://issues.apache.org/jira/browse/DERBY-5403
res = meta.getColumns(null, null, null, "ID");
while (res.next()) {
String tableName = res.getString("TABLE_NAME");
statement.executeUpdate("ALTER TABLE " + tableName + " ALTER COLUMN ID RESTART WITH 1");
}
res.close();

statement.close();
} catch (SQLException e) {
throw new IllegalStateException("Fail to truncate tables", e);

} finally {
closeQuietly(connection); // Important, otherwise tests can stuck
}
}

public static void stopDatabase() {
try {
if (datasource != null) {
datasource.close();
datasource = null;
}
DriverManager.getConnection("jdbc:derby:;shutdown=true");

} catch (SQLException e) {
// See http://db.apache.org/derby/docs/dev/getstart/rwwdactivity3.html
// XJ015 indicates successful shutdown of Derby
// 08006 successful shutdown of a single database
if (!"XJ015".equals(e.getSQLState())) {
throw new IllegalStateException("Fail to stop Derby", e);
}
// Ignore error
}
}

public InMemoryDatabase stop() {
public H2Database stop() {
return this;
}

@@ -146,7 +101,7 @@ public class InMemoryDatabase implements Database {
}

public Dialect getDialect() {
return new Derby();
return new H2();
}

public String getSchema() {

sonar-core/src/test/java/org/sonar/core/persistence/InMemoryDatabaseTest.java → sonar-core/src/test/java/org/sonar/core/persistence/H2DatabaseTest.java Voir le fichier

@@ -31,16 +31,12 @@ import static org.hamcrest.number.OrderingComparisons.greaterThan;
import static org.junit.Assert.assertNotNull;
import static org.junit.Assert.assertThat;

public class InMemoryDatabaseTest {

static {
DerbyUtils.fixDerbyLogs();
}
public class H2DatabaseTest {

@Test
public void shouldExecuteDdlAtStartup() throws SQLException {
int tables = 0;
InMemoryDatabase db = new InMemoryDatabase();
H2Database db = new H2Database();
try {
db.start();
assertNotNull(db.getDataSource());
@@ -60,7 +56,7 @@ public class InMemoryDatabaseTest {

@Test
public void shouldLimitThePoolSize() {
InMemoryDatabase db = new InMemoryDatabase();
H2Database db = new H2Database();
try {
db.startDatabase();
assertThat(((BasicDataSource) db.getDataSource()).getMaxActive(), Is.is(2));

+ 2
- 6
sonar-core/src/test/java/org/sonar/core/persistence/MyBatisTest.java Voir le fichier

@@ -32,16 +32,12 @@ import static org.junit.Assert.assertThat;

public class MyBatisTest {

static {
DerbyUtils.fixDerbyLogs();
}

private static MyBatis myBatis;
private static InMemoryDatabase database;
private static H2Database database;

@BeforeClass
public static void start() {
database = new InMemoryDatabase();
database = new H2Database();
myBatis = new MyBatis(database.start());
myBatis.start();
}

sonar-core/src/test/java/org/sonar/core/persistence/dialect/DerbyTest.java → sonar-core/src/test/java/org/sonar/core/persistence/dialect/H2Test.java Voir le fichier

@@ -24,19 +24,19 @@ import org.junit.Test;
import static org.hamcrest.CoreMatchers.is;
import static org.junit.Assert.assertThat;

public class DerbyTest {
public class H2Test {

private Derby derby = new Derby();
private H2 h2 = new H2();

@Test
public void matchesJdbcURL() {
assertThat(derby.matchesJdbcURL("jdbc:derby:foo"), is(true));
assertThat(derby.matchesJdbcURL("jdbc:hsql:foo"), is(false));
assertThat(h2.matchesJdbcURL("jdbc:h2:foo"), is(true));
assertThat(h2.matchesJdbcURL("jdbc:hsql:foo"), is(false));
}

@Test
public void testBooleanSqlValues() {
assertThat(derby.getTrueSqlValue(), is("true"));
assertThat(derby.getFalseSqlValue(), is("false"));
assertThat(h2.getTrueSqlValue(), is("true"));
assertThat(h2.getFalseSqlValue(), is("false"));
}
}

+ 11
- 35
sonar-core/src/test/java/org/sonar/jpa/test/AbstractDbUnitTestCase.java Voir le fichier

@@ -24,32 +24,30 @@ import org.dbunit.Assertion;
import org.dbunit.DataSourceDatabaseTester;
import org.dbunit.DatabaseUnitException;
import org.dbunit.IDatabaseTester;
import org.dbunit.database.DatabaseConfig;
import org.dbunit.database.IDatabaseConnection;
import org.dbunit.dataset.Column;
import org.dbunit.dataset.CompositeDataSet;
import org.dbunit.dataset.DataSetException;
import org.dbunit.dataset.IDataSet;
import org.dbunit.dataset.ITable;
import org.dbunit.dataset.ITableMetaData;
import org.dbunit.dataset.ReplacementDataSet;
import org.dbunit.dataset.filter.DefaultColumnFilter;
import org.dbunit.dataset.xml.FlatXmlDataSet;
import org.dbunit.ext.h2.H2DataTypeFactory;
import org.dbunit.operation.DatabaseOperation;
import org.junit.After;
import org.junit.AfterClass;
import org.junit.Before;
import org.junit.BeforeClass;
import org.sonar.api.database.DatabaseSession;
import org.sonar.core.persistence.Database;
import org.sonar.core.persistence.DatabaseCommands;
import org.sonar.core.persistence.InMemoryDatabase;
import org.sonar.core.persistence.H2Database;
import org.sonar.jpa.session.DatabaseSessionFactory;
import org.sonar.jpa.session.DefaultDatabaseConnector;
import org.sonar.jpa.session.JpaDatabaseSession;
import org.sonar.jpa.session.MemoryDatabaseConnector;

import java.io.InputStream;
import java.sql.ResultSet;
import java.sql.SQLException;

import static org.junit.Assert.fail;
@@ -68,13 +66,15 @@ public abstract class AbstractDbUnitTestCase {

@BeforeClass
public static void startDatabase() throws Exception {
database = new InMemoryDatabase();
database.start();
if (null == database) { // Create only once per vm
database = new H2Database();
database.start();

dbConnector = new MemoryDatabaseConnector(database);
dbConnector.start();
dbConnector = new MemoryDatabaseConnector(database);
dbConnector.start();

databaseCommands = DatabaseCommands.forDialect(database.getDialect());
databaseCommands = DatabaseCommands.forDialect(database.getDialect());
}
}

@Before
@@ -96,12 +96,6 @@ public abstract class AbstractDbUnitTestCase {
session.stop();
}

@AfterClass
public static void stopDatabase() {
dbConnector.stop();
database.stop();
}

public DatabaseSession getSession() {
return session;
}
@@ -152,32 +146,14 @@ public abstract class AbstractDbUnitTestCase {
databaseTester.setDataSet(compositeDataSet);
connection = databaseTester.getConnection();

connection.getConfig().setProperty(DatabaseConfig.PROPERTY_DATATYPE_FACTORY, new H2DataTypeFactory());
DatabaseOperation.CLEAN_INSERT.execute(connection, databaseTester.getDataSet());
resetDerbySequence(compositeDataSet);

} catch (Exception e) {
throw translateException("Could not setup DBUnit data", e);
}
}

private void resetDerbySequence(CompositeDataSet compositeDataSet) throws DataSetException, SQLException {
for (ITable table : compositeDataSet.getTables()) {
ITableMetaData tableMetaData = table.getTableMetaData();
String tableName = tableMetaData.getTableName();
for (Column column : tableMetaData.getColumns()) {
if ("id".equalsIgnoreCase(column.getColumnName())) { // TODO hard-coded value
String maxSql = "SELECT MAX(id) FROM " + tableName;
ResultSet res = connection.getConnection().prepareStatement(maxSql).executeQuery();
res.next();
int max = res.getInt(1);
res.close();
String alterSql = "ALTER TABLE " + tableName + " ALTER COLUMN id RESTART WITH " + (max + 1);
connection.getConnection().prepareStatement(alterSql).execute();
}
}
}
}

protected final void checkTables(String testName, String... tables) {
checkTables(testName, new String[0], tables);
}

+ 12
- 3
sonar-plugin-api/src/main/java/org/sonar/api/database/DatabaseProperties.java Voir le fichier

@@ -24,9 +24,9 @@ public interface DatabaseProperties {
int MAX_TEXT_SIZE = 16777215;

String PROP_URL = "sonar.jdbc.url";
String PROP_URL_DEFAULT_VALUE = "jdbc:derby://localhost:1527/sonar";
String PROP_URL_DEFAULT_VALUE = "jdbc:h2:tcp://localhost/sonar";
String PROP_DRIVER = "sonar.jdbc.driverClassName";
String PROP_DRIVER_DEFAULT_VALUE = "org.apache.derby.jdbc.ClientDriver";
String PROP_DRIVER_DEFAULT_VALUE = "org.h2.Driver";
String PROP_DRIVER_DEPRECATED = "sonar.jdbc.driver";
String PROP_USER = "sonar.jdbc.username";
String PROP_USER_DEPRECATED = "sonar.jdbc.user";
@@ -37,6 +37,15 @@ public interface DatabaseProperties {
String PROP_HIBERNATE_GENERATE_STATISTICS = "sonar.jdbc.hibernate.generate_statistics";
String PROP_DIALECT = "sonar.jdbc.dialect";
String PROP_HIBERNATE_DEFAULT_SCHEMA = "sonar.hibernate.default_schema";

String PROP_EMBEDDED_DATA_DIR = "sonar.embeddedDatabase.dataDir";

/**
* @since 3.2
*/
String PROP_EMBEDDED_PORT = "sonar.embeddedDatabase.port";

/**
* @since 3.2
*/
String PROP_EMBEDDED_PORT_DEFAULT_VALUE = "9092";
}

sonar-server/derby-start.bat → sonar-server/h2-start.bat Voir le fichier

@@ -1,2 +1,2 @@
set MAVEN_OPTS='-Xmx768m -XX:MaxPermSize=128m'
mvn clean jetty:run -Pstart-dev-server,derby
mvn clean jetty:run -Pstart-dev-server,h2

sonar-server/derby-start.sh → sonar-server/h2-start.sh Voir le fichier

@@ -1,3 +1,3 @@
#!/bin/sh
export MAVEN_OPTS='-Xmx768m -XX:MaxPermSize=128m'
mvn clean jetty:run -Pstart-dev-server,derby
mvn clean jetty:run -Pstart-dev-server,h2

+ 10
- 20
sonar-server/pom.xml Voir le fichier

@@ -51,11 +51,6 @@
<groupId>org.codehaus.sonar</groupId>
<artifactId>sonar-update-center-common</artifactId>
</dependency>
<dependency>
<groupId>org.apache.derby</groupId>
<artifactId>derbyclient</artifactId>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.codehaus.sonar</groupId>
<artifactId>sonar-plugin-api</artifactId>
@@ -76,12 +71,8 @@
<artifactId>commons-configuration</artifactId>
</dependency>
<dependency>
<groupId>org.apache.derby</groupId>
<artifactId>derby</artifactId>
</dependency>
<dependency>
<groupId>org.apache.derby</groupId>
<artifactId>derbynet</artifactId>
<groupId>com.h2database</groupId>
<artifactId>h2</artifactId>
</dependency>
<dependency>
<groupId>com.thoughtworks.xstream</groupId>
@@ -613,9 +604,9 @@
</profile>

<profile>
<id>derby</id>
<id>h2</id>
<properties>
<jdbcDialect>derby</jdbcDialect>
<jdbcDialect>h2</jdbcDialect>
</properties>
<build>
<plugins>
@@ -632,7 +623,7 @@
<outputDirectory>${project.build.directory}/classes</outputDirectory>
<resources>
<resource>
<directory>${basedir}/src/dev/derby</directory>
<directory>${basedir}/src/dev/h2</directory>
<filtering>false</filtering>
</resource>
</resources>
@@ -653,10 +644,9 @@
<configuration>
<overWriteIfNewer>true</overWriteIfNewer>
<overWriteReleases>true</overWriteReleases>
<includeGroupIds>org.apache.derby</includeGroupIds>
<includeArtifactIds>derbyclient</includeArtifactIds>
<outputDirectory>${project.build.directory}/sonar-dev-home/extensions/jdbc-driver/derby/
</outputDirectory>
<includeGroupIds>com.h2database</includeGroupIds>
<includeArtifactIds>h2</includeArtifactIds>
<outputDirectory>${project.build.directory}/sonar-dev-home/extensions/jdbc-driver/h2/</outputDirectory>
</configuration>
</execution>
</executions>
@@ -665,8 +655,8 @@
</build>
<dependencies>
<dependency>
<groupId>org.apache.derby</groupId>
<artifactId>derbyclient</artifactId>
<groupId>com.h2database</groupId>
<artifactId>h2</artifactId>
</dependency>
</dependencies>
</profile>

sonar-server/src/dev/derby/conf/logback.xml → sonar-server/src/dev/h2/conf/logback.xml Voir le fichier


sonar-server/src/dev/derby/conf/sonar.properties → sonar-server/src/dev/h2/conf/sonar.properties Voir le fichier

@@ -1,6 +1,6 @@
# Derby
sonar.jdbc.url: jdbc:derby://localhost:1527/sonar;create=true
sonar.jdbc.driverClassName: org.apache.derby.jdbc.ClientDriver
# H2
sonar.jdbc.url: jdbc:h2:tcp://localhost:9092/sonar
sonar.jdbc.driverClassName: org.h2.Driver
sonar.jdbc.defaultTransactionIsolation: 1
sonar.jdbc.username: sonar
sonar.jdbc.password: sonar
@@ -13,5 +13,5 @@ sonar.jdbc.timeBetweenEvictionRunsMillis: 30000

sonar.runtime.mode: development

sonar.derby.drda.portNumber: 1527
sonar.derby.drda.host: localhost
sonar.embeddedDatabase.port: 9092

+ 38
- 123
sonar-server/src/main/java/org/sonar/server/database/EmbeddedDatabase.java Voir le fichier

@@ -19,171 +19,86 @@
*/
package org.sonar.server.database;

import org.apache.commons.io.IOUtils;
import org.apache.commons.lang.StringUtils;
import org.apache.derby.drda.NetworkServerControl;
import org.h2.tools.Server;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.sonar.api.CoreProperties;
import org.sonar.api.config.Settings;
import org.sonar.api.database.DatabaseProperties;
import org.sonar.api.utils.Logs;
import org.sonar.api.utils.SonarException;
import org.sonar.server.platform.ServerStartException;

import java.io.File;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.PrintWriter;
import java.net.InetAddress;
import java.util.Properties;
import java.sql.DriverManager;
import java.sql.SQLException;

public class EmbeddedDatabase {
private static final Logger LOG = LoggerFactory.getLogger(EmbeddedDatabase.class);

private static final String DEFAULT_USER = "sonar";
private static final String DEFAULT_PWD = "sonar";

private NetworkServerControl serverControl = null;

private File dbHome;
private Properties dbProps;
private PrintWriter dbLog;
private final Settings settings;
private Server server;

public EmbeddedDatabase(Settings settings) {
this.dbHome = getDataDirectory(settings);
this.dbProps = getDefaultProperties(settings);
}

public EmbeddedDatabase(File dbHome, Properties dbProps) {
this.dbHome = dbHome;
this.dbProps = dbProps;
}

public File getDataDir() {
return dbHome;
}

protected File getDataDirectory(Settings settings) {
String dirName = settings.getString(DatabaseProperties.PROP_EMBEDDED_DATA_DIR);
if (StringUtils.isBlank(dirName)) {
File sonarHome = new File(settings.getString(CoreProperties.SONAR_HOME));
if (!sonarHome.isDirectory() || !sonarHome.exists()) {
throw new ServerStartException("Sonar home directory does not exist");
}
return new File(sonarHome, "data");
}
return new File(dirName);
}

public void setDbLog(PrintWriter dbLog) {
this.dbLog = dbLog;
this.settings = settings;
}

public void start() {
File dbHome = getDataDirectory(settings);
if (dbHome.exists() && !dbHome.isDirectory()) {
throw new SonarException("Database home " + dbHome.getPath() + " is not a directory");
}
if (!dbHome.exists()) {
dbHome.mkdirs();
}
System.setProperty("derby.system.home", dbHome.getPath());

saveDerbyPropertiesFile();
startListening();
Logs.INFO.info("Embedded database started. Data stored in: " + dbHome.getAbsolutePath());
}
String port = getSetting(DatabaseProperties.PROP_EMBEDDED_PORT, DatabaseProperties.PROP_EMBEDDED_PORT_DEFAULT_VALUE);
String user = getSetting(DatabaseProperties.PROP_USER, DatabaseProperties.PROP_USER_DEFAULT_VALUE);
String password = getSetting(DatabaseProperties.PROP_PASSWORD, DatabaseProperties.PROP_PASSWORD_DEFAULT_VALUE);

private void startListening() {
try {
int port = Integer.parseInt(dbProps.getProperty("derby.drda.portNumber"));
String host = dbProps.getProperty("derby.drda.host");
serverControl = new NetworkServerControl(InetAddress.getByName(host), port, DEFAULT_USER, DEFAULT_PWD);
Logs.INFO.info("Starting embedded database on port " + port);
serverControl.start(dbLog);
ensureServerIsUp();
} catch (Exception e) {
throw new SonarException(e);
}
}
createDatabase(dbHome, user, password);

private void saveDerbyPropertiesFile() {
FileOutputStream output = null;
try {
File derbyProps = new File(dbHome.getPath() + "/derby.properties");
output = new FileOutputStream(derbyProps);
dbProps.store(output, "GENERATED FILE, DO NOT EDIT ME UNLESS YOU WANT TO LOOSE YOUR TIME ;O)");
Server server = Server.createTcpServer("-tcpPort", port, "-tcpAllowOthers", "-ifExists", "-baseDir", dbHome.getAbsolutePath());

} catch (IOException e) {
throw new SonarException(e);
LOG.info("Starting embedded database on port " + server.getPort());
server.start();

} finally {
IOUtils.closeQuietly(output);
LOG.info("Embedded database started. Data stored in: " + dbHome.getAbsolutePath());
} catch (Exception e) {
throw new SonarException("Unable to start database", e);
}
}

public void stop() {
if (serverControl != null) {
try {
serverControl.shutdown();
ensureServerIsDown();
serverControl = null;
Logs.INFO.info("Embedded database stopped");

} catch (Exception e) {
throw new SonarException(e);
}
if (server != null) {
server.stop();
server = null;
LOG.info("Embedded database stopped");
}
}

private void ensureServerIsUp() {
for (int retry = 0; retry < 100; retry++) {
try {
serverControl.ping();
return;

} catch (Exception ex) {
sleep(300);
}
}
throw new SonarException("Embedded database does not respond to ping requests");
private String getSetting(String name, String defaultValue) {
return StringUtils.defaultIfBlank(settings.getString(name), defaultValue);
}

private void ensureServerIsDown() {
for (int retry = 0; retry < 100; retry++) {
try {
serverControl.ping();
sleep(300);

} catch (SonarException se) {
throw se;
private void createDatabase(File dbHome, String user, String password) throws SQLException {
String url = String.format("jdbc:h2:%s/sonar;USER=%s;PASSWORD=%s", dbHome.getAbsolutePath(), user, password);

} catch (Exception e) {
// normal case: the database does not respond to ping
return;
}
}
throw new SonarException("Fail to stop embedded database");
DriverManager.getConnection(url).close();
}

private static File getDataDirectory(Settings settings) {
String dirName = settings.getString(DatabaseProperties.PROP_EMBEDDED_DATA_DIR);
if (!StringUtils.isBlank(dirName)) {
return new File(dirName);
}

private void sleep(long time) {
try {
Thread.sleep(time);
} catch (InterruptedException e) {
throw new SonarException("Fail to ping embedded database", e);
File sonarHome = new File(settings.getString(CoreProperties.SONAR_HOME));
if (sonarHome.isDirectory() && sonarHome.exists()) {
return new File(sonarHome, "data");
}
}

public static Properties getDefaultProperties(Settings settings) {
Properties props = new Properties();
props.setProperty("derby.drda.startNetworkServer", "true");
props.setProperty("derby.drda.host", StringUtils.defaultIfBlank(settings.getString("sonar.derby.drda.host"), "localhost"));
props.setProperty("derby.drda.portNumber", StringUtils.defaultIfBlank(settings.getString("sonar.derby.drda.portNumber"), "1527"));
props.setProperty("derby.drda.maxThreads", StringUtils.defaultIfBlank(settings.getString("sonar.derby.drda.maxThreads"), "20"));
props.setProperty("derby.drda.minThreads", StringUtils.defaultIfBlank(settings.getString("sonar.derby.drda.minThreads"), "2"));
props.setProperty("derby.drda.logConnections", StringUtils.defaultIfBlank(settings.getString("sonar.derby.drda.logConnections"), "false"));
props.setProperty("derby.stream.error.logSeverityLevel", StringUtils.defaultIfBlank(settings.getString("sonar.derby.stream.error.logSeverityLevel"), "20000"));
props.setProperty("derby.connection.requireAuthentication", "true");
props.setProperty("derby.user." + DEFAULT_USER, DEFAULT_PWD);
return props;
throw new ServerStartException("Sonar home directory does not exist");
}

}

+ 10
- 5
sonar-server/src/main/java/org/sonar/server/database/EmbeddedDatabaseFactory.java Voir le fichier

@@ -21,20 +21,25 @@ package org.sonar.server.database;

import org.sonar.api.config.Settings;
import org.sonar.api.database.DatabaseProperties;
import org.sonar.core.persistence.dialect.H2;

public class EmbeddedDatabaseFactory {
private Settings settings;
private final Settings settings;
private final H2 dialect;
private EmbeddedDatabase embeddedDatabase;

public EmbeddedDatabaseFactory(Settings settings) {
this.settings = settings;
dialect = new H2();
}

public void start() {
String jdbcUrl = settings.getString(DatabaseProperties.PROP_URL);
if (jdbcUrl != null && jdbcUrl.startsWith("jdbc:derby://") && jdbcUrl.contains("create=true") && embeddedDatabase == null) {
embeddedDatabase = new EmbeddedDatabase(settings);
embeddedDatabase.start();
if (embeddedDatabase == null) {
String jdbcUrl = settings.getString(DatabaseProperties.PROP_URL);
if (dialect.matchesJdbcURL(jdbcUrl)) {
embeddedDatabase = new EmbeddedDatabase(settings);
embeddedDatabase.start();
}
}
}


+ 1
- 1
sonar-server/src/main/java/org/sonar/server/plugins/BatchResourcesServlet.java Voir le fichier

@@ -97,7 +97,7 @@ public class BatchResourcesServlet extends HttpServlet {
return libs;
}

private static final String[] IGNORE = { "derby", "jtds", "mysql", "postgresql", "jruby", "jfreechart", "eastwood", "jetty" };
private static final String[] IGNORE = {"h2", "jtds", "mysql", "postgresql", "jruby", "jfreechart", "eastwood", "jetty"};

/**
* Dirty hack to disable downloading for certain files.

+ 19
- 94
sonar-server/src/test/java/org/sonar/server/database/EmbeddedDatabaseTest.java Voir le fichier

@@ -19,120 +19,45 @@
*/
package org.sonar.server.database;

import org.apache.commons.io.FileUtils;
import org.apache.commons.lang.SystemUtils;
import org.apache.derby.jdbc.ClientDriver;
import org.junit.After;
import org.junit.Before;
import org.junit.Test;
import org.sonar.api.config.Settings;
import org.sonar.core.persistence.InMemoryDatabase;
import org.sonar.api.database.DatabaseProperties;

import java.io.File;
import java.io.IOException;
import java.net.ServerSocket;
import java.sql.Connection;
import java.sql.DriverManager;
import java.util.Properties;

import static junit.framework.Assert.fail;
import static org.junit.Assert.assertTrue;

public class EmbeddedDatabaseTest {
@Test(timeout = 5000)
public void should_start_and_stop() throws IOException {
int port = freeServerPort();

private final static String TEST_ROOT_DIR = "./target/";
private final static String TEST_DB_DIR_PREFIX = "testDB";

private EmbeddedDatabase database;
private String driverUrl;
private Properties defaultProps;
private static String testPort;

@Before
public void setUp() throws Exception {
// This test doesn't work if InMemoryDatabase is active
try {
InMemoryDatabase.stopDatabase();
} catch (Exception e) {
}

windowsCleanup();
if (testPort == null) {
testPort = Integer.toString(findFreeServerPort());
}
defaultProps = EmbeddedDatabase.getDefaultProperties(new Settings());
defaultProps.put("derby.drda.portNumber", testPort); // changing the default port
driverUrl = "jdbc:derby://localhost:" + testPort + "/sonar;create=true;user=sonar;password=sonar";
}

private void windowsCleanup() {
String os = System.getProperty("os.name");
if (os.toLowerCase().contains("windows")) {
File testRoot = new File(TEST_ROOT_DIR);
File[] files = testRoot.listFiles();
for (File file : files) {
if (file.isDirectory() &&
file.getName().startsWith(TEST_DB_DIR_PREFIX)) {
try {
FileUtils.deleteDirectory(file);
} catch (IOException e) {
}
}
}
}
}

private int findFreeServerPort() throws IOException, InterruptedException {
ServerSocket srv = new ServerSocket(0);
int port = srv.getLocalPort();
srv.close();
Thread.sleep(1500);
return port;
}

@Test
public void shouldStartAndStop() throws Exception {
database = new EmbeddedDatabase(new File(TEST_ROOT_DIR + TEST_DB_DIR_PREFIX + testPort), defaultProps);
EmbeddedDatabase database = new EmbeddedDatabase(settings(port));
database.start();
ClientDriver.class.newInstance();
Connection conn;

try {
conn = DriverManager.getConnection(driverUrl);
conn.close();
String driverUrl = String.format("jdbc:h2:tcp://localhost:%d/sonar;USER=login;PASSWORD=pwd", port);
DriverManager.getConnection(driverUrl).close();
} catch (Exception ex) {
fail("Unable to connect after start");
}
try {
conn = DriverManager.getConnection("jdbc:derby://localhost:" + testPort + "/sonar;user=foo;password=bar");
conn.close();
fail("Able to connect with wrong username and password");
} catch (Exception ex) {
}

File testDb = new File(database.getDataDir(), "sonar");
assertTrue(testDb.exists());
assertTrue(testDb.isDirectory());

database.stop();

try {
conn = DriverManager.getConnection(driverUrl);
conn.close();
fail("Able to connect after stop");
} catch (Exception ex) {
}
}

@After
public void tearDown() throws IOException {
if (database.getDataDir().exists()) {
if (!SystemUtils.IS_OS_WINDOWS) {
// avoid an issue with file lock issue under windows..
// thank you mr microsoft
// solution : no really good solution found.., the db home is not deleted under windows on teardown but only during test startup
FileUtils.deleteDirectory(database.getDataDir());
}
}
static Settings settings(int port) {
return new Settings()
.setProperty(DatabaseProperties.PROP_USER, "login")
.setProperty(DatabaseProperties.PROP_PASSWORD, "pwd")
.setProperty(DatabaseProperties.PROP_EMBEDDED_PORT, "" + port)
.setProperty(DatabaseProperties.PROP_EMBEDDED_DATA_DIR, "./target/testDB");
}

static int freeServerPort() throws IOException {
ServerSocket srv = new ServerSocket(0);
srv.close();
return srv.getLocalPort();
}
}

+ 30
- 31
sonar-server/src/test/java/org/sonar/server/filters/FilterExecutorTest.java Voir le fichier

@@ -23,7 +23,7 @@ import com.google.common.collect.Sets;
import org.junit.Test;
import org.sonar.api.resources.Qualifiers;
import org.sonar.api.resources.Resource;
import org.sonar.core.persistence.dialect.Derby;
import org.sonar.core.persistence.dialect.H2;
import org.sonar.core.persistence.dialect.MsSql;
import org.sonar.jpa.test.AbstractDbUnitTestCase;

@@ -39,7 +39,7 @@ public class FilterExecutorTest extends AbstractDbUnitTestCase {
@Test
public void mustDefineAtLeastOneQualifier() {
setupData("shared");
FilterExecutor executor = new FilterExecutor(getSession(), new Derby());
FilterExecutor executor = new FilterExecutor(getSession(), new H2());
FilterResult result = executor.execute(new Filter());
assertThat(result.size()).isEqualTo(0);// no qualifiers
}
@@ -47,7 +47,7 @@ public class FilterExecutorTest extends AbstractDbUnitTestCase {
@Test
public void filterOnScopes() {
setupData("shared");
FilterExecutor executor = new FilterExecutor(getSession(), new Derby());
FilterExecutor executor = new FilterExecutor(getSession(), new H2());
FilterResult result = executor.execute(Filter.createForAllQualifiers().setScopes(Sets.newHashSet(Resource.SCOPE_SPACE)));
assertSnapshotIds(result, 4);
}
@@ -55,7 +55,7 @@ public class FilterExecutorTest extends AbstractDbUnitTestCase {
@Test
public void filterOnQualifiers() {
setupData("shared");
FilterExecutor executor = new FilterExecutor(getSession(), new Derby());
FilterExecutor executor = new FilterExecutor(getSession(), new H2());
FilterResult result = executor.execute(new Filter().setQualifiers(Sets.newHashSet(Resource.QUALIFIER_PROJECT, Resource.QUALIFIER_MODULE)));
assertSnapshotIds(result, 2, 3);
}
@@ -63,7 +63,7 @@ public class FilterExecutorTest extends AbstractDbUnitTestCase {
@Test
public void filterOnLanguages() {
setupData("shared");
FilterExecutor executor = new FilterExecutor(getSession(), new Derby());
FilterExecutor executor = new FilterExecutor(getSession(), new H2());
FilterResult result = executor.execute(Filter.createForAllQualifiers().setLanguages(Sets.newHashSet("java")));
assertSnapshotIds(result, 2, 4);
}
@@ -71,7 +71,7 @@ public class FilterExecutorTest extends AbstractDbUnitTestCase {
@Test
public void filterOnDate() throws ParseException {
setupData("shared");
FilterExecutor executor = new FilterExecutor(getSession(), new Derby());
FilterExecutor executor = new FilterExecutor(getSession(), new H2());
Date date = new SimpleDateFormat("yyyy-MM-dd HH:mm").parse("2008-12-26 00:00");
FilterResult result = executor.execute(Filter.createForAllQualifiers().setDateCriterion(new DateCriterion(">", date)));
assertSnapshotIds(result, 3);
@@ -80,7 +80,7 @@ public class FilterExecutorTest extends AbstractDbUnitTestCase {
@Test
public void filterOnDateIncludesTime() throws ParseException {
setupData("shared");
FilterExecutor executor = new FilterExecutor(getSession(), new Derby());
FilterExecutor executor = new FilterExecutor(getSession(), new H2());
Date date = new SimpleDateFormat("yyyy-MM-dd HH:mm").parse("2008-12-25 03:00");
FilterResult result = executor.execute(Filter.createForAllQualifiers().setDateCriterion(new DateCriterion("<", date)));
assertSnapshotIds(result, 2, 4);
@@ -89,7 +89,7 @@ public class FilterExecutorTest extends AbstractDbUnitTestCase {
@Test
public void filterOnBaseSnapshot() {
setupData("shared");
FilterExecutor executor = new FilterExecutor(getSession(), new Derby());
FilterExecutor executor = new FilterExecutor(getSession(), new H2());
FilterResult result = executor.execute(Filter.createForAllQualifiers().setPath(2, 2, ""));
assertSnapshotIds(result, 4);
}
@@ -97,7 +97,7 @@ public class FilterExecutorTest extends AbstractDbUnitTestCase {
@Test
public void sortByName() {
setupData("shared");
FilterExecutor executor = new FilterExecutor(getSession(), new Derby());
FilterExecutor executor = new FilterExecutor(getSession(), new H2());
FilterResult result = executor.execute(Filter.createForAllQualifiers().setSortedByName());
assertSortedSnapshotIds(result, 2, 4, 3);
}
@@ -105,7 +105,7 @@ public class FilterExecutorTest extends AbstractDbUnitTestCase {
@Test
public void sortByKey() {
setupData("shared");
FilterExecutor executor = new FilterExecutor(getSession(), new Derby());
FilterExecutor executor = new FilterExecutor(getSession(), new H2());
FilterResult result = executor.execute(Filter.createForAllQualifiers().setSortedByKey());
assertSortedSnapshotIds(result, 3, 2, 4);
}
@@ -113,7 +113,7 @@ public class FilterExecutorTest extends AbstractDbUnitTestCase {
@Test
public void sortByDate() {
setupData("shared");
FilterExecutor executor = new FilterExecutor(getSession(), new Derby());
FilterExecutor executor = new FilterExecutor(getSession(), new H2());
FilterResult result = executor.execute(Filter.createForAllQualifiers().setSortedByDate());
assertSortedSnapshotIds(result, 2, 4, 3);
}
@@ -121,7 +121,7 @@ public class FilterExecutorTest extends AbstractDbUnitTestCase {
@Test
public void sortByDescendingDate() {
setupData("shared");
FilterExecutor executor = new FilterExecutor(getSession(), new Derby());
FilterExecutor executor = new FilterExecutor(getSession(), new H2());
FilterResult result = executor.execute(Filter.createForAllQualifiers().setSortedByDate().setAscendingSort(false));
assertSortedSnapshotIds(result, 3, 4, 2);
}
@@ -129,7 +129,7 @@ public class FilterExecutorTest extends AbstractDbUnitTestCase {
@Test
public void sortByAscendingDate() {
setupData("shared");
FilterExecutor executor = new FilterExecutor(getSession(), new Derby());
FilterExecutor executor = new FilterExecutor(getSession(), new H2());
FilterResult result = executor.execute(Filter.createForAllQualifiers().setSortedByDate().setAscendingSort(true));
assertSortedSnapshotIds(result, 2, 4, 3);
}
@@ -137,7 +137,7 @@ public class FilterExecutorTest extends AbstractDbUnitTestCase {
@Test
public void sortByAscendingMeasureValue() {
setupData("shared", "measures");
FilterExecutor executor = new FilterExecutor(getSession(), new Derby());
FilterExecutor executor = new FilterExecutor(getSession(), new H2());
Filter filter = new Filter()
.setQualifiers(Sets.newHashSet(Qualifiers.CLASS))
.setSortedMetricId(2, true, false);
@@ -149,7 +149,7 @@ public class FilterExecutorTest extends AbstractDbUnitTestCase {
@Test
public void sortByDecendingMeasureValue() {
setupData("shared", "measures");
FilterExecutor executor = new FilterExecutor(getSession(), new Derby());
FilterExecutor executor = new FilterExecutor(getSession(), new H2());
Filter filter = new Filter()
.setQualifiers(Sets.newHashSet(Qualifiers.CLASS))
.setSortedMetricId(2, true, false)
@@ -162,7 +162,7 @@ public class FilterExecutorTest extends AbstractDbUnitTestCase {
@Test
public void applySingleMeasureCriterion() {
setupData("shared", "measures");
FilterExecutor executor = new FilterExecutor(getSession(), new Derby());
FilterExecutor executor = new FilterExecutor(getSession(), new H2());
Filter filter = new Filter()
.setQualifiers(Sets.newHashSet(Qualifiers.CLASS))
.addMeasureCriterion(new MeasureCriterion(2, ">", 50.0, false));
@@ -174,7 +174,7 @@ public class FilterExecutorTest extends AbstractDbUnitTestCase {
@Test
public void applyManyMeasureCriteria() {
setupData("shared", "measures");
FilterExecutor executor = new FilterExecutor(getSession(), new Derby());
FilterExecutor executor = new FilterExecutor(getSession(), new H2());
Filter filter = new Filter()
.setQualifiers(Sets.newHashSet(Qualifiers.CLASS))
.addMeasureCriterion(new MeasureCriterion(2, ">", 50.0, false))
@@ -187,7 +187,7 @@ public class FilterExecutorTest extends AbstractDbUnitTestCase {
@Test
public void criteriaAreExclusive() {
setupData("shared", "measures");
FilterExecutor executor = new FilterExecutor(getSession(), new Derby());
FilterExecutor executor = new FilterExecutor(getSession(), new H2());
Filter filter = new Filter()
.setQualifiers(Sets.newHashSet(Qualifiers.CLASS))
.addMeasureCriterion(new MeasureCriterion(2, ">", 50.0, false))
@@ -200,7 +200,7 @@ public class FilterExecutorTest extends AbstractDbUnitTestCase {
@Test
public void sortAndFilterMeasures() {
setupData("shared", "measures");
FilterExecutor executor = new FilterExecutor(getSession(), new Derby());
FilterExecutor executor = new FilterExecutor(getSession(), new H2());
Filter filter = new Filter()
.setQualifiers(Sets.newHashSet(Qualifiers.CLASS))
.addMeasureCriterion(new MeasureCriterion(2, ">", 5.0, false))
@@ -214,7 +214,7 @@ public class FilterExecutorTest extends AbstractDbUnitTestCase {
@Test
public void sortDescendingAndFilterMeasures() {
setupData("shared", "measures");
FilterExecutor executor = new FilterExecutor(getSession(), new Derby());
FilterExecutor executor = new FilterExecutor(getSession(), new H2());
Filter filter = new Filter()
.setQualifiers(Sets.newHashSet(Qualifiers.CLASS))
.addMeasureCriterion(new MeasureCriterion(2, ">", 5.0, false)) // filter on coverage
@@ -229,7 +229,7 @@ public class FilterExecutorTest extends AbstractDbUnitTestCase {
@Test
public void filterByResourceKey() {
setupData("shared");
FilterExecutor executor = new FilterExecutor(getSession(), new Derby());
FilterExecutor executor = new FilterExecutor(getSession(), new H2());
FilterResult result = executor.execute(Filter.createForAllQualifiers().setKeyRegexp("*:org.sonar.*"));
assertSnapshotIds(result, 4);
}
@@ -237,7 +237,7 @@ public class FilterExecutorTest extends AbstractDbUnitTestCase {
@Test
public void filterByResourceKeyIsCaseInsensitive() {
setupData("shared");
FilterExecutor executor = new FilterExecutor(getSession(), new Derby());
FilterExecutor executor = new FilterExecutor(getSession(), new H2());
FilterResult result = executor.execute(Filter.createForAllQualifiers().setKeyRegexp("*:ORG.SonAR.*"));
assertSnapshotIds(result, 4);
}
@@ -245,7 +245,7 @@ public class FilterExecutorTest extends AbstractDbUnitTestCase {
@Test
public void filterByMissingMeasureValue() {
setupData("shared", "measures");
FilterExecutor executor = new FilterExecutor(getSession(), new Derby());
FilterExecutor executor = new FilterExecutor(getSession(), new H2());
Filter filter = new Filter()
.setQualifiers(Sets.newHashSet(Qualifiers.CLASS))
.addMeasureCriterion(new MeasureCriterion(3, ">", 0.0, false)); // filter on duplicated lines
@@ -257,7 +257,7 @@ public class FilterExecutorTest extends AbstractDbUnitTestCase {
@Test
public void filterByMissingMeasureValues() {
setupData("shared", "measures");
FilterExecutor executor = new FilterExecutor(getSession(), new Derby());
FilterExecutor executor = new FilterExecutor(getSession(), new H2());
Filter filter = new Filter()
.setQualifiers(Sets.newHashSet(Qualifiers.CLASS))
.addMeasureCriterion(new MeasureCriterion(1, ">", 0.0, false)) // filter on lines
@@ -270,7 +270,7 @@ public class FilterExecutorTest extends AbstractDbUnitTestCase {
@Test
public void sortByMissingMeasureValue() {
setupData("shared", "measures");
FilterExecutor executor = new FilterExecutor(getSession(), new Derby());
FilterExecutor executor = new FilterExecutor(getSession(), new H2());
Filter filter = new Filter()
.setQualifiers(Sets.newHashSet(Qualifiers.CLASS))
.setSortedMetricId(3, true, false); // sort by duplicated lines
@@ -282,7 +282,7 @@ public class FilterExecutorTest extends AbstractDbUnitTestCase {
@Test
public void filterByMeasureValueAndSortOnOtherMetric() {
setupData("shared", "measures");
FilterExecutor executor = new FilterExecutor(getSession(), new Derby());
FilterExecutor executor = new FilterExecutor(getSession(), new H2());
Filter filter = new Filter()
.setQualifiers(Sets.newHashSet(Qualifiers.CLASS))
.addMeasureCriterion(new MeasureCriterion(1, ">", 0.0, false)) // lines > 0
@@ -295,7 +295,7 @@ public class FilterExecutorTest extends AbstractDbUnitTestCase {
@Test
public void intersectionOfCriteriaOnSameMetric() {
setupData("shared", "measures");
FilterExecutor executor = new FilterExecutor(getSession(), new Derby());
FilterExecutor executor = new FilterExecutor(getSession(), new H2());
Filter filter = new Filter()
.setQualifiers(Sets.newHashSet(Qualifiers.CLASS))
.addMeasureCriterion(new MeasureCriterion(1, ">", 400.0, false)) // lines > 400
@@ -308,7 +308,7 @@ public class FilterExecutorTest extends AbstractDbUnitTestCase {
@Test
public void ignoreProjectCopiesOfViews() {
setupData("views");
FilterExecutor executor = new FilterExecutor(getSession(), new Derby());
FilterExecutor executor = new FilterExecutor(getSession(), new H2());
Filter filter = new Filter()
.setQualifiers(Sets.newHashSet(Qualifiers.PROJECT));

@@ -319,7 +319,7 @@ public class FilterExecutorTest extends AbstractDbUnitTestCase {
@Test
public void loadProjectCopiesIfPathIsAView() {
setupData("views");
FilterExecutor executor = new FilterExecutor(getSession(), new Derby());
FilterExecutor executor = new FilterExecutor(getSession(), new H2());
Filter filter = new Filter()
.setPath(2, 2, "")
.setQualifiers(Sets.newHashSet(Qualifiers.SUBVIEW, Qualifiers.PROJECT));
@@ -335,11 +335,10 @@ public class FilterExecutorTest extends AbstractDbUnitTestCase {
String sql = new FilterExecutor(getSession(), new MsSql()).toSql(filter);
assertThat(sql).contains(" WITH (INDEX(measures_sid_metric)) ");

sql = new FilterExecutor(getSession(), new Derby()).toSql(filter);
sql = new FilterExecutor(getSession(), new H2()).toSql(filter);
assertThat(sql).doesNotContain(" WITH (INDEX(measures_sid_metric)) ");
}


private void assertSnapshotIds(FilterResult result, int... snapshotIds) {
assertThat(result.size()).isEqualTo(snapshotIds.length);
for (int snapshotId : snapshotIds) {

+ 1
- 3
sonar-server/src/test/java/org/sonar/server/plugins/BatchResourcesServletTest.java Voir le fichier

@@ -79,9 +79,7 @@ public class BatchResourcesServletTest {
@Test
public void shouldIgnore() {
assertThat(BatchResourcesServlet.isIgnored("sonar-batch-2.6-SNAPSHOT.jar"), is(false));
assertThat(BatchResourcesServlet.isIgnored("derby-10.6.1.0.jar"), is(true));
assertThat(BatchResourcesServlet.isIgnored("derbyclient-10.6.1.0.jar"), is(true));
assertThat(BatchResourcesServlet.isIgnored("derbynet-10.6.1.0.jar"), is(true));
assertThat(BatchResourcesServlet.isIgnored("h2-1.3.166.jar"), is(true));
assertThat(BatchResourcesServlet.isIgnored("mysql-connector-java-5.1.13.jar"), is(true));
assertThat(BatchResourcesServlet.isIgnored("postgresql-9.0-801.jdbc3.jar"), is(true));
assertThat(BatchResourcesServlet.isIgnored("jtds-1.2.4.jar"), is(true));

+ 2
- 2
sonar-testing-harness/pom.xml Voir le fichier

@@ -41,8 +41,8 @@
<version>${project.version}</version>
</dependency>
<dependency>
<groupId>org.apache.derby</groupId>
<artifactId>derby</artifactId>
<groupId>com.h2database</groupId>
<artifactId>h2</artifactId>
</dependency>
<dependency>
<groupId>org.dbunit</groupId>

+ 12
- 0
sonar-web-test/pom.xml Voir le fichier

@@ -0,0 +1,12 @@
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<parent>
<groupId>org.codehaus.sonar</groupId>
<artifactId>sonar</artifactId>
<version>3.2-SNAPSHOT</version>
</parent>
<artifactId>sonar-web-test</artifactId>
<name>Sonar :: Web Test</name>
<description>Test of the web site</description>
</project>

Chargement…
Annuler
Enregistrer