]> source.dussan.org Git - sonarqube.git/commitdiff
SONAR-2016 Sonar plugins and so extensions are not accessible from the Sonar Maven...
authorsimonbrandhof <simon.brandhof@gmail.com>
Thu, 16 Dec 2010 11:41:17 +0000 (11:41 +0000)
committersimonbrandhof <simon.brandhof@gmail.com>
Thu, 16 Dec 2010 11:41:17 +0000 (11:41 +0000)
16 files changed:
sonar-batch/src/main/java/org/sonar/batch/Batch.java
sonar-batch/src/main/java/org/sonar/batch/BatchPluginRepository.java [deleted file]
sonar-batch/src/main/java/org/sonar/batch/ProjectBatch.java
sonar-batch/src/main/java/org/sonar/batch/RemoteClassLoader.java [deleted file]
sonar-batch/src/main/java/org/sonar/batch/bootstrap/BatchPluginRepository.java [new file with mode: 0644]
sonar-batch/src/main/java/org/sonar/batch/bootstrap/BootstrapClassLoader.java [new file with mode: 0644]
sonar-batch/src/main/java/org/sonar/batch/bootstrap/ExtensionDownloader.java [new file with mode: 0644]
sonar-batch/src/main/java/org/sonar/batch/bootstrap/TempDirectories.java [new file with mode: 0644]
sonar-batch/src/test/java/org/sonar/batch/BatchPluginRepositoryTest.java [deleted file]
sonar-batch/src/test/java/org/sonar/batch/RemoteClassLoaderTest.java [deleted file]
sonar-batch/src/test/java/org/sonar/batch/bootstrap/BatchPluginRepositoryTest.java [new file with mode: 0644]
sonar-batch/src/test/java/org/sonar/batch/bootstrap/BootstrapClassLoaderTest.java [new file with mode: 0644]
sonar-batch/src/test/java/org/sonar/batch/bootstrap/ExtensionDownloaderTest.java [new file with mode: 0644]
sonar-batch/src/test/java/org/sonar/batch/bootstrap/TempDirectoriesTest.java [new file with mode: 0644]
sonar-batch/src/test/resources/org/sonar/batch/RemoteClassLoaderTest/foo.jar [deleted file]
sonar-batch/src/test/resources/org/sonar/batch/bootstrap/BootstrapClassLoaderTest/foo.jar [new file with mode: 0644]

index d6c5c6a8bd668fce1465850bde6ae98c825288ec..91e981e41ac7b04370a4f8094aa621a5c7302e64 100644 (file)
@@ -29,6 +29,10 @@ import org.sonar.api.resources.Project;
 import org.sonar.api.utils.HttpDownloader;
 import org.sonar.api.utils.IocContainer;
 import org.sonar.api.utils.ServerHttpClient;
+import org.sonar.batch.bootstrap.BatchPluginRepository;
+import org.sonar.batch.bootstrap.BootstrapClassLoader;
+import org.sonar.batch.bootstrap.ExtensionDownloader;
+import org.sonar.batch.bootstrap.TempDirectories;
 import org.sonar.batch.index.*;
 import org.sonar.core.components.CacheMetricFinder;
 import org.sonar.core.components.CacheRuleFinder;
@@ -58,7 +62,7 @@ public class Batch {
     try {
       container = buildPicoContainer();
       container.start();
-      analyzeProjects(container);
+      analyzeModules(container);
 
     } finally {
       if (container != null) {
@@ -67,10 +71,9 @@ public class Batch {
     }
   }
 
-  private void analyzeProjects(MutablePicoContainer container) {
+  private void analyzeModules(MutablePicoContainer container) {
     // a child container is built to ensure database connector is up
     MutablePicoContainer batchContainer = container.makeChildContainer();
-    batchContainer.as(Characteristics.CACHE).addComponent(ServerMetadata.class);
     batchContainer.as(Characteristics.CACHE).addComponent(ProjectTree.class);
     batchContainer.as(Characteristics.CACHE).addComponent(DefaultResourceCreationLock.class);
     batchContainer.as(Characteristics.CACHE).addComponent(DefaultIndex.class);
@@ -86,7 +89,6 @@ public class Batch {
     batchContainer.as(Characteristics.CACHE).addComponent(BatchPluginRepository.class);
     batchContainer.as(Characteristics.CACHE).addComponent(Plugins.class);
     batchContainer.as(Characteristics.CACHE).addComponent(ServerHttpClient.class);
-    batchContainer.as(Characteristics.CACHE).addComponent(HttpDownloader.class);
     batchContainer.as(Characteristics.CACHE).addComponent(MeasuresDao.class);
     batchContainer.as(Characteristics.CACHE).addComponent(CacheRuleFinder.class);
     batchContainer.as(Characteristics.CACHE).addComponent(CacheMetricFinder.class);
@@ -94,7 +96,7 @@ public class Batch {
 
     ProjectTree projectTree = batchContainer.getComponent(ProjectTree.class);
     DefaultIndex index = batchContainer.getComponent(DefaultIndex.class);
-    analyzeProject(batchContainer, index, projectTree.getRootProject());
+    analyzeModule(batchContainer, index, projectTree.getRootProject());
 
     // batchContainer is stopped by its parent
   }
@@ -103,11 +105,17 @@ public class Batch {
     MutablePicoContainer container = IocContainer.buildPicoContainer();
 
     register(container, configuration);
-    URLClassLoader fullClassloader = RemoteClassLoader.createForJdbcDriver(configuration).getClassLoader();
+    register(container, ServerMetadata.class);// registered here because used by BootstrapClassLoader
+    register(container, TempDirectories.class);// registered here because used by BootstrapClassLoader
+    register(container, HttpDownloader.class);// registered here because used by BootstrapClassLoader
+    register(container, ExtensionDownloader.class);// registered here because used by BootstrapClassLoader
+    register(container, BootstrapClassLoader.class);
+
+    URLClassLoader bootstrapClassLoader = container.getComponent(BootstrapClassLoader.class).getClassLoader();
     // set as the current context classloader for hibernate, else it does not find the JDBC driver.
-    Thread.currentThread().setContextClassLoader(fullClassloader);
+    Thread.currentThread().setContextClassLoader(bootstrapClassLoader);
 
-    register(container, new DriverDatabaseConnector(configuration, fullClassloader));
+    register(container, new DriverDatabaseConnector(configuration, bootstrapClassLoader));
     register(container, ThreadLocalDatabaseSessionFactory.class);
     container.as(Characteristics.CACHE).addAdapter(new DatabaseSessionProvider());
     for (Object component : components) {
@@ -120,9 +128,9 @@ public class Batch {
     container.as(Characteristics.CACHE).addComponent(component);
   }
 
-  private void analyzeProject(MutablePicoContainer container, DefaultIndex index, Project project) {
+  private void analyzeModule(MutablePicoContainer container, DefaultIndex index, Project project) {
     for (Project module : project.getModules()) {
-      analyzeProject(container, index, module);
+      analyzeModule(container, index, module);
     }
     LOG.info("-------------  Analyzing {}", project.getName());
 
diff --git a/sonar-batch/src/main/java/org/sonar/batch/BatchPluginRepository.java b/sonar-batch/src/main/java/org/sonar/batch/BatchPluginRepository.java
deleted file mode 100644 (file)
index 63e3a95..0000000
+++ /dev/null
@@ -1,128 +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.batch;
-
-import com.google.common.collect.Lists;
-import org.apache.commons.configuration.Configuration;
-import org.apache.commons.lang.ArrayUtils;
-import org.apache.commons.lang.StringUtils;
-import org.picocontainer.MutablePicoContainer;
-import org.picocontainer.PicoContainer;
-import org.slf4j.Logger;
-import org.slf4j.LoggerFactory;
-import org.sonar.api.BatchExtension;
-import org.sonar.api.Plugin;
-import org.sonar.api.batch.AbstractCoverageExtension;
-import org.sonar.api.resources.Java;
-import org.sonar.api.resources.Project;
-import org.sonar.api.utils.SonarException;
-import org.sonar.core.classloaders.ClassLoadersCollection;
-import org.sonar.core.plugin.AbstractPluginRepository;
-import org.sonar.core.plugin.JpaPlugin;
-import org.sonar.core.plugin.JpaPluginDao;
-import org.sonar.core.plugin.JpaPluginFile;
-
-import java.net.MalformedURLException;
-import java.net.URL;
-import java.util.List;
-
-public class BatchPluginRepository extends AbstractPluginRepository {
-
-  private static final Logger LOG = LoggerFactory.getLogger(BatchPluginRepository.class);
-
-  private String baseUrl;
-  private JpaPluginDao dao;
-
-  private ClassLoadersCollection classLoaders;
-
-  public BatchPluginRepository(JpaPluginDao dao, ServerMetadata server) {
-    this.dao = dao;
-    this.baseUrl = server.getURL() + "/deploy/plugins/";
-  }
-
-  /**
-   * for unit tests only
-   */
-  BatchPluginRepository() {
-
-  }
-
-  public void start() {
-    classLoaders = new ClassLoadersCollection(Thread.currentThread().getContextClassLoader());
-    for (JpaPlugin pluginMetadata : dao.getPlugins()) {
-      String key = pluginMetadata.getKey();
-      List<URL> urls = Lists.newArrayList();
-      for (JpaPluginFile pluginFile : pluginMetadata.getFiles()) {
-        try {
-          URL url = new URL(baseUrl + pluginFile.getPath());
-          urls.add(url);
-        } catch (MalformedURLException e) {
-          throw new SonarException("Can not build the classloader of the plugin " + pluginFile.getPluginKey(), e);
-        }
-      }
-      if (LOG.isDebugEnabled()) {
-        LOG.debug("Classloader of plugin " + key + ":");
-        for (URL url : urls) {
-          LOG.debug("   -> " + url);
-        }
-      }
-      classLoaders.createClassLoader(key, urls, pluginMetadata.isUseChildFirstClassLoader() == Boolean.TRUE);
-    }
-    classLoaders.done();
-  }
-
-  public void registerPlugins(MutablePicoContainer pico) {
-    for (JpaPlugin pluginMetadata : dao.getPlugins()) {
-      try {
-        Class claz = classLoaders.get(pluginMetadata.getKey()).loadClass(pluginMetadata.getPluginClass());
-        Plugin plugin = (Plugin) claz.newInstance();
-        registerPlugin(pico, plugin, pluginMetadata.getKey());
-
-      } catch (Exception e) {
-        throw new SonarException("Fail to load extensions from plugin " + pluginMetadata.getKey(), e);
-      }
-    }
-    invokeExtensionProviders(pico);
-  }
-
-  @Override
-  protected boolean shouldRegisterExtension(PicoContainer container, String pluginKey, Object extension) {
-    boolean ok = isType(extension, BatchExtension.class);
-    if (ok && isType(extension, AbstractCoverageExtension.class)) {
-      ok = shouldRegisterCoverageExtension(pluginKey, container.getComponent(Project.class), container.getComponent(Configuration.class));
-      if ( !ok) {
-        LOG.debug("The following extension is ignored: " + extension + ". See the parameter " + AbstractCoverageExtension.PARAM_PLUGIN);
-      }
-    }
-    return ok;
-  }
-
-  boolean shouldRegisterCoverageExtension(String pluginKey, Project project, Configuration conf) {
-    boolean ok = true;
-    if (StringUtils.equals(project.getLanguageKey(), Java.KEY)) {
-      String[] selectedPluginKeys = conf.getStringArray(AbstractCoverageExtension.PARAM_PLUGIN);
-      if (ArrayUtils.isEmpty(selectedPluginKeys)) {
-        selectedPluginKeys = new String[] { AbstractCoverageExtension.DEFAULT_PLUGIN };
-      }
-      ok = ArrayUtils.contains(selectedPluginKeys, pluginKey);
-    }
-    return ok;
-  }
-}
index 104f7eb0660d06f7f3b827403715f56ecc7818e5..afccb16fddadb25bd23f9e914cb1ced1840c0b24 100644 (file)
@@ -35,6 +35,7 @@ import org.sonar.api.resources.Project;
 import org.sonar.api.rules.DefaultRulesManager;
 import org.sonar.api.utils.IocContainer;
 import org.sonar.api.utils.SonarException;
+import org.sonar.batch.bootstrap.BatchPluginRepository;
 import org.sonar.batch.index.DefaultIndex;
 import org.sonar.batch.index.DefaultResourcePersister;
 import org.sonar.batch.phases.Phases;
diff --git a/sonar-batch/src/main/java/org/sonar/batch/RemoteClassLoader.java b/sonar-batch/src/main/java/org/sonar/batch/RemoteClassLoader.java
deleted file mode 100644 (file)
index 31f0611..0000000
+++ /dev/null
@@ -1,69 +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.batch;
-
-import org.apache.commons.configuration.Configuration;
-
-import java.net.MalformedURLException;
-import java.net.URL;
-import java.net.URLClassLoader;
-import java.util.Collection;
-
-/**
- * Create classloader from remote URLs.
- *
- * IMPORTANT : it generates URLClassLoaders, which use the parent first delegation mode. It finds classes in the parent classloader THEN
- * in the plugin classloader.
- * Using a child-first delegation mode can avoid some conflicts with API dependencies (xml-api, antlr). It's
- * not possible for now, but it would be simple to implement by replacing the URLClassLoader by
- * the class ChildFirstClassLoader (see http://articles.qos.ch/classloader.html)
- */
-public class RemoteClassLoader {
-
-  private URLClassLoader classLoader;
-
-  public RemoteClassLoader(URL[] urls, ClassLoader parent) {
-    ClassLoader parentClassLoader = (parent==null ? RemoteClassLoader.class.getClassLoader() : parent);
-    classLoader = URLClassLoader.newInstance(urls, parentClassLoader);
-  }
-
-  public RemoteClassLoader(URL[] urls) {
-    this(urls, null);
-  }
-
-  public RemoteClassLoader(Collection<URL> urls, ClassLoader parent) {
-    this(urls.toArray(new URL[urls.size()]), parent);
-  }
-
-  public URLClassLoader getClassLoader() {
-    return classLoader;
-  }
-
-  public static RemoteClassLoader createForJdbcDriver(Configuration conf) {
-    String baseUrl = ServerMetadata.getURL(conf);
-    String url = baseUrl + "/deploy/jdbc-driver.jar";
-    try {
-      return new RemoteClassLoader(new URL[]{new URL(url)});
-
-    } catch (MalformedURLException e) {
-      throw new RuntimeException("Fail to download the JDBC driver from server: " + url, e);
-    }
-  }
-}
diff --git a/sonar-batch/src/main/java/org/sonar/batch/bootstrap/BatchPluginRepository.java b/sonar-batch/src/main/java/org/sonar/batch/bootstrap/BatchPluginRepository.java
new file mode 100644 (file)
index 0000000..6588cfc
--- /dev/null
@@ -0,0 +1,130 @@
+/*
+ * 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.bootstrap;
+
+import com.google.common.collect.Lists;
+import org.apache.commons.configuration.Configuration;
+import org.apache.commons.lang.ArrayUtils;
+import org.apache.commons.lang.StringUtils;
+import org.picocontainer.MutablePicoContainer;
+import org.picocontainer.PicoContainer;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+import org.sonar.api.BatchExtension;
+import org.sonar.api.Plugin;
+import org.sonar.api.batch.AbstractCoverageExtension;
+import org.sonar.api.resources.Java;
+import org.sonar.api.resources.Project;
+import org.sonar.api.utils.SonarException;
+import org.sonar.core.classloaders.ClassLoadersCollection;
+import org.sonar.core.plugin.AbstractPluginRepository;
+import org.sonar.core.plugin.JpaPlugin;
+import org.sonar.core.plugin.JpaPluginDao;
+import org.sonar.core.plugin.JpaPluginFile;
+
+import java.io.File;
+import java.net.MalformedURLException;
+import java.net.URL;
+import java.util.List;
+
+public class BatchPluginRepository extends AbstractPluginRepository {
+
+  private static final Logger LOG = LoggerFactory.getLogger(BatchPluginRepository.class);
+
+  private JpaPluginDao dao;
+
+  private ClassLoadersCollection classLoaders;
+  private ExtensionDownloader extensionDownloader;
+
+  public BatchPluginRepository(JpaPluginDao dao, ExtensionDownloader extensionDownloader) {
+    this.dao = dao;
+    this.extensionDownloader = extensionDownloader;
+  }
+
+  /**
+   * for unit tests only
+   */
+  BatchPluginRepository() {
+
+  }
+
+  public void start() {
+    classLoaders = new ClassLoadersCollection(Thread.currentThread().getContextClassLoader());
+    for (JpaPlugin pluginMetadata : dao.getPlugins()) {
+      String key = pluginMetadata.getKey();
+      List<URL> urls = Lists.newArrayList();
+      for (JpaPluginFile pluginFile : pluginMetadata.getFiles()) {
+        File file = extensionDownloader.downloadExtension(pluginFile);
+        try {
+          urls.add(file.toURI().toURL());
+          
+        } catch (MalformedURLException e) {
+          throw new SonarException("Can not get the URL of: " + file, e);
+        }
+      }
+      if (LOG.isDebugEnabled()) {
+        LOG.debug("Classloader of plugin " + key + ":");
+        for (URL url : urls) {
+          LOG.debug("   -> " + url);
+        }
+      }
+      classLoaders.createClassLoader(key, urls, pluginMetadata.isUseChildFirstClassLoader() == Boolean.TRUE);
+    }
+    classLoaders.done();
+  }
+
+  public void registerPlugins(MutablePicoContainer pico) {
+    for (JpaPlugin pluginMetadata : dao.getPlugins()) {
+      try {
+        Class claz = classLoaders.get(pluginMetadata.getKey()).loadClass(pluginMetadata.getPluginClass());
+        Plugin plugin = (Plugin) claz.newInstance();
+        registerPlugin(pico, plugin, pluginMetadata.getKey());
+
+      } catch (Exception e) {
+        throw new SonarException("Fail to load extensions from plugin " + pluginMetadata.getKey(), e);
+      }
+    }
+    invokeExtensionProviders(pico);
+  }
+
+  @Override
+  protected boolean shouldRegisterExtension(PicoContainer container, String pluginKey, Object extension) {
+    boolean ok = isType(extension, BatchExtension.class);
+    if (ok && isType(extension, AbstractCoverageExtension.class)) {
+      ok = shouldRegisterCoverageExtension(pluginKey, container.getComponent(Project.class), container.getComponent(Configuration.class));
+      if ( !ok) {
+        LOG.debug("The following extension is ignored: " + extension + ". See the parameter " + AbstractCoverageExtension.PARAM_PLUGIN);
+      }
+    }
+    return ok;
+  }
+
+  boolean shouldRegisterCoverageExtension(String pluginKey, Project project, Configuration conf) {
+    boolean ok = true;
+    if (StringUtils.equals(project.getLanguageKey(), Java.KEY)) {
+      String[] selectedPluginKeys = conf.getStringArray(AbstractCoverageExtension.PARAM_PLUGIN);
+      if (ArrayUtils.isEmpty(selectedPluginKeys)) {
+        selectedPluginKeys = new String[] { AbstractCoverageExtension.DEFAULT_PLUGIN };
+      }
+      ok = ArrayUtils.contains(selectedPluginKeys, pluginKey);
+    }
+    return ok;
+  }
+}
diff --git a/sonar-batch/src/main/java/org/sonar/batch/bootstrap/BootstrapClassLoader.java b/sonar-batch/src/main/java/org/sonar/batch/bootstrap/BootstrapClassLoader.java
new file mode 100644 (file)
index 0000000..ee91b71
--- /dev/null
@@ -0,0 +1,53 @@
+/*
+ * 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.bootstrap;
+
+import org.sonar.api.utils.SonarException;
+
+import java.io.File;
+import java.net.MalformedURLException;
+import java.net.URL;
+import java.net.URLClassLoader;
+
+/**
+ * ClassLoader extended with the JDBC Driver hosted on the server-side.
+ */
+public class BootstrapClassLoader {
+
+  private URLClassLoader classLoader;
+
+  public BootstrapClassLoader(ExtensionDownloader extensionDownloader) {
+    this(extensionDownloader.downloadJdbcDriver());
+  }
+
+  BootstrapClassLoader(File jdbcDriver) {
+    try {
+      ClassLoader parentClassLoader = BootstrapClassLoader.class.getClassLoader();
+      classLoader = URLClassLoader.newInstance(new URL[]{jdbcDriver.toURI().toURL()}, parentClassLoader);
+
+    } catch (MalformedURLException e) {
+      throw new SonarException("Fail to get URL of : " + jdbcDriver.getAbsolutePath(), e);
+    }
+  }
+
+  public URLClassLoader getClassLoader() {
+    return classLoader;
+  }
+}
diff --git a/sonar-batch/src/main/java/org/sonar/batch/bootstrap/ExtensionDownloader.java b/sonar-batch/src/main/java/org/sonar/batch/bootstrap/ExtensionDownloader.java
new file mode 100644 (file)
index 0000000..ee6d1a0
--- /dev/null
@@ -0,0 +1,69 @@
+/*
+ * 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.bootstrap;
+
+import org.slf4j.LoggerFactory;
+import org.sonar.api.utils.HttpDownloader;
+import org.sonar.api.utils.SonarException;
+import org.sonar.batch.ServerMetadata;
+import org.sonar.core.plugin.JpaPluginFile;
+
+import java.io.File;
+import java.net.URI;
+import java.net.URISyntaxException;
+
+public final class ExtensionDownloader {
+
+  private HttpDownloader httpDownloader;
+  private TempDirectories workingDirectories;
+  private String baseUrl;
+
+  public ExtensionDownloader(HttpDownloader httpDownloader, TempDirectories workingDirectories, ServerMetadata server) {
+    this.httpDownloader = httpDownloader;
+    this.workingDirectories = workingDirectories;
+    this.baseUrl = server.getURL();
+  }
+
+  public File downloadJdbcDriver() {
+    String url = baseUrl + "/deploy/jdbc-driver.jar";
+    try {
+      File jdbcDriver = new File(workingDirectories.getRoot(), "jdbc-driver.jar");
+      LoggerFactory.getLogger(getClass()).debug("Download JDBC Driver from " + url + " to " + jdbcDriver.getAbsolutePath());
+      httpDownloader.download(new URI(url), jdbcDriver);
+      return jdbcDriver;
+
+    } catch (URISyntaxException e) {
+      throw new SonarException("Fail to download the JDBC driver from : " + url, e);
+    }
+  }
+
+  public File downloadExtension(JpaPluginFile extension) {
+    File targetFile = new File(workingDirectories.getDir(extension.getPluginKey()), extension.getFilename());
+    String url = baseUrl + "/deploy/plugins/" + extension.getPluginKey() + "/" + extension.getFilename();
+    LoggerFactory.getLogger(getClass()).debug("Download " + url + " to " + targetFile.getAbsolutePath());
+    try {
+      httpDownloader.download(new URI(url), targetFile);
+      return targetFile;
+
+    } catch (URISyntaxException e) {
+      throw new SonarException("Can not download extension: " + url, e);
+    }
+  }
+}
diff --git a/sonar-batch/src/main/java/org/sonar/batch/bootstrap/TempDirectories.java b/sonar-batch/src/main/java/org/sonar/batch/bootstrap/TempDirectories.java
new file mode 100644 (file)
index 0000000..25b33c1
--- /dev/null
@@ -0,0 +1,82 @@
+/*
+ * 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.bootstrap;
+
+import com.google.common.collect.Maps;
+import org.apache.commons.io.FileUtils;
+import org.apache.commons.lang.StringUtils;
+import org.slf4j.LoggerFactory;
+import org.sonar.api.utils.SonarException;
+import org.sonar.api.utils.TempFileUtils;
+
+import java.io.File;
+import java.io.IOException;
+import java.util.Map;
+
+public final class TempDirectories {
+
+  private File rootDir;
+  private Map<String, File> directoriesByKey = Maps.newHashMap();
+
+  public TempDirectories() throws IOException {
+    this.rootDir = TempFileUtils.createTempDirectory("sonar-batch");
+    LoggerFactory.getLogger(getClass()).debug("Temporary directory: " + rootDir.getAbsolutePath());
+  }
+
+  public File getRoot() {
+    return rootDir;
+  }
+
+  /**
+   * Get or create a working directory
+   */
+  public File getDir(String key) {
+    if (StringUtils.isBlank(key)) {
+      return rootDir;
+    }
+
+    File dir = directoriesByKey.get(key);
+    if (dir == null) {
+      dir = new File(rootDir, key);
+      try {
+        FileUtils.forceMkdir(dir);
+        directoriesByKey.put(key, dir);
+
+      } catch (IOException e) {
+        throw new SonarException("Can not create the temp directory: " + dir, e);
+      }
+    }
+    return dir;
+  }
+
+  public File getFile(String directoryKey, String filename) {
+    File dir = getDir(directoryKey);
+    return new File(dir, filename);
+  }
+
+  /**
+   * This method is executed by picocontainer during shutdown.
+   */
+  public void stop() {
+    directoriesByKey.clear();
+    LoggerFactory.getLogger(getClass()).debug("Delete temporary directory: " + rootDir.getAbsolutePath());
+    FileUtils.deleteQuietly(rootDir);
+  }
+}
diff --git a/sonar-batch/src/test/java/org/sonar/batch/BatchPluginRepositoryTest.java b/sonar-batch/src/test/java/org/sonar/batch/BatchPluginRepositoryTest.java
deleted file mode 100644 (file)
index dacd396..0000000
+++ /dev/null
@@ -1,99 +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.batch;
-
-import static org.hamcrest.core.Is.is;
-import static org.junit.Assert.assertThat;
-
-import org.apache.commons.configuration.Configuration;
-import org.apache.commons.configuration.PropertiesConfiguration;
-import org.junit.Test;
-import org.picocontainer.MutablePicoContainer;
-import org.sonar.api.BatchExtension;
-import org.sonar.api.ServerExtension;
-import org.sonar.api.batch.AbstractCoverageExtension;
-import org.sonar.api.resources.Java;
-import org.sonar.api.resources.Project;
-import org.sonar.api.utils.IocContainer;
-
-public class BatchPluginRepositoryTest {
-
-  @Test
-  public void shouldRegisterBatchExtension() {
-    MutablePicoContainer pico = IocContainer.buildPicoContainer();
-    pico.addComponent(new PropertiesConfiguration());
-    BatchPluginRepository repository = new BatchPluginRepository();
-
-    // check classes
-    assertThat(repository.shouldRegisterExtension(pico, "foo", FakeBatchExtension.class), is(true));
-    assertThat(repository.shouldRegisterExtension(pico, "foo", FakeServerExtension.class), is(false));
-    assertThat(repository.shouldRegisterExtension(pico, "foo", String.class), is(false));
-
-    // check objects
-    assertThat(repository.shouldRegisterExtension(pico, "foo", new FakeBatchExtension()), is(true));
-    assertThat(repository.shouldRegisterExtension(pico, "foo", new FakeServerExtension()), is(false));
-    assertThat(repository.shouldRegisterExtension(pico, "foo", "bar"), is(false));
-  }
-
-  @Test
-  public void shouldRegisterOnlyCoberturaExtensionByDefault() {
-    BatchPluginRepository repository = new BatchPluginRepository();
-    PropertiesConfiguration conf = new PropertiesConfiguration();
-    assertThat(repository.shouldRegisterCoverageExtension("cobertura", newJavaProject(), conf), is(true));
-    assertThat(repository.shouldRegisterCoverageExtension("clover", newJavaProject(), conf), is(false));
-  }
-
-  @Test
-  public void shouldRegisterCustomCoverageExtension() {
-    Configuration conf = new PropertiesConfiguration();
-    conf.setProperty(AbstractCoverageExtension.PARAM_PLUGIN, "clover,phpunit");
-    BatchPluginRepository repository = new BatchPluginRepository();
-    assertThat(repository.shouldRegisterCoverageExtension("cobertura", newJavaProject(), conf), is(false));
-    assertThat(repository.shouldRegisterCoverageExtension("clover", newJavaProject(), conf), is(true));
-    assertThat(repository.shouldRegisterCoverageExtension("phpunit", newJavaProject(), conf), is(true));
-    assertThat(repository.shouldRegisterCoverageExtension("other", newJavaProject(), conf), is(false));
-  }
-
-  @Test
-  public void shouldNotCheckCoverageExtensionsOnNonJavaProjects() {
-    Configuration conf = new PropertiesConfiguration();
-    conf.setProperty(AbstractCoverageExtension.PARAM_PLUGIN, "cobertura");
-    BatchPluginRepository repository = new BatchPluginRepository();
-
-    assertThat(repository.shouldRegisterCoverageExtension("groovy", newGroovyProject(), conf), is(true));
-    assertThat(repository.shouldRegisterCoverageExtension("groovy", newJavaProject(), conf), is(false));
-  }
-
-  private static Project newJavaProject() {
-    return new Project("foo").setLanguageKey(Java.KEY);
-  }
-
-  private static Project newGroovyProject() {
-    return new Project("foo").setLanguageKey("grvy");
-  }
-
-  public static class FakeBatchExtension implements BatchExtension {
-
-  }
-
-  public static class FakeServerExtension implements ServerExtension {
-
-  }
-}
diff --git a/sonar-batch/src/test/java/org/sonar/batch/RemoteClassLoaderTest.java b/sonar-batch/src/test/java/org/sonar/batch/RemoteClassLoaderTest.java
deleted file mode 100644 (file)
index f79d453..0000000
+++ /dev/null
@@ -1,43 +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.batch;
-
-import org.junit.Test;
-
-import java.net.URL;
-import java.util.Arrays;
-
-import static junit.framework.Assert.assertNotNull;
-import static junit.framework.Assert.assertNull;
-
-public class RemoteClassLoaderTest {
-
-  @Test
-  public void testClassLoader() {
-    /* foo.jar has just one file /foo/foo.txt */
-    assertNull(getClass().getClassLoader().getResource("foo/foo.txt"));
-
-    URL url = getClass().getResource("/org/sonar/batch/RemoteClassLoaderTest/foo.jar");
-    RemoteClassLoader classloader = new RemoteClassLoader(Arrays.asList(url), null);
-    assertNotNull(classloader.getClassLoader());
-    assertNotNull(classloader.getClassLoader().getResource("foo/foo.txt"));
-    
-  }
-}
diff --git a/sonar-batch/src/test/java/org/sonar/batch/bootstrap/BatchPluginRepositoryTest.java b/sonar-batch/src/test/java/org/sonar/batch/bootstrap/BatchPluginRepositoryTest.java
new file mode 100644 (file)
index 0000000..7d5abca
--- /dev/null
@@ -0,0 +1,100 @@
+/*
+ * 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.bootstrap;
+
+import static org.hamcrest.core.Is.is;
+import static org.junit.Assert.assertThat;
+
+import org.apache.commons.configuration.Configuration;
+import org.apache.commons.configuration.PropertiesConfiguration;
+import org.junit.Test;
+import org.picocontainer.MutablePicoContainer;
+import org.sonar.api.BatchExtension;
+import org.sonar.api.ServerExtension;
+import org.sonar.api.batch.AbstractCoverageExtension;
+import org.sonar.api.resources.Java;
+import org.sonar.api.resources.Project;
+import org.sonar.api.utils.IocContainer;
+import org.sonar.batch.bootstrap.BatchPluginRepository;
+
+public class BatchPluginRepositoryTest {
+
+  @Test
+  public void shouldRegisterBatchExtension() {
+    MutablePicoContainer pico = IocContainer.buildPicoContainer();
+    pico.addComponent(new PropertiesConfiguration());
+    BatchPluginRepository repository = new BatchPluginRepository();
+
+    // check classes
+    assertThat(repository.shouldRegisterExtension(pico, "foo", FakeBatchExtension.class), is(true));
+    assertThat(repository.shouldRegisterExtension(pico, "foo", FakeServerExtension.class), is(false));
+    assertThat(repository.shouldRegisterExtension(pico, "foo", String.class), is(false));
+
+    // check objects
+    assertThat(repository.shouldRegisterExtension(pico, "foo", new FakeBatchExtension()), is(true));
+    assertThat(repository.shouldRegisterExtension(pico, "foo", new FakeServerExtension()), is(false));
+    assertThat(repository.shouldRegisterExtension(pico, "foo", "bar"), is(false));
+  }
+
+  @Test
+  public void shouldRegisterOnlyCoberturaExtensionByDefault() {
+    BatchPluginRepository repository = new BatchPluginRepository();
+    PropertiesConfiguration conf = new PropertiesConfiguration();
+    assertThat(repository.shouldRegisterCoverageExtension("cobertura", newJavaProject(), conf), is(true));
+    assertThat(repository.shouldRegisterCoverageExtension("clover", newJavaProject(), conf), is(false));
+  }
+
+  @Test
+  public void shouldRegisterCustomCoverageExtension() {
+    Configuration conf = new PropertiesConfiguration();
+    conf.setProperty(AbstractCoverageExtension.PARAM_PLUGIN, "clover,phpunit");
+    BatchPluginRepository repository = new BatchPluginRepository();
+    assertThat(repository.shouldRegisterCoverageExtension("cobertura", newJavaProject(), conf), is(false));
+    assertThat(repository.shouldRegisterCoverageExtension("clover", newJavaProject(), conf), is(true));
+    assertThat(repository.shouldRegisterCoverageExtension("phpunit", newJavaProject(), conf), is(true));
+    assertThat(repository.shouldRegisterCoverageExtension("other", newJavaProject(), conf), is(false));
+  }
+
+  @Test
+  public void shouldNotCheckCoverageExtensionsOnNonJavaProjects() {
+    Configuration conf = new PropertiesConfiguration();
+    conf.setProperty(AbstractCoverageExtension.PARAM_PLUGIN, "cobertura");
+    BatchPluginRepository repository = new BatchPluginRepository();
+
+    assertThat(repository.shouldRegisterCoverageExtension("groovy", newGroovyProject(), conf), is(true));
+    assertThat(repository.shouldRegisterCoverageExtension("groovy", newJavaProject(), conf), is(false));
+  }
+
+  private static Project newJavaProject() {
+    return new Project("foo").setLanguageKey(Java.KEY);
+  }
+
+  private static Project newGroovyProject() {
+    return new Project("foo").setLanguageKey("grvy");
+  }
+
+  public static class FakeBatchExtension implements BatchExtension {
+
+  }
+
+  public static class FakeServerExtension implements ServerExtension {
+
+  }
+}
diff --git a/sonar-batch/src/test/java/org/sonar/batch/bootstrap/BootstrapClassLoaderTest.java b/sonar-batch/src/test/java/org/sonar/batch/bootstrap/BootstrapClassLoaderTest.java
new file mode 100644 (file)
index 0000000..30ab990
--- /dev/null
@@ -0,0 +1,45 @@
+/*
+ * 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.bootstrap;
+
+import org.junit.Test;
+
+import java.io.File;
+import java.net.URISyntaxException;
+import java.net.URL;
+import java.util.Arrays;
+
+import static junit.framework.Assert.assertNotNull;
+import static junit.framework.Assert.assertNull;
+
+public class BootstrapClassLoaderTest {
+
+  @Test
+  public void testClassLoader() throws URISyntaxException {
+    /* foo.jar has just one file /foo/foo.txt */
+    assertNull(getClass().getClassLoader().getResource("foo/foo.txt"));
+
+    URL url = getClass().getResource("/org/sonar/batch/bootstrap/BootstrapClassLoaderTest/foo.jar");
+    BootstrapClassLoader classloader = new BootstrapClassLoader(new File(url.toURI()));
+    assertNotNull(classloader.getClassLoader());
+    assertNotNull(classloader.getClassLoader().getResource("foo/foo.txt"));
+    
+  }
+}
diff --git a/sonar-batch/src/test/java/org/sonar/batch/bootstrap/ExtensionDownloaderTest.java b/sonar-batch/src/test/java/org/sonar/batch/bootstrap/ExtensionDownloaderTest.java
new file mode 100644 (file)
index 0000000..3094860
--- /dev/null
@@ -0,0 +1,68 @@
+/*
+ * 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.bootstrap;
+
+import org.junit.Test;
+import org.sonar.api.utils.HttpDownloader;
+import org.sonar.batch.ServerMetadata;
+import org.sonar.core.plugin.JpaPlugin;
+import org.sonar.core.plugin.JpaPluginFile;
+
+import java.io.File;
+import java.io.IOException;
+import java.net.URI;
+import java.net.URISyntaxException;
+
+import static org.junit.Assert.assertNotNull;
+import static org.mockito.Mockito.*;
+
+public class ExtensionDownloaderTest {
+
+  @Test
+  public void shouldDownloadJdbcDriver() throws IOException, URISyntaxException {
+    ServerMetadata server = mock(ServerMetadata.class);
+    when(server.getURL()).thenReturn("http://sonar:8000");
+
+    HttpDownloader httpDownloader = mock(HttpDownloader.class);
+    TempDirectories workingDirectories = new TempDirectories();
+
+    ExtensionDownloader downloader = new ExtensionDownloader(httpDownloader, workingDirectories, server);
+    File jdbcDriver = downloader.downloadJdbcDriver();
+
+    assertNotNull(jdbcDriver);
+    verify(httpDownloader).download(new URI("http://sonar:8000/deploy/jdbc-driver.jar"), jdbcDriver);
+  }
+
+  @Test
+  public void shouldDownloadExtension() throws IOException, URISyntaxException {
+    ServerMetadata server = mock(ServerMetadata.class);
+    when(server.getURL()).thenReturn("http://sonar:8000");
+
+    HttpDownloader httpDownloader = mock(HttpDownloader.class);
+    TempDirectories workingDirectories = new TempDirectories();
+
+    ExtensionDownloader downloader = new ExtensionDownloader(httpDownloader, workingDirectories, server);
+    JpaPluginFile extension = new JpaPluginFile(new JpaPlugin("findbugs"), "bcel.jar");
+    File bcel = downloader.downloadExtension(extension);
+
+    assertNotNull(bcel);
+    verify(httpDownloader).download(new URI("http://sonar:8000/deploy/plugins/findbugs/bcel.jar"), bcel);
+  }
+}
diff --git a/sonar-batch/src/test/java/org/sonar/batch/bootstrap/TempDirectoriesTest.java b/sonar-batch/src/test/java/org/sonar/batch/bootstrap/TempDirectoriesTest.java
new file mode 100644 (file)
index 0000000..0812899
--- /dev/null
@@ -0,0 +1,83 @@
+/*
+ * 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.bootstrap;
+
+import org.junit.After;
+import org.junit.Before;
+import org.junit.Test;
+
+import java.io.File;
+import java.io.IOException;
+
+import static org.hamcrest.CoreMatchers.is;
+import static org.junit.Assert.assertNotNull;
+import static org.junit.Assert.assertThat;
+
+public class TempDirectoriesTest {
+
+  private TempDirectories tempDirectories;
+
+  @Before
+  public void before() throws IOException {
+    tempDirectories = new TempDirectories();
+  }
+
+  @After
+  public void after() throws IOException {
+    if (tempDirectories != null) {
+      tempDirectories.stop();
+    }
+  }
+
+  @Test
+  public void shouldCreateRoot() throws IOException {
+    assertNotNull(tempDirectories.getRoot());
+    assertThat(tempDirectories.getRoot().exists(), is(true));
+    assertThat(tempDirectories.getRoot().isDirectory(), is(true));
+  }
+
+  @Test
+  public void shouldCreateDirectory() throws IOException {
+    File findbugsDir = tempDirectories.getDir("findbugs");
+    assertNotNull(findbugsDir);
+    assertThat(findbugsDir.exists(), is(true));
+    assertThat(findbugsDir.getParentFile(), is(tempDirectories.getRoot()));
+    assertThat(findbugsDir.getName(), is("findbugs"));
+  }
+
+  @Test
+  public void shouldStopAndDeleteDirectory() throws IOException {
+    File root = tempDirectories.getRoot();
+    File findbugsDir = tempDirectories.getDir("findbugs");
+    assertThat(findbugsDir.exists(), is(true));
+
+    tempDirectories.stop();
+    
+    assertThat(root.exists(), is(false));
+    assertThat(findbugsDir.exists(), is(false));
+  }
+
+  @Test
+  public void shouldCreateDirectoryWhenGettingFile() {
+    File file = tempDirectories.getFile("findbugs", "bcel.jar");
+    assertNotNull(file);
+    assertThat(file.getParentFile().getName(), is("findbugs"));
+  }
+}
diff --git a/sonar-batch/src/test/resources/org/sonar/batch/RemoteClassLoaderTest/foo.jar b/sonar-batch/src/test/resources/org/sonar/batch/RemoteClassLoaderTest/foo.jar
deleted file mode 100644 (file)
index c2bde4e..0000000
Binary files a/sonar-batch/src/test/resources/org/sonar/batch/RemoteClassLoaderTest/foo.jar and /dev/null differ
diff --git a/sonar-batch/src/test/resources/org/sonar/batch/bootstrap/BootstrapClassLoaderTest/foo.jar b/sonar-batch/src/test/resources/org/sonar/batch/bootstrap/BootstrapClassLoaderTest/foo.jar
new file mode 100644 (file)
index 0000000..c2bde4e
Binary files /dev/null and b/sonar-batch/src/test/resources/org/sonar/batch/bootstrap/BootstrapClassLoaderTest/foo.jar differ