From 6b5035087075113699015583fd4d76b75bf36894 Mon Sep 17 00:00:00 2001
From: Evgeny Mandrikov
Date: Wed, 19 Jan 2011 02:20:45 +0300
Subject: [PATCH] SONAR-2106: New Java library to bootstrap project analysis
* Add BatchResourcesServlet to allow downloading libraries from server
* Create in memory POM for non-maven environments
* Provide fake MavenPluginExecutor for non-maven environments
* Add new module sonar-batch-maven-compat with shaded maven-project
---
pom.xml | 2 +
sonar-batch-bootstrapper/pom.xml | 27 ++++
.../batch/bootstrapper/BatchDownloader.java | 134 ++++++++++++++++++
.../bootstrapper/BootstrapperIOUtils.java | 79 +++++++++++
.../batch/bootstrapper/package-info.java | 22 +--
.../bootstrapper/BatchDownloaderTest.java | 54 +++++++
sonar-batch-maven-compat/pom.xml | 46 ++++++
sonar-batch/pom.xml | 2 +-
.../src/main/java/org/sonar/batch/Batch.java | 24 ++++
.../java/org/sonar/batch/MavenReactor.java | 17 ++-
.../java/org/sonar/batch/ProjectTree.java | 65 ++++++++-
.../batch/bootstrap/ProjectDefinition.java | 95 -------------
.../batch/bootstrapper/ProjectDefinition.java | 55 +++++++
.../org/sonar/batch/bootstrapper/Reactor.java | 48 +++++++
.../test/java/org/sonar/batch/BatchTest.java | 31 ++++
.../resources/DefaultFileSystemDirectory.java | 98 -------------
.../api/resources/FileSystemDirectory.java | 81 -----------
.../java/org/sonar/api/resources/Natures.java | 18 ---
sonar-server/pom.xml | 12 ++
.../server/plugins/BatchResourcesServlet.java | 104 ++++++++++++++
sonar-server/src/main/webapp/WEB-INF/web.xml | 10 +-
.../plugins/BatchResourcesServletTest.java | 59 ++++++++
22 files changed, 767 insertions(+), 316 deletions(-)
create mode 100644 sonar-batch-bootstrapper/pom.xml
create mode 100644 sonar-batch-bootstrapper/src/main/java/org/sonar/batch/bootstrapper/BatchDownloader.java
create mode 100644 sonar-batch-bootstrapper/src/main/java/org/sonar/batch/bootstrapper/BootstrapperIOUtils.java
rename sonar-batch/src/main/java/org/sonar/batch/Reactor.java => sonar-batch-bootstrapper/src/main/java/org/sonar/batch/bootstrapper/package-info.java (70%)
create mode 100644 sonar-batch-bootstrapper/src/test/java/org/sonar/batch/bootstrapper/BatchDownloaderTest.java
create mode 100644 sonar-batch-maven-compat/pom.xml
delete mode 100644 sonar-batch/src/main/java/org/sonar/batch/bootstrap/ProjectDefinition.java
create mode 100644 sonar-batch/src/main/java/org/sonar/batch/bootstrapper/ProjectDefinition.java
create mode 100644 sonar-batch/src/main/java/org/sonar/batch/bootstrapper/Reactor.java
create mode 100644 sonar-batch/src/test/java/org/sonar/batch/BatchTest.java
delete mode 100644 sonar-plugin-api/src/main/java/org/sonar/api/resources/DefaultFileSystemDirectory.java
delete mode 100644 sonar-plugin-api/src/main/java/org/sonar/api/resources/FileSystemDirectory.java
delete mode 100644 sonar-plugin-api/src/main/java/org/sonar/api/resources/Natures.java
create mode 100644 sonar-server/src/main/java/org/sonar/server/plugins/BatchResourcesServlet.java
create mode 100644 sonar-server/src/test/java/org/sonar/server/plugins/BatchResourcesServletTest.java
diff --git a/pom.xml b/pom.xml
index f582f85f35d..58a30f967e2 100644
--- a/pom.xml
+++ b/pom.xml
@@ -14,6 +14,8 @@
archetypes/sonar-basic-plugin
archetypes/sonar-gwt-plugin
sonar-batch
+ sonar-batch-bootstrapper
+ sonar-batch-maven-compat
sonar-channel
sonar-check-api
sonar-colorizer
diff --git a/sonar-batch-bootstrapper/pom.xml b/sonar-batch-bootstrapper/pom.xml
new file mode 100644
index 00000000000..75a7498f456
--- /dev/null
+++ b/sonar-batch-bootstrapper/pom.xml
@@ -0,0 +1,27 @@
+
+
+ 4.0.0
+
+
+ org.codehaus.sonar
+ sonar
+ 2.6-SNAPSHOT
+
+
+ sonar-batch-bootstrapper
+ Sonar :: Batch Bootstrapper
+ Provides API to bootstrap Sonar Batch.
+
+
+
+ junit
+ junit
+ test
+
+
+ org.hamcrest
+ hamcrest-all
+ test
+
+
+
diff --git a/sonar-batch-bootstrapper/src/main/java/org/sonar/batch/bootstrapper/BatchDownloader.java b/sonar-batch-bootstrapper/src/main/java/org/sonar/batch/bootstrapper/BatchDownloader.java
new file mode 100644
index 00000000000..b5eba165324
--- /dev/null
+++ b/sonar-batch-bootstrapper/src/main/java/org/sonar/batch/bootstrapper/BatchDownloader.java
@@ -0,0 +1,134 @@
+/*
+ * Sonar, open source software quality management tool.
+ * Copyright (C) 2009 SonarSource SA
+ * mailto:contact AT sonarsource DOT com
+ *
+ * Sonar is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 3 of the License, or (at your option) any later version.
+ *
+ * Sonar is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with Sonar; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02
+ */
+package org.sonar.batch.bootstrapper;
+
+import java.io.*;
+import java.net.HttpURLConnection;
+import java.net.URL;
+import java.util.ArrayList;
+import java.util.List;
+
+public class BatchDownloader {
+
+ private static final String VERSION_PATH = "/api/server/version";
+ private static final String BATCH_PATH = "/batch/";
+
+ public static final int CONNECT_TIMEOUT_MILLISECONDS = 30000;
+ public static final int READ_TIMEOUT_MILLISECONDS = 60000;
+
+ private String serverUrl;
+ private String serverVersion;
+
+ public BatchDownloader(String serverUrl) {
+ if (serverUrl.endsWith("/")) {
+ this.serverUrl = serverUrl.substring(0, serverUrl.length() - 1);
+ } else {
+ this.serverUrl = serverUrl;
+ }
+ }
+
+ /**
+ * @return server url
+ */
+ public String getServerUrl() {
+ return serverUrl;
+ }
+
+ /**
+ * @return server version
+ */
+ public String getServerVersion() {
+ if (serverVersion == null) {
+ try {
+ serverVersion = remoteContent(VERSION_PATH);
+ } catch (IOException e) {
+ throw new RuntimeException(e.getMessage(), e);
+ }
+ }
+ return serverVersion;
+ }
+
+ /**
+ * @return list of downloaded files
+ */
+ public List downloadBatchFiles(File toDir) {
+ try {
+ List files = new ArrayList();
+
+ String libs = remoteContent(BATCH_PATH);
+
+ for (String lib : libs.split(",")) {
+ File file = new File(toDir, lib);
+ remoteContentToFile(BATCH_PATH + lib, file);
+ files.add(file);
+ }
+
+ return files;
+ } catch (Exception e) {
+ throw new RuntimeException(e);
+ }
+ }
+
+ private void remoteContentToFile(String path, File toFile) {
+ InputStream input = null;
+ FileOutputStream output = null;
+ String fullUrl = serverUrl + path;
+ try {
+ HttpURLConnection connection = newHttpConnection(new URL(fullUrl));
+ output = new FileOutputStream(toFile, false);
+ input = connection.getInputStream();
+ BootstrapperIOUtils.copyLarge(input, output);
+ } catch (Exception e) {
+ BootstrapperIOUtils.closeQuietly(output);
+ BootstrapperIOUtils.deleteFileQuietly(toFile);
+ throw new RuntimeException("Fail to download the file: " + fullUrl);
+ } finally {
+ BootstrapperIOUtils.closeQuietly(input);
+ BootstrapperIOUtils.closeQuietly(output);
+ }
+ }
+
+ String remoteContent(String path) throws IOException {
+ String fullUrl = serverUrl + path;
+ HttpURLConnection conn = newHttpConnection(new URL(fullUrl));
+ Reader reader = new InputStreamReader((InputStream) conn.getContent());
+ try {
+ int statusCode = conn.getResponseCode();
+ if (statusCode != HttpURLConnection.HTTP_OK) {
+ throw new IOException("Status returned by url : '" + fullUrl + "' is invalid : " + statusCode);
+ }
+ return BootstrapperIOUtils.toString(reader);
+ } finally {
+ BootstrapperIOUtils.closeQuietly(reader);
+ conn.disconnect();
+ }
+ }
+
+ static HttpURLConnection newHttpConnection(URL url) throws IOException {
+ HttpURLConnection connection = (HttpURLConnection) url.openConnection();
+ connection.setConnectTimeout(CONNECT_TIMEOUT_MILLISECONDS);
+ connection.setReadTimeout(READ_TIMEOUT_MILLISECONDS);
+ connection.setInstanceFollowRedirects(true);
+ connection.setRequestMethod("GET");
+ // TODO connection.setRequestProperty("User-Agent", userAgent);
+ return connection;
+ }
+
+}
diff --git a/sonar-batch-bootstrapper/src/main/java/org/sonar/batch/bootstrapper/BootstrapperIOUtils.java b/sonar-batch-bootstrapper/src/main/java/org/sonar/batch/bootstrapper/BootstrapperIOUtils.java
new file mode 100644
index 00000000000..c764ac50105
--- /dev/null
+++ b/sonar-batch-bootstrapper/src/main/java/org/sonar/batch/bootstrapper/BootstrapperIOUtils.java
@@ -0,0 +1,79 @@
+package org.sonar.batch.bootstrapper;
+
+import java.io.*;
+
+final class BootstrapperIOUtils {
+
+ private BootstrapperIOUtils() {
+ }
+
+ /**
+ * The default buffer size to use.
+ */
+ private static final int DEFAULT_BUFFER_SIZE = 1024 * 4;
+
+ /**
+ * Unconditionally close a Closeable
.
+ */
+ public static void closeQuietly(Closeable closeable) {
+ try {
+ if (closeable != null) {
+ closeable.close();
+ }
+ } catch (IOException ioe) {
+ // ignore
+ }
+ }
+
+ /**
+ * Get the contents of a Reader
as a String.
+ */
+ public static String toString(Reader input) throws IOException {
+ StringWriter sw = new StringWriter();
+ copyLarge(input, sw);
+ return sw.toString();
+ }
+
+ /**
+ * Copy bytes from an InputStream
to an OutputStream
.
+ */
+ public static long copyLarge(InputStream input, OutputStream output) throws IOException {
+ byte[] buffer = new byte[DEFAULT_BUFFER_SIZE];
+ long count = 0;
+ int n = 0;
+ while (-1 != (n = input.read(buffer))) {
+ output.write(buffer, 0, n);
+ count += n;
+ }
+ return count;
+ }
+
+ /**
+ * Copy chars from a Reader
to a Writer
.
+ */
+ public static long copyLarge(Reader input, Writer output) throws IOException {
+ char[] buffer = new char[DEFAULT_BUFFER_SIZE];
+ long count = 0;
+ int n = 0;
+ while (-1 != (n = input.read(buffer))) {
+ output.write(buffer, 0, n);
+ count += n;
+ }
+ return count;
+ }
+
+ /**
+ * Deletes a file (not a directory).
+ */
+ public static boolean deleteFileQuietly(File file) {
+ if (file == null) {
+ return false;
+ }
+ try {
+ return file.delete();
+ } catch (Exception e) {
+ return false;
+ }
+ }
+
+}
diff --git a/sonar-batch/src/main/java/org/sonar/batch/Reactor.java b/sonar-batch-bootstrapper/src/main/java/org/sonar/batch/bootstrapper/package-info.java
similarity index 70%
rename from sonar-batch/src/main/java/org/sonar/batch/Reactor.java
rename to sonar-batch-bootstrapper/src/main/java/org/sonar/batch/bootstrapper/package-info.java
index 7dd900b7e4c..7c23a7aa9ec 100644
--- a/sonar-batch/src/main/java/org/sonar/batch/Reactor.java
+++ b/sonar-batch-bootstrapper/src/main/java/org/sonar/batch/bootstrapper/package-info.java
@@ -17,22 +17,8 @@
* 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;
-import org.apache.maven.project.MavenProject;
-
-import java.util.List;
-
-public class Reactor {
-
- private List sortedProjects;
-
- public Reactor(List sortedProjects) {
- this.sortedProjects = sortedProjects;
- }
-
- public List getSortedProjects() {
- return sortedProjects;
- }
-
-}
+/**
+ * Provides API to bootstrap Sonar Batch.
+ */
+package org.sonar.batch.bootstrapper;
\ No newline at end of file
diff --git a/sonar-batch-bootstrapper/src/test/java/org/sonar/batch/bootstrapper/BatchDownloaderTest.java b/sonar-batch-bootstrapper/src/test/java/org/sonar/batch/bootstrapper/BatchDownloaderTest.java
new file mode 100644
index 00000000000..1822a53f014
--- /dev/null
+++ b/sonar-batch-bootstrapper/src/test/java/org/sonar/batch/bootstrapper/BatchDownloaderTest.java
@@ -0,0 +1,54 @@
+/*
+ * Sonar, open source software quality management tool.
+ * Copyright (C) 2009 SonarSource SA
+ * mailto:contact AT sonarsource DOT com
+ *
+ * Sonar is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 3 of the License, or (at your option) any later version.
+ *
+ * Sonar is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with Sonar; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02
+ */
+package org.sonar.batch.bootstrapper;
+
+import org.junit.Test;
+
+import java.io.IOException;
+
+import static org.hamcrest.Matchers.is;
+import static org.junit.Assert.assertThat;
+
+public class BatchDownloaderTest {
+
+ @Test
+ public void shouldRemoveLastUrlSlash() {
+ BatchDownloader bootstrapper = new BatchDownloader("http://test/");
+ assertThat(bootstrapper.getServerUrl(), is("http://test"));
+ }
+
+ @Test(expected = Exception.class)
+ public void shouldFailIfCanNotConnectServer() {
+ BatchDownloader bootstrapper = new BatchDownloader("http://unknown.foo");
+ bootstrapper.getServerVersion();
+ }
+
+ @Test
+ public void shouldReturnValidVersion() {
+ BatchDownloader bootstrapper = new BatchDownloader("http://test") {
+ @Override
+ String remoteContent(String path) throws IOException {
+ return "2.6";
+ }
+ };
+ assertThat(bootstrapper.getServerVersion(), is("2.6"));
+ }
+
+}
diff --git a/sonar-batch-maven-compat/pom.xml b/sonar-batch-maven-compat/pom.xml
new file mode 100644
index 00000000000..1ebefa3e077
--- /dev/null
+++ b/sonar-batch-maven-compat/pom.xml
@@ -0,0 +1,46 @@
+
+
+ 4.0.0
+
+
+ org.codehaus.sonar
+ sonar
+ 2.6-SNAPSHOT
+
+
+ sonar-batch-maven-compat
+ Sonar :: Batch Maven Compat
+ Compatibility layer, which provides MavenProject for non-Maven environments.
+
+
+
+ org.apache.maven
+ maven-project
+ 2.0.7
+ compile
+
+
+ org.codehaus.plexus
+ plexus-container-default
+
+
+
+
+
+
+
+
+ org.apache.maven.plugins
+ maven-shade-plugin
+
+
+ package
+
+ shade
+
+
+
+
+
+
+
diff --git a/sonar-batch/pom.xml b/sonar-batch/pom.xml
index fd1ae8dffb2..8c21ce740f7 100644
--- a/sonar-batch/pom.xml
+++ b/sonar-batch/pom.xml
@@ -11,7 +11,7 @@
sonar-batch
jar
Sonar :: Batch
-
+
org.codehaus.sonar
diff --git a/sonar-batch/src/main/java/org/sonar/batch/Batch.java b/sonar-batch/src/main/java/org/sonar/batch/Batch.java
index bf5b1e348bd..373300542ec 100644
--- a/sonar-batch/src/main/java/org/sonar/batch/Batch.java
+++ b/sonar-batch/src/main/java/org/sonar/batch/Batch.java
@@ -25,6 +25,7 @@ import org.picocontainer.MutablePicoContainer;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.sonar.api.Plugins;
+import org.sonar.api.batch.maven.MavenPluginHandler;
import org.sonar.api.resources.Project;
import org.sonar.api.utils.HttpDownloader;
import org.sonar.api.utils.IocContainer;
@@ -128,9 +129,32 @@ public class Batch {
for (Object component : components) {
register(container, component);
}
+ if (!isMavenPluginExecutorRegistered()) {
+ register(container, FakeMavenPluginExecutor.class);
+ }
return container;
}
+ boolean isMavenPluginExecutorRegistered() {
+ for (Object component : components) {
+ if (component instanceof Class && MavenPluginExecutor.class.isAssignableFrom((Class>) component)) {
+ return true;
+ }
+ }
+ return false;
+ }
+
+ class FakeMavenPluginExecutor implements MavenPluginExecutor {
+ public void execute(Project project, String goal) {
+ // do nothing
+ }
+
+ public MavenPluginHandler execute(Project project, MavenPluginHandler handler) {
+ // do nothing
+ return handler;
+ }
+ }
+
private void register(MutablePicoContainer container, Object component) {
container.as(Characteristics.CACHE).addComponent(component);
}
diff --git a/sonar-batch/src/main/java/org/sonar/batch/MavenReactor.java b/sonar-batch/src/main/java/org/sonar/batch/MavenReactor.java
index a33e6889ec8..1f0acf8c19e 100644
--- a/sonar-batch/src/main/java/org/sonar/batch/MavenReactor.java
+++ b/sonar-batch/src/main/java/org/sonar/batch/MavenReactor.java
@@ -20,11 +20,24 @@
package org.sonar.batch;
import org.apache.maven.execution.MavenSession;
+import org.apache.maven.project.MavenProject;
-public class MavenReactor extends Reactor {
+import java.util.List;
+
+public class MavenReactor {
+
+ private List sortedProjects;
public MavenReactor(MavenSession mavenSession) {
- super(mavenSession.getSortedProjects());
+ this.sortedProjects = mavenSession.getSortedProjects();
+ }
+
+ public MavenReactor(List sortedProjects) {
+ this.sortedProjects = sortedProjects;
+ }
+
+ public List getSortedProjects() {
+ return sortedProjects;
}
}
diff --git a/sonar-batch/src/main/java/org/sonar/batch/ProjectTree.java b/sonar-batch/src/main/java/org/sonar/batch/ProjectTree.java
index 1f969befd10..8adf4987039 100644
--- a/sonar-batch/src/main/java/org/sonar/batch/ProjectTree.java
+++ b/sonar-batch/src/main/java/org/sonar/batch/ProjectTree.java
@@ -19,8 +19,13 @@
*/
package org.sonar.batch;
+import org.sonar.batch.bootstrapper.ProjectDefinition;
+
+import org.sonar.batch.bootstrapper.Reactor;
+
import com.google.common.collect.Lists;
import com.google.common.collect.Maps;
+import org.apache.maven.model.Reporting;
import org.apache.maven.project.MavenProject;
import org.slf4j.LoggerFactory;
import org.sonar.api.database.DatabaseSession;
@@ -36,11 +41,67 @@ public class ProjectTree {
private List poms;
private MavenProjectBuilder projectBuilder;
- public ProjectTree(Reactor reactor, DatabaseSession databaseSession) {
- this.poms = reactor.getSortedProjects();
+ public ProjectTree(MavenReactor mavenReactor, DatabaseSession databaseSession) {
+ this.poms = mavenReactor.getSortedProjects();
this.projectBuilder = new MavenProjectBuilder(databaseSession);
}
+ /**
+ * Hack for non-Maven environments.
+ */
+ public ProjectTree(Reactor sonarReactor, DatabaseSession databaseSession) {
+ this(createMavenReactor(sonarReactor), databaseSession);
+ }
+
+ private static MavenReactor createMavenReactor(Reactor sonarReactor) {
+ List sonarProjects = sonarReactor.getSortedProjects();
+ List mavenProjects = Lists.newArrayList();
+ for (ProjectDefinition project : sonarProjects) {
+ mavenProjects.add(createInMemoryPom(project));
+ }
+ return new MavenReactor(mavenProjects);
+ }
+
+ private static MavenProject createInMemoryPom(ProjectDefinition project) {
+ MavenProject pom = new MavenProject();
+
+ String key = project.getProperties().getString("project.key"); // TODO constant
+ String[] keys = key.split(":");
+ pom.setGroupId(keys[0]);
+ pom.setArtifactId(keys[1]);
+ pom.setVersion("0.1-SNAPSHOT"); // TODO hard-coded value
+
+ pom.setArtifacts(Collections.EMPTY_SET);
+
+ // Configure fake directories
+ String buildDirectory = project.getProperties().getString("project.build.directory");
+ File sonarDir = new File(buildDirectory, "sonar");
+ pom.setFile(new File(sonarDir, "fake-pom.xml"));
+ pom.getBuild().setDirectory(buildDirectory);
+ pom.getBuild().setOutputDirectory(buildDirectory + "/classes"); // TODO hard-coded value
+ Reporting reporting = new Reporting();
+ reporting.setOutputDirectory(buildDirectory + "/target/site"); // TODO hard-coded value
+ pom.setReporting(reporting);
+
+ // Configure source directories
+ // TODO
+ // for (FileSystemDirectory dir : project.getDirs()) {
+ // if (dir.getNature() == Natures.MAIN) {
+ // pom.addCompileSourceRoot(dir.getLocation().getAbsolutePath());
+ // }
+ // }
+
+ // Configure test directories
+ // TODO
+ // for (FileSystemDirectory dir : project.getDirs()) {
+ // if (dir.getNature() == Natures.TEST) {
+ // pom.addTestCompileSourceRoot(dir.getLocation().getAbsolutePath());
+ // }
+ // }
+
+ return pom;
+ }
+
/**
* for unit tests
*/
diff --git a/sonar-batch/src/main/java/org/sonar/batch/bootstrap/ProjectDefinition.java b/sonar-batch/src/main/java/org/sonar/batch/bootstrap/ProjectDefinition.java
deleted file mode 100644
index d12dc1a9af1..00000000000
--- a/sonar-batch/src/main/java/org/sonar/batch/bootstrap/ProjectDefinition.java
+++ /dev/null
@@ -1,95 +0,0 @@
-package org.sonar.batch.bootstrap;
-
-import com.google.common.collect.Lists;
-import org.apache.commons.configuration.Configuration;
-import org.sonar.api.resources.FileSystemDirectory;
-
-import java.io.File;
-import java.util.List;
-
-/**
- * Defines project in a form suitable to bootstrap Sonar batch.
- * We assume that project is just a set of configuration properties and directories.
- * This is a part of bootstrap process, so we should take care about backward compatibility.
- *
- * @since 2.6
- */
-public class ProjectDefinition {
-
- private Configuration configuration;
-
- private File workDir;
- private File basedir;
- private List dirs = Lists.newArrayList();
-
- private ProjectDefinition parent;
- private List modules;
-
- /**
- * @return project properties.
- */
- public Configuration getConfiguration() {
- return configuration;
- }
-
- public void setConfiguration(Configuration configuration) {
- this.configuration = configuration;
- }
-
- /**
- * @return Sonar working directory for this project.
- * It's "${project.build.directory}/sonar" ("${project.basedir}/target/sonar") for Maven projects.
- */
- public File getSonarWorkingDirectory() {
- return workDir;
- }
-
- public void setSonarWorkingDirectory(File workDir) {
- this.workDir = workDir;
- }
-
- /**
- * @return project root directory.
- * It's "${project.basedir}" for Maven projects.
- */
- public File getBasedir() {
- return basedir;
- }
-
- public void setBasedir(File basedir) {
- this.basedir = basedir;
- }
-
- /**
- * @return project directories.
- */
- public List getDirs() {
- return dirs;
- }
-
- public void addDir(FileSystemDirectory dir) {
- this.dirs.add(dir);
- }
-
- /**
- * @return parent project.
- */
- public ProjectDefinition getParent() {
- return parent;
- }
-
- public void setParent(ProjectDefinition parent) {
- this.parent = parent;
- if (parent != null) {
- parent.modules.add(this);
- }
- }
-
- /**
- * @return list of sub-projects.
- */
- public List getModules() {
- return modules;
- }
-
-}
diff --git a/sonar-batch/src/main/java/org/sonar/batch/bootstrapper/ProjectDefinition.java b/sonar-batch/src/main/java/org/sonar/batch/bootstrapper/ProjectDefinition.java
new file mode 100644
index 00000000000..2b0a2a27205
--- /dev/null
+++ b/sonar-batch/src/main/java/org/sonar/batch/bootstrapper/ProjectDefinition.java
@@ -0,0 +1,55 @@
+/*
+ * Sonar, open source software quality management tool.
+ * Copyright (C) 2009 SonarSource SA
+ * mailto:contact AT sonarsource DOT com
+ *
+ * Sonar is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 3 of the License, or (at your option) any later version.
+ *
+ * Sonar is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with Sonar; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02
+ */
+package org.sonar.batch.bootstrapper;
+
+import org.apache.commons.configuration.Configuration;
+
+import java.io.File;
+
+/**
+ * Defines project in a form suitable to bootstrap Sonar batch.
+ * We assume that project is just a set of configuration properties and directories.
+ * This is a part of bootstrap process, so we should take care about backward compatibility.
+ *
+ * @since 2.6
+ */
+public class ProjectDefinition {
+
+ private File baseDir;
+ private Configuration properties;
+
+ /**
+ * @param baseDir project base directory
+ * @param properties project properties
+ */
+ public ProjectDefinition(File baseDir, Configuration properties) {
+ this.baseDir = baseDir;
+ this.properties = properties;
+ }
+
+ public File getBaseDir() {
+ return baseDir;
+ }
+
+ public Configuration getProperties() {
+ return properties;
+ }
+
+}
diff --git a/sonar-batch/src/main/java/org/sonar/batch/bootstrapper/Reactor.java b/sonar-batch/src/main/java/org/sonar/batch/bootstrapper/Reactor.java
new file mode 100644
index 00000000000..909adedf847
--- /dev/null
+++ b/sonar-batch/src/main/java/org/sonar/batch/bootstrapper/Reactor.java
@@ -0,0 +1,48 @@
+/*
+ * Sonar, open source software quality management tool.
+ * Copyright (C) 2009 SonarSource SA
+ * mailto:contact AT sonarsource DOT com
+ *
+ * Sonar is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 3 of the License, or (at your option) any later version.
+ *
+ * Sonar is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with Sonar; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02
+ */
+package org.sonar.batch.bootstrapper;
+
+
+import java.util.Collections;
+import java.util.List;
+
+/**
+ * Defines order of projects.
+ * This is a part of bootstrap process, so we should take care about backward compatibility.
+ *
+ * @since 2.6
+ */
+public class Reactor {
+
+ private List projects;
+
+ public Reactor(ProjectDefinition project) {
+ this.projects = Collections.singletonList(project);
+ }
+
+ public Reactor(List sortedProjects) {
+ this.projects = sortedProjects;
+ }
+
+ public List getSortedProjects() {
+ return projects;
+ }
+
+}
diff --git a/sonar-batch/src/test/java/org/sonar/batch/BatchTest.java b/sonar-batch/src/test/java/org/sonar/batch/BatchTest.java
new file mode 100644
index 00000000000..9f5fbb7a7b0
--- /dev/null
+++ b/sonar-batch/src/test/java/org/sonar/batch/BatchTest.java
@@ -0,0 +1,31 @@
+package org.sonar.batch;
+
+import org.junit.Test;
+import org.sonar.api.batch.maven.MavenPluginHandler;
+import org.sonar.api.resources.Project;
+
+import static org.hamcrest.Matchers.is;
+import static org.junit.Assert.assertThat;
+
+public class BatchTest {
+
+ class MyMavenPluginExecutor implements MavenPluginExecutor {
+ public void execute(Project project, String goal) {
+ }
+
+ public MavenPluginHandler execute(Project project, MavenPluginHandler handler) {
+ return handler;
+ }
+ }
+
+ @Test
+ public void shouldSearchMavenPluginExecutor() {
+ Batch batch;
+
+ batch = new Batch(null, MyMavenPluginExecutor.class);
+ assertThat(batch.isMavenPluginExecutorRegistered(), is(true));
+
+ batch = new Batch(null);
+ assertThat(batch.isMavenPluginExecutorRegistered(), is(false));
+ }
+}
diff --git a/sonar-plugin-api/src/main/java/org/sonar/api/resources/DefaultFileSystemDirectory.java b/sonar-plugin-api/src/main/java/org/sonar/api/resources/DefaultFileSystemDirectory.java
deleted file mode 100644
index 44461fb4772..00000000000
--- a/sonar-plugin-api/src/main/java/org/sonar/api/resources/DefaultFileSystemDirectory.java
+++ /dev/null
@@ -1,98 +0,0 @@
-/*
- * Sonar, open source software quality management tool.
- * Copyright (C) 2009 SonarSource SA
- * mailto:contact AT sonarsource DOT com
- *
- * Sonar is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Lesser General Public
- * License as published by the Free Software Foundation; either
- * version 3 of the License, or (at your option) any later version.
- *
- * Sonar is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public
- * License along with Sonar; if not, write to the Free Software
- * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02
- */
-package org.sonar.api.resources;
-
-import com.google.common.collect.Lists;
-
-import java.io.File;
-import java.util.Collections;
-import java.util.List;
-
-public class DefaultFileSystemDirectory implements FileSystemDirectory {
-
- private String nature;
- private File location;
- private File outputLocation;
- private List inclusionPatterns;
- private List exclusionPatterns;
-
- public String getNature() {
- return nature;
- }
-
- public DefaultFileSystemDirectory setNature(String nature) {
- this.nature = nature;
- return this;
- }
-
- public File getLocation() {
- return location;
- }
-
- public DefaultFileSystemDirectory setLocation(File location) {
- this.location = location;
- return this;
- }
-
- public File getOutputLocation() {
- return outputLocation;
- }
-
- public DefaultFileSystemDirectory setOutputLocation(File outputLocation) {
- this.outputLocation = outputLocation;
- return this;
- }
-
- public List getInclusionPatterns() {
- if (inclusionPatterns == null) {
- return Collections.emptyList();
- }
- return Collections.unmodifiableList(inclusionPatterns);
- }
-
- /**
- * @param pattern Ant-like inclusion pattern
- */
- public DefaultFileSystemDirectory addInclusionPattern(String pattern) {
- if (inclusionPatterns == null) {
- inclusionPatterns = Lists.newArrayList();
- }
- inclusionPatterns.add(pattern);
- return this;
- }
-
- public List getExclusionPatterns() {
- if (exclusionPatterns == null) {
- return Collections.emptyList();
- }
- return Collections.unmodifiableList(exclusionPatterns);
- }
-
- /**
- * @param pattern Ant-like exclusion pattern
- */
- public DefaultFileSystemDirectory addExclusionPattern(String pattern) {
- if (exclusionPatterns == null) {
- exclusionPatterns = Lists.newArrayList();
- }
- exclusionPatterns.add(pattern);
- return this;
- }
-}
diff --git a/sonar-plugin-api/src/main/java/org/sonar/api/resources/FileSystemDirectory.java b/sonar-plugin-api/src/main/java/org/sonar/api/resources/FileSystemDirectory.java
deleted file mode 100644
index 17c8298836c..00000000000
--- a/sonar-plugin-api/src/main/java/org/sonar/api/resources/FileSystemDirectory.java
+++ /dev/null
@@ -1,81 +0,0 @@
-/*
- * Sonar, open source software quality management tool.
- * Copyright (C) 2009 SonarSource SA
- * mailto:contact AT sonarsource DOT com
- *
- * Sonar is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Lesser General Public
- * License as published by the Free Software Foundation; either
- * version 3 of the License, or (at your option) any later version.
- *
- * Sonar is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public
- * License along with Sonar; if not, write to the Free Software
- * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02
- */
-package org.sonar.api.resources;
-
-
-import java.io.File;
-import java.util.List;
-
-/**
- * Defines project directory in a form suitable for Sonar.
- * This is a part of bootstrap process, so we should take care about backward compatibility.
- *
- * Couple of examples to show what this structure defines:
- *
- * - Typical Java project based on Ant might consist of two directories:
- *
- * - sources (location "src", output location "bin", includes "*.java")
- * - resources (location "src", output location "bin", excludes "*.java")
- *
- *
- * - Typical Java project based on Maven might consist of four directories:
- *
- * - main sources (location "src/main/java", output location "target/classes")
- * - main resources (location "src/main/resources", output location "target/classes")
- * - test sources (location "src/test/java", output location "target/test-classes")
- * - test resources (location "src/test/resources", output location "target/test-classes")
- *
- *
- *
- *
- *
- * @since 2.6
- */
-public interface FileSystemDirectory {
-
- /**
- * @return nature of underlying files.
- * @see Natures
- */
- String getNature();
-
- /**
- * @return location of files for compilation.
- * In case of Java this would be directory with Java source files.
- */
- File getLocation();
-
- /**
- * @return location of binary files after compilation.
- * In case of Java this would be directory with Class files.
- */
- File getOutputLocation();
-
- /**
- * @return list of Ant-like inclusion patterns for files.
- */
- List getInclusionPatterns();
-
- /**
- * @return list of Ant-like exclusion patterns for files.
- */
- List getExclusionPatterns();
-
-}
diff --git a/sonar-plugin-api/src/main/java/org/sonar/api/resources/Natures.java b/sonar-plugin-api/src/main/java/org/sonar/api/resources/Natures.java
deleted file mode 100644
index 5b8f102fef6..00000000000
--- a/sonar-plugin-api/src/main/java/org/sonar/api/resources/Natures.java
+++ /dev/null
@@ -1,18 +0,0 @@
-package org.sonar.api.resources;
-
-/**
- * @since 2.6
- */
-public interface Natures {
-
- /**
- * Everything which relate to source code (for example "src/main/java" and "src/main/resources").
- */
- String MAIN = "MAIN";
-
- /**
- * Everything which relate to unit tests (for example "src/test/java" and "src/test/resources").
- */
- String TEST = "TEST";
-
-}
diff --git a/sonar-server/pom.xml b/sonar-server/pom.xml
index a90ae860b18..b240684563c 100644
--- a/sonar-server/pom.xml
+++ b/sonar-server/pom.xml
@@ -11,6 +11,18 @@
Sonar :: Server
+
+
+ org.codehaus.sonar
+ sonar-batch
+ ${project.version}
+
+
+ org.codehaus.sonar
+ sonar-batch-maven-compat
+ ${project.version}
+
+
org.codehaus.sonar
sonar-channel
diff --git a/sonar-server/src/main/java/org/sonar/server/plugins/BatchResourcesServlet.java b/sonar-server/src/main/java/org/sonar/server/plugins/BatchResourcesServlet.java
new file mode 100644
index 00000000000..1e8ab666578
--- /dev/null
+++ b/sonar-server/src/main/java/org/sonar/server/plugins/BatchResourcesServlet.java
@@ -0,0 +1,104 @@
+/*
+ * Sonar, open source software quality management tool.
+ * Copyright (C) 2009 SonarSource SA
+ * mailto:contact AT sonarsource DOT com
+ *
+ * Sonar is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 3 of the License, or (at your option) any later version.
+ *
+ * Sonar is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with Sonar; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02
+ */
+package org.sonar.server.plugins;
+
+import com.google.common.collect.Lists;
+import org.apache.commons.io.IOUtils;
+import org.apache.commons.lang.StringUtils;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+import java.io.IOException;
+import java.io.InputStream;
+import java.io.OutputStream;
+import java.io.PrintWriter;
+import java.util.List;
+import java.util.Set;
+
+import javax.servlet.ServletException;
+import javax.servlet.http.HttpServlet;
+import javax.servlet.http.HttpServletRequest;
+import javax.servlet.http.HttpServletResponse;
+
+/**
+ * This servlet allows to load libraries from directory "WEB-INF/lib" in order to provide them for batch-bootstrapper.
+ * Most probably this is not a best solution.
+ */
+public class BatchResourcesServlet extends HttpServlet {
+
+ private static final Logger LOG = LoggerFactory.getLogger(BatchResourcesServlet.class);
+
+ @Override
+ public void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
+ String resource = getResource(request);
+ if (StringUtils.isEmpty(resource)) {
+ PrintWriter writer = null;
+ try {
+ String libs = StringUtils.join(getLibs(), ",");
+ response.setContentType("text/html");
+ writer = response.getWriter();
+ writer.println(libs);
+ } catch (IOException e) {
+ LOG.error("Unable to provide list of batch resources", e);
+ response.sendError(HttpServletResponse.SC_INTERNAL_SERVER_ERROR);
+ } finally {
+ IOUtils.closeQuietly(writer);
+ }
+ } else {
+ InputStream in = null;
+ OutputStream out = null;
+ try {
+ in = getServletContext().getResourceAsStream("/WEB-INF/lib/" + resource);
+ if (in == null) {
+ // TODO
+ } else {
+ out = response.getOutputStream();
+ IOUtils.copy(in, out);
+ }
+ } catch (Exception e) {
+ LOG.error("Unable to load batch resource '" + resource + "'", e);
+ response.sendError(HttpServletResponse.SC_INTERNAL_SERVER_ERROR);
+ } finally {
+ IOUtils.closeQuietly(in);
+ IOUtils.closeQuietly(out);
+ }
+ }
+ }
+
+ List getLibs() {
+ List libs = Lists.newArrayList();
+ Set paths = getServletContext().getResourcePaths("/WEB-INF/lib");
+ for (Object obj : paths) {
+ String path = (String) obj;
+ if (StringUtils.endsWith(path, ".jar")) {
+ libs.add(StringUtils.removeStart(path, "/WEB-INF/lib/"));
+ }
+ }
+ return libs;
+ }
+
+ /**
+ * @return part of request URL after servlet path
+ */
+ String getResource(HttpServletRequest request) {
+ return StringUtils.substringAfter(request.getRequestURI(), request.getContextPath() + request.getServletPath() + "/");
+ }
+
+}
diff --git a/sonar-server/src/main/webapp/WEB-INF/web.xml b/sonar-server/src/main/webapp/WEB-INF/web.xml
index 99d68dcc5f6..25869629487 100644
--- a/sonar-server/src/main/webapp/WEB-INF/web.xml
+++ b/sonar-server/src/main/webapp/WEB-INF/web.xml
@@ -78,6 +78,10 @@
static
org.sonar.server.plugins.StaticResourcesServlet
+
+ batch
+ org.sonar.server.plugins.BatchResourcesServlet
+
chart
@@ -91,6 +95,10 @@
static
/static/*
+
+ batch
+ /batch/*
+
org.sonar.server.platform.PlatformLifecycleListener
@@ -103,4 +111,4 @@
30
-
\ No newline at end of file
+
diff --git a/sonar-server/src/test/java/org/sonar/server/plugins/BatchResourcesServletTest.java b/sonar-server/src/test/java/org/sonar/server/plugins/BatchResourcesServletTest.java
new file mode 100644
index 00000000000..3dadef9567f
--- /dev/null
+++ b/sonar-server/src/test/java/org/sonar/server/plugins/BatchResourcesServletTest.java
@@ -0,0 +1,59 @@
+package org.sonar.server.plugins;
+
+import com.google.common.collect.Sets;
+import org.junit.Before;
+import org.junit.Test;
+
+import java.util.Set;
+
+import javax.servlet.ServletContext;
+import javax.servlet.http.HttpServletRequest;
+
+import static org.hamcrest.Matchers.is;
+import static org.junit.Assert.assertThat;
+import static org.mockito.Matchers.anyString;
+import static org.mockito.Mockito.doReturn;
+import static org.mockito.Mockito.mock;
+import static org.mockito.Mockito.spy;
+import static org.mockito.Mockito.when;
+
+public class BatchResourcesServletTest {
+ private BatchResourcesServlet servlet;
+ private HttpServletRequest request;
+
+ @Before
+ public void setUp() throws Exception {
+ servlet = new BatchResourcesServlet();
+ request = mock(HttpServletRequest.class);
+ }
+
+ @Test
+ public void shouldDetermineResource() {
+ when(request.getContextPath()).thenReturn("sonar");
+ when(request.getServletPath()).thenReturn("/batch");
+
+ when(request.getRequestURI()).thenReturn("/sonar/batch/sonar-core-2.6.jar");
+ assertThat(servlet.getResource(request), is("sonar-core-2.6.jar"));
+
+ when(request.getRequestURI()).thenReturn("/sonar/batch/");
+ assertThat(servlet.getResource(request), is(""));
+
+ when(request.getRequestURI()).thenReturn("/sonar/batch");
+ assertThat(servlet.getResource(request), is(""));
+ }
+
+ @Test
+ public void shouldDetermineListOfResources() {
+ ServletContext servletContext = mock(ServletContext.class);
+ servlet = spy(servlet);
+ doReturn(servletContext).when(servlet).getServletContext();
+ Set libs = Sets.newHashSet();
+ libs.add("/WEB-INF/lib/sonar-core-2.6.jar");
+ libs.add("/WEB-INF/lib/treemap.rb");
+ libs.add("/WEB-INF/lib/directory/");
+ when(servletContext.getResourcePaths(anyString())).thenReturn(libs);
+
+ assertThat(servlet.getLibs().size(), is(1));
+ assertThat(servlet.getLibs().get(0), is("sonar-core-2.6.jar"));
+ }
+}
--
2.39.5