aboutsummaryrefslogtreecommitdiffstats
path: root/sonar-db
diff options
context:
space:
mode:
authorTeryk Bellahsene <teryk.bellahsene@sonarsource.com>2016-05-12 14:22:56 +0200
committerTeryk Bellahsene <teryk.bellahsene@sonarsource.com>2016-05-13 09:55:29 +0200
commit618a3af602f872b99aaaec3ef7b21510e36b45b0 (patch)
tree9d2688018fa8bb949dfcebf343768e8f20f6713b /sonar-db
parent9ac7dcbbf26081d499a2dbd40549ffeff159f93d (diff)
downloadsonarqube-618a3af602f872b99aaaec3ef7b21510e36b45b0.tar.gz
sonarqube-618a3af602f872b99aaaec3ef7b21510e36b45b0.zip
SONAR-7545 functional error when updating a project key
- when updating a project key and a sub-component has a key longer than 400 characters - when a component has a name longer than 2000 characters - when a component has a key longer than 400 characters
Diffstat (limited to 'sonar-db')
-rw-r--r--sonar-db/src/main/java/org/sonar/db/component/ComponentDto.java7
-rw-r--r--sonar-db/src/main/java/org/sonar/db/component/ComponentValidator.java55
-rw-r--r--sonar-db/src/main/java/org/sonar/db/component/ResourceDto.java7
-rw-r--r--sonar-db/src/main/java/org/sonar/db/component/ResourceKeyUpdaterDao.java12
-rw-r--r--sonar-db/src/test/java/org/sonar/db/component/ComponentValidatorTest.java87
-rw-r--r--sonar-db/src/test/java/org/sonar/db/component/ResourceKeyUpdaterDaoTest.java57
6 files changed, 195 insertions, 30 deletions
diff --git a/sonar-db/src/main/java/org/sonar/db/component/ComponentDto.java b/sonar-db/src/main/java/org/sonar/db/component/ComponentDto.java
index 3f18a8f07b2..d1ba2e6b605 100644
--- a/sonar-db/src/main/java/org/sonar/db/component/ComponentDto.java
+++ b/sonar-db/src/main/java/org/sonar/db/component/ComponentDto.java
@@ -26,6 +26,9 @@ import org.apache.commons.lang.builder.ToStringBuilder;
import org.sonar.api.component.Component;
import org.sonar.api.resources.Scopes;
+import static org.sonar.db.component.ComponentValidator.checkComponentKey;
+import static org.sonar.db.component.ComponentValidator.checkComponentName;
+
public class ComponentDto implements Component {
public static final String MODULE_UUID_PATH_SEP = ".";
@@ -160,7 +163,7 @@ public class ComponentDto implements Component {
}
public ComponentDto setName(String name) {
- this.name = name;
+ this.name = checkComponentName(name);
return this;
}
@@ -258,7 +261,7 @@ public class ComponentDto implements Component {
}
public ComponentDto setKey(String key) {
- this.kee = key;
+ this.kee = checkComponentKey(key);
return this;
}
diff --git a/sonar-db/src/main/java/org/sonar/db/component/ComponentValidator.java b/sonar-db/src/main/java/org/sonar/db/component/ComponentValidator.java
new file mode 100644
index 00000000000..eb628cdf6a0
--- /dev/null
+++ b/sonar-db/src/main/java/org/sonar/db/component/ComponentValidator.java
@@ -0,0 +1,55 @@
+/*
+ * SonarQube
+ * Copyright (C) 2009-2016 SonarSource SA
+ * mailto:contact AT sonarsource DOT com
+ *
+ * This program 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.
+ *
+ * This program 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 this program; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ */
+
+package org.sonar.db.component;
+
+import static com.google.common.base.Preconditions.checkArgument;
+
+public class ComponentValidator {
+ private static final int MAX_NAME_LENGTH = 2000;
+ private static final int MAX_KEY_LENGTH = 400;
+ private static final int MAX_QUALIFIER_LENGTH = 10;
+
+ private ComponentValidator() {
+ // prevent instantiation
+ }
+
+ public static String checkComponentName(String name) {
+ checkArgument(name.length() <= MAX_NAME_LENGTH, "Component name length (%s) is longer than the maximum authorized (%s). '%s' was provided.",
+ name.length(), MAX_NAME_LENGTH, name);
+ return name;
+ }
+
+ public static String checkComponentKey(String key) {
+ checkArgument(isComponentKeyValid(key), "Component key length (%s) is longer than the maximum authorized (%s). '%s' was provided.",
+ key.length(), MAX_KEY_LENGTH, key);
+ return key;
+ }
+
+ public static boolean isComponentKeyValid(String key) {
+ return key.length() <= MAX_KEY_LENGTH;
+ }
+
+ public static String checkComponentQualifier(String qualifier) {
+ checkArgument(qualifier.length() <= MAX_QUALIFIER_LENGTH, "Component qualifier length (%s) is longer than the maximum authorized (%s). '%s' was provided.",
+ qualifier.length(), MAX_QUALIFIER_LENGTH, qualifier);
+ return qualifier;
+ }
+}
diff --git a/sonar-db/src/main/java/org/sonar/db/component/ResourceDto.java b/sonar-db/src/main/java/org/sonar/db/component/ResourceDto.java
index 22b14fd2fac..84480314295 100644
--- a/sonar-db/src/main/java/org/sonar/db/component/ResourceDto.java
+++ b/sonar-db/src/main/java/org/sonar/db/component/ResourceDto.java
@@ -21,6 +21,9 @@ package org.sonar.db.component;
import java.util.Date;
+import static org.sonar.db.component.ComponentValidator.checkComponentKey;
+import static org.sonar.db.component.ComponentValidator.checkComponentName;
+
public class ResourceDto {
private Long id;
@@ -94,7 +97,7 @@ public class ResourceDto {
}
public ResourceDto setName(String name) {
- this.name = name;
+ this.name = checkComponentName(name);
return this;
}
@@ -103,7 +106,7 @@ public class ResourceDto {
}
public ResourceDto setKey(String s) {
- this.key = s;
+ this.key = checkComponentKey(s);
return this;
}
diff --git a/sonar-db/src/main/java/org/sonar/db/component/ResourceKeyUpdaterDao.java b/sonar-db/src/main/java/org/sonar/db/component/ResourceKeyUpdaterDao.java
index 7572ddee73c..a5b4f7db04d 100644
--- a/sonar-db/src/main/java/org/sonar/db/component/ResourceKeyUpdaterDao.java
+++ b/sonar-db/src/main/java/org/sonar/db/component/ResourceKeyUpdaterDao.java
@@ -123,11 +123,13 @@ public class ResourceKeyUpdaterDao implements Dao {
private static void runBatchUpdateForAllResources(Collection<ResourceDto> resources, String oldKey, String newKey, ResourceKeyUpdaterMapper mapper) {
for (ResourceDto resource : resources) {
- String resourceKey = resource.getKey();
- resource.setKey(newKey + resourceKey.substring(oldKey.length(), resourceKey.length()));
- String resourceDeprecatedKey = resource.getDeprecatedKey();
- if (StringUtils.isNotBlank(resourceDeprecatedKey)) {
- resource.setDeprecatedKey(newKey + resourceDeprecatedKey.substring(oldKey.length(), resourceDeprecatedKey.length()));
+ String oldResourceKey = resource.getKey();
+ String newResourceKey = newKey + oldResourceKey.substring(oldKey.length(), oldResourceKey.length());
+ resource.setKey(newResourceKey);
+ String oldResourceDeprecatedKey = resource.getDeprecatedKey();
+ if (StringUtils.isNotBlank(oldResourceDeprecatedKey)) {
+ String newResourceDeprecatedKey = newKey + oldResourceDeprecatedKey.substring(oldKey.length(), oldResourceDeprecatedKey.length());
+ resource.setDeprecatedKey(newResourceDeprecatedKey);
}
mapper.update(resource);
}
diff --git a/sonar-db/src/test/java/org/sonar/db/component/ComponentValidatorTest.java b/sonar-db/src/test/java/org/sonar/db/component/ComponentValidatorTest.java
new file mode 100644
index 00000000000..8e15e278edb
--- /dev/null
+++ b/sonar-db/src/test/java/org/sonar/db/component/ComponentValidatorTest.java
@@ -0,0 +1,87 @@
+/*
+ * SonarQube
+ * Copyright (C) 2009-2016 SonarSource SA
+ * mailto:contact AT sonarsource DOT com
+ *
+ * This program 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.
+ *
+ * This program 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 this program; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ */
+
+package org.sonar.db.component;
+
+import org.junit.Rule;
+import org.junit.Test;
+import org.junit.rules.ExpectedException;
+
+import static com.google.common.base.Strings.repeat;
+import static org.assertj.core.api.Assertions.assertThat;
+import static org.sonar.test.TestUtils.hasOnlyPrivateConstructors;
+
+public class ComponentValidatorTest {
+ @Rule
+ public ExpectedException expectedException = ExpectedException.none();
+
+ @Test
+ public void check_name() {
+ String name = repeat("a", 2000);
+
+ assertThat(ComponentValidator.checkComponentName(name)).isEqualTo(name);
+ }
+
+ @Test
+ public void fail_when_name_longer_than_2000_characters() {
+ expectedException.expect(IllegalArgumentException.class);
+ expectedException.expectMessage("Component name length");
+
+ ComponentValidator.checkComponentName(repeat("a", 2000 + 1));
+ }
+
+ @Test
+ public void check_key() {
+ String key = repeat("a", 400);
+
+ assertThat(ComponentValidator.isComponentKeyValid(key)).isTrue();
+ assertThat(ComponentValidator.checkComponentKey(key)).isEqualTo(key);
+ }
+
+ @Test
+ public void fail_when_key_longer_than_400_characters() {
+ expectedException.expect(IllegalArgumentException.class);
+ expectedException.expectMessage("Component key length");
+ String key = repeat("a", 400 + 1);
+
+ assertThat(ComponentValidator.isComponentKeyValid(key)).isFalse();
+ ComponentValidator.checkComponentKey(key);
+ }
+
+ @Test
+ public void check_qualifier() {
+ String qualifier = repeat("a", 10);
+
+ assertThat(ComponentValidator.checkComponentQualifier(qualifier)).isEqualTo(qualifier);
+ }
+
+ @Test
+ public void fail_when_qualifier_is_longer_than_10_characters() {
+ expectedException.expect(IllegalArgumentException.class);
+ expectedException.expectMessage("Component qualifier length");
+
+ ComponentValidator.checkComponentQualifier(repeat("a", 10 + 1));
+ }
+
+ @Test
+ public void private_constructor() {
+ assertThat(hasOnlyPrivateConstructors(ComponentValidator.class)).isTrue();
+ }
+}
diff --git a/sonar-db/src/test/java/org/sonar/db/component/ResourceKeyUpdaterDaoTest.java b/sonar-db/src/test/java/org/sonar/db/component/ResourceKeyUpdaterDaoTest.java
index c71fd65f1b4..c44ee35e9e4 100644
--- a/sonar-db/src/test/java/org/sonar/db/component/ResourceKeyUpdaterDaoTest.java
+++ b/sonar-db/src/test/java/org/sonar/db/component/ResourceKeyUpdaterDaoTest.java
@@ -19,6 +19,7 @@
*/
package org.sonar.db.component;
+import com.google.common.base.Strings;
import java.util.Map;
import org.junit.Rule;
import org.junit.Test;
@@ -27,7 +28,8 @@ import org.sonar.api.utils.System2;
import org.sonar.db.DbTester;
import static org.assertj.core.api.Assertions.assertThat;
-
+import static org.sonar.db.component.ComponentTesting.newFileDto;
+import static org.sonar.db.component.ComponentTesting.newProjectDto;
public class ResourceKeyUpdaterDaoTest {
@@ -35,71 +37,84 @@ public class ResourceKeyUpdaterDaoTest {
public ExpectedException thrown = ExpectedException.none();
@Rule
- public DbTester dbTester = DbTester.create(System2.INSTANCE);
+ public DbTester db = DbTester.create(System2.INSTANCE);
+ ComponentDbTester componentDb = new ComponentDbTester(db);
- ResourceKeyUpdaterDao dao = dbTester.getDbClient().resourceKeyUpdaterDao();
+ ResourceKeyUpdaterDao underTest = db.getDbClient().resourceKeyUpdaterDao();
@Test
public void shouldUpdateKey() {
- dbTester.prepareDbUnit(getClass(), "shared.xml");
+ db.prepareDbUnit(getClass(), "shared.xml");
- dao.updateKey(2, "struts:core");
+ underTest.updateKey(2, "struts:core");
- dbTester.assertDbUnit(getClass(), "shouldUpdateKey-result.xml", "projects");
+ db.assertDbUnit(getClass(), "shouldUpdateKey-result.xml", "projects");
}
@Test
public void shouldNotUpdateKey() {
- dbTester.prepareDbUnit(getClass(), "shared.xml");
+ db.prepareDbUnit(getClass(), "shared.xml");
thrown.expect(IllegalStateException.class);
thrown.expectMessage("Impossible to update key: a resource with \"org.struts:struts-ui\" key already exists.");
- dao.updateKey(2, "org.struts:struts-ui");
+ underTest.updateKey(2, "org.struts:struts-ui");
}
@Test
public void shouldBulkUpdateKey() {
- dbTester.prepareDbUnit(getClass(), "shared.xml");
+ db.prepareDbUnit(getClass(), "shared.xml");
- dao.bulkUpdateKey(1, "org.struts", "org.apache.struts");
+ underTest.bulkUpdateKey(1, "org.struts", "org.apache.struts");
- dbTester.assertDbUnit(getClass(), "shouldBulkUpdateKey-result.xml", "projects");
+ db.assertDbUnit(getClass(), "shouldBulkUpdateKey-result.xml", "projects");
}
@Test
public void shouldBulkUpdateKeyOnOnlyOneSubmodule() {
- dbTester.prepareDbUnit(getClass(), "shared.xml");
+ db.prepareDbUnit(getClass(), "shared.xml");
- dao.bulkUpdateKey(1, "struts-ui", "struts-web");
+ underTest.bulkUpdateKey(1, "struts-ui", "struts-web");
- dbTester.assertDbUnit(getClass(), "shouldBulkUpdateKeyOnOnlyOneSubmodule-result.xml", "projects");
+ db.assertDbUnit(getClass(), "shouldBulkUpdateKeyOnOnlyOneSubmodule-result.xml", "projects");
}
@Test
public void shouldFailBulkUpdateKeyIfKeyAlreadyExist() {
- dbTester.prepareDbUnit(getClass(), "shared.xml");
+ db.prepareDbUnit(getClass(), "shared.xml");
thrown.expect(IllegalStateException.class);
thrown.expectMessage("Impossible to update key: a resource with \"foo:struts-core\" key already exists.");
- dao.bulkUpdateKey(1, "org.struts", "foo");
+ underTest.bulkUpdateKey(1, "org.struts", "foo");
}
@Test
public void shouldNotUpdateAllSubmodules() {
- dbTester.prepareDbUnit(getClass(), "shouldNotUpdateAllSubmodules.xml");
+ db.prepareDbUnit(getClass(), "shouldNotUpdateAllSubmodules.xml");
+
+ underTest.bulkUpdateKey(1, "org.struts", "org.apache.struts");
- dao.bulkUpdateKey(1, "org.struts", "org.apache.struts");
+ db.assertDbUnit(getClass(), "shouldNotUpdateAllSubmodules-result.xml", "projects");
+ }
- dbTester.assertDbUnit(getClass(), "shouldNotUpdateAllSubmodules-result.xml", "projects");
+ @Test
+ public void fail_with_functional_exception_when_sub_component_key_is_longer_than_authorized() {
+ ComponentDto project = newProjectDto("project-uuid").setKey("old-project-key");
+ componentDb.insertComponent(project);
+ componentDb.insertComponent(newFileDto(project).setKey("old-project-key:file"));
+ String newLongProjectKey = Strings.repeat("a", 400);
+ thrown.expect(IllegalArgumentException.class);
+ thrown.expectMessage("Component key length (405) is longer than the maximum authorized (400). '" + newLongProjectKey + ":file' was provided.");
+
+ underTest.updateKey(project.getId(), newLongProjectKey);
}
@Test
public void shouldCheckModuleKeysBeforeRenaming() {
- dbTester.prepareDbUnit(getClass(), "shared.xml");
+ db.prepareDbUnit(getClass(), "shared.xml");
- Map<String, String> checkResults = dao.checkModuleKeysBeforeRenaming(1, "org.struts", "foo");
+ Map<String, String> checkResults = underTest.checkModuleKeysBeforeRenaming(1, "org.struts", "foo");
assertThat(checkResults.size()).isEqualTo(3);
assertThat(checkResults.get("org.struts:struts")).isEqualTo("foo:struts");
assertThat(checkResults.get("org.struts:struts-core")).isEqualTo("#duplicate_key#");