diff options
author | Jenkins CI <ci@sonarsource.com> | 2015-10-14 08:01:18 +0200 |
---|---|---|
committer | Jenkins CI <ci@sonarsource.com> | 2015-10-14 08:01:18 +0200 |
commit | e51e9c9eb0145ea5e9d40453554c456585b79936 (patch) | |
tree | 8b1adf27c56a12e762cdd304f09311cc7fff77bb | |
parent | 8350b39ed0563e9beb354fe27524c95ea4692b67 (diff) | |
parent | 3afe7a9001453a7106c488a1429e3bff91c8545f (diff) | |
download | sonarqube-e51e9c9eb0145ea5e9d40453554c456585b79936.tar.gz sonarqube-e51e9c9eb0145ea5e9d40453554c456585b79936.zip |
Automatic merge from branch-5.1
* origin/branch-5.2:
Improve message when trying to install a non-plugin JAR
Fix enforcer rule about size of zip
Fix reliability of NetworkUtils#freePort()
Fix Maven warnings
SONAR-6219 Fix ruby warning "don't put space before argument parentheses"
7 files changed, 129 insertions, 48 deletions
@@ -418,7 +418,7 @@ <configuration> <archive> <manifestEntries> - <Version>${pom.version}</Version> + <Version>${project.version}</Version> <!-- ${buildNumber} is the Git revision. It's generated by the buildnumber-maven-plugin --> <Implementation-Build>${buildNumber}</Implementation-Build> <Build-Time>${timestamp}</Build-Time> @@ -586,47 +586,47 @@ <dependency> <groupId>${project.groupId}</groupId> <artifactId>sonar-markdown</artifactId> - <version>${pom.version}</version> + <version>${project.version}</version> </dependency> <dependency> <groupId>${project.groupId}</groupId> <artifactId>sonar-check-api</artifactId> - <version>${pom.version}</version> + <version>${project.version}</version> </dependency> <dependency> <groupId>${project.groupId}</groupId> <artifactId>sonar-colorizer</artifactId> - <version>${pom.version}</version> + <version>${project.version}</version> </dependency> <dependency> <groupId>${project.groupId}</groupId> <artifactId>sonar-core</artifactId> - <version>${pom.version}</version> + <version>${project.version}</version> </dependency> <dependency> <groupId>${project.groupId}</groupId> <artifactId>sonar-db</artifactId> - <version>${pom.version}</version> + <version>${project.version}</version> </dependency> <dependency> <groupId>${project.groupId}</groupId> <artifactId>sonar-batch-protocol</artifactId> - <version>${pom.version}</version> + <version>${project.version}</version> </dependency> <dependency> <groupId>${project.groupId}</groupId> <artifactId>sonar-ws</artifactId> - <version>${pom.version}</version> + <version>${project.version}</version> </dependency> <dependency> <groupId>${project.groupId}</groupId> <artifactId>sonar-duplications</artifactId> - <version>${pom.version}</version> + <version>${project.version}</version> </dependency> <dependency> <groupId>${project.groupId}</groupId> <artifactId>sonar-home</artifactId> - <version>${pom.version}</version> + <version>${project.version}</version> </dependency> <dependency> <groupId>org.codehaus.sonar</groupId> @@ -651,7 +651,7 @@ <dependency> <groupId>${project.groupId}</groupId> <artifactId>sonar-plugin-api</artifactId> - <version>${pom.version}</version> + <version>${project.version}</version> </dependency> <dependency> <groupId>org.codehaus.sonar</groupId> @@ -661,7 +661,7 @@ <dependency> <groupId>${project.groupId}</groupId> <artifactId>sonar-server</artifactId> - <version>${pom.version}</version> + <version>${project.version}</version> </dependency> <dependency> <groupId>org.codehaus.sonar</groupId> @@ -681,7 +681,7 @@ <dependency> <groupId>org.sonarsource.sonarqube</groupId> <artifactId>sonar-xoo-plugin</artifactId> - <version>${pom.version}</version> + <version>${project.version}</version> <scope>test</scope> </dependency> <dependency> @@ -699,7 +699,7 @@ <dependency> <groupId>org.sonarsource.sonarqube</groupId> <artifactId>sonar-testing-harness</artifactId> - <version>${pom.version}</version> + <version>${project.version}</version> </dependency> <dependency> <groupId>org.sonarsource.sonarqube</groupId> diff --git a/server/sonar-process/src/main/java/org/sonar/process/NetworkUtils.java b/server/sonar-process/src/main/java/org/sonar/process/NetworkUtils.java index 5dd5813917f..6e5e567ec9d 100644 --- a/server/sonar-process/src/main/java/org/sonar/process/NetworkUtils.java +++ b/server/sonar-process/src/main/java/org/sonar/process/NetworkUtils.java @@ -19,34 +19,59 @@ */ package org.sonar.process; -import org.apache.commons.io.IOUtils; - import java.io.IOException; import java.net.InetSocketAddress; import java.net.ServerSocket; +import org.apache.commons.io.IOUtils; +import org.apache.commons.lang.ArrayUtils; -public class NetworkUtils { +public final class NetworkUtils { + + private static final RandomPortFinder RANDOM_PORT_FINDER = new RandomPortFinder(); private NetworkUtils() { - // only static stuff + // only statics } - /** - * Get an unused port - */ public static int freePort() { - ServerSocket socket = null; - try { - socket = new ServerSocket(); - socket.setReuseAddress(true); - socket.bind(new InetSocketAddress("localhost", 0)); - return socket.getLocalPort(); - - } catch (IOException e) { - throw new IllegalStateException("Can not find a free network port", e); - - } finally { - IOUtils.closeQuietly(socket); + return RANDOM_PORT_FINDER.getNextAvailablePort(); + } + + static class RandomPortFinder { + private static final int MAX_TRY = 10; + // Firefox blocks some reserved ports : http://www-archive.mozilla.org/projects/netlib/PortBanning.html + private static final int[] BLOCKED_PORTS = {2049, 4045, 6000}; + + public int getNextAvailablePort() { + for (int i = 0; i < MAX_TRY; i++) { + try { + int port = getRandomUnusedPort(); + if (isValidPort(port)) { + return port; + } + } catch (Exception e) { + throw new IllegalStateException("Can't find an open network port", e); + } + } + + throw new IllegalStateException("Can't find an open network port"); + } + + public int getRandomUnusedPort() throws IOException { + ServerSocket socket = null; + try { + socket = new ServerSocket(); + socket.bind(new InetSocketAddress("localhost", 0)); + return socket.getLocalPort(); + } catch (IOException e) { + throw new IllegalStateException("Can not find a free network port", e); + } finally { + IOUtils.closeQuietly(socket); + } + } + + public static boolean isValidPort(int port) { + return port > 1023 && !ArrayUtils.contains(BLOCKED_PORTS, port); } } } diff --git a/server/sonar-process/src/test/java/org/sonar/process/NetworkUtilsTest.java b/server/sonar-process/src/test/java/org/sonar/process/NetworkUtilsTest.java index e5723aa99cc..38cc3f2c6ae 100644 --- a/server/sonar-process/src/test/java/org/sonar/process/NetworkUtilsTest.java +++ b/server/sonar-process/src/test/java/org/sonar/process/NetworkUtilsTest.java @@ -19,29 +19,61 @@ */ package org.sonar.process; +import java.io.IOException; import org.junit.Test; -import org.sonar.test.TestUtils; +import org.sonar.process.NetworkUtils.RandomPortFinder; import static org.assertj.core.api.Assertions.assertThat; +import static org.mockito.Mockito.doReturn; +import static org.mockito.Mockito.doThrow; +import static org.mockito.Mockito.spy; public class NetworkUtilsTest { @Test - public void find_free_port() { - int port = NetworkUtils.freePort(); - assertThat(port).isGreaterThan(0); + public void shouldGetAvailablePortWithoutLockingHost() { + for (int i = 0; i < 1000; i++) { + /* + * The Well Known Ports are those from 0 through 1023. + * DCCP Well Known ports SHOULD NOT be used without IANA registration. + */ + assertThat(NetworkUtils.freePort()).isGreaterThan(1023); + } } @Test - public void find_multiple_free_port() { - int port1 = NetworkUtils.freePort(); - int port2 = NetworkUtils.freePort(); + public void shouldGetRandomPort() { + assertThat(NetworkUtils.freePort()).isNotEqualTo(NetworkUtils.freePort()); + } - assertThat(port1).isNotSameAs(port2); + @Test + public void shouldNotBeValidPorts() { + assertThat(RandomPortFinder.isValidPort(0)).isFalse();// <=1023 + assertThat(RandomPortFinder.isValidPort(50)).isFalse();// <=1023 + assertThat(RandomPortFinder.isValidPort(1023)).isFalse();// <=1023 + assertThat(RandomPortFinder.isValidPort(2049)).isFalse();// NFS + assertThat(RandomPortFinder.isValidPort(4045)).isFalse();// lockd } @Test - public void private_constructor() { - assertThat(TestUtils.hasOnlyPrivateConstructors(NetworkUtils.class)).isTrue(); + public void shouldBeValidPorts() { + assertThat(RandomPortFinder.isValidPort(1059)).isTrue(); + } + + @Test(expected = IllegalStateException.class) + public void shouldFailWhenNoValidPortIsAvailable() throws IOException { + RandomPortFinder randomPortFinder = spy(new RandomPortFinder()); + doReturn(0).when(randomPortFinder).getRandomUnusedPort(); + + randomPortFinder.getNextAvailablePort(); } + + @Test(expected = IllegalStateException.class) + public void shouldFailWhenItsNotPossibleToOpenASocket() throws IOException { + RandomPortFinder randomPortFinder = spy(new RandomPortFinder()); + doThrow(new IOException("Not possible")).when(randomPortFinder).getRandomUnusedPort(); + + randomPortFinder.getNextAvailablePort(); + } + } diff --git a/server/sonar-server/src/main/resources/org/sonar/server/dashboard/widget/timeline.html.erb b/server/sonar-server/src/main/resources/org/sonar/server/dashboard/widget/timeline.html.erb index 6ce83d7e090..2fa6a7a0af0 100644 --- a/server/sonar-server/src/main/resources/org/sonar/server/dashboard/widget/timeline.html.erb +++ b/server/sonar-server/src/main/resources/org/sonar/server/dashboard/widget/timeline.html.erb @@ -49,7 +49,7 @@ if previous_snapshot_id != sid if metric_count_per_snapshot_id[previous_snapshot_id] != total_number_of_metrics metric_map.keys.each do |metric_id| - unless metric_previous_snapshot_id.include? (metric_id) + unless metric_previous_snapshot_id.include?(metric_id) metric_data_map[metric_id] << {:date => previous_created_at, :value => 0.00, :sid => previous_snapshot_id} if metric_count_per_snapshot_id[previous_snapshot_id] metric_count_per_snapshot_id[previous_snapshot_id] += 1 diff --git a/sonar-application/pom.xml b/sonar-application/pom.xml index 9435b2310ae..373c924c2c3 100644 --- a/sonar-application/pom.xml +++ b/sonar-application/pom.xml @@ -220,8 +220,8 @@ <configuration> <rules> <requireFilesSize> - <minsize>84000000</minsize> - <maxsize>880000000</maxsize> + <minsize>100000000</minsize> + <maxsize>115000000</maxsize> <files> <file>${project.build.directory}/sonarqube-${project.version}.zip</file> </files> diff --git a/sonar-core/src/main/java/org/sonar/core/platform/PluginInfo.java b/sonar-core/src/main/java/org/sonar/core/platform/PluginInfo.java index 5d2759332eb..3ae4dc4543c 100644 --- a/sonar-core/src/main/java/org/sonar/core/platform/PluginInfo.java +++ b/sonar-core/src/main/java/org/sonar/core/platform/PluginInfo.java @@ -27,6 +27,7 @@ import com.google.common.base.Preconditions; import com.google.common.collect.ComparisonChain; import com.google.common.collect.Ordering; import java.io.File; +import java.io.IOException; import java.util.HashSet; import java.util.Set; import java.util.regex.Pattern; @@ -34,6 +35,7 @@ import javax.annotation.CheckForNull; import javax.annotation.Nonnull; import javax.annotation.Nullable; import org.apache.commons.lang.StringUtils; +import org.sonar.api.utils.MessageException; import org.sonar.api.utils.log.Loggers; import org.sonar.updatecenter.common.PluginManifest; import org.sonar.updatecenter.common.Version; @@ -137,7 +139,7 @@ public class PluginInfo implements Comparable<PluginInfo> { private final Set<RequiredPlugin> requiredPlugins = new HashSet<>(); public PluginInfo(String key) { - Preconditions.checkNotNull(key); + Preconditions.checkNotNull(key, "Plugin key is missing from manifest"); this.key = key; this.name = key; } @@ -364,13 +366,16 @@ public class PluginInfo implements Comparable<PluginInfo> { PluginManifest manifest = new PluginManifest(jarFile); return create(jarFile, manifest); - } catch (Exception e) { + } catch (IOException e) { throw new IllegalStateException("Fail to extract plugin metadata from file: " + jarFile, e); } } @VisibleForTesting static PluginInfo create(File jarFile, PluginManifest manifest) { + if (StringUtils.isBlank(manifest.getKey())) { + throw MessageException.of(String.format("File is not a plugin. Please delete it and restart: %s", jarFile.getAbsolutePath())); + } PluginInfo info = new PluginInfo(manifest.getKey()); info.setJarFile(jarFile); diff --git a/sonar-core/src/test/java/org/sonar/core/platform/PluginInfoTest.java b/sonar-core/src/test/java/org/sonar/core/platform/PluginInfoTest.java index 35893ede34e..1472639b0c6 100644 --- a/sonar-core/src/test/java/org/sonar/core/platform/PluginInfoTest.java +++ b/sonar-core/src/test/java/org/sonar/core/platform/PluginInfoTest.java @@ -28,7 +28,10 @@ import org.apache.commons.io.FileUtils; import org.assertj.core.api.Assertions; import org.junit.Rule; import org.junit.Test; +import org.junit.rules.ExpectedException; import org.junit.rules.TemporaryFolder; +import org.sonar.api.utils.MessageException; +import org.sonar.api.utils.ZipUtils; import org.sonar.updatecenter.common.PluginManifest; import org.sonar.updatecenter.common.Version; @@ -41,6 +44,9 @@ public class PluginInfoTest { @Rule public TemporaryFolder temp = new TemporaryFolder(); + @Rule + public ExpectedException expectedException = ExpectedException.none(); + @Test public void test_RequiredPlugin() throws Exception { PluginInfo.RequiredPlugin plugin = PluginInfo.RequiredPlugin.parse("java:1.1"); @@ -212,7 +218,20 @@ public class PluginInfoTest { public void l10n_plugins_should_not_extend_english_plugin() { PluginInfo pluginInfo = new PluginInfo("l10nfr").setBasePlugin("l10nen"); assertThat(pluginInfo.getBasePlugin()).isNull(); + } + + @Test + public void fail_when_jar_is_not_a_plugin() throws IOException { + // this JAR has a manifest but is not a plugin + File jarRootDir = temp.newFolder(); + FileUtils.write(new File(jarRootDir, "META-INF/MANIFEST.MF"), "Build-Jdk: 1.6.0_15"); + File jar = temp.newFile(); + ZipUtils.zipDir(jarRootDir, jar); + + expectedException.expect(MessageException.class); + expectedException.expectMessage("File is not a plugin. Please delete it and restart: " + jar.getAbsolutePath()); + PluginInfo.create(jar); } PluginInfo withMinSqVersion(@Nullable String version) { |