001 /*
002 * Sonar, open source software quality management tool.
003 * Copyright (C) 2009 SonarSource SA
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.checks.checkers;
021
022 import org.apache.commons.lang.StringUtils;
023 import org.sonar.api.checks.profiles.Check;
024 import org.sonar.api.checks.profiles.CheckProfile;
025 import org.sonar.check.AnnotationIntrospector;
026 import org.sonar.check.CheckProperty;
027
028 import java.lang.reflect.Field;
029 import java.util.Collection;
030 import java.util.HashMap;
031 import java.util.IdentityHashMap;
032 import java.util.Map;
033
034 /**
035 * @since 2.1 (experimental)
036 * @deprecated since 2.3
037 */
038 @Deprecated
039
040 public class AnnotationCheckerFactory<CHECKER> extends CheckerFactory<CHECKER> {
041
042 private CheckProfile profile;
043 private String repositoryKey;
044 private Collection<Class<CHECKER>> checkerClasses;
045
046 public AnnotationCheckerFactory(CheckProfile profile, String repositoryKey, Collection<Class<CHECKER>> checkerClasses) {
047 this.profile = profile;
048 this.repositoryKey = repositoryKey;
049 this.checkerClasses = checkerClasses;
050 }
051
052 public Map<Check, CHECKER> create() {
053 Map<String, Class<CHECKER>> classesByKey = getClassesByKey(checkerClasses);
054
055 Map<Check, CHECKER> map = new IdentityHashMap<Check, CHECKER>();
056 for (Check check : profile.getChecks(repositoryKey)) {
057 Class<CHECKER> clazz = classesByKey.get(check.getTemplateKey());
058 if (clazz != null) {
059 CHECKER checker = instantiate(check, clazz);
060 if (checker != null) {
061 map.put(check, checker);
062 }
063 }
064 }
065 return map;
066 }
067
068 CHECKER instantiate(Check check, Class<CHECKER> clazz) {
069 try {
070 CHECKER checker = clazz.newInstance();
071 configureFields(check, checker);
072 return checker;
073
074 } catch (UnvalidCheckerException e) {
075 throw e;
076
077 } catch (Exception e) {
078 throw new UnvalidCheckerException("The checker " + clazz.getCanonicalName() + " can not be created", e);
079 }
080 }
081
082 private void configureFields(Check check, CHECKER checker) throws IllegalAccessException {
083 for (Map.Entry<String, String> entry : check.getProperties().entrySet()) {
084 Field field = getField(checker, entry.getKey());
085 if (field == null) {
086 throw new UnvalidCheckerException("The field " + entry.getKey() + " does not exist or is not annotated with @CheckProperty");
087 }
088 if (StringUtils.isNotBlank(entry.getValue())) {
089 configureField(checker, field, entry);
090 }
091 }
092
093 }
094
095 private void configureField(Object checker, Field field, Map.Entry<String, String> parameter) throws IllegalAccessException {
096 field.setAccessible(true);
097
098 if (field.getType().equals(String.class)) {
099 field.set(checker, parameter.getValue());
100
101 } else if (field.getType().getSimpleName().equals("int")) {
102 field.setInt(checker, Integer.parseInt(parameter.getValue()));
103
104 } else if (field.getType().getSimpleName().equals("short")) {
105 field.setShort(checker, Short.parseShort(parameter.getValue()));
106
107 } else if (field.getType().getSimpleName().equals("long")) {
108 field.setLong(checker, Long.parseLong(parameter.getValue()));
109
110 } else if (field.getType().getSimpleName().equals("double")) {
111 field.setDouble(checker, Double.parseDouble(parameter.getValue()));
112
113 } else if (field.getType().getSimpleName().equals("boolean")) {
114 field.setBoolean(checker, Boolean.parseBoolean(parameter.getValue()));
115
116 } else if (field.getType().getSimpleName().equals("byte")) {
117 field.setByte(checker, Byte.parseByte(parameter.getValue()));
118
119 } else if (field.getType().equals(Integer.class)) {
120 field.set(checker, new Integer(Integer.parseInt(parameter.getValue())));
121
122 } else if (field.getType().equals(Long.class)) {
123 field.set(checker, new Long(Long.parseLong(parameter.getValue())));
124
125 } else if (field.getType().equals(Double.class)) {
126 field.set(checker, new Double(Double.parseDouble(parameter.getValue())));
127
128 } else if (field.getType().equals(Boolean.class)) {
129 field.set(checker, Boolean.valueOf(Boolean.parseBoolean(parameter.getValue())));
130
131 } else {
132 throw new UnvalidCheckerException("The type of the field " + field + " is not supported: " + field.getType());
133 }
134 }
135
136 private Field getField(Object checker, String key) {
137 Field[] fields = checker.getClass().getDeclaredFields();
138 for (Field field : fields) {
139 CheckProperty annotation = field.getAnnotation(CheckProperty.class);
140 if (annotation != null) {
141 if (key.equals(field.getName()) || key.equals(annotation.key())) {
142 return field;
143 }
144 }
145 }
146 return null;
147 }
148
149 private Map<String, Class<CHECKER>> getClassesByKey(Collection<Class<CHECKER>> checkerClasses) {
150 Map<String, Class<CHECKER>> result = new HashMap<String, Class<CHECKER>>();
151 for (Class<CHECKER> checkerClass : checkerClasses) {
152 String key = AnnotationIntrospector.getCheckKey(checkerClass);
153 if (key != null) {
154 result.put(key, checkerClass);
155 }
156 }
157 return result;
158 }
159
160 }