diff options
author | simonbrandhof <simon.brandhof@gmail.com> | 2010-09-06 14:08:06 +0000 |
---|---|---|
committer | simonbrandhof <simon.brandhof@gmail.com> | 2010-09-06 14:08:06 +0000 |
commit | aeadc1f9129274949daaa57738c7c4550bdfbc7b (patch) | |
tree | 08dadf5ef7474fc41d1d48f74648f1ba8b55f34d /sonar-plugin-api/src/main/java/org/sonar/api/checks | |
download | sonarqube-aeadc1f9129274949daaa57738c7c4550bdfbc7b.tar.gz sonarqube-aeadc1f9129274949daaa57738c7c4550bdfbc7b.zip |
SONAR-236 remove deprecated code from checkstyle plugin + display default value of rule parameters in Q profile console
Diffstat (limited to 'sonar-plugin-api/src/main/java/org/sonar/api/checks')
21 files changed, 1906 insertions, 0 deletions
diff --git a/sonar-plugin-api/src/main/java/org/sonar/api/checks/NoSonarFilter.java b/sonar-plugin-api/src/main/java/org/sonar/api/checks/NoSonarFilter.java new file mode 100644 index 00000000000..d583cae1575 --- /dev/null +++ b/sonar-plugin-api/src/main/java/org/sonar/api/checks/NoSonarFilter.java @@ -0,0 +1,50 @@ +/* + * Sonar, open source software quality management tool. + * Copyright (C) 2009 SonarSource SA + * mailto:contact AT sonarsource DOT com + * + * Sonar 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. + * + * Sonar 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 Sonar; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02 + */ +package org.sonar.api.checks; + +import org.sonar.api.resources.Resource; +import org.sonar.api.rules.Violation; +import org.sonar.api.rules.ViolationFilter; + +import java.util.HashMap; +import java.util.Map; +import java.util.Set; + +/** + * @since 2.1 + */ +public class NoSonarFilter implements ViolationFilter { + + private final Map<Resource, Set<Integer>> noSonarLinesByResource = new HashMap<Resource, Set<Integer>>(); + + public void addResource(Resource resource, Set<Integer> noSonarLines) { + if (resource != null && noSonarLines != null) { + noSonarLinesByResource.put(resource, noSonarLines); + } + } + + public boolean isIgnored(Violation violation) { + if (violation.getResource() != null && violation.getLineId() != null) { + Set<Integer> noSonarLines = noSonarLinesByResource.get(violation.getResource()); + return (noSonarLines != null && noSonarLines.contains(violation.getLineId())); + } + return false; + } +} diff --git a/sonar-plugin-api/src/main/java/org/sonar/api/checks/checkers/AnnotationCheckerFactory.java b/sonar-plugin-api/src/main/java/org/sonar/api/checks/checkers/AnnotationCheckerFactory.java new file mode 100644 index 00000000000..b12b8dcc34c --- /dev/null +++ b/sonar-plugin-api/src/main/java/org/sonar/api/checks/checkers/AnnotationCheckerFactory.java @@ -0,0 +1,157 @@ +/* + * Sonar, open source software quality management tool. + * Copyright (C) 2009 SonarSource SA + * mailto:contact AT sonarsource DOT com + * + * Sonar 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. + * + * Sonar 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 Sonar; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02 + */ +package org.sonar.api.checks.checkers; + +import org.apache.commons.lang.StringUtils; +import org.sonar.api.checks.profiles.Check; +import org.sonar.api.checks.profiles.CheckProfile; +import org.sonar.check.AnnotationIntrospector; +import org.sonar.check.CheckProperty; + +import java.lang.reflect.Field; +import java.util.Collection; +import java.util.HashMap; +import java.util.IdentityHashMap; +import java.util.Map; + +/** + * @since 2.1 + */ +public class AnnotationCheckerFactory<CHECKER> extends CheckerFactory<CHECKER> { + + private CheckProfile profile; + private String repositoryKey; + private Collection<Class<CHECKER>> checkerClasses; + + public AnnotationCheckerFactory(CheckProfile profile, String repositoryKey, Collection<Class<CHECKER>> checkerClasses) { + this.profile = profile; + this.repositoryKey = repositoryKey; + this.checkerClasses = checkerClasses; + } + + public Map<Check, CHECKER> create() { + Map<String, Class<CHECKER>> classesByKey = getClassesByKey(checkerClasses); + + Map<Check, CHECKER> map = new IdentityHashMap<Check, CHECKER>(); + for (Check check : profile.getChecks(repositoryKey)) { + Class<CHECKER> clazz = classesByKey.get(check.getTemplateKey()); + if (clazz != null) { + CHECKER checker = instantiate(check, clazz); + if (checker != null) { + map.put(check, checker); + } + } + } + return map; + } + + CHECKER instantiate(Check check, Class<CHECKER> clazz) { + try { + CHECKER checker = clazz.newInstance(); + configureFields(check, checker); + return checker; + + } catch (UnvalidCheckerException e) { + throw e; + + } catch (Exception e) { + throw new UnvalidCheckerException("The checker " + clazz.getCanonicalName() + " can not be created", e); + } + } + + private void configureFields(Check check, CHECKER checker) throws IllegalAccessException { + for (Map.Entry<String, String> entry : check.getProperties().entrySet()) { + Field field = getField(checker, entry.getKey()); + if (field == null) { + throw new UnvalidCheckerException("The field " + entry.getKey() + " does not exist or is not annotated with @CheckProperty"); + } + if (StringUtils.isNotBlank(entry.getValue())) { + configureField(checker, field, entry); + } + } + + } + + private void configureField(Object checker, Field field, Map.Entry<String, String> parameter) throws IllegalAccessException { + field.setAccessible(true); + + if (field.getType().equals(String.class)) { + field.set(checker, parameter.getValue()); + + } else if (field.getType().getSimpleName().equals("int")) { + field.setInt(checker, Integer.parseInt(parameter.getValue())); + + } else if (field.getType().getSimpleName().equals("short")) { + field.setShort(checker, Short.parseShort(parameter.getValue())); + + } else if (field.getType().getSimpleName().equals("long")) { + field.setLong(checker, Long.parseLong(parameter.getValue())); + + } else if (field.getType().getSimpleName().equals("double")) { + field.setDouble(checker, Double.parseDouble(parameter.getValue())); + + } else if (field.getType().getSimpleName().equals("boolean")) { + field.setBoolean(checker, Boolean.parseBoolean(parameter.getValue())); + + } else if (field.getType().getSimpleName().equals("byte")) { + field.setByte(checker, Byte.parseByte(parameter.getValue())); + + } else if (field.getType().equals(Integer.class)) { + field.set(checker, new Integer(Integer.parseInt(parameter.getValue()))); + + } else if (field.getType().equals(Long.class)) { + field.set(checker, new Long(Long.parseLong(parameter.getValue()))); + + } else if (field.getType().equals(Double.class)) { + field.set(checker, new Double(Double.parseDouble(parameter.getValue()))); + + } else if (field.getType().equals(Boolean.class)) { + field.set(checker, Boolean.valueOf(Boolean.parseBoolean(parameter.getValue()))); + + } else { + throw new UnvalidCheckerException("The type of the field " + field + " is not supported: " + field.getType()); + } + } + + private Field getField(Object checker, String key) { + Field[] fields = checker.getClass().getDeclaredFields(); + for (Field field : fields) { + CheckProperty annotation = field.getAnnotation(CheckProperty.class); + if (annotation != null) { + if (key.equals(field.getName()) || key.equals(annotation.key())) { + return field; + } + } + } + return null; + } + + private Map<String, Class<CHECKER>> getClassesByKey(Collection<Class<CHECKER>> checkerClasses) { + Map<String, Class<CHECKER>> result = new HashMap<String, Class<CHECKER>>(); + for (Class<CHECKER> checkerClass : checkerClasses) { + String key = AnnotationIntrospector.getCheckKey(checkerClass); + if (key != null) { + result.put(key, checkerClass); + } + } + return result; + } + +} diff --git a/sonar-plugin-api/src/main/java/org/sonar/api/checks/checkers/CheckerFactory.java b/sonar-plugin-api/src/main/java/org/sonar/api/checks/checkers/CheckerFactory.java new file mode 100644 index 00000000000..62d46f67de3 --- /dev/null +++ b/sonar-plugin-api/src/main/java/org/sonar/api/checks/checkers/CheckerFactory.java @@ -0,0 +1,31 @@ +/* + * Sonar, open source software quality management tool. + * Copyright (C) 2009 SonarSource SA + * mailto:contact AT sonarsource DOT com + * + * Sonar 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. + * + * Sonar 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 Sonar; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02 + */ +package org.sonar.api.checks.checkers; + +import org.sonar.api.checks.profiles.Check; + +import java.util.Map; + +/** + * @since 2.1 + */ +public abstract class CheckerFactory<CHECKER> { + public abstract Map<Check, CHECKER> create(); +} diff --git a/sonar-plugin-api/src/main/java/org/sonar/api/checks/checkers/MessageDispatcher.java b/sonar-plugin-api/src/main/java/org/sonar/api/checks/checkers/MessageDispatcher.java new file mode 100644 index 00000000000..6321210f2a5 --- /dev/null +++ b/sonar-plugin-api/src/main/java/org/sonar/api/checks/checkers/MessageDispatcher.java @@ -0,0 +1,106 @@ +/* + * Sonar, open source software quality management tool. + * Copyright (C) 2009 SonarSource SA + * mailto:contact AT sonarsource DOT com + * + * Sonar 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. + * + * Sonar 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 Sonar; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02 + */ +package org.sonar.api.checks.checkers; + +import com.google.common.collect.Maps; +import org.sonar.api.batch.SensorContext; +import org.sonar.api.checks.profiles.Check; +import org.sonar.api.checks.profiles.CheckProfile; +import org.sonar.api.resources.Resource; +import org.sonar.api.rules.Rule; +import org.sonar.api.rules.RulePriority; +import org.sonar.api.rules.Violation; +import org.sonar.check.Message; + +import java.util.Collection; +import java.util.Locale; +import java.util.Map; + +public class MessageDispatcher { + + private Map<Check, Object> checkersByCheck; + private Map<Object, Check> checksByChecker; + private SensorContext context; + + public MessageDispatcher(SensorContext context) { + this.context = context; + checkersByCheck = Maps.newIdentityHashMap(); + checksByChecker = Maps.newIdentityHashMap(); + } + + public void registerChecker(Check check, Object checker) { + checkersByCheck.put(check, checker); + checksByChecker.put(checker, check); + } + + public void registerCheckers(CheckerFactory factory) { + Map<Check, Object> map = factory.create(); + for (Map.Entry<Check, Object> entry : map.entrySet()) { + registerChecker(entry.getKey(), entry.getValue()); + } + } + + public void registerCheckers(CheckProfile profile) { + for (Check check : profile.getChecks()) { + registerChecker(check, check); + } + } + + public Object getChecker(Check check) { + return checkersByCheck.get(check); + } + + public Check getCheck(Object checker) { + return checksByChecker.get(checker); + } + + public Collection getCheckers() { + return checkersByCheck.values(); + } + + public void unregisterCheck(Check check) { + Object checker = checkersByCheck.remove(check); + if (checker != null) { + checksByChecker.remove(checker); + } + } + + public void unregisterChecks(CheckProfile profile) { + for (Check check : profile.getChecks()) { + unregisterCheck(check); + } + } + + public void log(Resource resource, Message message) { + Object checker = message.getChecker(); + Check check = getCheck(checker); + Violation violation = new Violation(new Rule(check.getRepositoryKey(), check.getTemplateKey()), resource); + violation.setLineId(message.getLine()); + violation.setMessage(message.getText(Locale.ENGLISH)); + violation.setPriority(RulePriority.fromCheckPriority(check.getPriority())); + context.saveViolation(violation); + } + + public void clear() { + checkersByCheck.clear(); + checksByChecker.clear(); + } + +}
\ No newline at end of file diff --git a/sonar-plugin-api/src/main/java/org/sonar/api/checks/checkers/UnvalidCheckerException.java b/sonar-plugin-api/src/main/java/org/sonar/api/checks/checkers/UnvalidCheckerException.java new file mode 100644 index 00000000000..e732b77c645 --- /dev/null +++ b/sonar-plugin-api/src/main/java/org/sonar/api/checks/checkers/UnvalidCheckerException.java @@ -0,0 +1,37 @@ +/* + * Sonar, open source software quality management tool. + * Copyright (C) 2009 SonarSource SA + * mailto:contact AT sonarsource DOT com + * + * Sonar 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. + * + * Sonar 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 Sonar; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02 + */ +package org.sonar.api.checks.checkers; + +public class UnvalidCheckerException extends RuntimeException { + public UnvalidCheckerException() { + } + + public UnvalidCheckerException(String message) { + super(message); + } + + public UnvalidCheckerException(String message, Throwable cause) { + super(message, cause); + } + + public UnvalidCheckerException(Throwable cause) { + super(cause); + } +} diff --git a/sonar-plugin-api/src/main/java/org/sonar/api/checks/profiles/AnnotationCheckProfileFactory.java b/sonar-plugin-api/src/main/java/org/sonar/api/checks/profiles/AnnotationCheckProfileFactory.java new file mode 100644 index 00000000000..056461b3953 --- /dev/null +++ b/sonar-plugin-api/src/main/java/org/sonar/api/checks/profiles/AnnotationCheckProfileFactory.java @@ -0,0 +1,67 @@ +/* + * Sonar, open source software quality management tool. + * Copyright (C) 2009 SonarSource SA + * mailto:contact AT sonarsource DOT com + * + * Sonar 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. + * + * Sonar 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 Sonar; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02 + */ +package org.sonar.api.checks.profiles; + +import org.sonar.check.AnnotationIntrospector; +import org.sonar.check.BelongsToProfile; +import org.sonar.check.BelongsToProfiles; + +import java.util.Collection; +import java.util.HashMap; +import java.util.Map; + +public final class AnnotationCheckProfileFactory { + + private AnnotationCheckProfileFactory() { + } + + public static Collection<CheckProfile> create(String repositoryKey, String language, Collection<Class> checkClasses) { + Map<String, CheckProfile> profilesByTitle = new HashMap<String, CheckProfile>(); + + if (checkClasses != null) { + for (Class aClass : checkClasses) { + BelongsToProfiles belongsToProfiles = (BelongsToProfiles) aClass.getAnnotation(BelongsToProfiles.class); + if (belongsToProfiles != null) { + for (BelongsToProfile belongsToProfile : belongsToProfiles.value()) { + registerProfile(profilesByTitle, aClass, belongsToProfile, repositoryKey, language); + } + } + BelongsToProfile belongsToProfile = (BelongsToProfile) aClass.getAnnotation(BelongsToProfile.class); + registerProfile(profilesByTitle, aClass, belongsToProfile, repositoryKey, language); + } + } + + return profilesByTitle.values(); + } + + private static void registerProfile(Map<String, CheckProfile> profilesByTitle, Class aClass, BelongsToProfile belongsToProfile, String repositoryKey, String language) { + if (belongsToProfile != null) { + String title = belongsToProfile.title(); + CheckProfile profile = profilesByTitle.get(title); + if (profile == null) { + profile = new CheckProfile(title, language); + profilesByTitle.put(title, profile); + } + Check check = new Check(repositoryKey, AnnotationIntrospector.getCheckKey(aClass)); + check.setPriority(belongsToProfile.priority()); + profile.addCheck(check); + } + } +} diff --git a/sonar-plugin-api/src/main/java/org/sonar/api/checks/profiles/Check.java b/sonar-plugin-api/src/main/java/org/sonar/api/checks/profiles/Check.java new file mode 100644 index 00000000000..617a084a695 --- /dev/null +++ b/sonar-plugin-api/src/main/java/org/sonar/api/checks/profiles/Check.java @@ -0,0 +1,109 @@ +/* + * Sonar, open source software quality management tool. + * Copyright (C) 2009 SonarSource SA + * mailto:contact AT sonarsource DOT com + * + * Sonar 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. + * + * Sonar 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 Sonar; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02 + */ +package org.sonar.api.checks.profiles; + +import org.apache.commons.lang.builder.ToStringBuilder; +import org.sonar.check.Priority; + +import java.util.HashMap; +import java.util.Map; + +/** + * EXPERIMENTAL - will be used in version 2.2 + */ +public class Check { + + private String repositoryKey; + private String templateKey; + private Priority priority = null; + private final Map<String, String> properties = new HashMap<String,String>(); + + public Check() { + } + + public Check(String repositoryKey, String templateKey) { + this.repositoryKey = repositoryKey; + this.templateKey = templateKey; + } + + public String getTemplateKey() { + return templateKey; + } + + public String getRepositoryKey() { + return repositoryKey; + } + + public void setRepositoryKey(String repositoryKey) { + this.repositoryKey = repositoryKey; + } + + public void setTemplateKey(String templateKey) { + this.templateKey = templateKey; + } + + public Priority getPriority() { + return priority; + } + + public void setPriority(Priority priority) { + this.priority = priority; + } + + public Map<String, String> getProperties() { + return properties; + } + + public String getProperty(String key) { + return properties.get(key); + } + + public void addProperty(String key, Object value) { + properties.put(key, value.toString()); + } + + public void addProperties(Map<String, String> properties) { + this.properties.putAll(properties); + } + + public void setProperties(Map<String, String> properties) { + this.properties.clear(); + this.properties.putAll(properties); + } + + @Override + public boolean equals(Object o) { + return o == this; + } + + @Override + public int hashCode() { + return super.hashCode(); + } + + @Override + public String toString() { + return new ToStringBuilder(this) + .append("repository", repositoryKey) + .append("template", templateKey) + .append("priority", priority) + .toString(); + } +} diff --git a/sonar-plugin-api/src/main/java/org/sonar/api/checks/profiles/CheckProfile.java b/sonar-plugin-api/src/main/java/org/sonar/api/checks/profiles/CheckProfile.java new file mode 100644 index 00000000000..7bb3c560af5 --- /dev/null +++ b/sonar-plugin-api/src/main/java/org/sonar/api/checks/profiles/CheckProfile.java @@ -0,0 +1,131 @@ +/* + * Sonar, open source software quality management tool. + * Copyright (C) 2009 SonarSource SA + * mailto:contact AT sonarsource DOT com + * + * Sonar 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. + * + * Sonar 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 Sonar; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02 + */ +package org.sonar.api.checks.profiles; + +import org.sonar.api.BatchExtension; +import org.sonar.api.ServerExtension; + +import java.util.ArrayList; +import java.util.Collection; +import java.util.List; + +public class CheckProfile implements BatchExtension, ServerExtension { + + private String name; + private String language; + private List<Check> checks = new ArrayList<Check>(); + + public CheckProfile(String name, String language) { + if (name == null) { + throw new IllegalArgumentException("Name can not be null"); + } + if (language == null) { + throw new IllegalArgumentException("Language can not be null"); + } + this.name = name; + this.language = language; + } + + public String getName() { + return name; + } + + public String getLanguage() { + return language; + } + + public List<Check> getChecks() { + return checks; + } + + public List<Check> getChecks(String repositoryKey) { + List<Check> result = new ArrayList<Check>(); + for (Check check : getChecks()) { + if (check.getRepositoryKey().equals(repositoryKey)) { + result.add(check); + } + } + return result; + } + + public List<Check> getChecks(String repositoryKey, String templateKey) { + List<Check> result = new ArrayList<Check>(); + List<Check> repoChecks = getChecks(repositoryKey); + for (Check repoCheck : repoChecks) { + if (repoCheck.getTemplateKey().equals(templateKey)) { + result.add(repoCheck); + } + } + return result; + } + + /** + * We assume there is only one check for this template + */ + public Check getCheck(String repositoryKey, String templateKey) { + List<Check> repoChecks = getChecks(repositoryKey); + for (Check repoCheck : repoChecks) { + if (repoCheck.getTemplateKey().equals(templateKey)) { + return repoCheck; + } + } + return null; + } + + public void addCheck(Check check) { + checks.add(check); + } + + public void setChecks(Collection<Check> list) { + checks.clear(); + checks.addAll(list); + } + + @Override + public boolean equals(Object o) { + if (this == o) { + return true; + } + if (o == null || getClass() != o.getClass()) { + return false; + } + + CheckProfile profile = (CheckProfile) o; + if (!language.equals(profile.language)) { + return false; + } + if (!name.equals(profile.name)) { + return false; + } + return true; + } + + @Override + public int hashCode() { + int result = name.hashCode(); + result = 31 * result + language.hashCode(); + return result; + } + + @Override + public String toString() { + return name; + } +} diff --git a/sonar-plugin-api/src/main/java/org/sonar/api/checks/profiles/CheckProfileProvider.java b/sonar-plugin-api/src/main/java/org/sonar/api/checks/profiles/CheckProfileProvider.java new file mode 100644 index 00000000000..8eb21ef01da --- /dev/null +++ b/sonar-plugin-api/src/main/java/org/sonar/api/checks/profiles/CheckProfileProvider.java @@ -0,0 +1,33 @@ +/* + * Sonar, open source software quality management tool. + * Copyright (C) 2009 SonarSource SA + * mailto:contact AT sonarsource DOT com + * + * Sonar 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. + * + * Sonar 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 Sonar; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02 + */ +package org.sonar.api.checks.profiles; + +import org.sonar.api.ServerExtension; + +import java.util.Collection; + +/** + * EXPERIMENTAL - will be used in version 2.2 + */ +public abstract class CheckProfileProvider implements ServerExtension { + + public abstract Collection<CheckProfile> provide(); + +} diff --git a/sonar-plugin-api/src/main/java/org/sonar/api/checks/profiles/CheckProfileXmlMarshaller.java b/sonar-plugin-api/src/main/java/org/sonar/api/checks/profiles/CheckProfileXmlMarshaller.java new file mode 100644 index 00000000000..3203b14e1e3 --- /dev/null +++ b/sonar-plugin-api/src/main/java/org/sonar/api/checks/profiles/CheckProfileXmlMarshaller.java @@ -0,0 +1,154 @@ +/* + * Sonar, open source software quality management tool. + * Copyright (C) 2009 SonarSource SA + * mailto:contact AT sonarsource DOT com + * + * Sonar 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. + * + * Sonar 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 Sonar; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02 + */ +package org.sonar.api.checks.profiles; + +import com.thoughtworks.xstream.XStream; +import com.thoughtworks.xstream.converters.Converter; +import com.thoughtworks.xstream.converters.MarshallingContext; +import com.thoughtworks.xstream.converters.UnmarshallingContext; +import com.thoughtworks.xstream.io.HierarchicalStreamReader; +import com.thoughtworks.xstream.io.HierarchicalStreamWriter; +import com.thoughtworks.xstream.io.xml.CompactWriter; +import com.thoughtworks.xstream.io.xml.XppDriver; +import org.apache.commons.io.IOUtils; +import org.sonar.check.Priority; + +import java.io.InputStreamReader; +import java.io.Reader; +import java.io.Writer; +import java.util.Map; + +/** + * EXPERIMENTAL - will be used in version 2.3 + */ +public final class CheckProfileXmlMarshaller { + + public static void toXml(CheckProfile profile, Writer writer) { + getXStream().toXML(profile, writer); + } + + public static CheckProfile fromXml(Reader xml) { + return (CheckProfile) getXStream().fromXML(xml); + } + + public static CheckProfile fromXmlInClasspath(String pathToXml) { + return fromXmlInClasspath(pathToXml, CheckProfileXmlMarshaller.class); + } + + public static CheckProfile fromXmlInClasspath(String pathToXml, Class clazz) { + Reader reader = new InputStreamReader(clazz.getResourceAsStream(pathToXml)); + try { + return fromXml(reader); + } finally { + IOUtils.closeQuietly(reader); + } + } + + private static XStream getXStream() { + XStream xstream = new XStream(new CompactDriver()); + xstream.setClassLoader(CheckProfileXmlMarshaller.class.getClassLoader()); + xstream.registerConverter(new CheckConverter()); + xstream.alias("profile", CheckProfile.class); + xstream.alias("check", Check.class); + xstream.addImplicitCollection(CheckProfile.class, "checks"); + return xstream; + } + + private static class CompactDriver extends XppDriver { + @Override + public HierarchicalStreamWriter createWriter(Writer out) { + return new XDataPrintWriter(out); + } + } + + + private static class XDataPrintWriter extends CompactWriter { + public XDataPrintWriter(Writer writer) { + super(writer, XML_1_0); + } + } + + private static class CheckConverter implements Converter { + + public boolean canConvert(Class clazz) { + return clazz.equals(Check.class); + } + + public void marshal(Object value, HierarchicalStreamWriter writer, MarshallingContext context) { + Check check = (Check) value; + writer.startNode("repository"); + writer.setValue(check.getRepositoryKey()); + writer.endNode(); + writer.startNode("template"); + writer.setValue(check.getTemplateKey()); + writer.endNode(); + writer.startNode("priority"); + writer.setValue(check.getPriority().toString()); + writer.endNode(); + for (Map.Entry<String, String> entry : check.getProperties().entrySet()) { + if (entry.getValue() != null) { + writer.startNode("property"); + writer.startNode("key"); + writer.setValue(entry.getKey()); + writer.endNode(); + writer.startNode("value"); + // TODO is escaping automatically supported by xstream ? + writer.setValue(entry.getValue()); + writer.endNode(); + writer.endNode(); + } + } + } + + public Object unmarshal(HierarchicalStreamReader reader, + UnmarshallingContext context) { + Check check = new Check(); + while (reader.hasMoreChildren()) { + reader.moveDown(); + readValue(reader, check); + reader.moveUp(); + } + return check; + } + + private void readValue(HierarchicalStreamReader reader, Check check) { + if (reader.getNodeName().equals("repository")) { + check.setRepositoryKey(reader.getValue()); + + } else if (reader.getNodeName().equals("template")) { + check.setTemplateKey(reader.getValue()); + + } else if (reader.getNodeName().equals("priority")) { + check.setPriority(Priority.valueOf(reader.getValue())); + + } else if (reader.getNodeName().equals("property")) { + reader.moveDown(); + String key = reader.getValue(); + reader.moveUp(); + + reader.moveDown(); + String value = reader.getValue(); + reader.moveUp(); + check.addProperty(key, value); + } + } + + } +} diff --git a/sonar-plugin-api/src/main/java/org/sonar/api/checks/templates/AnnotationCheckTemplateFactory.java b/sonar-plugin-api/src/main/java/org/sonar/api/checks/templates/AnnotationCheckTemplateFactory.java new file mode 100644 index 00000000000..7ea9638c8e7 --- /dev/null +++ b/sonar-plugin-api/src/main/java/org/sonar/api/checks/templates/AnnotationCheckTemplateFactory.java @@ -0,0 +1,112 @@ +/* + * Sonar, open source software quality management tool. + * Copyright (C) 2009 SonarSource SA + * mailto:contact AT sonarsource DOT com + * + * Sonar 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. + * + * Sonar 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 Sonar; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02 + */ +package org.sonar.api.checks.templates; + +import org.apache.commons.lang.StringUtils; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; +import org.sonar.check.AnnotationIntrospector; + +import java.lang.reflect.Field; +import java.util.ArrayList; +import java.util.Collection; +import java.util.List; + +/** + * Load templates from class annotations (see the library sonar-check-api) + */ +public class AnnotationCheckTemplateFactory { + + private static final Logger LOG = LoggerFactory.getLogger(AnnotationCheckTemplateFactory.class); + + private Collection<Class> annotatedClasses; + + public AnnotationCheckTemplateFactory(Collection<Class> annotatedClasses) { + this.annotatedClasses = annotatedClasses; + } + + public List<CheckTemplate> create() { + List<CheckTemplate> templates = new ArrayList<CheckTemplate>(); + for (Class annotatedClass : annotatedClasses) { + BundleCheckTemplate template = create(annotatedClass); + if (template != null) { + templates.add(template); + } + } + return templates; + } + + + protected BundleCheckTemplate create(Class annotatedClass) { + org.sonar.check.Check checkAnnotation = AnnotationIntrospector.getCheckAnnotation(annotatedClass); + if (checkAnnotation == null) { + LOG.warn("The class " + annotatedClass.getCanonicalName() + " is not a check template. It should be annotated with " + CheckTemplate.class); + return null; + } + + BundleCheckTemplate check = toTemplate(annotatedClass, checkAnnotation); + Field[] fields = annotatedClass.getDeclaredFields(); + if (fields != null) { + for (Field field : fields) { + BundleCheckTemplateProperty property = toProperty(check, field); + if (property != null) { + check.addProperty(property); + } + } + } + return check; + } + + private static BundleCheckTemplate toTemplate(Class annotatedClass, org.sonar.check.Check checkAnnotation) { + String key = AnnotationIntrospector.getCheckKey(annotatedClass); + String bundle = getBundleBaseName(checkAnnotation, annotatedClass); + + BundleCheckTemplate check = new BundleCheckTemplate(key, bundle); + check.setDefaultDescription(checkAnnotation.description()); + check.setDefaultTitle(checkAnnotation.title()); + check.setIsoCategory(checkAnnotation.isoCategory()); + check.setPriority(checkAnnotation.priority()); + + return check; + } + + private static String getBundleBaseName(org.sonar.check.Check checkAnnotation, Class annotatedClass) { + String bundle = checkAnnotation.bundle(); + if (StringUtils.isBlank(bundle)) { + bundle = annotatedClass.getCanonicalName(); + } + return bundle; + } + + private static BundleCheckTemplateProperty toProperty(BundleCheckTemplate check, Field field) { + org.sonar.check.CheckProperty propertyAnnotation = field.getAnnotation(org.sonar.check.CheckProperty.class); + if (propertyAnnotation != null) { + String fieldKey = propertyAnnotation.key(); + if (fieldKey==null || "".equals(fieldKey)) { + fieldKey = field.getName(); + } + BundleCheckTemplateProperty property = new BundleCheckTemplateProperty(check, fieldKey); + property.setDefaultTitle(propertyAnnotation.title()); + property.setDefaultDescription(propertyAnnotation.description()); + return property; + } + return null; + } +} diff --git a/sonar-plugin-api/src/main/java/org/sonar/api/checks/templates/BundleCheckTemplate.java b/sonar-plugin-api/src/main/java/org/sonar/api/checks/templates/BundleCheckTemplate.java new file mode 100644 index 00000000000..c1b50cc1676 --- /dev/null +++ b/sonar-plugin-api/src/main/java/org/sonar/api/checks/templates/BundleCheckTemplate.java @@ -0,0 +1,110 @@ +/* + * Sonar, open source software quality management tool. + * Copyright (C) 2009 SonarSource SA + * mailto:contact AT sonarsource DOT com + * + * Sonar 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. + * + * Sonar 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 Sonar; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02 + */ +package org.sonar.api.checks.templates; + +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +import java.util.Locale; +import java.util.MissingResourceException; +import java.util.ResourceBundle; + +/** + * Internationalized check template. Translations are loaded from resource bundles (properties files in the classpath) + * + * @since 2.1 + */ +public class BundleCheckTemplate extends CheckTemplate { + private static final Logger LOG = LoggerFactory.getLogger(BundleCheckTemplate.class); + + private String bundleBaseName; + private String defaultTitle; + private String defaultDescription; + + protected BundleCheckTemplate(String key, String bundleBaseName) { + super(key); + this.bundleBaseName = bundleBaseName; + } + + protected BundleCheckTemplate(String key, Class bundleClass) { + this(key, bundleClass.getCanonicalName()); + } + + protected String getDefaultTitle() { + if (defaultTitle == null || "".equals(defaultTitle)) { + return getKey(); + } + return defaultTitle; + } + + protected void setDefaultTitle(String defaultTitle) { + this.defaultTitle = defaultTitle; + } + + protected String getDefaultDescription() { + return defaultDescription; + } + + protected void setDefaultDescription(String defaultDescription) { + this.defaultDescription = defaultDescription; + } + + @Override + public String getTitle(Locale locale) { + return getText("title", locale, getDefaultTitle()); + } + + @Override + public String getDescription(Locale locale) { + return getText("description", locale, getDefaultDescription()); + } + + @Override + public String getMessage(Locale locale, String key, Object... params) { + return null; + } + + protected String getText(String key, Locale locale, String defaultValue) { + String result = null; + ResourceBundle bundle = getBundle(locale); + if (bundle != null) { + try { + result = bundle.getString(key); + } catch (MissingResourceException e) { + LOG.debug(e.getMessage()); + } + } + if (result == null) { + result = defaultValue; + } + return result; + } + + protected ResourceBundle getBundle(Locale locale) { + try { + if (locale != null) { + return ResourceBundle.getBundle(bundleBaseName, locale); + } + } catch (MissingResourceException e) { + // do nothing : use the default values + } + return null; + } +} diff --git a/sonar-plugin-api/src/main/java/org/sonar/api/checks/templates/BundleCheckTemplateProperty.java b/sonar-plugin-api/src/main/java/org/sonar/api/checks/templates/BundleCheckTemplateProperty.java new file mode 100644 index 00000000000..10dd2cbfefc --- /dev/null +++ b/sonar-plugin-api/src/main/java/org/sonar/api/checks/templates/BundleCheckTemplateProperty.java @@ -0,0 +1,64 @@ +/* + * Sonar, open source software quality management tool. + * Copyright (C) 2009 SonarSource SA + * mailto:contact AT sonarsource DOT com + * + * Sonar 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. + * + * Sonar 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 Sonar; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02 + */ +package org.sonar.api.checks.templates; + +import java.util.Locale; + +public class BundleCheckTemplateProperty extends CheckTemplateProperty { + + private BundleCheckTemplate check; + private String defaultTitle; + private String defaultDescription; + + public BundleCheckTemplateProperty(BundleCheckTemplate check, String key) { + setKey(key); + this.check = check; + } + + public String getDefaultTitle() { + if (defaultTitle == null || "".equals(defaultTitle)) { + return getKey(); + } + return defaultTitle; + } + + public void setDefaultTitle(String s) { + this.defaultTitle = s; + } + + + @Override + public String getTitle(Locale locale) { + return check.getText("property." + getKey() + ".title", locale, getDefaultTitle()); + } + + public String getDefaultDescription() { + return defaultDescription; + } + + public void setDefaultDescription(String s) { + this.defaultDescription = s; + } + + @Override + public String getDescription(Locale locale) { + return check.getText("property." + getKey() + ".description", locale, getDefaultDescription()); + } +} diff --git a/sonar-plugin-api/src/main/java/org/sonar/api/checks/templates/CheckTemplate.java b/sonar-plugin-api/src/main/java/org/sonar/api/checks/templates/CheckTemplate.java new file mode 100644 index 00000000000..f2dc214ce56 --- /dev/null +++ b/sonar-plugin-api/src/main/java/org/sonar/api/checks/templates/CheckTemplate.java @@ -0,0 +1,134 @@ +/* + * Sonar, open source software quality management tool. + * Copyright (C) 2009 SonarSource SA + * mailto:contact AT sonarsource DOT com + * + * Sonar 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. + * + * Sonar 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 Sonar; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02 + */ +package org.sonar.api.checks.templates; + +import org.sonar.check.IsoCategory; +import org.sonar.check.Priority; + +import java.util.ArrayList; +import java.util.Collections; +import java.util.List; +import java.util.Locale; + +/** + * EXPERIMENTAL - will be used in version 2.2 + * + * @since 2.1 + */ +public abstract class CheckTemplate { + + protected String key; + protected String configKey; + protected Priority priority; + protected IsoCategory isoCategory; + protected List<CheckTemplateProperty> properties; + + public CheckTemplate(String key) { + this.key = key; + } + + public CheckTemplate() { + } + + public String getKey() { + return key; + } + + public void setKey(String s) { + this.key = s; + } + + public Priority getPriority() { + return priority; + } + + public void setPriority(Priority p) { + this.priority = p; + } + + public IsoCategory getIsoCategory() { + return isoCategory; + } + + public void setIsoCategory(IsoCategory c) { + this.isoCategory = c; + } + + public String getConfigKey() { + return configKey; + } + + public void setConfigKey(String configKey) { + this.configKey = configKey; + } + + public abstract String getTitle(Locale locale); + + public abstract String getDescription(Locale locale); + + public abstract String getMessage(Locale locale, String key, Object... params); + + public List<CheckTemplateProperty> getProperties() { + if (properties==null) { + return Collections.emptyList(); + } + return properties; + } + + public void addProperty(CheckTemplateProperty p) { + if (properties==null) { + properties = new ArrayList<CheckTemplateProperty>(); + } + properties.add(p); + } + + public CheckTemplateProperty getProperty(String key) { + if (properties!=null) { + for (CheckTemplateProperty property : properties) { + if (property.getKey().equals(key)) { + return property; + } + } + } + return null; + } + + /** + * Checks are equal within the same plugin. Two plugins can have two different checks with the same key. + */ + @Override + public final boolean equals(Object o) { + if (this == o) { + return true; + } + if (!(o instanceof CheckTemplate)) { + return false; + } + + CheckTemplate checkTemplate = (CheckTemplate) o; + return key.equals(checkTemplate.key); + } + + @Override + public final int hashCode() { + return key.hashCode(); + } + +}
\ No newline at end of file diff --git a/sonar-plugin-api/src/main/java/org/sonar/api/checks/templates/CheckTemplateFactory.java b/sonar-plugin-api/src/main/java/org/sonar/api/checks/templates/CheckTemplateFactory.java new file mode 100644 index 00000000000..c1e93e87337 --- /dev/null +++ b/sonar-plugin-api/src/main/java/org/sonar/api/checks/templates/CheckTemplateFactory.java @@ -0,0 +1,32 @@ +/* + * Sonar, open source software quality management tool. + * Copyright (C) 2009 SonarSource SA + * mailto:contact AT sonarsource DOT com + * + * Sonar 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. + * + * Sonar 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 Sonar; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02 + */ +package org.sonar.api.checks.templates; + +import java.util.Collection; + +/** + * EXPERIMENTAL - will be used in version 2.2 + * @since 2.1 + */ +public abstract class CheckTemplateFactory { + + public abstract Collection<CheckTemplate> create(); + +} diff --git a/sonar-plugin-api/src/main/java/org/sonar/api/checks/templates/CheckTemplateProperty.java b/sonar-plugin-api/src/main/java/org/sonar/api/checks/templates/CheckTemplateProperty.java new file mode 100644 index 00000000000..91dc4428cde --- /dev/null +++ b/sonar-plugin-api/src/main/java/org/sonar/api/checks/templates/CheckTemplateProperty.java @@ -0,0 +1,71 @@ +/* + * Sonar, open source software quality management tool. + * Copyright (C) 2009 SonarSource SA + * mailto:contact AT sonarsource DOT com + * + * Sonar 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. + * + * Sonar 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 Sonar; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02 + */ +package org.sonar.api.checks.templates; + +import java.util.Locale; + +/** + * EXPERIMENTAL - will be used in version 2.2 + * + * @since 2.1 + */ +public abstract class CheckTemplateProperty implements Comparable<CheckTemplateProperty> { + + protected String key; + + public String getKey() { + return key; + } + + public void setKey(String s) { + this.key = s; + } + + public abstract String getTitle(Locale locale); + + public String getDescription() { + return getDescription(Locale.ENGLISH); + } + + + public abstract String getDescription(Locale locale); + + @Override + public final boolean equals(Object o) { + if (this == o) { + return true; + } + if (!(o instanceof CheckTemplateProperty)) { + return false; + } + + CheckTemplateProperty that = (CheckTemplateProperty) o; + return key.equals(that.key); + } + + @Override + public final int hashCode() { + return key.hashCode(); + } + + public int compareTo(CheckTemplateProperty o) { + return getKey().compareTo(o.getKey()); + } +} diff --git a/sonar-plugin-api/src/main/java/org/sonar/api/checks/templates/CheckTemplateRepositories.java b/sonar-plugin-api/src/main/java/org/sonar/api/checks/templates/CheckTemplateRepositories.java new file mode 100644 index 00000000000..c5e6ea6395a --- /dev/null +++ b/sonar-plugin-api/src/main/java/org/sonar/api/checks/templates/CheckTemplateRepositories.java @@ -0,0 +1,62 @@ +/* + * Sonar, open source software quality management tool. + * Copyright (C) 2009 SonarSource SA + * mailto:contact AT sonarsource DOT com + * + * Sonar 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. + * + * Sonar 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 Sonar; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02 + */ +package org.sonar.api.checks.templates; + +import org.sonar.api.ServerExtension; + +import java.util.Collection; +import java.util.HashMap; +import java.util.Map; + +/** + * @since 2.1 + */ +public class CheckTemplateRepositories implements ServerExtension { + + private Map<String, CheckTemplateRepository> repositoriesByKey = new HashMap<String, CheckTemplateRepository>(); + + public CheckTemplateRepositories(CheckTemplateRepository[] repositories) { + if (repositories != null) { + for (CheckTemplateRepository templateRepository : repositories) { + repositoriesByKey.put(templateRepository.getKey(), templateRepository); + } + } + } + + public CheckTemplateRepositories() { + // DO NOT REMOVE THIS CONSTRUCTOR. It is used by Picocontainer when no repositories are available. + } + + public CheckTemplateRepository getRepository(String key) { + return repositoriesByKey.get(key); + } + + public Collection<CheckTemplateRepository> getRepositories() { + return repositoriesByKey.values(); + } + + public CheckTemplate getTemplate(String repositoryKey, String templateKey) { + CheckTemplateRepository repo = getRepository(repositoryKey); + if (repo != null) { + return repo.getTemplate(templateKey); + } + return null; + } +} diff --git a/sonar-plugin-api/src/main/java/org/sonar/api/checks/templates/CheckTemplateRepository.java b/sonar-plugin-api/src/main/java/org/sonar/api/checks/templates/CheckTemplateRepository.java new file mode 100644 index 00000000000..4b98660ae44 --- /dev/null +++ b/sonar-plugin-api/src/main/java/org/sonar/api/checks/templates/CheckTemplateRepository.java @@ -0,0 +1,203 @@ +/* + * Sonar, open source software quality management tool. + * Copyright (C) 2009 SonarSource SA + * mailto:contact AT sonarsource DOT com + * + * Sonar 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. + * + * Sonar 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 Sonar; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02 + */ +package org.sonar.api.checks.templates; + +import org.apache.commons.io.IOUtils; +import org.sonar.api.profiles.RulesProfile; +import org.sonar.api.resources.Language; +import org.sonar.api.rules.*; +import org.sonar.check.IsoCategory; + +import java.io.InputStream; +import java.util.*; + +/** + * EXPERIMENTAL - will be used in version 2.3 + * + * @since 2.1 + */ +public class CheckTemplateRepository implements RulesRepository { + + private String key; + private Language language; + private List<CheckTemplate> templates; + private Map<String, CheckTemplate> templatesByKey; + + + public CheckTemplateRepository() { + } + + public CheckTemplateRepository(String key) { + if (key == null) { + throw new IllegalArgumentException("Key can not be null"); + } + this.key = key; + } + + public String getKey() { + return key; + } + + public CheckTemplateRepository setKey(String key) { + this.key = key; + return this; + } + + public Language getLanguage() { + return language; + } + + public CheckTemplateRepository setLanguage(Language l) { + this.language = l; + return this; + } + + public List<CheckTemplate> getTemplates() { + if (templates == null) { + return Collections.emptyList(); + } + return templates; + } + + public CheckTemplateRepository setTemplates(List<CheckTemplate> c) { + this.templates = c; + return this; + } + + public CheckTemplate getTemplate(String key) { + if (templatesByKey == null || templatesByKey.isEmpty()) { + templatesByKey = new HashMap<String, CheckTemplate>(); + for (CheckTemplate template : templates) { + templatesByKey.put(template.getKey(), template); + } + } + return templatesByKey.get(key); + } + + @Override + public boolean equals(Object o) { + if (this == o) { + return true; + } + if (o == null || getClass() != o.getClass()) { + return false; + } + + CheckTemplateRepository that = (CheckTemplateRepository) o; + return key.equals(that.key); + + } + + @Override + public int hashCode() { + return key.hashCode(); + } + + + public static CheckTemplateRepository createFromXml(String repositoryKey, Language language, String pathToXml) { + InputStream input = CheckTemplateRepository.class.getResourceAsStream(pathToXml); + try { + List<CheckTemplate> templates = new XmlCheckTemplateFactory().parse(input); + CheckTemplateRepository repository = new CheckTemplateRepository(repositoryKey); + repository.setTemplates(templates); + repository.setLanguage(language); + return repository; + + } finally { + IOUtils.closeQuietly(input); + } + } + + public static CheckTemplateRepository createFromAnnotatedClasses(String repositoryKey, Language language, Collection<Class> classes) { + AnnotationCheckTemplateFactory factory = new AnnotationCheckTemplateFactory(classes); + CheckTemplateRepository repository = new CheckTemplateRepository(repositoryKey); + repository.setTemplates(factory.create()); + repository.setLanguage(language); + return repository; + } + + + + + + + + + + + /* + + CODE FOR BACKWARD COMPATIBLITY + This class should not extend RulesRepository in next versions + + */ + + + public List<Rule> getInitialReferential() { + List<Rule> rules = new ArrayList<Rule>(); + for (CheckTemplate checkTemplate : getTemplates()) { + rules.add(toRule(checkTemplate)); + } + return rules; + } + + private Rule toRule(CheckTemplate checkTemplate) { + Rule rule = new Rule(getKey(), checkTemplate.getKey()); + rule.setDescription(checkTemplate.getDescription(Locale.ENGLISH)); + rule.setName(checkTemplate.getTitle(Locale.ENGLISH)); + rule.setPriority(RulePriority.fromCheckPriority(checkTemplate.getPriority())); + rule.setRulesCategory(toRuleCategory(checkTemplate.getIsoCategory())); + for (CheckTemplateProperty checkTemplateProperty : checkTemplate.getProperties()) { + RuleParam param = rule.createParameter(checkTemplateProperty.getKey()); + param.setDescription(checkTemplateProperty.getDescription(Locale.ENGLISH)); + param.setType("s"); + } + + return rule; + } + + private RulesCategory toRuleCategory(IsoCategory isoCategory) { + if (isoCategory == IsoCategory.Reliability) { + return Iso9126RulesCategories.RELIABILITY; + } + if (isoCategory == IsoCategory.Efficiency) { + return Iso9126RulesCategories.EFFICIENCY; + } + if (isoCategory == IsoCategory.Maintainability) { + return Iso9126RulesCategories.MAINTAINABILITY; + } + if (isoCategory == IsoCategory.Portability) { + return Iso9126RulesCategories.PORTABILITY; + } + if (isoCategory == IsoCategory.Usability) { + return Iso9126RulesCategories.USABILITY; + } + return null; + } + + + public List<Rule> parseReferential(String fileContent) { + return Collections.emptyList(); + } + + public List<RulesProfile> getProvidedProfiles() { + return Collections.emptyList(); + } +} diff --git a/sonar-plugin-api/src/main/java/org/sonar/api/checks/templates/DefaultCheckTemplate.java b/sonar-plugin-api/src/main/java/org/sonar/api/checks/templates/DefaultCheckTemplate.java new file mode 100644 index 00000000000..76f6fb6ca4e --- /dev/null +++ b/sonar-plugin-api/src/main/java/org/sonar/api/checks/templates/DefaultCheckTemplate.java @@ -0,0 +1,81 @@ +/* + * Sonar, open source software quality management tool. + * Copyright (C) 2009 SonarSource SA + * mailto:contact AT sonarsource DOT com + * + * Sonar 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. + * + * Sonar 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 Sonar; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02 + */ +package org.sonar.api.checks.templates; + +import org.apache.commons.lang.builder.ToStringBuilder; + +import java.util.Locale; + +/** + * EXPERIMENTAL - will be used in version 2.2 + * + * Non-internationalized check + * + * @since 2.1 + */ +public class DefaultCheckTemplate extends CheckTemplate { + + private String title; + private String description; + + public DefaultCheckTemplate() { + } + + public DefaultCheckTemplate(String key) { + super(key); + } + + public void setTitle(String title) { + this.title = title; + } + + public void setDescription(String description) { + this.description = description; + } + + @Override + public String getTitle(Locale locale) { + if (title == null || "".equals(title)) { + return getKey(); + } + return title; + } + + @Override + public String getDescription(Locale locale) { + return description; + } + + @Override + public String getMessage(Locale locale, String key, Object... params) { + return null; + } + + @Override + public String toString() { + return new ToStringBuilder(this) + .append("key", key) + .append("title", title) + .append("configKey", configKey) + .append("priority", priority) + .append("isoCategory", isoCategory) + .toString(); + } +} diff --git a/sonar-plugin-api/src/main/java/org/sonar/api/checks/templates/DefaultCheckTemplateProperty.java b/sonar-plugin-api/src/main/java/org/sonar/api/checks/templates/DefaultCheckTemplateProperty.java new file mode 100644 index 00000000000..142942b8ced --- /dev/null +++ b/sonar-plugin-api/src/main/java/org/sonar/api/checks/templates/DefaultCheckTemplateProperty.java @@ -0,0 +1,62 @@ +/* + * Sonar, open source software quality management tool. + * Copyright (C) 2009 SonarSource SA + * mailto:contact AT sonarsource DOT com + * + * Sonar 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. + * + * Sonar 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 Sonar; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02 + */ +package org.sonar.api.checks.templates; + +import org.sonar.api.checks.templates.CheckTemplateProperty; + +import java.util.Locale; + +/** + * @since 2.1 + */ +public class DefaultCheckTemplateProperty extends CheckTemplateProperty { + + private String title; + private String description; + + public String getTitle() { + if (title == null || "".equals(title)) { + return getKey(); + } + return title; + } + + @Override + public String getTitle(Locale locale) { + return getTitle(); + } + + public void setTitle(String s) { + this.title = s; + } + + public String getDescription() { + return description; + } + + public void setDescription(String s) { + this.description = s; + } + + @Override + public String getDescription(Locale locale) { + return getDescription(); + } +} diff --git a/sonar-plugin-api/src/main/java/org/sonar/api/checks/templates/XmlCheckTemplateFactory.java b/sonar-plugin-api/src/main/java/org/sonar/api/checks/templates/XmlCheckTemplateFactory.java new file mode 100644 index 00000000000..0b51222c53d --- /dev/null +++ b/sonar-plugin-api/src/main/java/org/sonar/api/checks/templates/XmlCheckTemplateFactory.java @@ -0,0 +1,100 @@ +/* + * Sonar, open source software quality management tool. + * Copyright (C) 2009 SonarSource SA + * mailto:contact AT sonarsource DOT com + * + * Sonar 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. + * + * Sonar 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 Sonar; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02 + */ +package org.sonar.api.checks.templates; + +import org.apache.commons.io.IOUtils; +import org.apache.commons.lang.CharEncoding; +import org.sonar.api.rules.Rule; +import org.sonar.api.rules.RuleParam; +import org.sonar.api.rules.StandardRulesXmlParser; +import org.sonar.api.utils.SonarException; + +import java.io.IOException; +import java.io.InputStream; +import java.io.Reader; +import java.util.ArrayList; +import java.util.List; + +/** + * EXPERIMENTAL - will be used in version 2.2 + * @since 2.1 + */ +public class XmlCheckTemplateFactory { + + public List<CheckTemplate> parseXml(String xml) { + InputStream input = null; + try { + input = IOUtils.toInputStream(xml, CharEncoding.UTF_8); + return parse(input); + + } catch (IOException e) { + throw new SonarException("Can't parse xml file", e); + + } finally { + IOUtils.closeQuietly(input); + } + } + + public List<CheckTemplate> parse(Reader reader) { + StandardRulesXmlParser parser = new StandardRulesXmlParser(); + List<Rule> rules = parser.parse(reader); + return toCheckTemplates(rules); + + } + + public List<CheckTemplate> parse(InputStream input) { + StandardRulesXmlParser parser = new StandardRulesXmlParser(); + List<Rule> rules = parser.parse(input); + return toCheckTemplates(rules); + + } + + private List<CheckTemplate> toCheckTemplates(List<Rule> rules) { + List<CheckTemplate> templates = new ArrayList<CheckTemplate>(); + if (rules != null) { + for (Rule rule : rules) { + DefaultCheckTemplate template = new DefaultCheckTemplate(rule.getKey()); + templates.add(template); + + template.setConfigKey(rule.getConfigKey()); + template.setDescription(rule.getDescription()); + template.setIsoCategory(rule.getRulesCategory().toIsoCategory()); + template.setPriority(rule.getPriority().toCheckPriority()); + template.setTitle(rule.getName()); + + if (rule.getParams() != null) { + for (RuleParam param : rule.getParams()) { + template.addProperty(toProperty(param)); + } + } + } + } + return templates; + } + + private CheckTemplateProperty toProperty(RuleParam param) { + DefaultCheckTemplateProperty property = new DefaultCheckTemplateProperty(); + property.setKey(param.getKey()); + property.setTitle(param.getKey()); + property.setDescription(param.getDescription()); + return property; + } + +}
\ No newline at end of file |