From 5733b0aea99e405672ce89bb2a25bf8fa6dfe60c Mon Sep 17 00:00:00 2001 From: Julien Lancelot Date: Wed, 24 Apr 2013 09:39:52 +0200 Subject: Rename PropertyDefinition by PropertyDef --- .../main/java/org/sonar/plugins/cpd/CpdPlugin.java | 64 +-- .../java/org/sonar/api/config/PropertyDef.java | 446 ++++++++++++++++++++ .../org/sonar/api/config/PropertyDefinition.java | 447 --------------------- .../org/sonar/api/config/PropertyDefinitions.java | 36 +- .../sonar/api/config/PropertyFieldDefinition.java | 4 +- .../main/java/org/sonar/api/config/Settings.java | 4 +- .../java/org/sonar/api/config/PropertyDefTest.java | 318 +++++++++++++++ .../sonar/api/config/PropertyDefinitionTest.java | 318 --------------- .../sonar/api/config/PropertyDefinitionsTest.java | 34 +- .../startup/RenameDeprecatedPropertyKeys.java | 4 +- 10 files changed, 835 insertions(+), 840 deletions(-) create mode 100644 sonar-plugin-api/src/main/java/org/sonar/api/config/PropertyDef.java delete mode 100644 sonar-plugin-api/src/main/java/org/sonar/api/config/PropertyDefinition.java create mode 100644 sonar-plugin-api/src/test/java/org/sonar/api/config/PropertyDefTest.java delete mode 100644 sonar-plugin-api/src/test/java/org/sonar/api/config/PropertyDefinitionTest.java diff --git a/plugins/sonar-cpd-plugin/src/main/java/org/sonar/plugins/cpd/CpdPlugin.java b/plugins/sonar-cpd-plugin/src/main/java/org/sonar/plugins/cpd/CpdPlugin.java index 5c3979cb886..27994970c68 100644 --- a/plugins/sonar-cpd-plugin/src/main/java/org/sonar/plugins/cpd/CpdPlugin.java +++ b/plugins/sonar-cpd-plugin/src/main/java/org/sonar/plugins/cpd/CpdPlugin.java @@ -23,7 +23,7 @@ import com.google.common.collect.ImmutableList; import org.sonar.api.CoreProperties; import org.sonar.api.PropertyType; import org.sonar.api.SonarPlugin; -import org.sonar.api.config.PropertyDefinition; +import org.sonar.api.config.PropertyDef; import org.sonar.api.resources.Qualifiers; import org.sonar.plugins.cpd.decorators.DuplicationDensityDecorator; import org.sonar.plugins.cpd.decorators.SumDuplicationsDecorator; @@ -35,38 +35,38 @@ public final class CpdPlugin extends SonarPlugin { public List getExtensions() { return ImmutableList.of( - PropertyDefinition.builder(CoreProperties.CPD_CROSS_RPOJECT) - .defaultValue(CoreProperties.CPD_CROSS_RPOJECT_DEFAULT_VALUE + "") - .name("Cross project duplication detection") - .description("SonarQube supports the detection of cross project duplications. Activating this property will slightly increase each Sonar analysis time.") - .onQualifiers(Qualifiers.PROJECT, Qualifiers.MODULE) - .category(CoreProperties.CATEGORY_DUPLICATIONS) - .type(PropertyType.BOOLEAN) - .build(), - PropertyDefinition.builder(CoreProperties.CPD_SKIP_PROPERTY) - .defaultValue("false") - .name("Skip") - .description("Disable detection of duplications") - .hidden() - .category(CoreProperties.CATEGORY_DUPLICATIONS) - .type(PropertyType.BOOLEAN) - .build(), - PropertyDefinition.builder(CoreProperties.CPD_EXCLUSIONS) - .defaultValue("") - .name("Duplication exclusions") - .description("Patterns used to exclude some source files from the duplication detection mechanism. " + - "See the \"Exclusions\" category to know how to use wildcards to specify this property.") - .onQualifiers(Qualifiers.PROJECT, Qualifiers.MODULE) - .category(CoreProperties.CATEGORY_DUPLICATIONS) - .multiValues(true) - .build(), + PropertyDef.builder(CoreProperties.CPD_CROSS_RPOJECT) + .defaultValue(CoreProperties.CPD_CROSS_RPOJECT_DEFAULT_VALUE + "") + .name("Cross project duplication detection") + .description("SonarQube supports the detection of cross project duplications. Activating this property will slightly increase each Sonar analysis time.") + .onQualifiers(Qualifiers.PROJECT, Qualifiers.MODULE) + .category(CoreProperties.CATEGORY_DUPLICATIONS) + .type(PropertyType.BOOLEAN) + .build(), + PropertyDef.builder(CoreProperties.CPD_SKIP_PROPERTY) + .defaultValue("false") + .name("Skip") + .description("Disable detection of duplications") + .hidden() + .category(CoreProperties.CATEGORY_DUPLICATIONS) + .type(PropertyType.BOOLEAN) + .build(), + PropertyDef.builder(CoreProperties.CPD_EXCLUSIONS) + .defaultValue("") + .name("Duplication exclusions") + .description("Patterns used to exclude some source files from the duplication detection mechanism. " + + "See the \"Exclusions\" category to know how to use wildcards to specify this property.") + .onQualifiers(Qualifiers.PROJECT, Qualifiers.MODULE) + .category(CoreProperties.CATEGORY_DUPLICATIONS) + .multiValues(true) + .build(), - CpdSensor.class, - SumDuplicationsDecorator.class, - DuplicationDensityDecorator.class, - IndexFactory.class, - SonarEngine.class, - SonarBridgeEngine.class); + CpdSensor.class, + SumDuplicationsDecorator.class, + DuplicationDensityDecorator.class, + IndexFactory.class, + SonarEngine.class, + SonarBridgeEngine.class); } } diff --git a/sonar-plugin-api/src/main/java/org/sonar/api/config/PropertyDef.java b/sonar-plugin-api/src/main/java/org/sonar/api/config/PropertyDef.java new file mode 100644 index 00000000000..389002f9c40 --- /dev/null +++ b/sonar-plugin-api/src/main/java/org/sonar/api/config/PropertyDef.java @@ -0,0 +1,446 @@ +/* + * SonarQube, open source software quality management tool. + * Copyright (C) 2008-2013 SonarSource + * mailto:contact AT sonarsource DOT com + * + * SonarQube 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. + * + * SonarQube 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.api.config; + +import com.google.common.base.Preconditions; +import com.google.common.base.Strings; +import com.google.common.collect.ImmutableList; +import com.google.common.collect.Lists; +import org.apache.commons.lang.StringUtils; +import org.apache.commons.lang.math.NumberUtils; +import org.sonar.api.BatchExtension; +import org.sonar.api.Property; +import org.sonar.api.PropertyType; +import org.sonar.api.ServerExtension; +import org.sonar.api.resources.Qualifiers; + +import javax.annotation.Nullable; + +import java.util.Arrays; +import java.util.List; + +import static com.google.common.collect.Lists.newArrayList; + +/** + * @since 3.0 + */ +public final class PropertyDef implements BatchExtension, ServerExtension { + + private String key; + private String defaultValue; + private String name; + private PropertyType type; + private List options; + private String description; + private String category; + private List qualifiers; + private boolean global; + private boolean multiValues; + private String propertySetKey; + private String deprecatedKey; + private List fields; + /** + * @since 3.6 + */ + private String subcategory; + private int index; + + /** + * @since 3.6 + */ + private PropertyDef(Builder builder) { + this.key = builder.key; + this.name = builder.name; + this.description = builder.description; + this.defaultValue = builder.defaultValue; + this.category = builder.category; + this.subcategory = builder.subcategory; + this.global = builder.global; + this.type = builder.type; + this.options = builder.options; + this.multiValues = builder.multiValues; + this.propertySetKey = builder.propertySetKey; + this.fields = builder.fields; + this.deprecatedKey = builder.deprecatedKey; + this.qualifiers = builder.onQualifiers; + this.qualifiers.addAll(builder.onlyOnQualifiers); + this.index = builder.index; + } + + /** + * @since 3.6 + */ + public static Builder builder(String key) { + return new Builder(key); + } + + /** + * @since 3.6 + */ + static PropertyDef create(Property annotation) { + Builder builder = PropertyDef.builder(annotation.key()) + .name(annotation.name()) + .defaultValue(annotation.defaultValue()) + .description(annotation.description()) + .category(annotation.category()) + .type(annotation.type()) + .options(Arrays.asList(annotation.options())) + .multiValues(annotation.multiValues()) + .propertySetKey(annotation.propertySetKey()) + .fields(PropertyFieldDefinition.create(annotation.fields())) + .deprecatedKey(annotation.deprecatedKey()); + List qualifiers = newArrayList(); + if (annotation.project()) { + qualifiers.add(Qualifiers.PROJECT); + } + if (annotation.module()) { + qualifiers.add(Qualifiers.MODULE); + } + if (annotation.global()) { + builder.onQualifiers(qualifiers); + } else { + builder.onlyOnQualifiers(qualifiers); + } + return builder.build(); + } + + public static Result validate(PropertyType type, @Nullable String value, List options) { + if (StringUtils.isNotBlank(value)) { + if (type == PropertyType.BOOLEAN) { + if (!StringUtils.equalsIgnoreCase(value, "true") && !StringUtils.equalsIgnoreCase(value, "false")) { + return Result.newError("notBoolean"); + } + } else if (type == PropertyType.INTEGER) { + if (!NumberUtils.isDigits(value)) { + return Result.newError("notInteger"); + } + } else if (type == PropertyType.FLOAT) { + try { + Double.parseDouble(value); + } catch (NumberFormatException e) { + return Result.newError("notFloat"); + } + } else if (type == PropertyType.SINGLE_SELECT_LIST) { + if (!options.contains(value)) { + return Result.newError("notInOptions"); + } + } + } + return Result.SUCCESS; + } + + public Result validate(@Nullable String value) { + return validate(type, value, options); + } + + /** + * Unique key within all plugins. It's recommended to prefix the key by 'sonar.' and the plugin name. Examples : + * 'sonar.cobertura.reportPath' and 'sonar.cpd.minimumTokens'. + */ + public String key() { + return key; + } + + public String defaultValue() { + return defaultValue; + } + + public String name() { + return name; + } + + public PropertyType type() { + return type; + } + + /** + * Options for *_LIST types + *

+ * Options for property of type PropertyType.SINGLE_SELECT_LIST + * For example {"property_1", "property_3", "property_3"}). + *

+ * Options for property of type PropertyType.METRIC. + * If no option is specified, any metric will match. + * If options are specified, all must match for the metric to be displayed. + * Three types of filter are supported key:REGEXP, domain:REGEXP and type:comma_separated__list_of_types. + * For example key:new_.* will match any metric which key starts by new_. + * For example type:INT,FLOAT will match any metric of type INT or FLOAT. + * For example type:NUMERIC will match any metric of numerictype. + */ + public List options() { + return options; + } + + public String description() { + return description; + } + + public String category() { + return category; + } + + /** + * @since 3.6 + */ + public String subcategory() { + return subcategory; + } + + /** + * Qualifiers that can display this property + * + * @since 3.6 + */ + public List qualifiers() { + return qualifiers; + } + + /** + * Is the property displayed in global settings page ? + */ + public boolean global() { + return global; + } + + /** + * @since 3.3 + */ + public boolean multiValues() { + return multiValues; + } + + /** + * @since 3.3 + */ + public String propertySetKey() { + return propertySetKey; + } + + /** + * @since 3.3 + */ + public List fields() { + return fields; + } + + /** + * @since 3.4 + */ + public String deprecatedKey() { + return deprecatedKey; + } + + /** + * Order to display properties in Sonar UI. When two properties have the same index then it is sorted by + * lexicographic order of property name. + * @since 3.6 + */ + public int index() { + return index; + } + + public static final class Result { + private static final Result SUCCESS = new Result(null); + private String errorKey = null; + + @Nullable + private Result(@Nullable String errorKey) { + this.errorKey = errorKey; + } + + private static Result newError(String key) { + return new Result(key); + } + + public boolean isValid() { + return StringUtils.isBlank(errorKey); + } + + @Nullable + public String getErrorKey() { + return errorKey; + } + } + + /** + * @since 3.6 + */ + public static class Builder { + private String key; + private String name; + private String description; + private String defaultValue; + private String category; + private String subcategory; + private List onQualifiers; + private List onlyOnQualifiers; + private boolean global; + private PropertyType type; + private List options; + private boolean multiValues; + private String propertySetKey; + private List fields; + private String deprecatedKey; + private boolean hidden; + private int index; + + private Builder(String key) { + this.key = key; + this.name = ""; + this.description = ""; + this.defaultValue = ""; + this.category = ""; + this.subcategory = "default"; + this.propertySetKey = ""; + this.deprecatedKey = ""; + this.global = true; + this.type = PropertyType.STRING; + this.onQualifiers = newArrayList(); + this.onlyOnQualifiers = newArrayList(); + this.options = newArrayList(); + this.fields = newArrayList(); + this.hidden = false; + this.index = 999; + } + + public Builder description(String description) { + this.description = description; + return this; + } + + public Builder name(String name) { + this.name = name; + return this; + } + + public Builder defaultValue(String defaultValue) { + this.defaultValue = defaultValue; + return this; + } + + public Builder category(String category) { + this.category = category; + return this; + } + + public Builder subcategory(String subcategory) { + this.subcategory = subcategory; + return this; + } + + public Builder onQualifiers(String first, String... rest) { + this.onQualifiers.addAll(Lists.asList(first, rest)); + this.global = true; + return this; + } + + public Builder onQualifiers(List qualifiers) { + this.onQualifiers.addAll(ImmutableList.copyOf(qualifiers)); + this.global = true; + return this; + } + + public Builder onlyOnQualifiers(String first, String... rest) { + this.onlyOnQualifiers.addAll(Lists.asList(first, rest)); + this.global = false; + return this; + } + + public Builder onlyOnQualifiers(List qualifiers) { + this.onlyOnQualifiers.addAll(ImmutableList.copyOf(qualifiers)); + this.global = false; + return this; + } + + public Builder type(PropertyType type) { + this.type = type; + return this; + } + + public Builder options(String first, String... rest) { + this.options.addAll(Lists.asList(first, rest)); + return this; + } + + public Builder options(List options) { + this.options.addAll(ImmutableList.copyOf(options)); + return this; + } + + public Builder multiValues(boolean multiValues) { + this.multiValues = multiValues; + return this; + } + + public Builder propertySetKey(String propertySetKey) { + this.propertySetKey = propertySetKey; + return this; + } + + public Builder fields(PropertyFieldDefinition first, PropertyFieldDefinition... rest) { + this.fields.addAll(Lists.asList(first, rest)); + return this; + } + + public Builder fields(List fields) { + this.fields.addAll(ImmutableList.copyOf(fields)); + return this; + } + + public Builder deprecatedKey(String deprecatedKey) { + this.deprecatedKey = deprecatedKey; + return this; + } + + public Builder hidden() { + this.hidden = true; + return this; + } + + public Builder index(int index) { + this.index = index; + return this; + } + + public PropertyDef build() { + Preconditions.checkArgument(!Strings.isNullOrEmpty(key), "Key must be set"); + fixType(key, type); + Preconditions.checkArgument(onQualifiers.isEmpty() || onlyOnQualifiers.isEmpty(), "Cannot define both onQualifiers and onlyOnQualifiers"); + Preconditions.checkArgument((!hidden || (onQualifiers.isEmpty()) && (!hidden || (onlyOnQualifiers.isEmpty()))), "Cannot be hidden and defining qualifiers on which to display"); + if (hidden) { + global = false; + } + return new PropertyDef(this); + } + + private void fixType(String key, PropertyType type) { + // Auto-detect passwords and licenses for old versions of plugins that + // do not declare property types + if (type == PropertyType.STRING) { + if (StringUtils.endsWith(key, ".password.secured")) { + this.type = PropertyType.PASSWORD; + } else if (StringUtils.endsWith(key, ".license.secured")) { + this.type = PropertyType.LICENSE; + } + } + } + } + +} diff --git a/sonar-plugin-api/src/main/java/org/sonar/api/config/PropertyDefinition.java b/sonar-plugin-api/src/main/java/org/sonar/api/config/PropertyDefinition.java deleted file mode 100644 index 374a594f118..00000000000 --- a/sonar-plugin-api/src/main/java/org/sonar/api/config/PropertyDefinition.java +++ /dev/null @@ -1,447 +0,0 @@ -/* - * SonarQube, open source software quality management tool. - * Copyright (C) 2008-2013 SonarSource - * mailto:contact AT sonarsource DOT com - * - * SonarQube 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. - * - * SonarQube 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.api.config; - -import com.google.common.base.Preconditions; -import com.google.common.base.Strings; -import com.google.common.collect.ImmutableList; -import com.google.common.collect.Lists; -import org.apache.commons.lang.StringUtils; -import org.apache.commons.lang.math.NumberUtils; -import org.sonar.api.BatchExtension; -import org.sonar.api.Property; -import org.sonar.api.PropertyType; -import org.sonar.api.ServerExtension; -import org.sonar.api.resources.Qualifiers; - -import javax.annotation.Nullable; - -import java.util.Arrays; -import java.util.List; - -import static com.google.common.collect.Lists.newArrayList; - -/** - * - * @since 3.0 - */ -public final class PropertyDefinition implements BatchExtension, ServerExtension { - - private String key; - private String defaultValue; - private String name; - private PropertyType type; - private List options; - private String description; - private String category; - private List qualifiers; - private boolean global; - private boolean multiValues; - private String propertySetKey; - private String deprecatedKey; - private List fields; - /** - * @since 3.6 - */ - private String subcategory; - private int index; - - /** - * @since 3.6 - */ - private PropertyDefinition(Builder builder) { - this.key = builder.key; - this.name = builder.name; - this.description = builder.description; - this.defaultValue = builder.defaultValue; - this.category = builder.category; - this.subcategory = builder.subcategory; - this.global = builder.global; - this.type = builder.type; - this.options = builder.options; - this.multiValues = builder.multiValues; - this.propertySetKey = builder.propertySetKey; - this.fields = builder.fields; - this.deprecatedKey = builder.deprecatedKey; - this.qualifiers = builder.onQualifiers; - this.qualifiers.addAll(builder.onlyOnQualifiers); - this.index = builder.index; - } - - /** - * @since 3.6 - */ - public static Builder builder(String key) { - return new Builder(key); - } - - /** - * @since 3.6 - */ - static PropertyDefinition create(Property annotation) { - Builder builder = PropertyDefinition.builder(annotation.key()) - .name(annotation.name()) - .defaultValue(annotation.defaultValue()) - .description(annotation.description()) - .category(annotation.category()) - .type(annotation.type()) - .options(Arrays.asList(annotation.options())) - .multiValues(annotation.multiValues()) - .propertySetKey(annotation.propertySetKey()) - .fields(PropertyFieldDefinition.create(annotation.fields())) - .deprecatedKey(annotation.deprecatedKey()); - List qualifiers = newArrayList(); - if (annotation.project()) { - qualifiers.add(Qualifiers.PROJECT); - } - if (annotation.module()) { - qualifiers.add(Qualifiers.MODULE); - } - if (annotation.global()) { - builder.onQualifiers(qualifiers); - } else { - builder.onlyOnQualifiers(qualifiers); - } - return builder.build(); - } - - public static Result validate(PropertyType type, @Nullable String value, List options) { - if (StringUtils.isNotBlank(value)) { - if (type == PropertyType.BOOLEAN) { - if (!StringUtils.equalsIgnoreCase(value, "true") && !StringUtils.equalsIgnoreCase(value, "false")) { - return Result.newError("notBoolean"); - } - } else if (type == PropertyType.INTEGER) { - if (!NumberUtils.isDigits(value)) { - return Result.newError("notInteger"); - } - } else if (type == PropertyType.FLOAT) { - try { - Double.parseDouble(value); - } catch (NumberFormatException e) { - return Result.newError("notFloat"); - } - } else if (type == PropertyType.SINGLE_SELECT_LIST) { - if (!options.contains(value)) { - return Result.newError("notInOptions"); - } - } - } - return Result.SUCCESS; - } - - public Result validate(@Nullable String value) { - return validate(type, value, options); - } - - /** - * Unique key within all plugins. It's recommended to prefix the key by 'sonar.' and the plugin name. Examples : - * 'sonar.cobertura.reportPath' and 'sonar.cpd.minimumTokens'. - */ - public String key() { - return key; - } - - public String defaultValue() { - return defaultValue; - } - - public String name() { - return name; - } - - public PropertyType type() { - return type; - } - - /** - * Options for *_LIST types - *

- * Options for property of type PropertyType.SINGLE_SELECT_LIST - * For example {"property_1", "property_3", "property_3"}). - *

- * Options for property of type PropertyType.METRIC. - * If no option is specified, any metric will match. - * If options are specified, all must match for the metric to be displayed. - * Three types of filter are supported key:REGEXP, domain:REGEXP and type:comma_separated__list_of_types. - * For example key:new_.* will match any metric which key starts by new_. - * For example type:INT,FLOAT will match any metric of type INT or FLOAT. - * For example type:NUMERIC will match any metric of numerictype. - */ - public List options() { - return options; - } - - public String description() { - return description; - } - - public String category() { - return category; - } - - /** - * @since 3.6 - */ - public String subcategory() { - return subcategory; - } - - /** - * Qualifiers that can display this property - * - * @since 3.6 - */ - public List qualifiers() { - return qualifiers; - } - - /** - * Is the property displayed in global settings page ? - */ - public boolean global() { - return global; - } - - /** - * @since 3.3 - */ - public boolean multiValues() { - return multiValues; - } - - /** - * @since 3.3 - */ - public String propertySetKey() { - return propertySetKey; - } - - /** - * @since 3.3 - */ - public List fields() { - return fields; - } - - /** - * @since 3.4 - */ - public String deprecatedKey() { - return deprecatedKey; - } - - /** - * Order to display properties in Sonar UI. When two properties have the same index then it is sorted by - * lexicographic order of property name. - * @since 3.6 - */ - public int index() { - return index; - } - - public static final class Result { - private static final Result SUCCESS = new Result(null); - private String errorKey = null; - - @Nullable - private Result(@Nullable String errorKey) { - this.errorKey = errorKey; - } - - private static Result newError(String key) { - return new Result(key); - } - - public boolean isValid() { - return StringUtils.isBlank(errorKey); - } - - @Nullable - public String getErrorKey() { - return errorKey; - } - } - - /** - * @since 3.6 - */ - public static class Builder { - private String key; - private String name; - private String description; - private String defaultValue; - private String category; - private String subcategory; - private List onQualifiers; - private List onlyOnQualifiers; - private boolean global; - private PropertyType type; - private List options; - private boolean multiValues; - private String propertySetKey; - private List fields; - private String deprecatedKey; - private boolean hidden; - private int index; - - private Builder(String key) { - this.key = key; - this.name = ""; - this.description = ""; - this.defaultValue = ""; - this.category = ""; - this.subcategory = "default"; - this.propertySetKey = ""; - this.deprecatedKey = ""; - this.global = true; - this.type = PropertyType.STRING; - this.onQualifiers = newArrayList(); - this.onlyOnQualifiers = newArrayList(); - this.options = newArrayList(); - this.fields = newArrayList(); - this.hidden = false; - this.index = 999; - } - - public Builder description(String description) { - this.description = description; - return this; - } - - public Builder name(String name) { - this.name = name; - return this; - } - - public Builder defaultValue(String defaultValue) { - this.defaultValue = defaultValue; - return this; - } - - public Builder category(String category) { - this.category = category; - return this; - } - - public Builder subcategory(String subcategory) { - this.subcategory = subcategory; - return this; - } - - public Builder onQualifiers(String first, String... rest) { - this.onQualifiers.addAll(Lists.asList(first, rest)); - this.global = true; - return this; - } - - public Builder onQualifiers(List qualifiers) { - this.onQualifiers.addAll(ImmutableList.copyOf(qualifiers)); - this.global = true; - return this; - } - - public Builder onlyOnQualifiers(String first, String... rest) { - this.onlyOnQualifiers.addAll(Lists.asList(first, rest)); - this.global = false; - return this; - } - - public Builder onlyOnQualifiers(List qualifiers) { - this.onlyOnQualifiers.addAll(ImmutableList.copyOf(qualifiers)); - this.global = false; - return this; - } - - public Builder type(PropertyType type) { - this.type = type; - return this; - } - - public Builder options(String first, String... rest) { - this.options.addAll(Lists.asList(first, rest)); - return this; - } - - public Builder options(List options) { - this.options.addAll(ImmutableList.copyOf(options)); - return this; - } - - public Builder multiValues(boolean multiValues) { - this.multiValues = multiValues; - return this; - } - - public Builder propertySetKey(String propertySetKey) { - this.propertySetKey = propertySetKey; - return this; - } - - public Builder fields(PropertyFieldDefinition first, PropertyFieldDefinition... rest) { - this.fields.addAll(Lists.asList(first, rest)); - return this; - } - - public Builder fields(List fields) { - this.fields.addAll(ImmutableList.copyOf(fields)); - return this; - } - - public Builder deprecatedKey(String deprecatedKey) { - this.deprecatedKey = deprecatedKey; - return this; - } - - public Builder hidden() { - this.hidden = true; - return this; - } - - public Builder index(int index) { - this.index = index; - return this; - } - - public PropertyDefinition build() { - Preconditions.checkArgument(!Strings.isNullOrEmpty(key), "Key must be set"); - fixType(key, type); - Preconditions.checkArgument(onQualifiers.isEmpty() || onlyOnQualifiers.isEmpty(), "Cannot define both onQualifiers and onlyOnQualifiers"); - Preconditions.checkArgument((!hidden || (onQualifiers.isEmpty()) && (!hidden || (onlyOnQualifiers.isEmpty()))), "Cannot be hidden and defining qualifiers on which to display"); - if (hidden) { - global = false; - } - return new PropertyDefinition(this); - } - - private void fixType(String key, PropertyType type) { - // Auto-detect passwords and licenses for old versions of plugins that - // do not declare property types - if (type == PropertyType.STRING) { - if (StringUtils.endsWith(key, ".password.secured")) { - this.type = PropertyType.PASSWORD; - } else if (StringUtils.endsWith(key, ".license.secured")) { - this.type = PropertyType.LICENSE; - } - } - } - } - -} diff --git a/sonar-plugin-api/src/main/java/org/sonar/api/config/PropertyDefinitions.java b/sonar-plugin-api/src/main/java/org/sonar/api/config/PropertyDefinitions.java index 17eac9c0cb7..452ba25f82e 100644 --- a/sonar-plugin-api/src/main/java/org/sonar/api/config/PropertyDefinitions.java +++ b/sonar-plugin-api/src/main/java/org/sonar/api/config/PropertyDefinitions.java @@ -30,11 +30,7 @@ import org.sonar.api.utils.AnnotationUtils; import javax.annotation.Nullable; -import java.util.ArrayList; -import java.util.Arrays; -import java.util.Collection; -import java.util.HashMap; -import java.util.Map; +import java.util.*; /** * Metadata of all the properties declared by plugins @@ -43,7 +39,7 @@ import java.util.Map; */ public final class PropertyDefinitions implements BatchComponent, ServerComponent { - private final Map definitions = Maps.newHashMap(); + private final Map definitions = Maps.newHashMap(); private final Map categories = Maps.newHashMap(); private final Map subcategories = Maps.newHashMap(); @@ -73,8 +69,8 @@ public final class PropertyDefinitions implements BatchComponent, ServerComponen public PropertyDefinitions addComponent(Object component, String defaultCategory) { addComponentFromAnnotationProperty(component, defaultCategory); - if (component instanceof PropertyDefinition) { - PropertyDefinition propertyDefinition = (PropertyDefinition) component; + if (component instanceof PropertyDef) { + PropertyDef propertyDefinition = (PropertyDef) component; add(propertyDefinition, defaultCategory); } return this; @@ -95,11 +91,11 @@ public final class PropertyDefinitions implements BatchComponent, ServerComponen } private PropertyDefinitions addProperty(Property property, String defaultCategory) { - PropertyDefinition definition = PropertyDefinition.create(property); + PropertyDef definition = PropertyDef.create(property); return add(definition, defaultCategory); } - private PropertyDefinitions add(PropertyDefinition definition, String defaultCategory) { + private PropertyDefinitions add(PropertyDef definition, String defaultCategory) { if (!definitions.containsKey(definition.key())) { definitions.put(definition.key(), definition); categories.put(definition.key(), StringUtils.defaultIfBlank(definition.category(), defaultCategory)); @@ -111,11 +107,11 @@ public final class PropertyDefinitions implements BatchComponent, ServerComponen return this; } - public PropertyDefinition get(String key) { + public PropertyDef get(String key) { return definitions.get(validKey(key)); } - public Collection getAll() { + public Collection getAll() { return definitions.values(); } @@ -126,18 +122,18 @@ public final class PropertyDefinitions implements BatchComponent, ServerComponen /** * @since 3.6 */ - public Map>> getPropertiesByCategory(@Nullable String qualifier) { - Map>> byCategory = new HashMap>>(); + public Map>> getPropertiesByCategory(@Nullable String qualifier) { + Map>> byCategory = new HashMap>>(); - for (PropertyDefinition definition : getAll()) { + for (PropertyDef definition : getAll()) { if (qualifier == null ? definition.global() : definition.qualifiers().contains(qualifier)) { String category = getCategory(definition.key()); if (!byCategory.containsKey(category)) { - byCategory.put(category, new HashMap>()); + byCategory.put(category, new HashMap>()); } String subCategory = getSubCategory(definition.key()); if (!byCategory.get(category).containsKey(subCategory)) { - byCategory.get(category).put(subCategory, new ArrayList()); + byCategory.get(category).put(subCategory, new ArrayList()); } byCategory.get(category).get(subCategory).add(definition); } @@ -146,12 +142,12 @@ public final class PropertyDefinitions implements BatchComponent, ServerComponen return byCategory; } - public Map>> getPropertiesByCategory() { + public Map>> getPropertiesByCategory() { return getPropertiesByCategory(null); } public String getDefaultValue(String key) { - PropertyDefinition def = get(key); + PropertyDef def = get(key); if (def == null) { return null; } @@ -175,7 +171,7 @@ public final class PropertyDefinitions implements BatchComponent, ServerComponen } public String getDeprecatedKey(String key) { - PropertyDefinition def = get(key); + PropertyDef def = get(key); if (def == null) { return null; } diff --git a/sonar-plugin-api/src/main/java/org/sonar/api/config/PropertyFieldDefinition.java b/sonar-plugin-api/src/main/java/org/sonar/api/config/PropertyFieldDefinition.java index b48c1808ab6..3c3d4748ccd 100644 --- a/sonar-plugin-api/src/main/java/org/sonar/api/config/PropertyFieldDefinition.java +++ b/sonar-plugin-api/src/main/java/org/sonar/api/config/PropertyFieldDefinition.java @@ -94,8 +94,8 @@ public final class PropertyFieldDefinition { return options; } - public PropertyDefinition.Result validate(@Nullable String value) { - return PropertyDefinition.validate(type, value, options); + public PropertyDef.Result validate(@Nullable String value) { + return PropertyDef.validate(type, value, options); } public static class Builder { diff --git a/sonar-plugin-api/src/main/java/org/sonar/api/config/Settings.java b/sonar-plugin-api/src/main/java/org/sonar/api/config/Settings.java index 8623e9c458a..f63934c6228 100644 --- a/sonar-plugin-api/src/main/java/org/sonar/api/config/Settings.java +++ b/sonar-plugin-api/src/main/java/org/sonar/api/config/Settings.java @@ -190,7 +190,7 @@ public class Settings implements BatchComponent, ServerComponent { * */ public String[] getStringArray(String key) { - PropertyDefinition property = getDefinitions().get(key); + PropertyDef property = getDefinitions().get(key); if ((null != property) && (property.multiValues())) { String value = getString(key); if (value == null) { @@ -258,7 +258,7 @@ public class Settings implements BatchComponent, ServerComponent { } public Settings setProperty(String key, @Nullable String[] values) { - PropertyDefinition property = getDefinitions().get(key); + PropertyDef property = getDefinitions().get(key); if ((null == property) || (!property.multiValues())) { throw new IllegalStateException("Fail to set multiple values on a single value property " + key); } diff --git a/sonar-plugin-api/src/test/java/org/sonar/api/config/PropertyDefTest.java b/sonar-plugin-api/src/test/java/org/sonar/api/config/PropertyDefTest.java new file mode 100644 index 00000000000..4a284b97c30 --- /dev/null +++ b/sonar-plugin-api/src/test/java/org/sonar/api/config/PropertyDefTest.java @@ -0,0 +1,318 @@ +/* + * SonarQube, open source software quality management tool. + * Copyright (C) 2008-2013 SonarSource + * mailto:contact AT sonarsource DOT com + * + * SonarQube 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. + * + * SonarQube 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.api.config; + +import org.junit.Test; +import org.sonar.api.Properties; +import org.sonar.api.Property; +import org.sonar.api.PropertyField; +import org.sonar.api.PropertyType; +import org.sonar.api.resources.Qualifiers; +import org.sonar.api.utils.AnnotationUtils; + +import static org.fest.assertions.Assertions.assertThat; +import static org.fest.assertions.Fail.fail; + +public class PropertyDefTest { + + @Test + public void should_create_property() { + PropertyDef def = PropertyDef.builder("hello") + .name("Hello") + .defaultValue("world") + .category("categ") + .options("de", "en") + .description("desc") + .type(PropertyType.FLOAT) + .onlyOnQualifiers(Qualifiers.FILE, Qualifiers.CLASS) + .multiValues(true) + .propertySetKey("set") + .build(); + + assertThat(def.key()).isEqualTo("hello"); + assertThat(def.name()).isEqualTo("Hello"); + assertThat(def.defaultValue()).isEqualTo("world"); + assertThat(def.category()).isEqualTo("categ"); + assertThat(def.options()).containsOnly("de", "en"); + assertThat(def.description()).isEqualTo("desc"); + assertThat(def.type()).isEqualTo(PropertyType.FLOAT); + assertThat(def.global()).isFalse(); + assertThat(def.qualifiers()).containsOnly(Qualifiers.FILE, Qualifiers.CLASS); + assertThat(def.multiValues()).isTrue(); + assertThat(def.propertySetKey()).isEqualTo("set"); + assertThat(def.fields()).isEmpty(); + } + + @Test + public void should_create_from_annotation() { + Properties props = AnnotationUtils.getAnnotation(Init.class, Properties.class); + Property prop = props.value()[0]; + + PropertyDef def = PropertyDef.create(prop); + + assertThat(def.key()).isEqualTo("hello"); + assertThat(def.name()).isEqualTo("Hello"); + assertThat(def.defaultValue()).isEqualTo("world"); + assertThat(def.category()).isEqualTo("categ"); + assertThat(def.options()).containsOnly("de", "en"); + assertThat(def.description()).isEqualTo("desc"); + assertThat(def.type()).isEqualTo(PropertyType.FLOAT); + assertThat(def.global()).isFalse(); + assertThat(def.qualifiers()).containsOnly(Qualifiers.PROJECT, Qualifiers.MODULE); + assertThat(def.multiValues()).isTrue(); + assertThat(def.propertySetKey()).isEqualTo("set"); + assertThat(def.fields()).isEmpty(); + } + + @Test + public void should_create_hidden_property() { + PropertyDef def = PropertyDef.builder("hello") + .name("Hello") + .hidden() + .build(); + + assertThat(def.key()).isEqualTo("hello"); + assertThat(def.qualifiers()).isEmpty(); + assertThat(def.global()).isFalse(); + } + + @Test + public void should_create_property_with_default_values() { + PropertyDef def = PropertyDef.builder("hello") + .name("Hello") + .build(); + + assertThat(def.key()).isEqualTo("hello"); + assertThat(def.name()).isEqualTo("Hello"); + assertThat(def.defaultValue()).isEmpty(); + assertThat(def.category()).isEmpty(); + assertThat(def.options()).isEmpty(); + assertThat(def.description()).isEmpty(); + assertThat(def.type()).isEqualTo(PropertyType.STRING); + assertThat(def.global()).isTrue(); + assertThat(def.qualifiers()).isEmpty(); + assertThat(def.multiValues()).isFalse(); + assertThat(def.propertySetKey()).isEmpty(); + assertThat(def.fields()).isEmpty(); + } + + @Test + public void should_create_from_annotation_default_values() { + Properties props = AnnotationUtils.getAnnotation(DefaultValues.class, Properties.class); + Property prop = props.value()[0]; + + PropertyDef def = PropertyDef.create(prop); + + assertThat(def.key()).isEqualTo("hello"); + assertThat(def.name()).isEqualTo("Hello"); + assertThat(def.defaultValue()).isEmpty(); + assertThat(def.category()).isEmpty(); + assertThat(def.options()).isEmpty(); + assertThat(def.description()).isEmpty(); + assertThat(def.type()).isEqualTo(PropertyType.STRING); + assertThat(def.global()).isTrue(); + assertThat(def.qualifiers()).isEmpty(); + assertThat(def.multiValues()).isFalse(); + assertThat(def.propertySetKey()).isEmpty(); + assertThat(def.fields()).isEmpty(); + } + + @Test + public void should_support_property_sets() { + PropertyDef def = PropertyDef.builder("hello") + .name("Hello") + .fields( + PropertyFieldDefinition.build("first").name("First").description("Description").options("A", "B").build(), + PropertyFieldDefinition.build("second").name("Second").type(PropertyType.INTEGER).indicativeSize(5).build() + ) + .build(); + + assertThat(def.fields()).hasSize(2); + assertThat(def.fields().get(0).key()).isEqualTo("first"); + assertThat(def.fields().get(0).name()).isEqualTo("First"); + assertThat(def.fields().get(0).description()).isEqualTo("Description"); + assertThat(def.fields().get(0).type()).isEqualTo(PropertyType.STRING); + assertThat(def.fields().get(0).options()).containsOnly("A", "B"); + assertThat(def.fields().get(0).indicativeSize()).isEqualTo(20); + assertThat(def.fields().get(1).key()).isEqualTo("second"); + assertThat(def.fields().get(1).name()).isEqualTo("Second"); + assertThat(def.fields().get(1).type()).isEqualTo(PropertyType.INTEGER); + assertThat(def.fields().get(1).options()).isEmpty(); + assertThat(def.fields().get(1).indicativeSize()).isEqualTo(5); + } + + @Test + public void should_support_property_sets_from_annotation() { + Properties props = AnnotationUtils.getAnnotation(WithPropertySet.class, Properties.class); + Property prop = props.value()[0]; + + PropertyDef def = PropertyDef.create(prop); + + assertThat(def.fields()).hasSize(2); + assertThat(def.fields().get(0).key()).isEqualTo("first"); + assertThat(def.fields().get(0).name()).isEqualTo("First"); + assertThat(def.fields().get(0).description()).isEqualTo("Description"); + assertThat(def.fields().get(0).type()).isEqualTo(PropertyType.STRING); + assertThat(def.fields().get(0).options()).containsOnly("A", "B"); + assertThat(def.fields().get(0).indicativeSize()).isEqualTo(20); + assertThat(def.fields().get(1).key()).isEqualTo("second"); + assertThat(def.fields().get(1).name()).isEqualTo("Second"); + assertThat(def.fields().get(1).type()).isEqualTo(PropertyType.INTEGER); + assertThat(def.fields().get(1).options()).isEmpty(); + assertThat(def.fields().get(1).indicativeSize()).isEqualTo(5); + } + + @Test + public void should_validate_string() { + PropertyDef def = PropertyDef.builder("foo").name("foo").type(PropertyType.STRING).build(); + + assertThat(def.validate(null).isValid()).isTrue(); + assertThat(def.validate("").isValid()).isTrue(); + assertThat(def.validate(" ").isValid()).isTrue(); + assertThat(def.validate("foo").isValid()).isTrue(); + } + + @Test + public void should_validate_boolean() { + PropertyDef def = PropertyDef.builder("foo").name("foo").type(PropertyType.BOOLEAN).build(); + + assertThat(def.validate(null).isValid()).isTrue(); + assertThat(def.validate("").isValid()).isTrue(); + assertThat(def.validate(" ").isValid()).isTrue(); + assertThat(def.validate("true").isValid()).isTrue(); + assertThat(def.validate("false").isValid()).isTrue(); + + assertThat(def.validate("foo").isValid()).isFalse(); + assertThat(def.validate("foo").getErrorKey()).isEqualTo("notBoolean"); + } + + @Test + public void should_validate_integer() { + PropertyDef def = PropertyDef.builder("foo").name("foo").type(PropertyType.INTEGER).build(); + + assertThat(def.validate(null).isValid()).isTrue(); + assertThat(def.validate("").isValid()).isTrue(); + assertThat(def.validate(" ").isValid()).isTrue(); + assertThat(def.validate("123456").isValid()).isTrue(); + + assertThat(def.validate("foo").isValid()).isFalse(); + assertThat(def.validate("foo").getErrorKey()).isEqualTo("notInteger"); + } + + @Test + public void should_validate_float() { + PropertyDef def = PropertyDef.builder("foo").name("foo").type(PropertyType.FLOAT).build(); + + assertThat(def.validate(null).isValid()).isTrue(); + assertThat(def.validate("").isValid()).isTrue(); + assertThat(def.validate(" ").isValid()).isTrue(); + assertThat(def.validate("123456").isValid()).isTrue(); + assertThat(def.validate("3.14").isValid()).isTrue(); + + assertThat(def.validate("foo").isValid()).isFalse(); + assertThat(def.validate("foo").getErrorKey()).isEqualTo("notFloat"); + } + + @Test + public void should_validate_single_select_list() { + PropertyDef def = PropertyDef.builder("foo").name("foo").type(PropertyType.SINGLE_SELECT_LIST).options("de", "en").build(); + + assertThat(def.validate(null).isValid()).isTrue(); + assertThat(def.validate("").isValid()).isTrue(); + assertThat(def.validate(" ").isValid()).isTrue(); + assertThat(def.validate("de").isValid()).isTrue(); + assertThat(def.validate("en").isValid()).isTrue(); + + assertThat(def.validate("fr").isValid()).isFalse(); + assertThat(def.validate("fr").getErrorKey()).isEqualTo("notInOptions"); + } + + @Test + public void should_auto_detect_password_type() { + PropertyDef def = PropertyDef.builder("scm.password.secured").name("SCM password").build(); + + assertThat(def.key()).isEqualTo("scm.password.secured"); + assertThat(def.type()).isEqualTo(PropertyType.PASSWORD); + } + + @Test + public void PropertyDef() { + PropertyDef def = PropertyDef.builder("views.license.secured").name("Views license").build(); + + assertThat(def.key()).isEqualTo("views.license.secured"); + assertThat(def.type()).isEqualTo(PropertyType.LICENSE); + } + + @Test + public void should_not_authorise_empty_key() { + try { + PropertyDef.builder(null).build(); + fail(); + } catch (Exception e) { + assertThat(e).hasMessage("Key must be set").isInstanceOf(IllegalArgumentException.class); + } + } + + @Test + public void should_not_authorize_defining_on_qualifiers_and_hidden() { + try { + PropertyDef.builder("foo").name("foo").onQualifiers(Qualifiers.FILE).hidden().build(); + fail(); + } catch (Exception e) { + assertThat(e).hasMessage("Cannot be hidden and defining qualifiers on which to display").isInstanceOf(IllegalArgumentException.class); + } + } + + @Test + public void should_not_authorize_defining_ony_on_qualifiers_and_hidden() { + try { + PropertyDef.builder("foo").name("foo").onlyOnQualifiers(Qualifiers.FILE).hidden().build(); + fail(); + } catch (Exception e) { + assertThat(e).hasMessage("Cannot be hidden and defining qualifiers on which to display").isInstanceOf(IllegalArgumentException.class); + } + } + + @Test + public void should_not_authorize_defining_on_qualifiers_and_only_on_qualifiers() { + try { + PropertyDef.builder("foo").name("foo").onQualifiers(Qualifiers.FILE).onlyOnQualifiers(Qualifiers.PROJECT).build(); + fail(); + } catch (Exception e) { + assertThat(e).hasMessage("Cannot define both onQualifiers and onlyOnQualifiers").isInstanceOf(IllegalArgumentException.class); + } + } + + @Properties(@Property(key = "hello", name = "Hello", defaultValue = "world", description = "desc", + options = {"de", "en"}, category = "categ", type = PropertyType.FLOAT, global = false, project = true, module = true, multiValues = true, propertySetKey = "set")) + static class Init { + } + + @Properties(@Property(key = "hello", name = "Hello", fields = { + @PropertyField(key = "first", name = "First", description = "Description", options = {"A", "B"}), + @PropertyField(key = "second", name = "Second", type = PropertyType.INTEGER, indicativeSize = 5)})) + static class WithPropertySet { + } + + @Properties(@Property(key = "hello", name = "Hello")) + static class DefaultValues { + } + +} diff --git a/sonar-plugin-api/src/test/java/org/sonar/api/config/PropertyDefinitionTest.java b/sonar-plugin-api/src/test/java/org/sonar/api/config/PropertyDefinitionTest.java deleted file mode 100644 index 84978ff1795..00000000000 --- a/sonar-plugin-api/src/test/java/org/sonar/api/config/PropertyDefinitionTest.java +++ /dev/null @@ -1,318 +0,0 @@ -/* - * SonarQube, open source software quality management tool. - * Copyright (C) 2008-2013 SonarSource - * mailto:contact AT sonarsource DOT com - * - * SonarQube 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. - * - * SonarQube 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.api.config; - -import org.junit.Test; -import org.sonar.api.Properties; -import org.sonar.api.Property; -import org.sonar.api.PropertyField; -import org.sonar.api.PropertyType; -import org.sonar.api.resources.Qualifiers; -import org.sonar.api.utils.AnnotationUtils; - -import static org.fest.assertions.Assertions.assertThat; -import static org.fest.assertions.Fail.fail; - -public class PropertyDefinitionTest { - - @Test - public void should_create_property() { - PropertyDefinition def = PropertyDefinition.builder("hello") - .name("Hello") - .defaultValue("world") - .category("categ") - .options("de", "en") - .description("desc") - .type(PropertyType.FLOAT) - .onlyOnQualifiers(Qualifiers.FILE, Qualifiers.CLASS) - .multiValues(true) - .propertySetKey("set") - .build(); - - assertThat(def.key()).isEqualTo("hello"); - assertThat(def.name()).isEqualTo("Hello"); - assertThat(def.defaultValue()).isEqualTo("world"); - assertThat(def.category()).isEqualTo("categ"); - assertThat(def.options()).containsOnly("de", "en"); - assertThat(def.description()).isEqualTo("desc"); - assertThat(def.type()).isEqualTo(PropertyType.FLOAT); - assertThat(def.global()).isFalse(); - assertThat(def.qualifiers()).containsOnly(Qualifiers.FILE, Qualifiers.CLASS); - assertThat(def.multiValues()).isTrue(); - assertThat(def.propertySetKey()).isEqualTo("set"); - assertThat(def.fields()).isEmpty(); - } - - @Test - public void should_create_from_annotation() { - Properties props = AnnotationUtils.getAnnotation(Init.class, Properties.class); - Property prop = props.value()[0]; - - PropertyDefinition def = PropertyDefinition.create(prop); - - assertThat(def.key()).isEqualTo("hello"); - assertThat(def.name()).isEqualTo("Hello"); - assertThat(def.defaultValue()).isEqualTo("world"); - assertThat(def.category()).isEqualTo("categ"); - assertThat(def.options()).containsOnly("de", "en"); - assertThat(def.description()).isEqualTo("desc"); - assertThat(def.type()).isEqualTo(PropertyType.FLOAT); - assertThat(def.global()).isFalse(); - assertThat(def.qualifiers()).containsOnly(Qualifiers.PROJECT, Qualifiers.MODULE); - assertThat(def.multiValues()).isTrue(); - assertThat(def.propertySetKey()).isEqualTo("set"); - assertThat(def.fields()).isEmpty(); - } - - @Test - public void should_create_hidden_property() { - PropertyDefinition def = PropertyDefinition.builder("hello") - .name("Hello") - .hidden() - .build(); - - assertThat(def.key()).isEqualTo("hello"); - assertThat(def.qualifiers()).isEmpty(); - assertThat(def.global()).isFalse(); - } - - @Test - public void should_create_property_with_default_values() { - PropertyDefinition def = PropertyDefinition.builder("hello") - .name("Hello") - .build(); - - assertThat(def.key()).isEqualTo("hello"); - assertThat(def.name()).isEqualTo("Hello"); - assertThat(def.defaultValue()).isEmpty(); - assertThat(def.category()).isEmpty(); - assertThat(def.options()).isEmpty(); - assertThat(def.description()).isEmpty(); - assertThat(def.type()).isEqualTo(PropertyType.STRING); - assertThat(def.global()).isTrue(); - assertThat(def.qualifiers()).isEmpty(); - assertThat(def.multiValues()).isFalse(); - assertThat(def.propertySetKey()).isEmpty(); - assertThat(def.fields()).isEmpty(); - } - - @Test - public void should_create_from_annotation_default_values() { - Properties props = AnnotationUtils.getAnnotation(DefaultValues.class, Properties.class); - Property prop = props.value()[0]; - - PropertyDefinition def = PropertyDefinition.create(prop); - - assertThat(def.key()).isEqualTo("hello"); - assertThat(def.name()).isEqualTo("Hello"); - assertThat(def.defaultValue()).isEmpty(); - assertThat(def.category()).isEmpty(); - assertThat(def.options()).isEmpty(); - assertThat(def.description()).isEmpty(); - assertThat(def.type()).isEqualTo(PropertyType.STRING); - assertThat(def.global()).isTrue(); - assertThat(def.qualifiers()).isEmpty(); - assertThat(def.multiValues()).isFalse(); - assertThat(def.propertySetKey()).isEmpty(); - assertThat(def.fields()).isEmpty(); - } - - @Test - public void should_support_property_sets() { - PropertyDefinition def = PropertyDefinition.builder("hello") - .name("Hello") - .fields( - PropertyFieldDefinition.build("first").name("First").description("Description").options("A", "B").build(), - PropertyFieldDefinition.build("second").name("Second").type(PropertyType.INTEGER).indicativeSize(5).build() - ) - .build(); - - assertThat(def.fields()).hasSize(2); - assertThat(def.fields().get(0).key()).isEqualTo("first"); - assertThat(def.fields().get(0).name()).isEqualTo("First"); - assertThat(def.fields().get(0).description()).isEqualTo("Description"); - assertThat(def.fields().get(0).type()).isEqualTo(PropertyType.STRING); - assertThat(def.fields().get(0).options()).containsOnly("A", "B"); - assertThat(def.fields().get(0).indicativeSize()).isEqualTo(20); - assertThat(def.fields().get(1).key()).isEqualTo("second"); - assertThat(def.fields().get(1).name()).isEqualTo("Second"); - assertThat(def.fields().get(1).type()).isEqualTo(PropertyType.INTEGER); - assertThat(def.fields().get(1).options()).isEmpty(); - assertThat(def.fields().get(1).indicativeSize()).isEqualTo(5); - } - - @Test - public void should_support_property_sets_from_annotation() { - Properties props = AnnotationUtils.getAnnotation(WithPropertySet.class, Properties.class); - Property prop = props.value()[0]; - - PropertyDefinition def = PropertyDefinition.create(prop); - - assertThat(def.fields()).hasSize(2); - assertThat(def.fields().get(0).key()).isEqualTo("first"); - assertThat(def.fields().get(0).name()).isEqualTo("First"); - assertThat(def.fields().get(0).description()).isEqualTo("Description"); - assertThat(def.fields().get(0).type()).isEqualTo(PropertyType.STRING); - assertThat(def.fields().get(0).options()).containsOnly("A", "B"); - assertThat(def.fields().get(0).indicativeSize()).isEqualTo(20); - assertThat(def.fields().get(1).key()).isEqualTo("second"); - assertThat(def.fields().get(1).name()).isEqualTo("Second"); - assertThat(def.fields().get(1).type()).isEqualTo(PropertyType.INTEGER); - assertThat(def.fields().get(1).options()).isEmpty(); - assertThat(def.fields().get(1).indicativeSize()).isEqualTo(5); - } - - @Test - public void should_validate_string() { - PropertyDefinition def = PropertyDefinition.builder("foo").name("foo").type(PropertyType.STRING).build(); - - assertThat(def.validate(null).isValid()).isTrue(); - assertThat(def.validate("").isValid()).isTrue(); - assertThat(def.validate(" ").isValid()).isTrue(); - assertThat(def.validate("foo").isValid()).isTrue(); - } - - @Test - public void should_validate_boolean() { - PropertyDefinition def = PropertyDefinition.builder("foo").name("foo").type(PropertyType.BOOLEAN).build(); - - assertThat(def.validate(null).isValid()).isTrue(); - assertThat(def.validate("").isValid()).isTrue(); - assertThat(def.validate(" ").isValid()).isTrue(); - assertThat(def.validate("true").isValid()).isTrue(); - assertThat(def.validate("false").isValid()).isTrue(); - - assertThat(def.validate("foo").isValid()).isFalse(); - assertThat(def.validate("foo").getErrorKey()).isEqualTo("notBoolean"); - } - - @Test - public void should_validate_integer() { - PropertyDefinition def = PropertyDefinition.builder("foo").name("foo").type(PropertyType.INTEGER).build(); - - assertThat(def.validate(null).isValid()).isTrue(); - assertThat(def.validate("").isValid()).isTrue(); - assertThat(def.validate(" ").isValid()).isTrue(); - assertThat(def.validate("123456").isValid()).isTrue(); - - assertThat(def.validate("foo").isValid()).isFalse(); - assertThat(def.validate("foo").getErrorKey()).isEqualTo("notInteger"); - } - - @Test - public void should_validate_float() { - PropertyDefinition def = PropertyDefinition.builder("foo").name("foo").type(PropertyType.FLOAT).build(); - - assertThat(def.validate(null).isValid()).isTrue(); - assertThat(def.validate("").isValid()).isTrue(); - assertThat(def.validate(" ").isValid()).isTrue(); - assertThat(def.validate("123456").isValid()).isTrue(); - assertThat(def.validate("3.14").isValid()).isTrue(); - - assertThat(def.validate("foo").isValid()).isFalse(); - assertThat(def.validate("foo").getErrorKey()).isEqualTo("notFloat"); - } - - @Test - public void should_validate_single_select_list() { - PropertyDefinition def = PropertyDefinition.builder("foo").name("foo").type(PropertyType.SINGLE_SELECT_LIST).options("de", "en").build(); - - assertThat(def.validate(null).isValid()).isTrue(); - assertThat(def.validate("").isValid()).isTrue(); - assertThat(def.validate(" ").isValid()).isTrue(); - assertThat(def.validate("de").isValid()).isTrue(); - assertThat(def.validate("en").isValid()).isTrue(); - - assertThat(def.validate("fr").isValid()).isFalse(); - assertThat(def.validate("fr").getErrorKey()).isEqualTo("notInOptions"); - } - - @Test - public void should_auto_detect_password_type() { - PropertyDefinition def = PropertyDefinition.builder("scm.password.secured").name("SCM password").build(); - - assertThat(def.key()).isEqualTo("scm.password.secured"); - assertThat(def.type()).isEqualTo(PropertyType.PASSWORD); - } - - @Test - public void should_auto_detect_license_type() { - PropertyDefinition def = PropertyDefinition.builder("views.license.secured").name("Views license").build(); - - assertThat(def.key()).isEqualTo("views.license.secured"); - assertThat(def.type()).isEqualTo(PropertyType.LICENSE); - } - - @Test - public void should_not_authorise_empty_key() { - try { - PropertyDefinition.builder(null).build(); - fail(); - } catch (Exception e) { - assertThat(e).hasMessage("Key must be set").isInstanceOf(IllegalArgumentException.class); - } - } - - @Test - public void should_not_authorize_defining_on_qualifiers_and_hidden() { - try { - PropertyDefinition.builder("foo").name("foo").onQualifiers(Qualifiers.FILE).hidden().build(); - fail(); - } catch (Exception e) { - assertThat(e).hasMessage("Cannot be hidden and defining qualifiers on which to display").isInstanceOf(IllegalArgumentException.class); - } - } - - @Test - public void should_not_authorize_defining_ony_on_qualifiers_and_hidden() { - try { - PropertyDefinition.builder("foo").name("foo").onlyOnQualifiers(Qualifiers.FILE).hidden().build(); - fail(); - } catch (Exception e) { - assertThat(e).hasMessage("Cannot be hidden and defining qualifiers on which to display").isInstanceOf(IllegalArgumentException.class); - } - } - - @Test - public void should_not_authorize_defining_on_qualifiers_and_only_on_qualifiers() { - try { - PropertyDefinition.builder("foo").name("foo").onQualifiers(Qualifiers.FILE).onlyOnQualifiers(Qualifiers.PROJECT).build(); - fail(); - } catch (Exception e) { - assertThat(e).hasMessage("Cannot define both onQualifiers and onlyOnQualifiers").isInstanceOf(IllegalArgumentException.class); - } - } - - @Properties(@Property(key = "hello", name = "Hello", defaultValue = "world", description = "desc", - options = {"de", "en"}, category = "categ", type = PropertyType.FLOAT, global = false, project = true, module = true, multiValues = true, propertySetKey = "set")) - static class Init { - } - - @Properties(@Property(key = "hello", name = "Hello", fields = { - @PropertyField(key = "first", name = "First", description = "Description", options = {"A", "B"}), - @PropertyField(key = "second", name = "Second", type = PropertyType.INTEGER, indicativeSize = 5)})) - static class WithPropertySet { - } - - @Properties(@Property(key = "hello", name = "Hello")) - static class DefaultValues { - } - -} diff --git a/sonar-plugin-api/src/test/java/org/sonar/api/config/PropertyDefinitionsTest.java b/sonar-plugin-api/src/test/java/org/sonar/api/config/PropertyDefinitionsTest.java index f21fb611206..cdd9afc4f0e 100644 --- a/sonar-plugin-api/src/test/java/org/sonar/api/config/PropertyDefinitionsTest.java +++ b/sonar-plugin-api/src/test/java/org/sonar/api/config/PropertyDefinitionsTest.java @@ -31,9 +31,9 @@ public class PropertyDefinitionsTest { @Test public void should_inspect_plugin_objects() { PropertyDefinitions def = new PropertyDefinitions( - PropertyDefinition.builder("foo").name("Foo").build(), - PropertyDefinition.builder("one").name("One").build(), - PropertyDefinition.builder("two").name("Two").defaultValue("2").build() + PropertyDef.builder("foo").name("Foo").build(), + PropertyDef.builder("one").name("One").build(), + PropertyDef.builder("two").name("Two").defaultValue("2").build() ); assertProperties(def); @@ -56,8 +56,8 @@ public class PropertyDefinitionsTest { @Test public void test_categories() { PropertyDefinitions def = new PropertyDefinitions( - PropertyDefinition.builder("inCateg").name("In Categ").category("categ").build(), - PropertyDefinition.builder("noCateg").name("No categ").build() + PropertyDef.builder("inCateg").name("In Categ").category("categ").build(), + PropertyDef.builder("noCateg").name("No categ").build() ); assertThat(def.getCategory("inCateg")).isEqualTo("categ"); @@ -75,8 +75,8 @@ public class PropertyDefinitionsTest { @Test public void test_default_category() { PropertyDefinitions def = new PropertyDefinitions(); - def.addComponent(PropertyDefinition.builder("inCateg").name("In Categ").category("categ").build(), "default"); - def.addComponent(PropertyDefinition.builder("noCateg").name("No categ").build(), "default"); + def.addComponent(PropertyDef.builder("inCateg").name("In Categ").category("categ").build(), "default"); + def.addComponent(PropertyDef.builder("noCateg").name("No categ").build(), "default"); assertThat(def.getCategory("inCateg")).isEqualTo("categ"); assertThat(def.getCategory("noCateg")).isEqualTo("default"); @@ -93,12 +93,12 @@ public class PropertyDefinitionsTest { @Test public void should_group_by_category() { PropertyDefinitions def = new PropertyDefinitions( - PropertyDefinition.builder("global1").name("Global1").category("catGlobal1").build(), - PropertyDefinition.builder("global2").name("Global2").category("catGlobal1").build(), - PropertyDefinition.builder("global3").name("Global3").category("catGlobal2").build(), - PropertyDefinition.builder("project").name("Project").category("catProject").onlyOnQualifiers(Qualifiers.PROJECT).build(), - PropertyDefinition.builder("module").name("Module").category("catModule").onlyOnQualifiers(Qualifiers.MODULE).build(), - PropertyDefinition.builder("view").name("View").category("catView").onlyOnQualifiers(Qualifiers.VIEW).build() + PropertyDef.builder("global1").name("Global1").category("catGlobal1").build(), + PropertyDef.builder("global2").name("Global2").category("catGlobal1").build(), + PropertyDef.builder("global3").name("Global3").category("catGlobal2").build(), + PropertyDef.builder("project").name("Project").category("catProject").onlyOnQualifiers(Qualifiers.PROJECT).build(), + PropertyDef.builder("module").name("Module").category("catModule").onlyOnQualifiers(Qualifiers.MODULE).build(), + PropertyDef.builder("view").name("View").category("catView").onlyOnQualifiers(Qualifiers.VIEW).build() ); assertThat(def.getPropertiesByCategory(null).keySet()).containsOnly("catGlobal1", "catGlobal2"); @@ -111,10 +111,10 @@ public class PropertyDefinitionsTest { @Test public void should_group_by_subcategory() { PropertyDefinitions def = new PropertyDefinitions( - PropertyDefinition.builder("global1").name("Global1").category("catGlobal1").subcategory("sub1").build(), - PropertyDefinition.builder("global2").name("Global2").category("catGlobal1").subcategory("sub2").build(), - PropertyDefinition.builder("global3").name("Global3").category("catGlobal1").build(), - PropertyDefinition.builder("global4").name("Global4").category("catGlobal2").build() + PropertyDef.builder("global1").name("Global1").category("catGlobal1").subcategory("sub1").build(), + PropertyDef.builder("global2").name("Global2").category("catGlobal1").subcategory("sub2").build(), + PropertyDef.builder("global3").name("Global3").category("catGlobal1").build(), + PropertyDef.builder("global4").name("Global4").category("catGlobal2").build() ); assertThat(def.getPropertiesByCategory(null).get("catGlobal1").keySet()).containsOnly("default", "sub1", "sub2"); diff --git a/sonar-server/src/main/java/org/sonar/server/startup/RenameDeprecatedPropertyKeys.java b/sonar-server/src/main/java/org/sonar/server/startup/RenameDeprecatedPropertyKeys.java index 68e6ccf27d9..93bcd99ca3e 100644 --- a/sonar-server/src/main/java/org/sonar/server/startup/RenameDeprecatedPropertyKeys.java +++ b/sonar-server/src/main/java/org/sonar/server/startup/RenameDeprecatedPropertyKeys.java @@ -21,7 +21,7 @@ package org.sonar.server.startup; import com.google.common.base.Strings; import org.slf4j.LoggerFactory; -import org.sonar.api.config.PropertyDefinition; +import org.sonar.api.config.PropertyDef; import org.sonar.api.config.PropertyDefinitions; import org.sonar.core.properties.PropertiesDao; @@ -40,7 +40,7 @@ public class RenameDeprecatedPropertyKeys { public void start() { LoggerFactory.getLogger(RenameDeprecatedPropertyKeys.class).info("Rename deprecated property keys"); - for (PropertyDefinition definition : definitions.getAll()) { + for (PropertyDef definition : definitions.getAll()) { if (!Strings.isNullOrEmpty(definition.deprecatedKey())) { dao.renamePropertyKey(definition.deprecatedKey(), definition.key()); } -- cgit v1.2.3