aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorJenkins CI <ci@sonarsource.com>2015-10-14 08:01:18 +0200
committerJenkins CI <ci@sonarsource.com>2015-10-14 08:01:18 +0200
commite51e9c9eb0145ea5e9d40453554c456585b79936 (patch)
tree8b1adf27c56a12e762cdd304f09311cc7fff77bb
parent8350b39ed0563e9beb354fe27524c95ea4692b67 (diff)
parent3afe7a9001453a7106c488a1429e3bff91c8545f (diff)
downloadsonarqube-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"
-rw-r--r--pom.xml28
-rw-r--r--server/sonar-process/src/main/java/org/sonar/process/NetworkUtils.java63
-rw-r--r--server/sonar-process/src/test/java/org/sonar/process/NetworkUtilsTest.java52
-rw-r--r--server/sonar-server/src/main/resources/org/sonar/server/dashboard/widget/timeline.html.erb2
-rw-r--r--sonar-application/pom.xml4
-rw-r--r--sonar-core/src/main/java/org/sonar/core/platform/PluginInfo.java9
-rw-r--r--sonar-core/src/test/java/org/sonar/core/platform/PluginInfoTest.java19
7 files changed, 129 insertions, 48 deletions
diff --git a/pom.xml b/pom.xml
index a940436810d..3a00ac5d9e0 100644
--- a/pom.xml
+++ b/pom.xml
@@ -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) {