aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorSimon Brandhof <simon.brandhof@gmail.com>2011-10-25 16:20:07 +0200
committerSimon Brandhof <simon.brandhof@gmail.com>2011-10-25 16:20:15 +0200
commit3c07047ac56b549b0d5fe6543db0666c176ec23c (patch)
tree8a6523f91e8054533a81d1bc6676b9baaf52a00c
parent44535b310d471e67ce33b02668f6f09d031d15f1 (diff)
downloadsonarqube-3c07047ac56b549b0d5fe6543db0666c176ec23c.tar.gz
sonarqube-3c07047ac56b549b0d5fe6543db0666c176ec23c.zip
SONAR-2642 first step to integration mybatis
-rw-r--r--sonar-batch/src/main/java/org/sonar/batch/bootstrap/BatchDatabase.java43
-rw-r--r--sonar-batch/src/main/java/org/sonar/batch/bootstrap/BootstrapModule.java9
-rw-r--r--sonar-core/pom.xml16
-rw-r--r--sonar-core/src/main/java/org/sonar/jpa/session/CustomHibernateConnectionProvider.java36
-rw-r--r--sonar-core/src/main/java/org/sonar/jpa/session/DefaultDatabaseConnector.java85
-rw-r--r--sonar-core/src/main/java/org/sonar/persistence/Database.java31
-rw-r--r--sonar-core/src/main/java/org/sonar/persistence/DefaultDatabase.java134
-rw-r--r--sonar-core/src/main/java/org/sonar/persistence/InMemoryDatabase.java93
-rw-r--r--sonar-core/src/main/java/org/sonar/persistence/MyBatis.java87
-rw-r--r--sonar-core/src/main/java/org/sonar/persistence/dao/DuplicationDao.java98
-rw-r--r--sonar-core/src/main/java/org/sonar/persistence/dao/RuleDao.java49
-rw-r--r--sonar-core/src/main/java/org/sonar/persistence/model/Duplication.java51
-rw-r--r--sonar-core/src/main/java/org/sonar/persistence/model/DuplicationMapper.java38
-rw-r--r--sonar-core/src/main/java/org/sonar/persistence/model/Rule.java77
-rw-r--r--sonar-core/src/main/java/org/sonar/persistence/model/RuleMapper.java28
-rw-r--r--sonar-core/src/main/resources/org/sonar/persistence/master_derby.ddl257
-rw-r--r--sonar-core/src/main/resources/org/sonar/persistence/model/DuplicationMapper.xml28
-rw-r--r--sonar-core/src/main/resources/org/sonar/persistence/model/RuleMapper.xml10
-rw-r--r--sonar-core/src/test/java/org/sonar/persistence/model/RuleMapperTest.java128
-rw-r--r--sonar-core/src/test/resources/org/sonar/persistence/model/RuleMapperTest/selectAll.xml5
-rw-r--r--sonar-server/src/main/java/org/sonar/server/platform/Platform.java12
21 files changed, 1306 insertions, 9 deletions
diff --git a/sonar-batch/src/main/java/org/sonar/batch/bootstrap/BatchDatabase.java b/sonar-batch/src/main/java/org/sonar/batch/bootstrap/BatchDatabase.java
new file mode 100644
index 00000000000..55871f76d0d
--- /dev/null
+++ b/sonar-batch/src/main/java/org/sonar/batch/bootstrap/BatchDatabase.java
@@ -0,0 +1,43 @@
+/*
+ * 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.batch.bootstrap;
+
+import org.sonar.api.config.Settings;
+import org.sonar.persistence.DefaultDatabase;
+
+import java.util.Properties;
+
+/**
+ * @since 2.12
+ */
+public class BatchDatabase extends DefaultDatabase {
+
+ public BatchDatabase(Settings settings) {
+ super(settings);
+ }
+
+ @Override
+ protected void doCompleteProperties(Properties properties) {
+ // two connections are required : one for Hibernate and one for MyBatis
+ // Note that Hibernate will be remove soon
+ properties.setProperty("sonar.jdbc.initialSize", "2");
+ properties.setProperty("sonar.jdbc.maxActive", "2");
+ }
+}
diff --git a/sonar-batch/src/main/java/org/sonar/batch/bootstrap/BootstrapModule.java b/sonar-batch/src/main/java/org/sonar/batch/bootstrap/BootstrapModule.java
index 28cb581735b..f6e60a928ca 100644
--- a/sonar-batch/src/main/java/org/sonar/batch/bootstrap/BootstrapModule.java
+++ b/sonar-batch/src/main/java/org/sonar/batch/bootstrap/BootstrapModule.java
@@ -21,7 +21,6 @@ package org.sonar.batch.bootstrap;
import org.apache.commons.configuration.PropertiesConfiguration;
import org.sonar.api.batch.bootstrap.ProjectReactor;
-import org.sonar.api.config.Settings;
import org.sonar.api.utils.HttpDownloader;
import org.sonar.batch.FakeMavenPluginExecutor;
import org.sonar.batch.MavenPluginExecutor;
@@ -29,8 +28,10 @@ import org.sonar.batch.ServerMetadata;
import org.sonar.batch.config.BatchSettings;
import org.sonar.batch.config.BatchSettingsEnhancer;
import org.sonar.jpa.session.DatabaseSessionProvider;
-import org.sonar.jpa.session.DriverDatabaseConnector;
+import org.sonar.jpa.session.DefaultDatabaseConnector;
import org.sonar.jpa.session.ThreadLocalDatabaseSessionFactory;
+import org.sonar.persistence.DefaultDatabase;
+import org.sonar.persistence.MyBatis;
import java.net.URLClassLoader;
@@ -63,7 +64,9 @@ public class BootstrapModule extends Module {
// set as the current context classloader for hibernate, else it does not find the JDBC driver.
Thread.currentThread().setContextClassLoader(bootstrapClassLoader);
- addCoreSingleton(new DriverDatabaseConnector(getComponentByType(Settings.class), bootstrapClassLoader));
+ addCoreSingleton(BatchDatabase.class);
+ addCoreSingleton(MyBatis.class);
+ addCoreSingleton(DefaultDatabaseConnector.class);
addCoreSingleton(ThreadLocalDatabaseSessionFactory.class);
addAdapter(new DatabaseSessionProvider());
for (Object component : boostrapperComponents) {
diff --git a/sonar-core/pom.xml b/sonar-core/pom.xml
index 302e57dfe68..c2e865c7143 100644
--- a/sonar-core/pom.xml
+++ b/sonar-core/pom.xml
@@ -1,5 +1,6 @@
<?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">
+<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>
@@ -38,6 +39,19 @@
</exclusions>
</dependency>
<dependency>
+ <groupId>org.mybatis</groupId>
+ <artifactId>mybatis</artifactId>
+ <version>3.0.6</version>
+ </dependency>
+ <dependency>
+ <groupId>org.apache.derby</groupId>
+ <artifactId>derby</artifactId>
+ </dependency>
+ <dependency>
+ <groupId>org.apache.derby</groupId>
+ <artifactId>derbynet</artifactId>
+ </dependency>
+ <dependency>
<groupId>org.codehaus.sonar</groupId>
<artifactId>sonar-update-center-common</artifactId>
</dependency>
diff --git a/sonar-core/src/main/java/org/sonar/jpa/session/CustomHibernateConnectionProvider.java b/sonar-core/src/main/java/org/sonar/jpa/session/CustomHibernateConnectionProvider.java
new file mode 100644
index 00000000000..e391d3ad130
--- /dev/null
+++ b/sonar-core/src/main/java/org/sonar/jpa/session/CustomHibernateConnectionProvider.java
@@ -0,0 +1,36 @@
+/*
+ * 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.jpa.session;
+
+import org.hibernate.ejb.connection.InjectedDataSourceConnectionProvider;
+
+import javax.sql.DataSource;
+import java.util.Properties;
+
+public class CustomHibernateConnectionProvider extends InjectedDataSourceConnectionProvider {
+
+ static DataSource datasource;
+
+ @Override
+ public void configure(Properties props) {
+ setDataSource(datasource);
+ super.configure(props);
+ }
+}
diff --git a/sonar-core/src/main/java/org/sonar/jpa/session/DefaultDatabaseConnector.java b/sonar-core/src/main/java/org/sonar/jpa/session/DefaultDatabaseConnector.java
new file mode 100644
index 00000000000..2f3861b4fda
--- /dev/null
+++ b/sonar-core/src/main/java/org/sonar/jpa/session/DefaultDatabaseConnector.java
@@ -0,0 +1,85 @@
+/*
+ * 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.jpa.session;
+
+import org.hibernate.cfg.Environment;
+import org.sonar.api.config.Settings;
+import org.sonar.api.utils.SonarException;
+import org.sonar.jpa.entity.SchemaMigration;
+import org.sonar.persistence.Database;
+
+import java.sql.Connection;
+import java.sql.SQLException;
+import java.util.Properties;
+
+public class DefaultDatabaseConnector extends AbstractDatabaseConnector {
+
+ private Database database;
+
+ public DefaultDatabaseConnector(Database database, Settings configuration) {
+ super(configuration, false);
+ this.database = database;
+ }
+
+ @Override
+ public boolean isOperational() {
+ if (isStarted() && getDatabaseVersion() != SchemaMigration.LAST_VERSION) {
+ // connector was started and connection OK but schema version was not OK
+ // call start again to check if this is now ok (schema created by rails)
+ start();
+ }
+ return super.isOperational();
+ }
+
+ @Override
+ public void start() {
+ if (!isStarted()) {
+ createDatasource();
+ }
+ if (!super.isOperational()) {
+ super.start();
+ }
+ }
+
+ @Override
+ public void stop() {
+ database = null;
+ super.stop();
+ }
+
+
+ private void createDatasource() {
+ try {
+ CustomHibernateConnectionProvider.datasource = database.getDataSource();
+ } catch (Exception e) {
+ throw new SonarException("Fail to connect to database", e);
+ }
+ }
+
+ public Connection getConnection() throws SQLException {
+ return database != null && database.getDataSource() != null ? database.getDataSource().getConnection() : null;
+ }
+
+ @Override
+ public void setupEntityManagerFactory(Properties factoryProps) {
+ factoryProps.put(Environment.CONNECTION_PROVIDER, CustomHibernateConnectionProvider.class.getName());
+ }
+
+} \ No newline at end of file
diff --git a/sonar-core/src/main/java/org/sonar/persistence/Database.java b/sonar-core/src/main/java/org/sonar/persistence/Database.java
new file mode 100644
index 00000000000..8b232037809
--- /dev/null
+++ b/sonar-core/src/main/java/org/sonar/persistence/Database.java
@@ -0,0 +1,31 @@
+/*
+ * 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 javax.sql.DataSource;
+
+/**
+ * @since 2.12
+ */
+public interface Database {
+ void start();
+ void stop();
+ DataSource getDataSource();
+}
diff --git a/sonar-core/src/main/java/org/sonar/persistence/DefaultDatabase.java b/sonar-core/src/main/java/org/sonar/persistence/DefaultDatabase.java
new file mode 100644
index 00000000000..f8417d201e6
--- /dev/null
+++ b/sonar-core/src/main/java/org/sonar/persistence/DefaultDatabase.java
@@ -0,0 +1,134 @@
+/*
+ * 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.commons.dbcp.BasicDataSource;
+import org.apache.commons.dbcp.BasicDataSourceFactory;
+import org.apache.commons.lang.StringUtils;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+import org.sonar.api.config.Settings;
+import org.sonar.api.database.DatabaseProperties;
+
+import javax.sql.DataSource;
+import java.sql.SQLException;
+import java.util.List;
+import java.util.Map;
+import java.util.Properties;
+
+/**
+ * @since 2.12
+ */
+public class DefaultDatabase implements Database {
+
+ private static final Logger LOG = LoggerFactory.getLogger(Database.class);
+
+ private Settings settings;
+ private BasicDataSource datasource;
+
+ public DefaultDatabase(Settings settings) {
+ this.settings = settings;
+ }
+
+ public final void start() {
+ try {
+ doBeforeStart();
+
+ LOG.info("Create JDBC datasource");
+ datasource = (BasicDataSource) BasicDataSourceFactory.createDataSource(getCommonsDbcpProperties());
+
+ } catch (Exception e) {
+ throw new IllegalStateException("Fail to connect to database", e);
+ }
+ }
+
+ protected void doBeforeStart() {
+ }
+
+ public final void stop() {
+ doBeforeStop();
+ if (datasource != null) {
+ try {
+ datasource.close();
+ } catch (SQLException e) {
+ throw new IllegalStateException("Fail to stop JDBC connection pool", e);
+ }
+ }
+ }
+
+ protected void doBeforeStop() {
+
+ }
+
+ public final DataSource getDataSource() {
+ return datasource;
+ }
+
+ public final Properties getProperties() {
+ Properties properties = new Properties();
+ completeProperties(settings, properties, "sonar.jdbc.");
+ completeProperties(settings, properties, "sonar.hibernate.");
+ completeDefaultProperties(properties);
+ doCompleteProperties(properties);
+ return properties;
+ }
+
+ protected void doCompleteProperties(Properties properties) {
+
+ }
+
+ static void completeProperties(Settings settings, Properties properties, String prefix) {
+ List<String> jdbcKeys = settings.getKeysStartingWith(prefix);
+ for (String jdbcKey : jdbcKeys) {
+ String value = settings.getString(jdbcKey);
+ properties.setProperty(jdbcKey, value);
+ }
+ }
+
+ Properties getCommonsDbcpProperties() {
+ Properties result = new Properties();
+ Properties props = getProperties();
+ for (Map.Entry<Object, Object> entry : props.entrySet()) {
+ String key = (String) entry.getKey();
+ if (StringUtils.startsWith(key, "sonar.jdbc.")) {
+ result.setProperty(StringUtils.removeStart(key, "sonar.jdbc."), (String) entry.getValue());
+ }
+ }
+
+ // This property is required by the Ruby Oracle enhanced adapter.
+ // It directly uses the Connection implementation provided by the Oracle driver
+ result.setProperty("accessToUnderlyingConnectionAllowed", "true");
+ return result;
+ }
+
+ private static void completeDefaultProperties(Properties props) {
+ completeDefaultProperty(props, DatabaseProperties.PROP_DRIVER, props.getProperty(DatabaseProperties.PROP_DRIVER_DEPRECATED, DatabaseProperties.PROP_DRIVER_DEFAULT_VALUE));
+ completeDefaultProperty(props, DatabaseProperties.PROP_URL, DatabaseProperties.PROP_URL_DEFAULT_VALUE);
+ completeDefaultProperty(props, DatabaseProperties.PROP_USER, props.getProperty(DatabaseProperties.PROP_USER_DEPRECATED, DatabaseProperties.PROP_USER_DEFAULT_VALUE));
+ completeDefaultProperty(props, DatabaseProperties.PROP_PASSWORD, DatabaseProperties.PROP_PASSWORD_DEFAULT_VALUE);
+ completeDefaultProperty(props, DatabaseProperties.PROP_HIBERNATE_HBM2DLL, "validate");
+ }
+
+ private static void completeDefaultProperty(Properties props, String key, String defaultValue) {
+ if (props.getProperty(key) == null) {
+ props.setProperty(key, defaultValue);
+ }
+ }
+}
diff --git a/sonar-core/src/main/java/org/sonar/persistence/InMemoryDatabase.java b/sonar-core/src/main/java/org/sonar/persistence/InMemoryDatabase.java
new file mode 100644
index 00000000000..31742ea91dc
--- /dev/null
+++ b/sonar-core/src/main/java/org/sonar/persistence/InMemoryDatabase.java
@@ -0,0 +1,93 @@
+/*
+ * 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.commons.dbcp.BasicDataSource;
+import org.apache.commons.dbcp.BasicDataSourceFactory;
+import org.apache.commons.io.FileUtils;
+import org.apache.commons.io.IOUtils;
+import org.apache.commons.lang.StringUtils;
+import org.apache.ibatis.io.Resources;
+
+import javax.sql.DataSource;
+import java.io.IOException;
+import java.sql.Connection;
+import java.sql.DriverManager;
+import java.sql.SQLException;
+import java.sql.Statement;
+import java.util.List;
+import java.util.Properties;
+
+public class InMemoryDatabase implements Database {
+
+ private BasicDataSource datasource;
+
+ public void start() {
+ startDatabase();
+ executeDdl();
+ }
+
+ private void startDatabase() {
+ try {
+ Properties properties = new Properties();
+ properties.put("driverClassName", "org.apache.derby.jdbc.EmbeddedDriver");
+ properties.put("username", "sonar");
+ properties.put("password", "sonar");
+ properties.put("url", "jdbc:derby:memory:sonar;create=true;user=sonar;password=sonar");
+ datasource = (BasicDataSource) BasicDataSourceFactory.createDataSource(properties);
+
+ } catch (Exception e) {
+ throw new IllegalStateException("Fail to start Derby", e);
+ }
+ }
+
+ private void executeDdl() {
+ try {
+ Connection connection = datasource.getConnection();
+ List<String> lines = IOUtils.readLines(getClass().getResourceAsStream("/org/sonar/persistence/master_derby.ddl"));
+ for (String line : lines) {
+ if (StringUtils.isNotBlank(line) && !StringUtils.startsWith(line, "--")) {
+ Statement statement = connection.createStatement();
+ statement.execute(line);
+ statement.close();
+ }
+ }
+ connection.commit();
+ } catch (Exception e) {
+ e.printStackTrace();
+ }
+ }
+
+ public void stop() {
+ try {
+ if (datasource != null) {
+ datasource.close();
+ }
+ DriverManager.getConnection("jdbc:derby:memory:sonar;shutdown=true;user=sonar;password=sonar");
+
+ } catch (SQLException e) {
+ throw new IllegalStateException("Fail to stop Derby", e);
+ }
+ }
+
+ public DataSource getDataSource() {
+ return datasource;
+ }
+}
diff --git a/sonar-core/src/main/java/org/sonar/persistence/MyBatis.java b/sonar-core/src/main/java/org/sonar/persistence/MyBatis.java
new file mode 100644
index 00000000000..9f25636cd21
--- /dev/null
+++ b/sonar-core/src/main/java/org/sonar/persistence/MyBatis.java
@@ -0,0 +1,87 @@
+/*
+ * 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.commons.io.IOUtils;
+import org.apache.commons.lang.StringUtils;
+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.persistence.model.DuplicationMapper;
+import org.sonar.persistence.model.RuleMapper;
+import org.sonar.persistence.model.Duplication;
+import org.sonar.persistence.model.Rule;
+
+import java.io.IOException;
+import java.io.InputStream;
+
+public class MyBatis {
+
+ private Database database;
+ private SqlSessionFactory sessionFactory;
+
+ public MyBatis(Database database) {
+ this.database = database;
+ }
+
+ public MyBatis start() throws IOException {
+ Configuration conf = new Configuration();
+ conf.setEnvironment(new Environment("production", createTransactionFactory(), database.getDataSource()));
+ conf.setUseGeneratedKeys(true);
+
+ loadMapper(conf, DuplicationMapper.class, "Duplication", Duplication.class);
+ loadMapper(conf, RuleMapper.class, "Rule", Rule.class);
+
+ sessionFactory = new SqlSessionFactoryBuilder().build(conf);
+ return this;
+ }
+
+ public SqlSessionFactory getSessionFactory() {
+ return sessionFactory;
+ }
+
+ public SqlSession openSession() {
+ return sessionFactory.openSession();
+ }
+
+ public SqlSession openSession(ExecutorType type) {
+ return sessionFactory.openSession(type);
+ }
+
+ private void loadMapper(Configuration conf, Class mapperClass, String alias, Class dtoClass) throws IOException {
+ // trick to use database-specific XML files for a single Mapper Java interface
+ InputStream input = getClass().getResourceAsStream("/" + StringUtils.replace(mapperClass.getName(), ".", "/") + ".xml");
+ try {
+ conf.getTypeAliasRegistry().registerAlias(alias, dtoClass);
+ XMLMapperBuilder mapperParser = new XMLMapperBuilder(input, conf, mapperClass.getName(), conf.getSqlFragments());
+ mapperParser.parse();
+ conf.addLoadedResource(mapperClass.getName());
+
+ } finally {
+ IOUtils.closeQuietly(input);
+ }
+ }
+
+ private static JdbcTransactionFactory createTransactionFactory() {
+ return new JdbcTransactionFactory();
+ }
+
+}
diff --git a/sonar-core/src/main/java/org/sonar/persistence/dao/DuplicationDao.java b/sonar-core/src/main/java/org/sonar/persistence/dao/DuplicationDao.java
new file mode 100644
index 00000000000..f9ff75d208c
--- /dev/null
+++ b/sonar-core/src/main/java/org/sonar/persistence/dao/DuplicationDao.java
@@ -0,0 +1,98 @@
+/*
+ * 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.dao;
+
+import org.apache.ibatis.session.SqlSession;
+import org.sonar.api.BatchComponent;
+import org.sonar.api.ServerComponent;
+import org.sonar.persistence.MyBatis;
+import org.sonar.persistence.model.Duplication;
+import org.sonar.persistence.model.DuplicationMapper;
+
+import java.util.List;
+
+public class DuplicationDao implements BatchComponent, ServerComponent {
+
+ private MyBatis mybatis;
+
+ public DuplicationDao(MyBatis mybatis) {
+ this.mybatis = mybatis;
+ }
+
+ public Duplication selectById(Long id) {
+ SqlSession sqlSession = mybatis.openSession();
+ try {
+ DuplicationMapper mapper = sqlSession.getMapper(DuplicationMapper.class);
+ return mapper.selectById(id);
+
+ } finally {
+ sqlSession.close();
+ }
+ }
+
+ public List<Duplication> selectAll() {
+ SqlSession sqlSession = mybatis.openSession();
+ try {
+ DuplicationMapper mapper = sqlSession.getMapper(DuplicationMapper.class);
+ return mapper.selectAll();
+ } finally {
+ sqlSession.close();
+ }
+ }
+
+ public Integer insert(Duplication duplication) {
+ SqlSession session = mybatis.openSession();
+ Integer status = null;
+ try {
+ DuplicationMapper mapper = session.getMapper(DuplicationMapper.class);
+ status = mapper.insert(duplication);
+ session.commit();
+ } finally {
+ session.close();
+ }
+ return status;
+ }
+
+ public Integer update(Duplication duplication) {
+ SqlSession session = mybatis.openSession();
+ Integer status = null;
+ try {
+ DuplicationMapper mapper = session.getMapper(DuplicationMapper.class);
+ status = mapper.update(duplication);
+ session.commit();
+ } finally {
+ session.close();
+ }
+ return status;
+ }
+
+ public Integer delete(Long id) {
+ SqlSession session = mybatis.openSession();
+ Integer status = null;
+ try {
+ DuplicationMapper mapper = session.getMapper(DuplicationMapper.class);
+ status = mapper.delete(id);
+ session.commit();
+ } finally {
+ session.close();
+ }
+ return status;
+ }
+}
diff --git a/sonar-core/src/main/java/org/sonar/persistence/dao/RuleDao.java b/sonar-core/src/main/java/org/sonar/persistence/dao/RuleDao.java
new file mode 100644
index 00000000000..6391990c517
--- /dev/null
+++ b/sonar-core/src/main/java/org/sonar/persistence/dao/RuleDao.java
@@ -0,0 +1,49 @@
+/*
+ * 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.dao;
+
+import org.apache.ibatis.session.SqlSession;
+import org.sonar.api.BatchComponent;
+import org.sonar.api.ServerComponent;
+import org.sonar.persistence.MyBatis;
+import org.sonar.persistence.model.Rule;
+import org.sonar.persistence.model.RuleMapper;
+
+import java.util.List;
+
+public class RuleDao implements BatchComponent, ServerComponent {
+
+ private MyBatis mybatis;
+
+ public RuleDao(MyBatis mybatis) {
+ this.mybatis = mybatis;
+ }
+
+ public List<Rule> selectAll() {
+ SqlSession sqlSession = mybatis.openSession();
+ try {
+ RuleMapper mapper = sqlSession.getMapper(RuleMapper.class);
+ return mapper.selectAll();
+ } finally {
+ sqlSession.close();
+ }
+ }
+
+}
diff --git a/sonar-core/src/main/java/org/sonar/persistence/model/Duplication.java b/sonar-core/src/main/java/org/sonar/persistence/model/Duplication.java
new file mode 100644
index 00000000000..fde9d0c6ea7
--- /dev/null
+++ b/sonar-core/src/main/java/org/sonar/persistence/model/Duplication.java
@@ -0,0 +1,51 @@
+/*
+ * 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.model;
+
+/**
+ * A simple DTO (Data Transfer Object) class that provides the mapping of data to a table similar to this:
+ * table: status
+ * columns: status_id (INT),status_name (VARCHAR)
+ */
+public class Duplication {
+ private Long id;
+ private String name;
+
+ public Long getId() {
+ return id;
+ }
+
+ public void setId(Long id) {
+ this.id = id;
+ }
+
+ public String getName() {
+ return name;
+ }
+
+ public void setName(String name) {
+ this.name = name;
+ }
+
+ @Override
+ public String toString() {
+ return "[Duplication] " + "(" + id + ") " + name;
+ }
+}
diff --git a/sonar-core/src/main/java/org/sonar/persistence/model/DuplicationMapper.java b/sonar-core/src/main/java/org/sonar/persistence/model/DuplicationMapper.java
new file mode 100644
index 00000000000..612c56c3a12
--- /dev/null
+++ b/sonar-core/src/main/java/org/sonar/persistence/model/DuplicationMapper.java
@@ -0,0 +1,38 @@
+/*
+ * 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.model;
+
+import org.sonar.persistence.model.Duplication;
+
+import java.util.List;
+
+public interface DuplicationMapper {
+
+ Duplication selectById(Long id);
+
+ List<Duplication> selectAll();
+
+ Integer insert(Duplication duplication);
+
+ Integer update(Duplication duplication);
+
+ Integer delete(Long id);
+}
+
diff --git a/sonar-core/src/main/java/org/sonar/persistence/model/Rule.java b/sonar-core/src/main/java/org/sonar/persistence/model/Rule.java
new file mode 100644
index 00000000000..d86d68c498b
--- /dev/null
+++ b/sonar-core/src/main/java/org/sonar/persistence/model/Rule.java
@@ -0,0 +1,77 @@
+/*
+ * 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.model;
+
+public class Rule {
+ private Long id;
+ private String repositoryKey;
+ private String ruleKey;
+ private String description;
+ private boolean enabled;
+ private String name;
+
+ public Long getId() {
+ return id;
+ }
+
+ public void setId(Long id) {
+ this.id = id;
+ }
+
+ public String getRepositoryKey() {
+ return repositoryKey;
+ }
+
+ public void setRepositoryKey(String repositoryKey) {
+ this.repositoryKey = repositoryKey;
+ }
+
+ public String getRuleKey() {
+ return ruleKey;
+ }
+
+ public void setRuleKey(String ruleKey) {
+ this.ruleKey = ruleKey;
+ }
+
+ public String getDescription() {
+ return description;
+ }
+
+ public void setDescription(String description) {
+ this.description = description;
+ }
+
+ public boolean isEnabled() {
+ return enabled;
+ }
+
+ public void setEnabled(boolean enabled) {
+ this.enabled = enabled;
+ }
+
+ public String getName() {
+ return name;
+ }
+
+ public void setName(String name) {
+ this.name = name;
+ }
+}
diff --git a/sonar-core/src/main/java/org/sonar/persistence/model/RuleMapper.java b/sonar-core/src/main/java/org/sonar/persistence/model/RuleMapper.java
new file mode 100644
index 00000000000..7f390de9e33
--- /dev/null
+++ b/sonar-core/src/main/java/org/sonar/persistence/model/RuleMapper.java
@@ -0,0 +1,28 @@
+/*
+ * 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.model;
+
+import org.sonar.persistence.model.Rule;
+
+import java.util.List;
+
+public interface RuleMapper {
+ List<Rule> selectAll();
+}
diff --git a/sonar-core/src/main/resources/org/sonar/persistence/master_derby.ddl b/sonar-core/src/main/resources/org/sonar/persistence/master_derby.ddl
new file mode 100644
index 00000000000..be3e9ffdb6b
--- /dev/null
+++ b/sonar-core/src/main/resources/org/sonar/persistence/master_derby.ddl
@@ -0,0 +1,257 @@
+-- Structure of version 2.11
+
+-- This file has been generated manually :
+-- 1. start sonar with property sonar.useStructureDump=false
+-- 2. execute $DERBY_HOME/bin/dblook -d 'jdbc:derby://localhost:1527/sonar;user=sonar;password=sonar' -o /derby.ddl
+-- 3. copy the generated derby.ddl into this file
+
+CREATE TABLE "QUALITY_MODELS" ("ID" INTEGER NOT NULL GENERATED BY DEFAULT AS IDENTITY (START WITH 1, INCREMENT BY 1), "NAME" VARCHAR(100))
+
+CREATE TABLE "GROUPS_USERS" ("USER_ID" INTEGER, "GROUP_ID" INTEGER)
+
+CREATE TABLE "CHARACTERISTIC_EDGES" ("CHILD_ID" INTEGER, "PARENT_ID" INTEGER)
+
+CREATE TABLE "CRITERIA" ("ID" INTEGER NOT NULL GENERATED BY DEFAULT AS IDENTITY (START WITH 1, INCREMENT BY 1), "FILTER_ID" INTEGER, "FAMILY" VARCHAR(100), "KEE" VARCHAR(100), "OPERATOR" VARCHAR(20), "VALUE" DECIMAL(30,20), "TEXT_VALUE" VARCHAR(256), "VARIATION" SMALLINT)
+
+CREATE TABLE "DEPENDENCIES" ("ID" INTEGER 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, "TO_RESOURCE_ID" INTEGER, "DEP_USAGE" VARCHAR(30), "DEP_WEIGHT" INTEGER, "PROJECT_SNAPSHOT_ID" INTEGER, "PARENT_DEPENDENCY_ID" BIGINT, "FROM_SCOPE" VARCHAR(3), "TO_SCOPE" VARCHAR(3))
+
+CREATE TABLE "CHARACTERISTICS" ("ID" INTEGER NOT NULL GENERATED BY DEFAULT AS IDENTITY (START WITH 1, INCREMENT BY 1), "QUALITY_MODEL_ID" INTEGER, "KEE" VARCHAR(100), "NAME" VARCHAR(100), "RULE_ID" INTEGER, "DEPTH" INTEGER, "CHARACTERISTIC_ORDER" INTEGER, "DESCRIPTION" VARCHAR(4000), "ENABLED" SMALLINT)
+
+CREATE TABLE "RULES_PARAMETERS" ("ID" INTEGER NOT NULL GENERATED BY DEFAULT AS IDENTITY (START WITH 1, INCREMENT BY 1), "RULE_ID" INTEGER NOT NULL, "NAME" VARCHAR(128) NOT NULL, "PARAM_TYPE" VARCHAR(512) NOT NULL, "DEFAULT_VALUE" VARCHAR(4000), "DESCRIPTION" VARCHAR(4000))
+
+CREATE TABLE "RULES_PROFILES" ("ID" INTEGER NOT NULL GENERATED BY DEFAULT AS IDENTITY (START WITH 1, INCREMENT BY 1), "NAME" VARCHAR(100) NOT NULL, "DEFAULT_PROFILE" SMALLINT DEFAULT 0, "PROVIDED" SMALLINT NOT NULL DEFAULT 0, "LANGUAGE" VARCHAR(16), "PARENT_NAME" VARCHAR(100), "ENABLED" SMALLINT NOT NULL DEFAULT 1, "VERSION" INTEGER DEFAULT 1, "USED_PROFILE" SMALLINT DEFAULT 0)
+
+CREATE TABLE "WIDGETS" ("ID" INTEGER NOT NULL GENERATED BY DEFAULT AS IDENTITY (START WITH 1, INCREMENT BY 1), "DASHBOARD_ID" INTEGER NOT NULL, "WIDGET_KEY" VARCHAR(256) NOT NULL, "NAME" VARCHAR(256), "DESCRIPTION" VARCHAR(1000), "COLUMN_INDEX" INTEGER, "ROW_INDEX" INTEGER, "CONFIGURED" SMALLINT, "CREATED_AT" TIMESTAMP, "UPDATED_AT" TIMESTAMP)
+
+CREATE TABLE "FILTER_COLUMNS" ("ID" INTEGER NOT NULL GENERATED BY DEFAULT AS IDENTITY (START WITH 1, INCREMENT BY 1), "FILTER_ID" INTEGER, "FAMILY" VARCHAR(100), "KEE" VARCHAR(100), "SORT_DIRECTION" VARCHAR(5), "ORDER_INDEX" INTEGER, "VARIATION" SMALLINT)
+
+CREATE TABLE "MEASURE_DATA" ("ID" INTEGER NOT NULL GENERATED BY DEFAULT AS IDENTITY (START WITH 1, INCREMENT BY 1), "MEASURE_ID" INTEGER, "SNAPSHOT_ID" INTEGER, "DATA" BLOB(2147483647))
+
+CREATE TABLE "GROUPS" ("ID" INTEGER NOT NULL GENERATED BY DEFAULT AS IDENTITY (START WITH 1, INCREMENT BY 1), "NAME" VARCHAR(40), "DESCRIPTION" VARCHAR(200), "CREATED_AT" TIMESTAMP, "UPDATED_AT" TIMESTAMP)
+
+CREATE TABLE "ACTIVE_RULE_PARAM_CHANGES" ("ID" INTEGER NOT NULL GENERATED BY DEFAULT AS IDENTITY (START WITH 1, INCREMENT BY 1), "ACTIVE_RULE_CHANGE_ID" INTEGER NOT NULL, "RULES_PARAMETER_ID" INTEGER NOT NULL, "OLD_VALUE" VARCHAR(4000), "NEW_VALUE" VARCHAR(4000))
+
+CREATE TABLE "SNAPSHOTS" ("ID" INTEGER NOT NULL GENERATED BY DEFAULT AS IDENTITY (START WITH 1, INCREMENT BY 1), "CREATED_AT" TIMESTAMP, "PROJECT_ID" INTEGER NOT NULL, "PARENT_SNAPSHOT_ID" INTEGER, "STATUS" VARCHAR(4) NOT NULL DEFAULT 'U', "ISLAST" SMALLINT NOT NULL DEFAULT 0, "SCOPE" VARCHAR(3), "QUALIFIER" VARCHAR(3), "ROOT_SNAPSHOT_ID" INTEGER, "VERSION" VARCHAR(60), "PATH" VARCHAR(96), "DEPTH" INTEGER, "ROOT_PROJECT_ID" INTEGER, "PERIOD1_MODE" VARCHAR(100), "PERIOD1_PARAM" VARCHAR(100), "PERIOD1_DATE" TIMESTAMP, "PERIOD2_MODE" VARCHAR(100), "PERIOD2_PARAM" VARCHAR(100), "PERIOD2_DATE" TIMESTAMP, "PERIOD3_MODE" VARCHAR(100), "PERIOD3_PARAM" VARCHAR(100), "PERIOD3_DATE" TIMESTAMP, "PERIOD4_MODE" VARCHAR(100), "PERIOD4_PARAM" VARCHAR(100), "PERIOD4_DATE" TIMESTAMP, "PERIOD5_MODE" VARCHAR(100), "PERIOD5_PARAM" VARCHAR(100), "PERIOD5_DATE" TIMESTAMP)
+
+CREATE TABLE "SCHEMA_MIGRATIONS" ("VERSION" VARCHAR(256) NOT NULL)
+
+CREATE TABLE "GROUP_ROLES" ("ID" INTEGER NOT NULL GENERATED BY DEFAULT AS IDENTITY (START WITH 1, INCREMENT BY 1), "GROUP_ID" INTEGER, "RESOURCE_ID" INTEGER, "ROLE" VARCHAR(64) NOT NULL)
+
+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), "PRIORITY" INTEGER, "ENABLED" SMALLINT, "CARDINALITY" VARCHAR(10), "PARENT_ID" INTEGER, "PLUGIN_CONFIG_KEY" VARCHAR(500), "NAME" VARCHAR(200))
+
+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 "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))
+
+CREATE TABLE "PROPERTIES" ("ID" INTEGER NOT NULL GENERATED BY DEFAULT AS IDENTITY (START WITH 1, INCREMENT BY 1), "PROP_KEY" VARCHAR(512), "RESOURCE_ID" INTEGER, "TEXT_VALUE" CLOB(2147483647), "USER_ID" INTEGER)
+
+CREATE TABLE "PROJECT_LINKS" ("ID" INTEGER NOT NULL GENERATED BY DEFAULT AS IDENTITY (START WITH 1, INCREMENT BY 1), "PROJECT_ID" INTEGER NOT NULL, "LINK_TYPE" VARCHAR(20), "NAME" VARCHAR(128), "HREF" VARCHAR(2048) NOT NULL)
+
+CREATE TABLE "DUPLICATIONS_INDEX" ("ID" INTEGER NOT NULL GENERATED BY DEFAULT AS IDENTITY (START WITH 1, INCREMENT BY 1), "PROJECT_SNAPSHOT_ID" INTEGER NOT NULL, "SNAPSHOT_ID" INTEGER NOT NULL, "HASH" VARCHAR(50) NOT NULL, "INDEX_IN_FILE" INTEGER NOT NULL, "START_LINE" INTEGER NOT NULL, "END_LINE" INTEGER NOT NULL)
+
+CREATE TABLE "REVIEW_COMMENTS" ("ID" INTEGER NOT NULL GENERATED BY DEFAULT AS IDENTITY (START WITH 1, INCREMENT BY 1), "CREATED_AT" TIMESTAMP, "UPDATED_AT" TIMESTAMP, "REVIEW_ID" INTEGER, "USER_ID" INTEGER, "REVIEW_TEXT" CLOB(2147483647))
+
+CREATE TABLE "ACTIVE_RULE_CHANGES" ("ID" INTEGER NOT NULL GENERATED BY DEFAULT AS IDENTITY (START WITH 1, INCREMENT BY 1), "USER_NAME" VARCHAR(200) NOT NULL, "PROFILE_ID" INTEGER NOT NULL, "PROFILE_VERSION" INTEGER NOT NULL, "RULE_ID" INTEGER NOT NULL, "CHANGE_DATE" TIMESTAMP NOT NULL, "ENABLED" SMALLINT, "OLD_SEVERITY" INTEGER, "NEW_SEVERITY" INTEGER)
+
+CREATE TABLE "PROJECT_MEASURES" ("ID" INTEGER NOT NULL GENERATED BY DEFAULT AS IDENTITY (START WITH 1, INCREMENT BY 1), "VALUE" DECIMAL(30,20), "METRIC_ID" INTEGER NOT NULL, "SNAPSHOT_ID" INTEGER, "RULE_ID" INTEGER, "RULES_CATEGORY_ID" INTEGER, "TEXT_VALUE" VARCHAR(96), "TENDENCY" INTEGER, "MEASURE_DATE" TIMESTAMP, "PROJECT_ID" INTEGER, "ALERT_STATUS" VARCHAR(5), "ALERT_TEXT" VARCHAR(4000), "URL" VARCHAR(2000), "DESCRIPTION" VARCHAR(4000), "RULE_PRIORITY" INTEGER, "CHARACTERISTIC_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))
+
+CREATE TABLE "SNAPSHOT_SOURCES" ("ID" INTEGER NOT NULL GENERATED BY DEFAULT AS IDENTITY (START WITH 1, INCREMENT BY 1), "SNAPSHOT_ID" INTEGER NOT NULL, "DATA" CLOB(2147483647))
+
+CREATE TABLE "PROJECTS" ("ID" INTEGER NOT NULL GENERATED BY DEFAULT AS IDENTITY (START WITH 1, INCREMENT BY 1), "NAME" VARCHAR(256), "DESCRIPTION" VARCHAR(2000), "ENABLED" SMALLINT NOT NULL DEFAULT 1, "SCOPE" VARCHAR(3), "QUALIFIER" VARCHAR(3), "KEE" VARCHAR(400), "ROOT_ID" INTEGER, "PROFILE_ID" INTEGER, "LANGUAGE" VARCHAR(5), "COPY_RESOURCE_ID" INTEGER, "LONG_NAME" VARCHAR(256))
+
+CREATE TABLE "REVIEWS" ("ID" INTEGER NOT NULL GENERATED BY DEFAULT AS IDENTITY (START WITH 1, INCREMENT BY 1), "CREATED_AT" TIMESTAMP, "UPDATED_AT" TIMESTAMP, "USER_ID" INTEGER, "ASSIGNEE_ID" INTEGER, "TITLE" VARCHAR(500), "STATUS" VARCHAR(10), "SEVERITY" VARCHAR(10), "RULE_FAILURE_PERMANENT_ID" INTEGER, "PROJECT_ID" INTEGER, "RESOURCE_ID" INTEGER, "RESOURCE_LINE" INTEGER, "RESOLUTION" VARCHAR(200))
+
+CREATE TABLE "RULES_CATEGORIES" ("ID" INTEGER NOT NULL GENERATED BY DEFAULT AS IDENTITY (START WITH 1, INCREMENT BY 1), "NAME" VARCHAR(255) NOT NULL, "DESCRIPTION" VARCHAR(1000) NOT NULL)
+
+CREATE TABLE "ACTIVE_FILTERS" ("ID" INTEGER NOT NULL GENERATED BY DEFAULT AS IDENTITY (START WITH 1, INCREMENT BY 1), "FILTER_ID" INTEGER, "USER_ID" INTEGER, "ORDER_INDEX" INTEGER)
+
+CREATE TABLE "MANUAL_MEASURES" ("ID" INTEGER 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), "TEXT_VALUE" VARCHAR(4000), "USER_LOGIN" VARCHAR(40), "DESCRIPTION" VARCHAR(4000), "CREATED_AT" TIMESTAMP, "UPDATED_AT" TIMESTAMP)
+
+CREATE TABLE "ACTIVE_RULES" ("ID" INTEGER NOT NULL GENERATED BY DEFAULT AS IDENTITY (START WITH 1, INCREMENT BY 1), "PROFILE_ID" INTEGER NOT NULL, "RULE_ID" INTEGER NOT NULL, "FAILURE_LEVEL" INTEGER NOT NULL, "INHERITANCE" VARCHAR(10))
+
+CREATE TABLE "NOTIFICATIONS" ("ID" INTEGER NOT NULL GENERATED BY DEFAULT AS IDENTITY (START WITH 1, INCREMENT BY 1), "CREATED_AT" TIMESTAMP, "DATA" BLOB(2147483647))
+
+CREATE TABLE "USER_ROLES" ("ID" INTEGER NOT NULL GENERATED BY DEFAULT AS IDENTITY (START WITH 1, INCREMENT BY 1), "USER_ID" INTEGER, "RESOURCE_ID" INTEGER, "ROLE" VARCHAR(64) NOT NULL)
+
+CREATE TABLE "ACTIVE_DASHBOARDS" ("ID" INTEGER NOT NULL GENERATED BY DEFAULT AS IDENTITY (START WITH 1, INCREMENT BY 1), "DASHBOARD_ID" INTEGER NOT NULL, "USER_ID" INTEGER, "ORDER_INDEX" INTEGER)
+
+CREATE TABLE "ACTIVE_RULE_PARAMETERS" ("ID" INTEGER NOT NULL GENERATED BY DEFAULT AS IDENTITY (START WITH 1, INCREMENT BY 1), "ACTIVE_RULE_ID" INTEGER NOT NULL, "RULES_PARAMETER_ID" INTEGER NOT NULL, "VALUE" VARCHAR(4000))
+
+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), "TEXT_VALUE" VARCHAR(4000))
+
+CREATE TABLE "USERS" ("ID" INTEGER NOT NULL GENERATED BY DEFAULT AS IDENTITY (START WITH 1, INCREMENT BY 1), "LOGIN" VARCHAR(40), "NAME" VARCHAR(200), "EMAIL" VARCHAR(100), "CRYPTED_PASSWORD" VARCHAR(40), "SALT" VARCHAR(40), "CREATED_AT" TIMESTAMP, "UPDATED_AT" TIMESTAMP, "REMEMBER_TOKEN" VARCHAR(500), "REMEMBER_TOKEN_EXPIRES_AT" TIMESTAMP)
+
+CREATE TABLE "FILTERS" ("ID" INTEGER NOT NULL GENERATED BY DEFAULT AS IDENTITY (START WITH 1, INCREMENT BY 1), "NAME" VARCHAR(100), "USER_ID" INTEGER, "SHARED" SMALLINT, "FAVOURITES" SMALLINT, "RESOURCE_ID" INTEGER, "DEFAULT_VIEW" VARCHAR(20), "PAGE_SIZE" INTEGER, "PERIOD_INDEX" INTEGER)
+
+CREATE TABLE "DASHBOARDS" ("ID" INTEGER NOT NULL GENERATED BY DEFAULT AS IDENTITY (START WITH 1, INCREMENT BY 1), "USER_ID" INTEGER, "NAME" VARCHAR(256), "DESCRIPTION" VARCHAR(1000), "COLUMN_LAYOUT" VARCHAR(20), "SHARED" SMALLINT, "CREATED_AT" TIMESTAMP, "UPDATED_AT" TIMESTAMP)
+
+CREATE TABLE "RULE_FAILURES" ("ID" INTEGER NOT NULL GENERATED BY DEFAULT AS IDENTITY (START WITH 1, INCREMENT BY 1), "SNAPSHOT_ID" INTEGER NOT NULL, "RULE_ID" INTEGER NOT NULL, "FAILURE_LEVEL" INTEGER NOT NULL, "MESSAGE" VARCHAR(4000), "LINE" INTEGER, "COST" DECIMAL(30,20), "CREATED_AT" TIMESTAMP, "CHECKSUM" VARCHAR(1000), "PERMANENT_ID" INTEGER, "SWITCHED_OFF" SMALLINT)
+
+CREATE TABLE "METRICS" ("ID" INTEGER NOT NULL GENERATED BY DEFAULT AS IDENTITY (START WITH 1, INCREMENT BY 1), "NAME" VARCHAR(64) NOT NULL, "DESCRIPTION" VARCHAR(255), "DIRECTION" INTEGER NOT NULL DEFAULT 0, "DOMAIN" VARCHAR(64), "SHORT_NAME" VARCHAR(64), "QUALITATIVE" SMALLINT NOT NULL DEFAULT 0, "VAL_TYPE" VARCHAR(8), "USER_MANAGED" SMALLINT DEFAULT 0, "ENABLED" SMALLINT DEFAULT 1, "ORIGIN" VARCHAR(3), "WORST_VALUE" DECIMAL(30,20), "BEST_VALUE" DECIMAL(30,20), "OPTIMIZED_BEST_VALUE" SMALLINT, "HIDDEN" SMALLINT)
+
+-- ----------------------------------------------
+-- DDL Statements for indexes
+-- ----------------------------------------------
+
+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 "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")
+
+-- ----------------------------------------------
+-- DDL Statements for keys
+-- ----------------------------------------------
+
+-- primary/unique
+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 "DUPLICATIONS_INDEX" ADD CONSTRAINT "SQL110927104441080" PRIMARY KEY ("ID")
+
+ALTER TABLE "SNAPSHOT_SOURCES" ADD CONSTRAINT "SQL110927104437590" PRIMARY KEY ("ID")
+
+ALTER TABLE "NOTIFICATIONS" ADD CONSTRAINT "SQL110927104441030" PRIMARY KEY ("ID")
+
+ALTER TABLE "RULES_CATEGORIES" ADD CONSTRAINT "SQL110927104437060" 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_FILTERS" ADD CONSTRAINT "SQL110927104438740" 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") \ No newline at end of file
diff --git a/sonar-core/src/main/resources/org/sonar/persistence/model/DuplicationMapper.xml b/sonar-core/src/main/resources/org/sonar/persistence/model/DuplicationMapper.xml
new file mode 100644
index 00000000000..887472a4ef6
--- /dev/null
+++ b/sonar-core/src/main/resources/org/sonar/persistence/model/DuplicationMapper.xml
@@ -0,0 +1,28 @@
+<?xml version="1.0" encoding="UTF-8" ?>
+<!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd">
+
+<mapper namespace="org.sonar.persistence.model.DuplicationMapper">
+
+ <select id="selectById" parameterType="long" resultType="Duplication">
+ select id, name from duplications where id = #{id}
+ </select>
+
+ <select id="selectAll" resultType="Duplication">
+ select id, name from duplications
+ </select>
+
+ <insert id="create" keyColumn="id" useGeneratedKeys="true" parameterType="Duplication">
+ insert into duplications(name) values (#{name})
+ </insert>
+
+ <update id="update" parameterType="Duplication">
+ update duplications set name = #{name} where id = #{id}
+ </update>
+
+ <delete id="delete" parameterType="long">
+ delete from duplications where id = #{id}
+ </delete>
+
+
+</mapper>
+
diff --git a/sonar-core/src/main/resources/org/sonar/persistence/model/RuleMapper.xml b/sonar-core/src/main/resources/org/sonar/persistence/model/RuleMapper.xml
new file mode 100644
index 00000000000..0c0304650b7
--- /dev/null
+++ b/sonar-core/src/main/resources/org/sonar/persistence/model/RuleMapper.xml
@@ -0,0 +1,10 @@
+<?xml version="1.0" encoding="UTF-8" ?>
+<!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd">
+
+<mapper namespace="org.sonar.persistence.model.RuleMapper">
+
+ <select id="selectAll" resultType="Rule">
+ select id, plugin_rule_key as "ruleKey", plugin_name as "repositoryKey", description, enabled, name from RULES
+ </select>
+</mapper>
+
diff --git a/sonar-core/src/test/java/org/sonar/persistence/model/RuleMapperTest.java b/sonar-core/src/test/java/org/sonar/persistence/model/RuleMapperTest.java
new file mode 100644
index 00000000000..c110d75f139
--- /dev/null
+++ b/sonar-core/src/test/java/org/sonar/persistence/model/RuleMapperTest.java
@@ -0,0 +1,128 @@
+/*
+ * 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.model;
+
+import org.apache.commons.io.IOUtils;
+import org.apache.ibatis.session.SqlSession;
+import org.dbunit.DataSourceDatabaseTester;
+import org.dbunit.IDatabaseTester;
+import org.dbunit.database.DatabaseConfig;
+import org.dbunit.database.IDatabaseConnection;
+import org.dbunit.dataset.CompositeDataSet;
+import org.dbunit.dataset.IDataSet;
+import org.dbunit.dataset.ReplacementDataSet;
+import org.dbunit.dataset.xml.FlatXmlDataSet;
+import org.dbunit.operation.DatabaseOperation;
+import org.hamcrest.core.Is;
+import org.junit.After;
+import org.junit.Before;
+import org.junit.Test;
+import org.sonar.persistence.InMemoryDatabase;
+import org.sonar.persistence.MyBatis;
+
+import java.io.InputStream;
+import java.util.List;
+
+import static org.junit.Assert.assertThat;
+
+public class RuleMapperTest {
+
+ protected IDatabaseTester databaseTester;
+ private MyBatis myBatis;
+ private InMemoryDatabase database;
+
+ @Before
+ public final void startDatabase() throws Exception {
+ database = new InMemoryDatabase();
+ myBatis = new MyBatis(database);
+
+ database.start();
+ myBatis.start();
+
+ databaseTester = new DataSourceDatabaseTester(database.getDataSource());
+ }
+
+ @After
+ public final void stopDatabase() throws Exception {
+ if (databaseTester != null) {
+ databaseTester.onTearDown();
+ }
+ }
+
+ @Test
+ public void testSelectAll() throws Exception {
+ setupData("selectAll");
+ SqlSession sqlSession = myBatis.openSession();
+ RuleMapper ruleMapper = sqlSession.getMapper(RuleMapper.class);
+ List<Rule> rules = ruleMapper.selectAll();
+ sqlSession.close();
+
+ assertThat(rules.size(), Is.is(1));
+ Rule rule = rules.get(0);
+ assertThat(rule.getId(), Is.is(1L));
+ assertThat(rule.getName(), Is.is("Avoid Null"));
+ assertThat(rule.getDescription(), Is.is("Should avoid NULL"));
+ assertThat(rule.isEnabled(), Is.is(true));
+ assertThat(rule.getRepositoryKey(), Is.is("checkstyle"));
+ }
+
+ protected final void setupData(String... testNames) throws Exception {
+ InputStream[] streams = new InputStream[testNames.length];
+ try {
+ for (int i = 0; i < testNames.length; i++) {
+ String className = getClass().getName();
+ className = String.format("/%s/%s.xml", className.replace(".", "/"), testNames[i]);
+ streams[i] = getClass().getResourceAsStream(className);
+ if (streams[i] == null) {
+ throw new RuntimeException("Test not found :" + className);
+ }
+ }
+
+ setupData(streams);
+
+ } finally {
+ for (InputStream stream : streams) {
+ IOUtils.closeQuietly(stream);
+ }
+ }
+ }
+
+ protected final void setupData(InputStream... dataSetStream) throws Exception {
+ IDataSet[] dataSets = new IDataSet[dataSetStream.length];
+ for (int i = 0; i < dataSetStream.length; i++) {
+ ReplacementDataSet dataSet = new ReplacementDataSet(new FlatXmlDataSet(dataSetStream[i]));
+ dataSet.addReplacementObject("[null]", null);
+ dataSets[i] = dataSet;
+ }
+ CompositeDataSet compositeDataSet = new CompositeDataSet(dataSets);
+
+ databaseTester.setDataSet(compositeDataSet);
+ IDatabaseConnection connection = databaseTester.getConnection();
+ DatabaseConfig config = connection.getConfig();
+ //config.setProperty(DatabaseConfig.PROPERTY_DATATYPE_FACTORY, new Db2DataTypeFactory());
+
+ DatabaseOperation.CLEAN_INSERT.execute(connection, databaseTester.getDataSet());
+
+ connection.getConnection().commit();
+ connection.close();
+
+ }
+
+}
diff --git a/sonar-core/src/test/resources/org/sonar/persistence/model/RuleMapperTest/selectAll.xml b/sonar-core/src/test/resources/org/sonar/persistence/model/RuleMapperTest/selectAll.xml
new file mode 100644
index 00000000000..cb8db141d81
--- /dev/null
+++ b/sonar-core/src/test/resources/org/sonar/persistence/model/RuleMapperTest/selectAll.xml
@@ -0,0 +1,5 @@
+<dataset>
+
+ <RULES id="1" plugin_rule_key="AvoidNull" plugin_name="checkstyle" name="Avoid Null" description="Should avoid NULL" enabled="1" />
+
+</dataset> \ No newline at end of file
diff --git a/sonar-server/src/main/java/org/sonar/server/platform/Platform.java b/sonar-server/src/main/java/org/sonar/server/platform/Platform.java
index 3c4ae6601ce..1ad12af6cd1 100644
--- a/sonar-server/src/main/java/org/sonar/server/platform/Platform.java
+++ b/sonar-server/src/main/java/org/sonar/server/platform/Platform.java
@@ -46,9 +46,9 @@ import org.sonar.jpa.dao.DaoFacade;
import org.sonar.jpa.dao.MeasuresDao;
import org.sonar.jpa.dao.ProfilesDao;
import org.sonar.jpa.dao.RulesDao;
-import org.sonar.jpa.session.DatabaseSessionFactory;
-import org.sonar.jpa.session.DatabaseSessionProvider;
-import org.sonar.jpa.session.ThreadLocalDatabaseSessionFactory;
+import org.sonar.jpa.session.*;
+import org.sonar.persistence.DefaultDatabase;
+import org.sonar.persistence.MyBatis;
import org.sonar.server.charts.ChartFactory;
import org.sonar.server.configuration.Backup;
import org.sonar.server.configuration.ProfilesManager;
@@ -121,13 +121,15 @@ public final class Platform {
rootContainer.addSingleton(new BaseConfiguration());
rootContainer.addSingleton(ServerSettings.class);
rootContainer.addSingleton(EmbeddedDatabaseFactory.class);
- rootContainer.addSingleton(JndiDatabaseConnector.class);
+ rootContainer.addSingleton(DefaultDatabase.class);
+ rootContainer.addSingleton(MyBatis.class);
+ rootContainer.addSingleton(DefaultDatabaseConnector.class);
rootContainer.addSingleton(DefaultServerUpgradeStatus.class);
rootContainer.startComponents();
}
private boolean isUpToDateDatabase() {
- JndiDatabaseConnector databaseConnector = getContainer().getComponentByType(JndiDatabaseConnector.class);
+ DefaultDatabaseConnector databaseConnector = getContainer().getComponentByType(DefaultDatabaseConnector.class);
return databaseConnector.isOperational();
}