001 /*
002 * Sonar, open source software quality management tool.
003 * Copyright (C) 2008-2012 SonarSource
004 * mailto:contact AT sonarsource DOT com
005 *
006 * Sonar is free software; you can redistribute it and/or
007 * modify it under the terms of the GNU Lesser General Public
008 * License as published by the Free Software Foundation; either
009 * version 3 of the License, or (at your option) any later version.
010 *
011 * Sonar is distributed in the hope that it will be useful,
012 * but WITHOUT ANY WARRANTY; without even the implied warranty of
013 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
014 * Lesser General Public License for more details.
015 *
016 * You should have received a copy of the GNU Lesser General Public
017 * License along with Sonar; if not, write to the Free Software
018 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02
019 */
020 package org.sonar.api.config;
021
022 import org.apache.commons.lang.ArrayUtils;
023 import org.apache.commons.lang.StringUtils;
024 import org.apache.commons.lang.math.NumberUtils;
025 import org.sonar.api.Property;
026 import org.sonar.api.PropertyType;
027
028 import javax.annotation.Nullable;
029
030 /**
031 * @since 3.0
032 */
033 public final class PropertyDefinition {
034
035 public static final class Result {
036 private static final Result SUCCESS = new Result(null);
037
038 private String errorKey = null;
039
040 private static Result newError(String key) {
041 return new Result(key);
042 }
043
044 @Nullable
045 private Result(@Nullable String errorKey) {
046 this.errorKey = errorKey;
047 }
048
049 public boolean isValid() {
050 return StringUtils.isBlank(errorKey);
051 }
052
053 @Nullable
054 public String getErrorKey() {
055 return errorKey;
056 }
057 }
058
059 private String key;
060 private String defaultValue;
061 private String name;
062 private PropertyType type = PropertyType.STRING;
063 private String[] options;
064 private String description;
065 private String category;
066 private boolean onProject = false;
067 private boolean onModule = false;
068 private boolean isGlobal = true;
069
070 private PropertyDefinition(Property annotation) {
071 this.key = annotation.key();
072 this.name = annotation.name();
073 this.defaultValue = annotation.defaultValue();
074 this.description = annotation.description();
075 this.isGlobal = annotation.global();
076 this.onProject = annotation.project();
077 this.onModule = annotation.module();
078 this.category = annotation.category();
079 this.type = fixType(annotation.key(), annotation.type());
080 this.options = annotation.options();
081 }
082
083 private PropertyType fixType(String key, PropertyType type) {
084 // Auto-detect passwords and licenses for old versions of plugins that
085 // do not declare property types
086 PropertyType fix = type;
087 if (type == PropertyType.STRING) {
088 if (StringUtils.endsWith(key, ".password.secured")) {
089 fix = PropertyType.PASSWORD;
090 } else if (StringUtils.endsWith(key, ".license.secured")) {
091 fix = PropertyType.LICENSE;
092 }
093 }
094 return fix;
095 }
096
097 private PropertyDefinition(String key, PropertyType type, String[] options) {
098 this.key = key;
099 this.type = type;
100 this.options = options;
101 }
102
103 public static PropertyDefinition create(Property annotation) {
104 return new PropertyDefinition(annotation);
105 }
106
107 public static PropertyDefinition create(String key, PropertyType type, String[] options) {
108 return new PropertyDefinition(key, type, options);
109 }
110
111 public Result validate(@Nullable String value) {
112 // TODO REFACTORING REQUIRED HERE
113 Result result = Result.SUCCESS;
114 if (StringUtils.isNotBlank(value)) {
115 if (type == PropertyType.BOOLEAN) {
116 if (!StringUtils.equalsIgnoreCase(value, "true") && !StringUtils.equalsIgnoreCase(value, "false")) {
117 result = Result.newError("notBoolean");
118 }
119 } else if (type == PropertyType.INTEGER) {
120 if (!NumberUtils.isDigits(value)) {
121 result = Result.newError("notInteger");
122 }
123 } else if (type == PropertyType.FLOAT) {
124 try {
125 Double.parseDouble(value);
126 } catch (NumberFormatException e) {
127 result = Result.newError("notFloat");
128 }
129 } else if (type == PropertyType.SINGLE_SELECT_LIST) {
130 if (!ArrayUtils.contains(options, value)) {
131 result = Result.newError("notInOptions");
132 }
133 }
134 }
135 return result;
136 }
137
138 public String getKey() {
139 return key;
140 }
141
142 public String getDefaultValue() {
143 return defaultValue;
144 }
145
146 public String getName() {
147 return name;
148 }
149
150 public PropertyType getType() {
151 return type;
152 }
153
154 public String[] getOptions() {
155 return options.clone();
156 }
157
158 public String getDescription() {
159 return description;
160 }
161
162 public String getCategory() {
163 return category;
164 }
165
166 public boolean isOnProject() {
167 return onProject;
168 }
169
170 public boolean isOnModule() {
171 return onModule;
172 }
173
174 public boolean isGlobal() {
175 return isGlobal;
176 }
177 }