- 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
import org.sonar.api.resources.Qualifiers;
import static com.google.common.base.Preconditions.checkArgument;
+import static org.sonar.db.component.ComponentValidator.checkComponentKey;
+import static org.sonar.db.component.ComponentValidator.checkComponentName;
+import static org.sonar.db.component.ComponentValidator.checkComponentQualifier;
public class NewComponent {
- private static final int MAX_KEY_LENGHT = 400;
- private static final int MAX_NAME_LENGTH = 2000;
- private static final int MAX_QUALIFIER_LENGTH = 10;
private String key;
private String branch;
private String qualifier;
}
public NewComponent setQualifier(@Nullable String qualifier) {
- if (qualifier != null) {
- checkArgument(qualifier.length() <= MAX_QUALIFIER_LENGTH,
- "Component qualifier length (%s) is longer than the maximum authorized (%s)", qualifier.length(), MAX_QUALIFIER_LENGTH);
- }
-
- this.qualifier = qualifier;
+ this.qualifier = qualifier == null ? null : checkComponentQualifier(qualifier);
return this;
}
public static NewComponent create(String key, String name) {
- checkArgument(key != null, "Key can't be null");
- checkArgument(key.length() <= MAX_KEY_LENGHT, "Component key length (%s) is longer than the maximum authorized (%s)", key.length(), MAX_KEY_LENGHT);
- checkArgument(name != null, "Name can't be null");
- checkArgument(name.length() <= MAX_NAME_LENGTH, "Component name length (%s) is longer than the maximum authorized (%s)", name.length(), MAX_NAME_LENGTH);
+ checkArgument(key!=null, "Key can't be null");
+ checkComponentKey(key);
+ checkArgument(name!=null, "Name can't be null");
+ checkComponentName(name);
return new NewComponent(key, name);
}
}
import org.junit.Test;
import org.junit.rules.ExpectedException;
-import static org.apache.commons.lang.RandomStringUtils.randomAlphabetic;
+import static com.google.common.base.Strings.repeat;
public class NewComponentTest {
@Rule
expectedException.expect(IllegalArgumentException.class);
expectedException.expectMessage("Component key length (401) is longer than the maximum authorized (400)");
- NewComponent.create(randomAlphabetic(401), "name");
+ NewComponent.create(repeat("a", 400 + 1), "name");
}
@Test
expectedException.expect(IllegalArgumentException.class);
expectedException.expectMessage("Component name length (2001) is longer than the maximum authorized (2000)");
- NewComponent.create("key", randomAlphabetic(2001));
+ NewComponent.create("key", repeat("a", 2001));
}
@Test
expectedException.expect(IllegalArgumentException.class);
expectedException.expectMessage("Component qualifier length (11) is longer than the maximum authorized (10)");
- NewComponent.create("key", "name").setQualifier(randomAlphabetic(11));
+ NewComponent.create("key", "name").setQualifier(repeat("a", 10 + 1));
}
}
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 = ".";
}
public ComponentDto setName(String name) {
- this.name = name;
+ this.name = checkComponentName(name);
return this;
}
}
public ComponentDto setKey(String key) {
- this.kee = key;
+ this.kee = checkComponentKey(key);
return this;
}
--- /dev/null
+/*
+ * 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;
+ }
+}
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;
}
public ResourceDto setName(String name) {
- this.name = name;
+ this.name = checkComponentName(name);
return this;
}
}
public ResourceDto setKey(String s) {
- this.key = s;
+ this.key = checkComponentKey(s);
return this;
}
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);
}
--- /dev/null
+/*
+ * 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();
+ }
+}
*/
package org.sonar.db.component;
+import com.google.common.base.Strings;
import java.util.Map;
import org.junit.Rule;
import org.junit.Test;
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 {
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#");