From 6b5035087075113699015583fd4d76b75bf36894 Mon Sep 17 00:00:00 2001 From: Evgeny Mandrikov Date: Wed, 19 Jan 2011 02:20:45 +0300 Subject: 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 --- sonar-batch-bootstrapper/pom.xml | 27 +++++ .../sonar/batch/bootstrapper/BatchDownloader.java | 134 +++++++++++++++++++++ .../batch/bootstrapper/BootstrapperIOUtils.java | 79 ++++++++++++ .../org/sonar/batch/bootstrapper/package-info.java | 24 ++++ .../batch/bootstrapper/BatchDownloaderTest.java | 54 +++++++++ 5 files changed, 318 insertions(+) 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 create mode 100644 sonar-batch-bootstrapper/src/main/java/org/sonar/batch/bootstrapper/package-info.java create mode 100644 sonar-batch-bootstrapper/src/test/java/org/sonar/batch/bootstrapper/BatchDownloaderTest.java (limited to 'sonar-batch-bootstrapper') 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-bootstrapper/src/main/java/org/sonar/batch/bootstrapper/package-info.java b/sonar-batch-bootstrapper/src/main/java/org/sonar/batch/bootstrapper/package-info.java new file mode 100644 index 00000000000..7c23a7aa9ec --- /dev/null +++ b/sonar-batch-bootstrapper/src/main/java/org/sonar/batch/bootstrapper/package-info.java @@ -0,0 +1,24 @@ +/* + * 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 + */ + +/** + * 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")); + } + +} -- cgit v1.2.3