diff options
author | Simon Brandhof <simon.brandhof@sonarsource.com> | 2014-04-30 00:40:47 +0200 |
---|---|---|
committer | Simon Brandhof <simon.brandhof@sonarsource.com> | 2014-04-30 00:40:47 +0200 |
commit | fb07ad49fadece0e6af7a3fcd200b03e6dc97601 (patch) | |
tree | 4adbd3da56152ccda4de3f398d3ad0088b8dcdb5 /sonar-server/src/main | |
parent | 5ec7e9789b904e8f5b03af122cc5b7743379be18 (diff) | |
download | sonarqube-fb07ad49fadece0e6af7a3fcd200b03e6dc97601.tar.gz sonarqube-fb07ad49fadece0e6af7a3fcd200b03e6dc97601.zip |
Continue draft of search framework
Diffstat (limited to 'sonar-server/src/main')
12 files changed, 477 insertions, 146 deletions
diff --git a/sonar-server/src/main/java/org/sonar/server/rule2/Rule.java b/sonar-server/src/main/java/org/sonar/server/rule2/Rule.java index e925ae2b09c..62f5c934c10 100644 --- a/sonar-server/src/main/java/org/sonar/server/rule2/Rule.java +++ b/sonar-server/src/main/java/org/sonar/server/rule2/Rule.java @@ -20,7 +20,7 @@ package org.sonar.server.rule2; import org.sonar.api.rule.RuleKey; -import org.sonar.api.rule.Severity; +import org.sonar.api.rule.RuleStatus; import org.sonar.api.server.debt.DebtRemediationFunction; import javax.annotation.CheckForNull; @@ -40,14 +40,30 @@ public interface Rule { String description(); - Severity severity(); + /** + * Default severity when activated on a Quality profile + * + * @see org.sonar.api.rule.Severity + */ + String severity(); - String status(); + /** + * @see org.sonar.api.rule.RuleStatus + */ + RuleStatus status(); boolean template(); + /** + * Tags that can be customized by administrators + */ List<String> tags(); + /** + * Read-only tags defined by plugins + */ + List<String> systemTags(); + List<RuleParam> params(); @CheckForNull diff --git a/sonar-server/src/main/java/org/sonar/server/rule2/RuleDoc.java b/sonar-server/src/main/java/org/sonar/server/rule2/RuleDoc.java new file mode 100644 index 00000000000..791609101ea --- /dev/null +++ b/sonar-server/src/main/java/org/sonar/server/rule2/RuleDoc.java @@ -0,0 +1,142 @@ +/* + * SonarQube, open source software quality management tool. + * Copyright (C) 2008-2014 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. + */ +/* +* SonarQube, open source software quality management tool. +* Copyright (C) 2008-2014 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.server.rule2; + +import org.sonar.api.rule.RuleKey; +import org.sonar.api.rule.RuleStatus; +import org.sonar.api.server.debt.DebtRemediationFunction; +import org.sonar.server.search.Hit; + +import java.util.Date; +import java.util.List; +import java.util.Map; + +/** + * Implementation of Rule based on an Elasticsearch document + */ +class RuleDoc implements Rule { + + private final Map<String, Object> fields; + + RuleDoc(Map<String, Object> fields) { + this.fields = fields; + } + + RuleDoc(Hit hit) { + this.fields = hit.getFields(); + } + + @Override + public RuleKey key() { + return RuleKey.of((String) fields.get("repositoryKey"), + (String) fields.get("ruleKey")); + } + + @Override + public String language() { + return (String) fields.get("language"); + } + + @Override + public String name() { + return (String) fields.get("name"); + } + + @Override + public String description() { + return (String) fields.get("description"); + } + + @Override + public String severity() { + return (String) fields.get("severity"); + } + + @Override + public RuleStatus status() { + return RuleStatus.valueOf((String) fields.get("status")); + } + + @Override + public boolean template() { + throw new UnsupportedOperationException(); + } + + @Override + @SuppressWarnings("unchecked") + public List<String> tags() { + return (List<String>) fields.get("tags"); + } + + @Override + @SuppressWarnings("unchecked") + public List<String> systemTags() { + return (List<String>) fields.get("sysTags"); + } + + @Override + public List<RuleParam> params() { + throw new UnsupportedOperationException("TODO"); + } + + @Override + public String debtCharacteristicKey() { + throw new UnsupportedOperationException("TODO"); + } + + @Override + public String debtSubCharacteristicKey() { + throw new UnsupportedOperationException("TODO"); + } + + @Override + public DebtRemediationFunction debtRemediationFunction() { + throw new UnsupportedOperationException("TODO"); + } + + @Override + public Date createdAt() { + return (Date) fields.get("createdAt"); + } + + @Override + public Date updatedAt() { + return (Date) fields.get("updatedAt"); + } +} diff --git a/sonar-server/src/main/java/org/sonar/server/rule2/RuleImpl.java b/sonar-server/src/main/java/org/sonar/server/rule2/RuleImpl.java deleted file mode 100644 index c096b145ec2..00000000000 --- a/sonar-server/src/main/java/org/sonar/server/rule2/RuleImpl.java +++ /dev/null @@ -1,117 +0,0 @@ -/* - * SonarQube, open source software quality management tool. - * Copyright (C) 2008-2014 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.server.rule2; - -import org.sonar.api.rule.RuleKey; -import org.sonar.api.rule.Severity; -import org.sonar.api.server.debt.DebtRemediationFunction; - -import java.util.Date; -import java.util.List; - -public class RuleImpl implements Rule { - - - - @Override - public RuleKey key() { - // TODO Auto-generated method stub - return null; - } - - @Override - public String language() { - // TODO Auto-generated method stub - return null; - } - - @Override - public String name() { - // TODO Auto-generated method stub - return null; - } - - @Override - public String description() { - // TODO Auto-generated method stub - return null; - } - - @Override - public Severity severity() { - // TODO Auto-generated method stub - return null; - } - - @Override - public String status() { - // TODO Auto-generated method stub - return null; - } - - @Override - public boolean template() { - // TODO Auto-generated method stub - return false; - } - - @Override - public List<String> tags() { - // TODO Auto-generated method stub - return null; - } - - @Override - public List<RuleParam> params() { - // TODO Auto-generated method stub - return null; - } - - @Override - public String debtCharacteristicKey() { - // TODO Auto-generated method stub - return null; - } - - @Override - public String debtSubCharacteristicKey() { - // TODO Auto-generated method stub - return null; - } - - @Override - public DebtRemediationFunction debtRemediationFunction() { - // TODO Auto-generated method stub - return null; - } - - @Override - public Date createdAt() { - // TODO Auto-generated method stub - return null; - } - - @Override - public Date updatedAt() { - // TODO Auto-generated method stub - return null; - } - -} diff --git a/sonar-server/src/main/java/org/sonar/server/rule2/RuleQuery.java b/sonar-server/src/main/java/org/sonar/server/rule2/RuleQuery.java index d526c2839dd..156b4503d94 100644 --- a/sonar-server/src/main/java/org/sonar/server/rule2/RuleQuery.java +++ b/sonar-server/src/main/java/org/sonar/server/rule2/RuleQuery.java @@ -19,6 +19,117 @@ */ package org.sonar.server.rule2; +import com.google.common.base.Preconditions; +import org.sonar.api.rule.RuleStatus; +import org.sonar.api.rule.Severity; + +import javax.annotation.CheckForNull; +import javax.annotation.Nullable; + public class RuleQuery { + private String key; + private String queryText; + private String[] languages; + private String[] repositories; + private String[] severities; + private RuleStatus[] statuses; + private String[] tags; + private String[] debtCharacteristics; + private Boolean hasDebtCharacteristic; + + @CheckForNull + public String getKey() { + return key; + } + + public RuleQuery setKey(@Nullable String key) { + this.key = key; + return this; + } + + @CheckForNull + public String getQueryText() { + return queryText; + } + + public RuleQuery setQueryText(@Nullable String queryText) { + this.queryText = queryText; + return this; + } + + @CheckForNull + public String[] getLanguages() { + return languages; + } + + public RuleQuery setLanguages(@Nullable String[] languages) { + this.languages = languages; + return this; + } + + @CheckForNull + public String[] getRepositories() { + return repositories; + } + + public RuleQuery setRepositories(@Nullable String[] repositories) { + this.repositories = repositories; + return this; + } + + @CheckForNull + public String[] getSeverities() { + return severities; + } + + public RuleQuery setSeverities(@Nullable String[] severities) { + if (severities != null) { + for (String severity : severities) { + Preconditions.checkArgument(Severity.ALL.contains(severity), "Unknown severity: " + severity); + } + } + this.severities = severities; + return this; + } + + @CheckForNull + public RuleStatus[] getStatuses() { + return statuses; + } + + public RuleQuery setStatuses(@Nullable RuleStatus[] statuses) { + this.statuses = statuses; + return this; + } + + @CheckForNull + public String[] getTags() { + return tags; + } + + public RuleQuery setTags(@Nullable String[] tags) { + this.tags = tags; + return this; + } + + @CheckForNull + public String[] getDebtCharacteristics() { + return debtCharacteristics; + } + + public RuleQuery setDebtCharacteristics(@Nullable String[] debtCharacteristics) { + this.debtCharacteristics = debtCharacteristics; + return this; + } + + @CheckForNull + public Boolean getHasDebtCharacteristic() { + return hasDebtCharacteristic; + } + + public RuleQuery setHasDebtCharacteristic(@Nullable Boolean hasDebtCharacteristic) { + this.hasDebtCharacteristic = hasDebtCharacteristic; + return this; + } } diff --git a/sonar-server/src/main/java/org/sonar/server/rule2/RuleService.java b/sonar-server/src/main/java/org/sonar/server/rule2/RuleService.java index 35d1c0ee18b..c712d96d2a5 100644 --- a/sonar-server/src/main/java/org/sonar/server/rule2/RuleService.java +++ b/sonar-server/src/main/java/org/sonar/server/rule2/RuleService.java @@ -22,12 +22,11 @@ package org.sonar.server.rule2; import org.sonar.api.ServerComponent; import org.sonar.api.rule.RuleKey; import org.sonar.core.rule.RuleDao; -import org.sonar.core.rule.RuleDto; import org.sonar.server.search.Hit; +import org.sonar.server.search.QueryOptions; +import org.sonar.server.search.Results; import javax.annotation.CheckForNull; -import java.util.Collection; -import java.util.Collections; /** * @since 4.4 @@ -46,23 +45,12 @@ public class RuleService implements ServerComponent { public Rule getByKey(RuleKey key) { Hit hit = index.getByKey(key); if (hit != null) { - return toRule(hit); - } else { - return null; + return new RuleDoc(hit); } + return null; } - public Collection<Hit> search(RuleQuery query) { - - return Collections.emptyList(); - } - - public static Rule toRule(RuleDto ruleDto) { - return new RuleImpl(); - } - - public static Rule toRule(Hit hit) { -// BeanUtils.setProperty(bean, name, value); - return new RuleImpl(); + public Results search(RuleQuery query, QueryOptions options) { + throw new UnsupportedOperationException("TODO"); } } diff --git a/sonar-server/src/main/java/org/sonar/server/rule2/ws/RulesWebService.java b/sonar-server/src/main/java/org/sonar/server/rule2/ws/RulesWebService.java index 7b54490d79e..923aac08004 100644 --- a/sonar-server/src/main/java/org/sonar/server/rule2/ws/RulesWebService.java +++ b/sonar-server/src/main/java/org/sonar/server/rule2/ws/RulesWebService.java @@ -35,8 +35,7 @@ public class RulesWebService implements WebService { public void define(Context context) { NewController controller = context .createController("api/rules2") - .setDescription("Coding rules") - .setSince("4.4"); + .setDescription("Coding rules"); search.define(controller); show.define(controller); diff --git a/sonar-server/src/main/java/org/sonar/server/rule2/ws/SearchAction.java b/sonar-server/src/main/java/org/sonar/server/rule2/ws/SearchAction.java index ccd61ea14b4..30dff403069 100644 --- a/sonar-server/src/main/java/org/sonar/server/rule2/ws/SearchAction.java +++ b/sonar-server/src/main/java/org/sonar/server/rule2/ws/SearchAction.java @@ -19,6 +19,8 @@ */ package org.sonar.server.rule2.ws; +import org.sonar.api.rule.RuleStatus; +import org.sonar.api.rule.Severity; import org.sonar.api.server.ws.Request; import org.sonar.api.server.ws.RequestHandler; import org.sonar.api.server.ws.Response; @@ -39,7 +41,7 @@ public class SearchAction implements RequestHandler { void define(WebService.NewController controller) { WebService.NewAction action = controller .createAction("search") - .setDescription("Returns a collection of relevant rules matching a specified query") + .setDescription("Search for a collection of relevant rules matching a specified query") .setSince("4.4") .setHandler(this); @@ -49,6 +51,23 @@ public class SearchAction implements RequestHandler { .setExampleValue("null pointer"); action + .createParam("severities") + .setDescription("Comma-separated list of default severities. Not the same than severity of rules in Quality profiles.") + .setPossibleValues(Severity.ALL) + .setExampleValue("CRITICAL,BLOCKER"); + + action + .createParam("statuses") + .setDescription("Comma-separated list of status codes") + .setPossibleValues(RuleStatus.values()) + .setExampleValue("BETA,DEPRECATED"); + + action + .createParam("tags") + .setDescription("Comma-separated list of tags") + .setExampleValue("security,java8"); + + action .createParam("qProfile") .setDescription("Key of Quality profile") .setExampleValue("java:Sonar way"); diff --git a/sonar-server/src/main/java/org/sonar/server/rule2/ws/ShowAction.java b/sonar-server/src/main/java/org/sonar/server/rule2/ws/ShowAction.java index 0c9b75b1a49..6d7f71ca119 100644 --- a/sonar-server/src/main/java/org/sonar/server/rule2/ws/ShowAction.java +++ b/sonar-server/src/main/java/org/sonar/server/rule2/ws/ShowAction.java @@ -19,10 +19,14 @@ */ package org.sonar.server.rule2.ws; +import org.sonar.api.rule.RuleKey; import org.sonar.api.server.ws.Request; import org.sonar.api.server.ws.RequestHandler; import org.sonar.api.server.ws.Response; import org.sonar.api.server.ws.WebService; +import org.sonar.api.utils.text.JsonWriter; +import org.sonar.server.exceptions.NotFoundException; +import org.sonar.server.rule2.Rule; import org.sonar.server.rule2.RuleService; /** @@ -39,7 +43,7 @@ public class ShowAction implements RequestHandler { void define(WebService.NewController controller) { WebService.NewAction action = controller .createAction("show") - .setDescription("Returns detailed information about a rule") + .setDescription("Get detailed information about a rule") .setSince("4.4") .setHandler(this); @@ -58,6 +62,28 @@ public class ShowAction implements RequestHandler { @Override public void handle(Request request, Response response) { + String repoKey = request.mandatoryParam("repo"); + String ruleKey = request.mandatoryParam("key"); + Rule rule = service.getByKey(RuleKey.of(repoKey, ruleKey)); + if (rule == null) { + throw new NotFoundException("Rule not found"); + } + JsonWriter json = response.newJsonWriter().beginObject().name("rule").beginObject(); + writeRule(rule, json); + json.endObject().endObject().close(); + } + private void writeRule(Rule rule, JsonWriter json) { + json.prop("repo", rule.key().repository()); + json.prop("key", rule.key().rule()); + json.prop("lang", rule.language()); + json.prop("name", rule.name()); + json.prop("desc", rule.description()); + json.prop("status", rule.status().toString()); + json.prop("template", rule.template()); + json.prop("severity", rule.severity().toString()); + json.name("tags").beginArray().values(rule.tags()).endArray(); + json.name("sysTags").beginArray().values(rule.systemTags()).endArray(); + //TODO debt, params } } diff --git a/sonar-server/src/main/java/org/sonar/server/search/Index.java b/sonar-server/src/main/java/org/sonar/server/search/Index.java index 1eb8de436ff..6a45b550dde 100644 --- a/sonar-server/src/main/java/org/sonar/server/search/Index.java +++ b/sonar-server/src/main/java/org/sonar/server/search/Index.java @@ -23,6 +23,7 @@ import org.elasticsearch.common.xcontent.XContentBuilder; import org.picocontainer.Startable; import org.sonar.core.cluster.IndexAction; +import javax.annotation.CheckForNull; import java.io.Serializable; public interface Index<K extends Serializable> extends Startable { @@ -31,6 +32,7 @@ public interface Index<K extends Serializable> extends Startable { void executeAction(IndexAction<K> action); + @CheckForNull Hit getByKey(K key); void insert(K key); diff --git a/sonar-server/src/main/java/org/sonar/server/search/QueryOptions.java b/sonar-server/src/main/java/org/sonar/server/search/QueryOptions.java new file mode 100644 index 00000000000..7fb36475def --- /dev/null +++ b/sonar-server/src/main/java/org/sonar/server/search/QueryOptions.java @@ -0,0 +1,104 @@ +/* + * SonarQube, open source software quality management tool. + * Copyright (C) 2008-2014 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.server.search; + +import com.google.common.base.Preconditions; + +import javax.annotation.CheckForNull; +import javax.annotation.Nullable; + +/** + * Options about paging, sorting and fields to return + */ +public class QueryOptions { + + public static final int DEFAULT_OFFSET = 0; + public static final int DEFAULT_LIMIT = 10; + public static final boolean DEFAULT_ASCENDING = true; + + private int offset = DEFAULT_OFFSET; + private int limit = DEFAULT_LIMIT; + private boolean ascending = DEFAULT_ASCENDING; + private String sortField; + private String[] fieldsToReturn; + + /** + * Offset of the first result to return. Defaults to {@link #DEFAULT_OFFSET} + */ + public int getOffset() { + return offset; + } + + /** + * Sets the offset of the first result to return (zero-based). + */ + public QueryOptions setOffset(int offset) { + Preconditions.checkArgument(offset >= 0, "Offset must be positive"); + this.offset = offset; + return this; + } + + /** + * Limit on the number of results to return. Defaults to {@link #DEFAULT_LIMIT}. + */ + public int getLimit() { + return limit; + } + + /** + * Sets the limit on the number of results to return. + */ + public QueryOptions setLimit(int limit) { + this.limit = limit; + return this; + } + + /** + * Is ascending sort ? Defaults to {@link #DEFAULT_ASCENDING} + */ + public boolean isAscending() { + return ascending; + } + + public QueryOptions setAscending(boolean ascending) { + this.ascending = ascending; + return this; + } + + @CheckForNull + public String getSortField() { + return sortField; + } + + public QueryOptions setSortField(@Nullable String sortField) { + this.sortField = sortField; + return this; + } + + @CheckForNull + public String[] getFieldsToReturn() { + return fieldsToReturn; + } + + public QueryOptions setFieldsToReturn(@Nullable String[] fieldsToReturn) { + this.fieldsToReturn = fieldsToReturn; + return this; + } +} diff --git a/sonar-server/src/main/java/org/sonar/server/search/Results.java b/sonar-server/src/main/java/org/sonar/server/search/Results.java new file mode 100644 index 00000000000..3504fb2ad76 --- /dev/null +++ b/sonar-server/src/main/java/org/sonar/server/search/Results.java @@ -0,0 +1,43 @@ +/* + * SonarQube, open source software quality management tool. + * Copyright (C) 2008-2014 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.server.search; + +import java.util.Collection; + +public class Results { + + private Collection<Hit> hits; + + private int total; + + private int offset; + + public Collection<Hit> getHits() { + return hits; + } + + public int getTotal() { + return total; + } + + public int getOffset() { + return offset; + } +} diff --git a/sonar-server/src/main/java/org/sonar/server/ws/ListingWs.java b/sonar-server/src/main/java/org/sonar/server/ws/ListingWs.java index c67c5f107f2..87a256700b8 100644 --- a/sonar-server/src/main/java/org/sonar/server/ws/ListingWs.java +++ b/sonar-server/src/main/java/org/sonar/server/ws/ListingWs.java @@ -19,10 +19,8 @@ */ package org.sonar.server.ws; -import com.google.common.base.Charsets; import com.google.common.base.Function; import com.google.common.collect.Ordering; -import org.apache.commons.io.IOUtils; import org.sonar.api.server.ws.Request; import org.sonar.api.server.ws.RequestHandler; import org.sonar.api.server.ws.Response; @@ -83,7 +81,7 @@ public class ListingWs implements WebService { .newJsonWriter() .beginObject() .prop("format", action.responseExampleFormat()) - .prop("example", IOUtils.toString(action.responseExample(), Charsets.UTF_8)) + .prop("example", action.responseExampleAsString()) .endObject() .close(); } else { @@ -136,7 +134,7 @@ public class ListingWs implements WebService { writer.prop("since", action.since()); writer.prop("internal", action.isInternal()); writer.prop("post", action.isPost()); - writer.prop("hasResponseExample", action.responseExample()!=null); + writer.prop("hasResponseExample", action.responseExample() != null); if (!action.params().isEmpty()) { // sort parameters by key Ordering<Param> ordering = Ordering.natural().onResultOf(new Function<Param, String>() { |