]> source.dussan.org Git - sonarqube.git/commitdiff
SONAR-3895 Remove Local Mode and fix Dry Run on postgresql
authorDavid Gageot <david@gageot.net>
Fri, 26 Oct 2012 14:36:13 +0000 (16:36 +0200)
committerDavid Gageot <david@gageot.net>
Fri, 26 Oct 2012 15:46:10 +0000 (17:46 +0200)
16 files changed:
sonar-batch/src/main/java/org/sonar/batch/bootstrap/BootstrapModule.java
sonar-batch/src/main/java/org/sonar/batch/local/DryRunDatabase.java [new file with mode: 0644]
sonar-batch/src/main/java/org/sonar/batch/local/DryRunExporter.java [new file with mode: 0644]
sonar-batch/src/main/java/org/sonar/batch/local/LocalDatabase.java [deleted file]
sonar-batch/src/main/java/org/sonar/batch/phases/PostJobsExecutor.java
sonar-batch/src/test/java/org/sonar/batch/phases/PostJobsExecutorTest.java
sonar-core/src/main/java/org/sonar/core/persistence/DbTemplate.java
sonar-core/src/main/java/org/sonar/core/persistence/DryRunDatabaseFactory.java [new file with mode: 0644]
sonar-core/src/main/java/org/sonar/core/persistence/LocalDatabaseFactory.java [deleted file]
sonar-core/src/test/java/org/sonar/core/persistence/DryRunDatabaseFactoryTest.java [new file with mode: 0644]
sonar-core/src/test/java/org/sonar/core/persistence/LocalDatabaseFactoryTest.java [deleted file]
sonar-core/src/test/resources/org/sonar/core/persistence/DryRunDatabaseFactoryTest/should_create_database.xml [new file with mode: 0644]
sonar-core/src/test/resources/org/sonar/core/persistence/LocalDatabaseFactoryTest/should_create_database.xml [deleted file]
sonar-server/src/main/java/org/sonar/server/platform/Platform.java
sonar-server/src/main/java/org/sonar/server/ui/JRubyFacade.java
sonar-server/src/main/webapp/WEB-INF/app/controllers/api/synchro_controller.rb

index 0c7e9bd997d791b25da0bef5a8609c5770254dae..fa787fa78a68de0e952f28e2e44b6f91b0573783 100644 (file)
@@ -28,7 +28,8 @@ import org.sonar.batch.FakeMavenPluginExecutor;
 import org.sonar.batch.MavenPluginExecutor;
 import org.sonar.batch.config.BatchDatabaseSettingsLoader;
 import org.sonar.batch.config.BootstrapSettings;
-import org.sonar.batch.local.LocalDatabase;
+import org.sonar.batch.local.DryRunDatabase;
+import org.sonar.batch.local.DryRunExporter;
 import org.sonar.core.config.Logback;
 import org.sonar.core.i18n.I18nManager;
 import org.sonar.core.i18n.RuleI18nManager;
@@ -60,6 +61,7 @@ public class BootstrapModule extends Module {
     container.addSingleton(BatchPluginRepository.class);
     container.addSingleton(ExtensionInstaller.class);
     container.addSingleton(DryRun.class);
+    container.addSingleton(DryRunExporter.class);
     container.addSingleton(Logback.class);
     container.addSingleton(ServerClient.class);
     container.addSingleton(TempDirectories.class);
@@ -81,7 +83,7 @@ public class BootstrapModule extends Module {
 
   private void addDatabaseComponents() {
     container.addSingleton(JdbcDriverHolder.class);
-    container.addSingleton(LocalDatabase.class);
+    container.addSingleton(DryRunDatabase.class);
 
     // mybatis
     container.addSingleton(BatchDatabase.class);
diff --git a/sonar-batch/src/main/java/org/sonar/batch/local/DryRunDatabase.java b/sonar-batch/src/main/java/org/sonar/batch/local/DryRunDatabase.java
new file mode 100644 (file)
index 0000000..172d6b1
--- /dev/null
@@ -0,0 +1,81 @@
+/*
+ * 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.batch.local;
+
+import org.sonar.api.BatchComponent;
+import org.sonar.api.batch.bootstrap.ProjectReactor;
+import org.sonar.api.config.Settings;
+import org.sonar.api.database.DatabaseProperties;
+import org.sonar.batch.bootstrap.DryRun;
+import org.sonar.batch.bootstrap.ServerClient;
+import org.sonar.batch.bootstrap.TempDirectories;
+
+import java.io.File;
+
+/**
+ * @since 3.4
+ */
+public class DryRunDatabase implements BatchComponent {
+  private static final String API_SYNCHRO = "/api/synchro";
+  private static final String DIALECT = "h2";
+  private static final String DRIVER = "org.h2.Driver";
+  private static final String URL = "jdbc:h2:";
+  private static final String USER = "sonar";
+  private static final String PASSWORD = "sonar";
+
+  private final DryRun dryRun;
+  private final Settings settings;
+  private final ServerClient server;
+  private final TempDirectories tempDirectories;
+  private final ProjectReactor reactor;
+
+  public DryRunDatabase(DryRun dryRun, Settings settings, ServerClient server, TempDirectories tempDirectories, ProjectReactor reactor) {
+    this.dryRun = dryRun;
+    this.settings = settings;
+    this.server = server;
+    this.tempDirectories = tempDirectories;
+    this.reactor = reactor;
+  }
+
+  public void start() {
+    if (!dryRun.isEnabled()) {
+      return;
+    }
+
+    File file = tempDirectories.getFile("dry_run", "db.h2.db");
+    String h2DatabasePath = file.getAbsolutePath().replaceAll(".h2.db", "");
+
+    downloadDatabase(reactor.getRoot().getKey(), file);
+    replaceSettings(h2DatabasePath);
+  }
+
+  private void downloadDatabase(String projectKey, File toFile) {
+    server.download(API_SYNCHRO + "?resource=" + projectKey, toFile);
+  }
+
+  private void replaceSettings(String h2DatabasePath) {
+    settings
+        .setProperty(DatabaseProperties.PROP_DIALECT, DIALECT)
+        .setProperty(DatabaseProperties.PROP_DRIVER, DRIVER)
+        .setProperty(DatabaseProperties.PROP_USER, USER)
+        .setProperty(DatabaseProperties.PROP_PASSWORD, PASSWORD)
+        .setProperty(DatabaseProperties.PROP_URL, URL + h2DatabasePath);
+  }
+}
diff --git a/sonar-batch/src/main/java/org/sonar/batch/local/DryRunExporter.java b/sonar-batch/src/main/java/org/sonar/batch/local/DryRunExporter.java
new file mode 100644 (file)
index 0000000..25d9649
--- /dev/null
@@ -0,0 +1,47 @@
+/*
+ * 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.batch.local;
+
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+import org.sonar.api.BatchComponent;
+import org.sonar.api.batch.SensorContext;
+import org.sonar.batch.bootstrap.DryRun;
+
+/**
+ * @since 3.4
+ */
+public class DryRunExporter implements BatchComponent {
+  private static final Logger LOG = LoggerFactory.getLogger(DryRunExporter.class);
+
+  private final DryRun dryRun;
+
+  public DryRunExporter(DryRun dryRun) {
+    this.dryRun = dryRun;
+  }
+
+  public void execute(SensorContext context) {
+    if (!dryRun.isEnabled()) {
+      return;
+    }
+
+    LOG.info("Exporting dry run results");
+  }
+}
diff --git a/sonar-batch/src/main/java/org/sonar/batch/local/LocalDatabase.java b/sonar-batch/src/main/java/org/sonar/batch/local/LocalDatabase.java
deleted file mode 100644 (file)
index 42b466f..0000000
+++ /dev/null
@@ -1,81 +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.batch.local;
-
-import org.sonar.api.BatchComponent;
-import org.sonar.api.batch.bootstrap.ProjectReactor;
-import org.sonar.api.config.Settings;
-import org.sonar.api.database.DatabaseProperties;
-import org.sonar.batch.bootstrap.DryRun;
-import org.sonar.batch.bootstrap.ServerClient;
-import org.sonar.batch.bootstrap.TempDirectories;
-
-import java.io.File;
-
-/**
- * @since 3.4
- */
-public class LocalDatabase implements BatchComponent {
-  private static final String API_SYNCHRO = "/api/synchro";
-  private static final String DIALECT = "h2";
-  private static final String DRIVER = "org.h2.Driver";
-  private static final String URL = "jdbc:h2:";
-  private static final String USER = "sonar";
-  private static final String PASSWORD = "sonar";
-
-  private final DryRun dryRun;
-  private final Settings settings;
-  private final ServerClient server;
-  private ProjectReactor reactor;
-  private final TempDirectories tempDirectories;
-
-  public LocalDatabase(DryRun dryRun, Settings settings, ServerClient server, TempDirectories tempDirectories, ProjectReactor reactor) {
-    this.dryRun = dryRun;
-    this.settings = settings;
-    this.server = server;
-    this.reactor = reactor;
-    this.tempDirectories = tempDirectories;
-  }
-
-  public void start() {
-    if (!dryRun.isEnabled()) {
-      return;
-    }
-
-    File file = tempDirectories.getFile("local", "db.h2.db");
-    String h2DatabasePath = file.getAbsolutePath().replaceAll(".h2.db", "");
-
-    downloadDatabase(reactor.getRoot().getKey(), file);
-    replaceSettings(h2DatabasePath);
-  }
-
-  private void downloadDatabase(String projectKey, File toFile) {
-    server.download(API_SYNCHRO + "?resource=" + projectKey, toFile);
-  }
-
-  private void replaceSettings(String h2DatabasePath) {
-    settings
-      .setProperty(DatabaseProperties.PROP_DIALECT, DIALECT)
-      .setProperty(DatabaseProperties.PROP_DRIVER, DRIVER)
-      .setProperty(DatabaseProperties.PROP_USER, USER)
-      .setProperty(DatabaseProperties.PROP_PASSWORD, PASSWORD)
-      .setProperty(DatabaseProperties.PROP_URL, URL + h2DatabasePath);
-  }
-}
index 9ac28d6b6d76063062948c1a7be13fb676166187..f5530102336eeea08a16fe1d1917ab875b8f8f6c 100644 (file)
@@ -31,30 +31,35 @@ import org.sonar.api.batch.maven.DependsUponMavenPlugin;
 import org.sonar.api.batch.maven.MavenPluginHandler;
 import org.sonar.api.resources.Project;
 import org.sonar.batch.MavenPluginExecutor;
+import org.sonar.batch.local.DryRunExporter;
 
 import java.util.Collection;
 
 public class PostJobsExecutor implements BatchComponent {
   private static final Logger LOG = LoggerFactory.getLogger(PostJobsExecutor.class);
 
-  private MavenPluginExecutor mavenExecutor;
-  private ProjectDefinition projectDefinition;
-  private Project project;
-  private BatchExtensionDictionnary selector;
+  private final BatchExtensionDictionnary selector;
+  private final Project project;
+  private final ProjectDefinition projectDefinition;
+  private final MavenPluginExecutor mavenExecutor;
+  private final DryRunExporter localModeExporter;
 
-  public PostJobsExecutor(BatchExtensionDictionnary selector, Project project, ProjectDefinition projectDefinition, MavenPluginExecutor mavenExecutor) {
+  public PostJobsExecutor(BatchExtensionDictionnary selector, Project project, ProjectDefinition projectDefinition, MavenPluginExecutor mavenExecutor,
+      DryRunExporter localModeExporter) {
     this.selector = selector;
-    this.mavenExecutor = mavenExecutor;
     this.project = project;
     this.projectDefinition = projectDefinition;
+    this.mavenExecutor = mavenExecutor;
+    this.localModeExporter = localModeExporter;
   }
 
   public void execute(SensorContext context) {
     Collection<PostJob> postJobs = selector.select(PostJob.class, project, true);
     execute(context, postJobs);
+    exportLocalModeResults(context);
   }
 
-  void execute(SensorContext context, Collection<PostJob> postJobs) {
+  private void execute(SensorContext context, Collection<PostJob> postJobs) {
     logPostJobs(postJobs);
 
     for (PostJob postJob : postJobs) {
@@ -78,4 +83,8 @@ public class PostJobsExecutor implements BatchComponent {
       }
     }
   }
+
+  private void exportLocalModeResults(SensorContext context) {
+    localModeExporter.execute(context);
+  }
 }
index 9a7334ae5420817665df333efb358628a3dc20d4..1af0a26cc9eeabced77aa9b0481a857bae2decb2 100644 (file)
  */
 package org.sonar.batch.phases;
 
+import org.junit.Before;
 import org.junit.Test;
+import org.sonar.api.batch.BatchExtensionDictionnary;
 import org.sonar.api.batch.PostJob;
 import org.sonar.api.batch.SensorContext;
 import org.sonar.api.batch.bootstrap.ProjectDefinition;
 import org.sonar.api.resources.Project;
 import org.sonar.batch.MavenPluginExecutor;
+import org.sonar.batch.local.DryRunExporter;
 
 import java.util.Arrays;
-import java.util.List;
 
 import static org.mockito.Mockito.mock;
 import static org.mockito.Mockito.verify;
+import static org.mockito.Mockito.when;
 
 public class PostJobsExecutorTest {
+  PostJobsExecutor executor;
+
+  Project project = new Project("project");
+  BatchExtensionDictionnary selector = mock(BatchExtensionDictionnary.class);
+  MavenPluginExecutor mavenPluginExecutor = mock(MavenPluginExecutor.class);
+  DryRunExporter localModeExporter = mock(DryRunExporter.class);
+  PostJob job1 = mock(PostJob.class);
+  PostJob job2 = mock(PostJob.class);
+  SensorContext context = mock(SensorContext.class);
+
+  @Before
+  public void setUp() {
+    executor = new PostJobsExecutor(selector, project, ProjectDefinition.create(), mavenPluginExecutor, localModeExporter);
+  }
 
   @Test
-  public void executeAllPostJobs() {
-    PostJob job1 = mock(PostJob.class);
-    PostJob job2 = mock(PostJob.class);
-    List<PostJob> jobs = Arrays.asList(job1, job2);
+  public void should_execute_post_jobs() {
+    when(selector.select(PostJob.class, project, true)).thenReturn(Arrays.asList(job1, job2));
 
-    Project project = new Project("project");
-    ProjectDefinition projectDefinition = ProjectDefinition.create();
-    PostJobsExecutor executor = new PostJobsExecutor(null, project, projectDefinition, mock(MavenPluginExecutor.class));
-    SensorContext context = mock(SensorContext.class);
-    executor.execute(context, jobs);
+    executor.execute(context);
 
     verify(job1).executeOn(project, context);
     verify(job2).executeOn(project, context);
 
   }
+
+  @Test
+  public void should_export_local_mode_results() {
+    executor.execute(context);
+
+    verify(localModeExporter).execute(context);
+  }
 }
index 9dec7ff067f7a49f682f09d28ffadcaa1024f0ba..bca98d80f8ebccf5c87e73d0991b69e89584ae87 100644 (file)
@@ -40,8 +40,6 @@ public class DbTemplate implements ServerComponent {
   public DbTemplate copyTable(DataSource source, DataSource dest, String table, String query) {
     LOG.info("Copy table " + table);
 
-    int colCount = getColumnCount(source, table);
-
     truncate(dest, table);
 
     Connection sourceConnection = null;
@@ -49,29 +47,35 @@ public class DbTemplate implements ServerComponent {
     ResultSet sourceResultSet = null;
     Connection destConnection = null;
     ResultSet destResultSet = null;
+    PreparedStatement destStatement = null;
     try {
       sourceConnection = source.getConnection();
       sourceStatement = sourceConnection.createStatement();
       sourceResultSet = sourceStatement.executeQuery(query);
 
-      destConnection = dest.getConnection();
-      destConnection.setAutoCommit(false);
+      if (sourceResultSet.next()) {
+        int colCount = sourceResultSet.getMetaData().getColumnCount();
 
-      PreparedStatement destStatement = destConnection.prepareStatement("INSERT INTO " + table + " VALUES(" + StringUtils.repeat("?", ",", colCount) + ")");
-      while (sourceResultSet.next()) {
-        for (int col = 1; col <= colCount; col++) {
-          Object value = sourceResultSet.getObject(col);
-          destStatement.setObject(col, value);
-        }
-        destStatement.addBatch();
-      }
+        destConnection = dest.getConnection();
+        destConnection.setAutoCommit(false);
 
-      destStatement.executeBatch();
-      destConnection.commit();
-      destStatement.close();
+        destStatement = destConnection.prepareStatement("INSERT INTO " + table + " VALUES(" + StringUtils.repeat("?", ",", colCount) + ")");
+        do {
+          for (int col = 1; col <= colCount; col++) {
+            Object value = sourceResultSet.getObject(col);
+            destStatement.setObject(col, value);
+          }
+          destStatement.addBatch();
+        } while (sourceResultSet.next());
+
+        destStatement.executeBatch();
+        destConnection.commit();
+      }
     } catch (SQLException e) {
+      LOG.error("Fail to copy table " + table, e);
       throw new SonarException("Fail to copy table " + table, e);
     } finally {
+      DatabaseUtils.closeQuietly(destStatement);
       DatabaseUtils.closeQuietly(destResultSet);
       DatabaseUtils.closeQuietly(destConnection);
       DatabaseUtils.closeQuietly(sourceResultSet);
@@ -82,28 +86,7 @@ public class DbTemplate implements ServerComponent {
     return this;
   }
 
-  public int getColumnCount(DataSource dataSource, String table) {
-    Connection connection = null;
-    ResultSet metaData = null;
-    try {
-      connection = dataSource.getConnection();
-      metaData = connection.getMetaData().getColumns(null, null, table, null);
-
-      int nbColumns = 0;
-      while (metaData.next()) {
-        nbColumns++;
-      }
-
-      return nbColumns;
-    } catch (SQLException e) {
-      throw new SonarException("Fail to get column count for table " + table, e);
-    } finally {
-      DatabaseUtils.closeQuietly(metaData);
-      DatabaseUtils.closeQuietly(connection);
-    }
-  }
-
-  public int getRowCount(BasicDataSource dataSource, String table) {
+  public int getRowCount(DataSource dataSource, String table) {
     Connection connection = null;
     Statement statement = null;
     ResultSet resultSet = null;
@@ -114,6 +97,7 @@ public class DbTemplate implements ServerComponent {
 
       return resultSet.next() ? resultSet.getInt(1) : 0;
     } catch (SQLException e) {
+      LOG.error("Fail to get row count for table " + table, e);
       throw new SonarException("Fail to get row count for table " + table, e);
     } finally {
       DatabaseUtils.closeQuietly(resultSet);
@@ -130,6 +114,7 @@ public class DbTemplate implements ServerComponent {
       statement = connection.createStatement();
       statement.executeUpdate("TRUNCATE TABLE " + table);
     } catch (SQLException e) {
+      LOG.error("Fail to truncate table " + table, e);
       throw new SonarException("Fail to truncate table " + table, e);
     } finally {
       DatabaseUtils.closeQuietly(statement);
@@ -154,6 +139,7 @@ public class DbTemplate implements ServerComponent {
       connection = dataSource.getConnection();
       DdlUtils.createSchema(connection, dialect);
     } catch (SQLException e) {
+      LOG.error("Fail to createSchema local database schema", e);
       throw new SonarException("Fail to createSchema local database schema", e);
     } finally {
       DatabaseUtils.closeQuietly(connection);
diff --git a/sonar-core/src/main/java/org/sonar/core/persistence/DryRunDatabaseFactory.java b/sonar-core/src/main/java/org/sonar/core/persistence/DryRunDatabaseFactory.java
new file mode 100644 (file)
index 0000000..156db8a
--- /dev/null
@@ -0,0 +1,100 @@
+/*
+ * 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 com.google.common.io.Files;
+import org.apache.commons.dbcp.BasicDataSource;
+import org.sonar.api.ServerComponent;
+import org.sonar.api.platform.ServerFileSystem;
+import org.sonar.api.utils.SonarException;
+
+import javax.sql.DataSource;
+
+import java.io.File;
+import java.io.IOException;
+import java.sql.SQLException;
+
+public class DryRunDatabaseFactory implements ServerComponent {
+  private static final String DIALECT = "h2";
+  private static final String DRIVER = "org.h2.Driver";
+  private static final String URL = "jdbc:h2:";
+  private static final String USER = "sonar";
+  private static final String PASSWORD = "sonar";
+
+  private final Database database;
+  private final ServerFileSystem serverFileSystem;
+
+  public DryRunDatabaseFactory(Database database, ServerFileSystem serverFileSystem) {
+    this.database = database;
+    this.serverFileSystem = serverFileSystem;
+  }
+
+  public byte[] createDatabaseForDryRun(int resourceId) {
+    String name = serverFileSystem.getTempDir().getAbsolutePath() + "db-" + System.nanoTime();
+
+    try {
+      BasicDataSource destination = create(DIALECT, DRIVER, USER, PASSWORD, URL + name);
+      copy(database.getDataSource(), destination, resourceId);
+      close(destination);
+
+      return dbFileContent(name);
+    } catch (SQLException e) {
+      throw new SonarException("Unable to create database for dry run", e);
+    }
+  }
+
+  private void copy(DataSource source, DataSource dest, int resourceId) {
+    new DbTemplate()
+        .copyTable(source, dest, "PROPERTIES",
+            "SELECT * FROM PROPERTIES WHERE (((USER_ID IS NULL) AND (RESOURCE_ID IS NULL)) OR (RESOURCE_ID='" + resourceId +
+              "')) AND NOT (PROP_KEY LIKE '%.secured')")
+        .copyTable(source, dest, "RULES_PROFILES", "SELECT * FROM RULES_PROFILES")
+        .copyTable(source, dest, "RULES", "SELECT * FROM RULES")
+        .copyTable(source, dest, "RULES_PARAMETERS", "SELECT * FROM RULES_PARAMETERS")
+        .copyTable(source, dest, "ACTIVE_RULES", "SELECT * FROM ACTIVE_RULES")
+        .copyTable(source, dest, "ACTIVE_RULE_PARAMETERS", "SELECT * FROM ACTIVE_RULE_PARAMETERS")
+        .copyTable(source, dest, "METRICS", "SELECT * FROM METRICS")
+        .copyTable(source, dest, "CHARACTERISTICS", "SELECT * FROM CHARACTERISTICS")
+        .copyTable(source, dest, "CHARACTERISTIC_PROPERTIES", "SELECT * FROM CHARACTERISTIC_PROPERTIES")
+        .copyTable(source, dest, "CHARACTERISTIC_EDGES", "SELECT * FROM CHARACTERISTIC_EDGES")
+        .copyTable(source, dest, "QUALITY_MODELS", "SELECT * FROM QUALITY_MODELS");
+  }
+
+  private BasicDataSource create(String dialect, String driver, String user, String password, String url) {
+    BasicDataSource dataSource = new DbTemplate().dataSource(driver, user, password, url);
+    new DbTemplate().createSchema(dataSource, dialect);
+    return dataSource;
+  }
+
+  private void close(BasicDataSource dest) throws SQLException {
+    dest.close();
+  }
+
+  private byte[] dbFileContent(String name) {
+    try {
+      File dbFile = new File(name + ".h2.db");
+      byte[] content = Files.toByteArray(dbFile);
+      dbFile.delete();
+      return content;
+    } catch (IOException e) {
+      throw new SonarException("Unable to read h2 database file", e);
+    }
+  }
+}
diff --git a/sonar-core/src/main/java/org/sonar/core/persistence/LocalDatabaseFactory.java b/sonar-core/src/main/java/org/sonar/core/persistence/LocalDatabaseFactory.java
deleted file mode 100644 (file)
index edebb89..0000000
+++ /dev/null
@@ -1,99 +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 com.google.common.io.Files;
-import org.apache.commons.dbcp.BasicDataSource;
-import org.sonar.api.ServerComponent;
-import org.sonar.api.platform.ServerFileSystem;
-import org.sonar.api.utils.SonarException;
-
-import javax.sql.DataSource;
-
-import java.io.File;
-import java.io.IOException;
-import java.sql.SQLException;
-
-public class LocalDatabaseFactory implements ServerComponent {
-  private static final String DIALECT = "h2";
-  private static final String DRIVER = "org.h2.Driver";
-  private static final String URL = "jdbc:h2:";
-  private static final String USER = "sonar";
-  private static final String PASSWORD = "sonar";
-
-  private final Database database;
-  private final ServerFileSystem serverFileSystem;
-
-  public LocalDatabaseFactory(Database database, ServerFileSystem serverFileSystem) {
-    this.database = database;
-    this.serverFileSystem = serverFileSystem;
-  }
-
-  public byte[] createDatabaseForLocalMode(int resourceId) {
-    String name = serverFileSystem.getTempDir().getAbsolutePath() + "db-" + System.nanoTime();
-
-    try {
-      BasicDataSource destination = create(DIALECT, DRIVER, USER, PASSWORD, URL + name);
-      copy(database.getDataSource(), destination, resourceId);
-      close(destination);
-
-      return dbFileContent(name);
-    } catch (SQLException e) {
-      throw new SonarException("Unable to create database for local mode", e);
-    }
-  }
-
-  private void copy(DataSource source, DataSource dest, int resourceId) {
-    new DbTemplate()
-        .copyTable(source, dest, "PROPERTIES",
-            "SELECT * FROM PROPERTIES WHERE (((USER_ID IS NULL) AND (RESOURCE_ID IS NULL)) OR (RESOURCE_ID='" + resourceId + "')) AND NOT (PROP_KEY LIKE '%.secured')")
-        .copyTable(source, dest, "RULES_PROFILES", "SELECT * FROM RULES_PROFILES")
-        .copyTable(source, dest, "RULES", "SELECT * FROM RULES")
-        .copyTable(source, dest, "RULES_PARAMETERS", "SELECT * FROM RULES_PARAMETERS")
-        .copyTable(source, dest, "ACTIVE_RULES", "SELECT * FROM ACTIVE_RULES")
-        .copyTable(source, dest, "ACTIVE_RULE_PARAMETERS", "SELECT * FROM ACTIVE_RULE_PARAMETERS")
-        .copyTable(source, dest, "METRICS", "SELECT * FROM METRICS")
-        .copyTable(source, dest, "CHARACTERISTICS", "SELECT * FROM CHARACTERISTICS")
-        .copyTable(source, dest, "CHARACTERISTIC_PROPERTIES", "SELECT * FROM CHARACTERISTIC_PROPERTIES")
-        .copyTable(source, dest, "CHARACTERISTIC_EDGES", "SELECT * FROM CHARACTERISTIC_EDGES")
-        .copyTable(source, dest, "QUALITY_MODELS", "SELECT * FROM QUALITY_MODELS");
-  }
-
-  private BasicDataSource create(String dialect, String driver, String user, String password, String url) {
-    BasicDataSource dataSource = new DbTemplate().dataSource(driver, user, password, url);
-    new DbTemplate().createSchema(dataSource, dialect);
-    return dataSource;
-  }
-
-  private void close(BasicDataSource dest) throws SQLException {
-    dest.close();
-  }
-
-  private byte[] dbFileContent(String name) {
-    try {
-      File dbFile = new File(name + ".h2.db");
-      byte[] content = Files.toByteArray(dbFile);
-      dbFile.delete();
-      return content;
-    } catch (IOException e) {
-      throw new SonarException("Unable to read h2 database file", e);
-    }
-  }
-}
diff --git a/sonar-core/src/test/java/org/sonar/core/persistence/DryRunDatabaseFactoryTest.java b/sonar-core/src/test/java/org/sonar/core/persistence/DryRunDatabaseFactoryTest.java
new file mode 100644 (file)
index 0000000..b44340a
--- /dev/null
@@ -0,0 +1,82 @@
+/*
+ * 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 com.google.common.io.Files;
+import org.apache.commons.dbcp.BasicDataSource;
+import org.junit.After;
+import org.junit.Before;
+import org.junit.Rule;
+import org.junit.Test;
+import org.junit.rules.TemporaryFolder;
+import org.sonar.api.platform.ServerFileSystem;
+
+import java.io.File;
+import java.io.IOException;
+import java.sql.SQLException;
+
+import static org.fest.assertions.Assertions.assertThat;
+import static org.mockito.Mockito.mock;
+import static org.mockito.Mockito.when;
+
+public class DryRunDatabaseFactoryTest extends AbstractDaoTestCase {
+  private DryRunDatabaseFactory localDatabaseFactory;
+
+  private ServerFileSystem serverFileSystem = mock(ServerFileSystem.class);
+  private BasicDataSource dataSource;
+
+  @Rule
+  public TemporaryFolder temporaryFolder = new TemporaryFolder();
+
+  @Before
+  public void setUp() {
+    localDatabaseFactory = new DryRunDatabaseFactory(getDatabase(), serverFileSystem);
+  }
+
+  @After
+  public void closeDatabase() throws SQLException {
+    if (dataSource != null) {
+      dataSource.close();
+    }
+  }
+
+  @Test
+  public void should_create_database() throws IOException, SQLException {
+    setupData("should_create_database");
+
+    when(serverFileSystem.getTempDir()).thenReturn(temporaryFolder.getRoot());
+
+    byte[] database = localDatabaseFactory.createDatabaseForDryRun(1);
+    dataSource = createDatabase(database);
+
+    assertThat(rowCount("PROPERTIES")).isEqualTo(2);
+    assertThat(rowCount("PROJECTS")).isZero();
+  }
+
+  private BasicDataSource createDatabase(byte[] db) throws IOException {
+    File file = temporaryFolder.newFile("db.h2.db");
+    Files.write(db, file);
+    return new DbTemplate().dataSource("org.h2.Driver", "sonar", "sonar", "jdbc:h2:" + file.getAbsolutePath().replaceAll(".h2.db", ""));
+  }
+
+  private int rowCount(String table) {
+    return new DbTemplate().getRowCount(dataSource, table);
+  }
+}
diff --git a/sonar-core/src/test/java/org/sonar/core/persistence/LocalDatabaseFactoryTest.java b/sonar-core/src/test/java/org/sonar/core/persistence/LocalDatabaseFactoryTest.java
deleted file mode 100644 (file)
index 3eb0d75..0000000
+++ /dev/null
@@ -1,82 +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 com.google.common.io.Files;
-import org.apache.commons.dbcp.BasicDataSource;
-import org.junit.After;
-import org.junit.Before;
-import org.junit.Rule;
-import org.junit.Test;
-import org.junit.rules.TemporaryFolder;
-import org.sonar.api.platform.ServerFileSystem;
-
-import java.io.File;
-import java.io.IOException;
-import java.sql.SQLException;
-
-import static org.fest.assertions.Assertions.assertThat;
-import static org.mockito.Mockito.mock;
-import static org.mockito.Mockito.when;
-
-public class LocalDatabaseFactoryTest extends AbstractDaoTestCase {
-  private LocalDatabaseFactory localDatabaseFactory;
-
-  private ServerFileSystem serverFileSystem = mock(ServerFileSystem.class);
-  private BasicDataSource dataSource;
-
-  @Rule
-  public TemporaryFolder temporaryFolder = new TemporaryFolder();
-
-  @Before
-  public void setUp() {
-    localDatabaseFactory = new LocalDatabaseFactory(getDatabase(), serverFileSystem);
-  }
-
-  @After
-  public void closeDatabase() throws SQLException {
-    if (dataSource != null) {
-      dataSource.close();
-    }
-  }
-
-  @Test
-  public void should_create_database() throws IOException {
-    setupData("should_create_database");
-
-    when(serverFileSystem.getTempDir()).thenReturn(temporaryFolder.getRoot());
-
-    byte[] database = localDatabaseFactory.createDatabaseForLocalMode(1);
-    dataSource = createDatabase(database);
-
-    assertThat(rowCount("PROPERTIES")).isEqualTo(2);
-    assertThat(rowCount("PROJECTS")).isZero();
-  }
-
-  private BasicDataSource createDatabase(byte[] db) throws IOException {
-    File file = temporaryFolder.newFile("db.h2.db");
-    Files.write(db, file);
-    return new DbTemplate().dataSource("org.h2.Driver", "sonar", "sonar", "jdbc:h2:" + file.getAbsolutePath().replaceAll(".h2.db", ""));
-  }
-
-  private int rowCount(String table) {
-    return new DbTemplate().getRowCount(dataSource, table);
-  }
-}
diff --git a/sonar-core/src/test/resources/org/sonar/core/persistence/DryRunDatabaseFactoryTest/should_create_database.xml b/sonar-core/src/test/resources/org/sonar/core/persistence/DryRunDatabaseFactoryTest/should_create_database.xml
new file mode 100644 (file)
index 0000000..0e26651
--- /dev/null
@@ -0,0 +1,11 @@
+<dataset>
+  <properties id="1" prop_key="resourceProperty" text_value="value1" resource_id="1" user_id="[null]"/>
+  <properties id="2" prop_key="resourceProperty" text_value="value2" resource_id="2" user_id="[null]"/>
+  <properties id="3" prop_key="globalProperty" text_value="value3" resource_id="[null]" user_id="[null]"/>
+  <properties id="4" prop_key="userProperty" text_value="value4" resource_id="[null]" user_id="1"/>
+  <properties id="5" prop_key="property.secured" text_value="value5" resource_id="[null]" user_id="[null]"/>
+
+  <rules_profiles id="1" name="Sonar way with Findbugs" language="java" parent_name="" version="1"
+                  used_profile="false"/>
+
+</dataset>
\ No newline at end of file
diff --git a/sonar-core/src/test/resources/org/sonar/core/persistence/LocalDatabaseFactoryTest/should_create_database.xml b/sonar-core/src/test/resources/org/sonar/core/persistence/LocalDatabaseFactoryTest/should_create_database.xml
deleted file mode 100644 (file)
index 3034397..0000000
+++ /dev/null
@@ -1,7 +0,0 @@
-<dataset>
-  <properties id="1" prop_key="resourceProperty" text_value="value1" resource_id="1" user_id="[null]"/>
-  <properties id="2" prop_key="resourceProperty" text_value="value2" resource_id="2" user_id="[null]"/>
-  <properties id="3" prop_key="globalProperty" text_value="value3" resource_id="[null]" user_id="[null]"/>
-  <properties id="4" prop_key="userProperty" text_value="value4" resource_id="[null]" user_id="1"/>
-  <properties id="5" prop_key="property.secured" text_value="value5" resource_id="[null]" user_id="[null]"/>
-</dataset>
\ No newline at end of file
index b5d69bd28909d88115ee5973b6d57b10cc3ed2c8..eb261aa6f7a557d68b333ac6e545646ce15d9be0 100644 (file)
@@ -51,6 +51,7 @@ import org.sonar.core.persistence.DaoUtils;
 import org.sonar.core.persistence.DatabaseMigrator;
 import org.sonar.core.persistence.DatabaseVersion;
 import org.sonar.core.persistence.DefaultDatabase;
+import org.sonar.core.persistence.DryRunDatabaseFactory;
 import org.sonar.core.persistence.MyBatis;
 import org.sonar.core.qualitymodel.DefaultModelFinder;
 import org.sonar.core.rule.DefaultRuleFinder;
@@ -68,7 +69,6 @@ import org.sonar.server.charts.ChartFactory;
 import org.sonar.server.configuration.Backup;
 import org.sonar.server.configuration.ProfilesManager;
 import org.sonar.server.database.EmbeddedDatabaseFactory;
-import org.sonar.core.persistence.LocalDatabaseFactory;
 import org.sonar.server.notifications.NotificationService;
 import org.sonar.server.notifications.reviews.ReviewsNotificationManager;
 import org.sonar.server.plugins.ApplicationDeployer;
@@ -180,7 +180,7 @@ public final class Platform {
     rootContainer.addSingleton(I18nManager.class);
     rootContainer.addSingleton(RuleI18nManager.class);
     rootContainer.addSingleton(GwtI18n.class);
-    rootContainer.addSingleton(LocalDatabaseFactory.class);
+    rootContainer.addSingleton(DryRunDatabaseFactory.class);
     rootContainer.startComponents();
   }
 
@@ -249,7 +249,7 @@ public final class Platform {
     servicesContainer.addSingleton(MeasureFilterDecoder.class);
     servicesContainer.addSingleton(MeasureFilterExecutor.class);
     servicesContainer.addSingleton(MeasureFilterEngine.class);
-    servicesContainer.addSingleton(LocalDatabaseFactory.class);
+    servicesContainer.addSingleton(DryRunDatabaseFactory.class);
 
     // Notifications
     servicesContainer.addSingleton(EmailSettings.class);
index 7fa81d9328e87ed67500a56e6e354c1b2ac928f8..8fb4fc40ae0261aa3e341472f724340930a72109 100644 (file)
@@ -39,7 +39,11 @@ import org.sonar.api.resources.ResourceTypes;
 import org.sonar.api.rules.RulePriority;
 import org.sonar.api.rules.RuleRepository;
 import org.sonar.api.utils.ValidationMessages;
-import org.sonar.api.web.*;
+import org.sonar.api.web.Footer;
+import org.sonar.api.web.NavigationSection;
+import org.sonar.api.web.Page;
+import org.sonar.api.web.RubyRailsWebservice;
+import org.sonar.api.web.Widget;
 import org.sonar.api.workflow.Review;
 import org.sonar.api.workflow.internal.DefaultReview;
 import org.sonar.api.workflow.internal.DefaultWorkflowContext;
@@ -49,6 +53,7 @@ import org.sonar.core.measure.MeasureFilterEngine;
 import org.sonar.core.measure.MeasureFilterRow;
 import org.sonar.core.persistence.Database;
 import org.sonar.core.persistence.DatabaseMigrator;
+import org.sonar.core.persistence.DryRunDatabaseFactory;
 import org.sonar.core.purge.PurgeDao;
 import org.sonar.core.resource.ResourceIndexerDao;
 import org.sonar.core.resource.ResourceKeyUpdaterDao;
@@ -57,13 +62,22 @@ import org.sonar.markdown.Markdown;
 import org.sonar.server.configuration.Backup;
 import org.sonar.server.configuration.ProfilesManager;
 import org.sonar.server.notifications.reviews.ReviewsNotificationManager;
-import org.sonar.server.platform.*;
-import org.sonar.server.plugins.*;
+import org.sonar.server.platform.NewUserNotifier;
+import org.sonar.server.platform.Platform;
+import org.sonar.server.platform.ServerIdGenerator;
+import org.sonar.server.platform.ServerSettings;
+import org.sonar.server.platform.SettingsChangeNotifier;
+import org.sonar.server.plugins.DefaultServerPluginRepository;
+import org.sonar.server.plugins.PluginDeployer;
+import org.sonar.server.plugins.PluginDownloader;
+import org.sonar.server.plugins.UpdateCenterMatrix;
+import org.sonar.server.plugins.UpdateCenterMatrixFactory;
 import org.sonar.server.rules.ProfilesConsole;
 import org.sonar.server.rules.RulesConsole;
 import org.sonar.updatecenter.common.Version;
 
 import javax.annotation.Nullable;
+
 import java.net.InetAddress;
 import java.sql.Connection;
 import java.util.Collection;
@@ -300,7 +314,7 @@ public final class JRubyFacade {
 
   public void ruleSeverityChanged(int parentProfileId, int activeRuleId, int oldSeverityId, int newSeverityId, String userName) {
     getProfilesManager().ruleSeverityChanged(parentProfileId, activeRuleId, RulePriority.values()[oldSeverityId],
-      RulePriority.values()[newSeverityId], userName);
+        RulePriority.values()[newSeverityId], userName);
   }
 
   public void ruleDeactivated(int parentProfileId, int deactivatedRuleId, String userName) {
@@ -496,10 +510,14 @@ public final class JRubyFacade {
     // notifier is null when creating the administrator in the migration script 011.
     if (notifier != null) {
       notifier.onNewUser(NewUserHandler.Context.builder()
-        .setLogin(fields.get("login"))
-        .setName(fields.get("name"))
-        .setEmail(fields.get("email"))
-        .build());
+          .setLogin(fields.get("login"))
+          .setName(fields.get("name"))
+          .setEmail(fields.get("email"))
+          .build());
     }
   }
+
+  public byte[] createDatabaseForDryRun(int resourceId) {
+    return get(DryRunDatabaseFactory.class).createDatabaseForDryRun(resourceId);
+  }
 }
index c4f7298b66b72a281485f4560946c02fdf7bbfdf..0dc1be27f8b83cc62805fcabf5398a6ee002a4a7 100644 (file)
@@ -27,8 +27,7 @@ class Api::SynchroController < Api::ApiController
     require_parameters :resource
     load_resource()
 
-    database_factory = java_facade.getCoreComponentByClassname('org.sonar.core.persistence.LocalDatabaseFactory')
-    dbFileContent = database_factory.createDatabaseForLocalMode(@resource.id)
+    dbFileContent = java_facade.createDatabaseForDryRun(@resource.id)
 
     send_data String.from_java_bytes(dbFileContent)
   end