summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--plugins/sonar-core-plugin/src/main/java/org/sonar/plugins/core/CorePlugin.java5
-rw-r--r--plugins/sonar-core-plugin/src/main/java/org/sonar/plugins/core/reviews/JiraLinkReviewAction.java31
-rw-r--r--sonar-core/src/main/java/org/sonar/core/persistence/DatabaseUtils.java1
-rw-r--r--sonar-core/src/main/java/org/sonar/core/persistence/DatabaseVersion.java2
-rw-r--r--sonar-core/src/main/resources/org/sonar/core/persistence/schema-derby.ddl11
-rw-r--r--sonar-plugin-api/src/main/java/org/sonar/api/reviews/LinkReviewAction.java11
-rw-r--r--sonar-plugin-api/src/main/java/org/sonar/api/reviews/ReviewAction.java20
-rw-r--r--sonar-server/src/main/java/org/sonar/server/platform/Platform.java31
-rw-r--r--sonar-server/src/main/java/org/sonar/server/reviews/ReviewActionsManager.java54
-rw-r--r--sonar-server/src/main/java/org/sonar/server/ui/JRubyFacade.java28
-rw-r--r--sonar-server/src/main/webapp/WEB-INF/app/controllers/reviews_controller.rb7
-rw-r--r--sonar-server/src/main/webapp/WEB-INF/app/models/review.rb39
-rw-r--r--sonar-server/src/main/webapp/WEB-INF/app/models/review_data.rb26
-rw-r--r--sonar-server/src/main/webapp/WEB-INF/app/views/resource/_violation.html.erb5
-rw-r--r--sonar-server/src/main/webapp/WEB-INF/app/views/reviews/_violation_comment_form.html.erb17
-rw-r--r--sonar-server/src/main/webapp/WEB-INF/db/migrate/301_add_review_data.rb31
-rw-r--r--sonar-server/src/main/webapp/javascripts/resource.js5
-rw-r--r--sonar-server/src/test/java/org/sonar/server/reviews/ReviewActionsManagerTest.java63
18 files changed, 368 insertions, 19 deletions
diff --git a/plugins/sonar-core-plugin/src/main/java/org/sonar/plugins/core/CorePlugin.java b/plugins/sonar-core-plugin/src/main/java/org/sonar/plugins/core/CorePlugin.java
index e9daf7bf788..dc4a9877d7f 100644
--- a/plugins/sonar-core-plugin/src/main/java/org/sonar/plugins/core/CorePlugin.java
+++ b/plugins/sonar-core-plugin/src/main/java/org/sonar/plugins/core/CorePlugin.java
@@ -40,6 +40,7 @@ import org.sonar.plugins.core.dashboards.DefaultDashboard;
import org.sonar.plugins.core.dashboards.HotspotsDashboard;
import org.sonar.plugins.core.dashboards.ReviewsDashboard;
import org.sonar.plugins.core.dashboards.TimeMachineDashboard;
+import org.sonar.plugins.core.reviews.JiraLinkReviewAction;
import org.sonar.plugins.core.security.ApplyProjectRolesDecorator;
import org.sonar.plugins.core.sensors.BranchCoverageDecorator;
import org.sonar.plugins.core.sensors.CheckAlertThresholds;
@@ -241,7 +242,6 @@ import java.util.List;
defaultValue = CoreProperties.TIMEMACHINE_DEFAULT_PERIOD_5,
category = CoreProperties.CATEGORY_DIFFERENTIAL_VIEWS),
-
// SERVER-SIDE TECHNICAL PROPERTIES
@Property(
@@ -385,6 +385,9 @@ public final class CorePlugin extends SonarPlugin {
extensions.add(NewItCoverageFileAnalyzer.class);
extensions.add(NewCoverageAggregator.class);
+ // reviews
+ extensions.add(JiraLinkReviewAction.class);
+
return extensions;
}
}
diff --git a/plugins/sonar-core-plugin/src/main/java/org/sonar/plugins/core/reviews/JiraLinkReviewAction.java b/plugins/sonar-core-plugin/src/main/java/org/sonar/plugins/core/reviews/JiraLinkReviewAction.java
new file mode 100644
index 00000000000..7184c6ecba8
--- /dev/null
+++ b/plugins/sonar-core-plugin/src/main/java/org/sonar/plugins/core/reviews/JiraLinkReviewAction.java
@@ -0,0 +1,31 @@
+package org.sonar.plugins.core.reviews;
+
+import org.sonar.api.reviews.LinkReviewAction;
+
+import java.util.Map;
+import java.util.Map.Entry;
+
+/**
+ * @since 3.1
+ */
+public class JiraLinkReviewAction implements LinkReviewAction {
+
+ public String getId() {
+ return "jira-link";
+ }
+
+ public String getName() {
+ return "Link to JIRA";
+ }
+
+ public void execute(Map<String, String> reviewContext) {
+ System.out.println("============>");
+
+ for (Entry<String, String> mapEntry : reviewContext.entrySet()) {
+ System.out.println(mapEntry.getKey() + " // " + mapEntry.getValue());
+ }
+
+ System.out.println("<============");
+ }
+
+}
diff --git a/sonar-core/src/main/java/org/sonar/core/persistence/DatabaseUtils.java b/sonar-core/src/main/java/org/sonar/core/persistence/DatabaseUtils.java
index 113301c2f11..cf12b8a3064 100644
--- a/sonar-core/src/main/java/org/sonar/core/persistence/DatabaseUtils.java
+++ b/sonar-core/src/main/java/org/sonar/core/persistence/DatabaseUtils.java
@@ -72,6 +72,7 @@ public final class DatabaseUtils {
"resource_index",
"reviews",
"review_comments",
+ "review_data",
"rules",
"rules_parameters",
"rules_profiles",
diff --git a/sonar-core/src/main/java/org/sonar/core/persistence/DatabaseVersion.java b/sonar-core/src/main/java/org/sonar/core/persistence/DatabaseVersion.java
index 63e9ae79b84..053615c2761 100644
--- a/sonar-core/src/main/java/org/sonar/core/persistence/DatabaseVersion.java
+++ b/sonar-core/src/main/java/org/sonar/core/persistence/DatabaseVersion.java
@@ -32,7 +32,7 @@ import java.util.List;
*/
public class DatabaseVersion implements BatchComponent, ServerComponent {
- public static final int LAST_VERSION = 302;
+ public static final int LAST_VERSION = 302;
public static enum Status {
UP_TO_DATE, REQUIRES_UPGRADE, REQUIRES_DOWNGRADE, FRESH_INSTALL
diff --git a/sonar-core/src/main/resources/org/sonar/core/persistence/schema-derby.ddl b/sonar-core/src/main/resources/org/sonar/core/persistence/schema-derby.ddl
index 9233e1b9a57..0c331f6db42 100644
--- a/sonar-core/src/main/resources/org/sonar/core/persistence/schema-derby.ddl
+++ b/sonar-core/src/main/resources/org/sonar/core/persistence/schema-derby.ddl
@@ -506,6 +506,13 @@ CREATE TABLE "AUTHORS" (
"UPDATED_AT" TIMESTAMP
);
+CREATE TABLE "REVIEW_DATA" (
+ "ID" INTEGER NOT NULL GENERATED BY DEFAULT AS IDENTITY (START WITH 1, INCREMENT BY 1),
+ "KEE" VARCHAR(200),
+ "REVIEW_ID" INTEGER,
+ "DATA" BLOB(2147483647)
+);
+
-- ----------------------------------------------
-- DDL Statements for indexes
@@ -605,6 +612,8 @@ CREATE INDEX "INDEX_RULE_NOTES_ON_ACTIVE_RULE_ID" ON "RULE_NOTES" ("RULE_ID");
CREATE INDEX "REVIEWS_RID" ON "REVIEWS" ("RESOURCE_ID");
+CREATE INDEX "REVIEW_DATA_REVIEW_ID" ON "REVIEW_DATA" ("REVIEW_ID");
+
-- ----------------------------------------------
-- DDL Statements for keys
@@ -696,3 +705,5 @@ ALTER TABLE "RULE_NOTES" ADD PRIMARY KEY ("ID");
ALTER TABLE "AUTHORS" ADD PRIMARY KEY ("ID");
ALTER TABLE "RESOURCE_INDEX" ADD PRIMARY KEY ("ID");
+
+ALTER TABLE "REVIEW_DATA" ADD PRIMARY KEY ("ID");
diff --git a/sonar-plugin-api/src/main/java/org/sonar/api/reviews/LinkReviewAction.java b/sonar-plugin-api/src/main/java/org/sonar/api/reviews/LinkReviewAction.java
new file mode 100644
index 00000000000..823012c157e
--- /dev/null
+++ b/sonar-plugin-api/src/main/java/org/sonar/api/reviews/LinkReviewAction.java
@@ -0,0 +1,11 @@
+package org.sonar.api.reviews;
+
+import com.google.common.annotations.Beta;
+
+/**
+ * @since 3.1
+ */
+@Beta
+public interface LinkReviewAction extends ReviewAction {
+
+}
diff --git a/sonar-plugin-api/src/main/java/org/sonar/api/reviews/ReviewAction.java b/sonar-plugin-api/src/main/java/org/sonar/api/reviews/ReviewAction.java
new file mode 100644
index 00000000000..d6f49ab6968
--- /dev/null
+++ b/sonar-plugin-api/src/main/java/org/sonar/api/reviews/ReviewAction.java
@@ -0,0 +1,20 @@
+package org.sonar.api.reviews;
+
+import com.google.common.annotations.Beta;
+import org.sonar.api.ServerExtension;
+
+import java.util.Map;
+
+/**
+ * @since 3.1
+ */
+@Beta
+public interface ReviewAction extends ServerExtension {
+
+ String getId();
+
+ String getName();
+
+ void execute(Map<String, String> reviewContext);
+
+}
diff --git a/sonar-server/src/main/java/org/sonar/server/platform/Platform.java b/sonar-server/src/main/java/org/sonar/server/platform/Platform.java
index 52ec833c377..76cb88f4c70 100644
--- a/sonar-server/src/main/java/org/sonar/server/platform/Platform.java
+++ b/sonar-server/src/main/java/org/sonar/server/platform/Platform.java
@@ -41,7 +41,11 @@ import org.sonar.core.i18n.I18nManager;
import org.sonar.core.i18n.RuleI18nManager;
import org.sonar.core.metric.DefaultMetricFinder;
import org.sonar.core.notification.DefaultNotificationManager;
-import org.sonar.core.persistence.*;
+import org.sonar.core.persistence.DaoUtils;
+import org.sonar.core.persistence.DatabaseMigrator;
+import org.sonar.core.persistence.DatabaseVersion;
+import org.sonar.core.persistence.DefaultDatabase;
+import org.sonar.core.persistence.MyBatis;
import org.sonar.core.qualitymodel.DefaultModelFinder;
import org.sonar.core.rule.DefaultRuleFinder;
import org.sonar.core.user.DefaultUserFinder;
@@ -60,11 +64,29 @@ import org.sonar.server.database.EmbeddedDatabaseFactory;
import org.sonar.server.filters.FilterExecutor;
import org.sonar.server.notifications.NotificationService;
import org.sonar.server.notifications.reviews.ReviewsNotificationManager;
-import org.sonar.server.plugins.*;
+import org.sonar.server.plugins.ApplicationDeployer;
+import org.sonar.server.plugins.DefaultServerPluginRepository;
+import org.sonar.server.plugins.PluginDeployer;
+import org.sonar.server.plugins.PluginDownloader;
+import org.sonar.server.plugins.ServerExtensionInstaller;
+import org.sonar.server.plugins.UpdateCenterClient;
+import org.sonar.server.plugins.UpdateCenterMatrixFactory;
import org.sonar.server.qualitymodel.DefaultModelManager;
+import org.sonar.server.reviews.ReviewActionsManager;
import org.sonar.server.rules.ProfilesConsole;
import org.sonar.server.rules.RulesConsole;
-import org.sonar.server.startup.*;
+import org.sonar.server.startup.ActivateDefaultProfiles;
+import org.sonar.server.startup.DeleteDeprecatedMeasures;
+import org.sonar.server.startup.EnableProfiles;
+import org.sonar.server.startup.GeneratePluginIndex;
+import org.sonar.server.startup.GwtPublisher;
+import org.sonar.server.startup.JdbcDriverDeployer;
+import org.sonar.server.startup.RegisterMetrics;
+import org.sonar.server.startup.RegisterNewDashboards;
+import org.sonar.server.startup.RegisterProvidedProfiles;
+import org.sonar.server.startup.RegisterQualityModels;
+import org.sonar.server.startup.RegisterRules;
+import org.sonar.server.startup.ServerMetadataPersister;
import org.sonar.server.ui.CodeColorizers;
import org.sonar.server.ui.JRubyI18n;
import org.sonar.server.ui.SecurityRealmFactory;
@@ -218,6 +240,9 @@ public final class Platform {
servicesContainer.addSingleton(DefaultNotificationManager.class);
servicesContainer.addSingleton(ReviewsNotificationManager.class);
+ // Reviews
+ servicesContainer.addSingleton(ReviewActionsManager.class);
+
servicesContainer.startComponents();
}
diff --git a/sonar-server/src/main/java/org/sonar/server/reviews/ReviewActionsManager.java b/sonar-server/src/main/java/org/sonar/server/reviews/ReviewActionsManager.java
new file mode 100644
index 00000000000..6a9f547f057
--- /dev/null
+++ b/sonar-server/src/main/java/org/sonar/server/reviews/ReviewActionsManager.java
@@ -0,0 +1,54 @@
+package org.sonar.server.reviews;
+
+import com.google.common.collect.Lists;
+import com.google.common.collect.Maps;
+import org.sonar.api.reviews.ReviewAction;
+import org.sonar.api.utils.SonarException;
+
+import java.util.Collection;
+import java.util.Map;
+
+/**
+ * @since 3.1
+ */
+public class ReviewActionsManager {
+
+ private Map<String, ReviewAction> idToAction = Maps.newHashMap();
+ private Map<String, Collection<ReviewAction>> interfaceToAction = Maps.newHashMap();
+
+ public ReviewActionsManager(ReviewAction[] reviewActions) {
+ for (ReviewAction reviewAction : reviewActions) {
+ idToAction.put(reviewAction.getId(), reviewAction);
+ }
+ }
+
+ public ReviewActionsManager() {
+ this(new ReviewAction[0]);
+ }
+
+ public ReviewAction getAction(String actionId) {
+ return idToAction.get(actionId);
+ }
+
+ @SuppressWarnings({"unchecked", "rawtypes"})
+ public Collection<ReviewAction> getActions(String interfaceName) {
+ Collection<ReviewAction> result = interfaceToAction.get(interfaceName);
+ if (result == null) {
+ result = Lists.newArrayList();
+ interfaceToAction.put(interfaceName, result);
+ try {
+ Class interfaceClass = Class.forName(interfaceName);
+ for (ReviewAction reviewAction : idToAction.values()) {
+ if (interfaceClass.isAssignableFrom(reviewAction.getClass())) {
+ result.add(reviewAction);
+ }
+ }
+ } catch (ClassNotFoundException e) {
+ throw new SonarException("The following interface for review actions does not exist: " + interfaceName);
+ }
+
+ }
+ return result;
+ }
+
+}
diff --git a/sonar-server/src/main/java/org/sonar/server/ui/JRubyFacade.java b/sonar-server/src/main/java/org/sonar/server/ui/JRubyFacade.java
index a7b5b34efbd..5e726fbc4f3 100644
--- a/sonar-server/src/main/java/org/sonar/server/ui/JRubyFacade.java
+++ b/sonar-server/src/main/java/org/sonar/server/ui/JRubyFacade.java
@@ -33,10 +33,15 @@ import org.sonar.api.profiles.ProfileImporter;
import org.sonar.api.resources.Language;
import org.sonar.api.resources.ResourceType;
import org.sonar.api.resources.ResourceTypes;
+import org.sonar.api.reviews.ReviewAction;
import org.sonar.api.rules.RulePriority;
import org.sonar.api.rules.RuleRepository;
import org.sonar.api.utils.ValidationMessages;
-import org.sonar.api.web.*;
+import org.sonar.api.web.Footer;
+import org.sonar.api.web.NavigationSection;
+import org.sonar.api.web.Page;
+import org.sonar.api.web.RubyRailsWebservice;
+import org.sonar.api.web.Widget;
import org.sonar.core.i18n.RuleI18nManager;
import org.sonar.core.persistence.Database;
import org.sonar.core.persistence.DatabaseMigrator;
@@ -52,12 +57,18 @@ import org.sonar.server.notifications.reviews.ReviewsNotificationManager;
import org.sonar.server.platform.GlobalSettingsUpdater;
import org.sonar.server.platform.Platform;
import org.sonar.server.platform.ServerIdGenerator;
-import org.sonar.server.plugins.*;
+import org.sonar.server.plugins.DefaultServerPluginRepository;
+import org.sonar.server.plugins.PluginDeployer;
+import org.sonar.server.plugins.PluginDownloader;
+import org.sonar.server.plugins.UpdateCenterMatrix;
+import org.sonar.server.plugins.UpdateCenterMatrixFactory;
+import org.sonar.server.reviews.ReviewActionsManager;
import org.sonar.server.rules.ProfilesConsole;
import org.sonar.server.rules.RulesConsole;
import org.sonar.updatecenter.common.Version;
import javax.annotation.Nullable;
+
import java.net.InetAddress;
import java.sql.Connection;
import java.util.Collection;
@@ -167,7 +178,6 @@ public final class JRubyFacade {
return getContainer().getComponentByType(PluginRepository.class).getMetadata();
}
-
// SYNTAX HIGHLIGHTING ------------------------------------------------------
public String colorizeCode(String code, String language) {
@@ -184,7 +194,6 @@ public final class JRubyFacade {
return Markdown.convertToHtml(input);
}
-
public List<ViewProxy<Widget>> getWidgets(String resourceScope, String resourceQualifier, String resourceLanguage, Object[] availableMeasures) {
return getContainer().getComponentByType(Views.class).getWidgets(resourceScope, resourceQualifier, resourceLanguage, (String[]) availableMeasures);
}
@@ -466,4 +475,15 @@ public final class JRubyFacade {
public ComponentContainer getContainer() {
return Platform.getInstance().getContainer();
}
+
+ // REVIEWS ------------------------------------------------------------------
+
+ public Collection<ReviewAction> getReviewActions(String interfaceName) {
+ return getContainer().getComponentByType(ReviewActionsManager.class).getActions(interfaceName);
+ }
+
+ public ReviewAction getReviewAction(String actionId) {
+ return getContainer().getComponentByType(ReviewActionsManager.class).getAction(actionId);
+ }
+
}
diff --git a/sonar-server/src/main/webapp/WEB-INF/app/controllers/reviews_controller.rb b/sonar-server/src/main/webapp/WEB-INF/app/controllers/reviews_controller.rb
index 2342c9eb750..928c04ae9ec 100644
--- a/sonar-server/src/main/webapp/WEB-INF/app/controllers/reviews_controller.rb
+++ b/sonar-server/src/main/webapp/WEB-INF/app/controllers/reviews_controller.rb
@@ -138,6 +138,9 @@ class ReviewsController < ApplicationController
if !params[:comment_id].blank? && @violation.review
@comment = @violation.review.comments.find(params[:comment_id])
end
+ unless params[:review_action_id].blank?
+ @review_action = Review.getAction(params[:review_action_id])
+ end
render :partial => 'reviews/violation_comment_form'
end
@@ -157,11 +160,11 @@ class ReviewsController < ApplicationController
:user => current_user)
end
- unless params[:text].blank?
+ if !params[:text].blank? || !params[:review_action_id].blank?
if params[:comment_id]
violation.review.edit_comment(current_user, params[:comment_id].to_i, params[:text])
else
- violation.review.create_comment(:user => current_user, :text => params[:text])
+ violation.review.create_comment({:user => current_user, :text => params[:text]}, params[:review_action_id])
end
end
diff --git a/sonar-server/src/main/webapp/WEB-INF/app/models/review.rb b/sonar-server/src/main/webapp/WEB-INF/app/models/review.rb
index 7ee6e2281b7..bede6e6c2ba 100644
--- a/sonar-server/src/main/webapp/WEB-INF/app/models/review.rb
+++ b/sonar-server/src/main/webapp/WEB-INF/app/models/review.rb
@@ -24,6 +24,7 @@ class Review < ActiveRecord::Base
belongs_to :project, :class_name => "Project", :foreign_key => "project_id"
belongs_to :rule
has_many :review_comments, :order => "created_at", :dependent => :destroy
+ has_many :review_data, :class_name => 'ReviewData', :dependent => :destroy
alias_attribute :comments, :review_comments
has_and_belongs_to_many :action_plans
@@ -71,12 +72,25 @@ class Review < ActiveRecord::Base
#
#
- # params are mandatory:
+ # params of 'comment_values' are mandatory:
# - :user
# - :text
- def create_comment(options={})
- comment = comments.create!(options)
+ #
+ # param review_action_id is optional (=> specifies an action to
+ # trigger instead of creating a simple comment)
+ def create_comment(comment_values={}, review_action_id=nil)
+ if review_action_id
+ action = Review.getAction(review_action_id)
+ if action
+ action.execute({"review.id" => id.to_s, "user.login" => comment_values[:user].login, "comment.text" => comment_values[:text]})
+ end
+ else
+ # simple comment
+ comment = comments.create!(comment_values)
+ end
touch
+ comments.reload
+ comment = comments.last
notification_manager.notifyChanged(id.to_i, comment.user.login.to_java, to_java_map, to_java_map("comment" => comment.text))
end
@@ -250,6 +264,25 @@ class Review < ActiveRecord::Base
action_plans[0]
end
+ def self.available_link_actions(current_review=nil)
+ link_actions = Java::OrgSonarServerUi::JRubyFacade.getInstance().getReviewActions("org.sonar.api.reviews.LinkReviewAction")
+ if current_review
+ link_actions.select do |action|
+ data_found = false
+ current_review.review_data.each do |data|
+ data_found = true if data.key==action.getId()
+ end
+ !data_found
+ end
+ else
+ link_actions
+ end
+ end
+
+ def self.getAction(actionId)
+ Java::OrgSonarServerUi::JRubyFacade.getInstance().getReviewAction(actionId)
+ end
+
#
#
# SEARCH METHODS
diff --git a/sonar-server/src/main/webapp/WEB-INF/app/models/review_data.rb b/sonar-server/src/main/webapp/WEB-INF/app/models/review_data.rb
new file mode 100644
index 00000000000..c87e2da1aed
--- /dev/null
+++ b/sonar-server/src/main/webapp/WEB-INF/app/models/review_data.rb
@@ -0,0 +1,26 @@
+#
+# Sonar, entreprise quality control tool.
+# Copyright (C) 2008-2012 SonarSource
+# 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
+#
+class ReviewData < ActiveRecord::Base
+ set_table_name :review_data
+
+ belongs_to :review
+ alias_attribute :key, :kee
+
+end
diff --git a/sonar-server/src/main/webapp/WEB-INF/app/views/resource/_violation.html.erb b/sonar-server/src/main/webapp/WEB-INF/app/views/resource/_violation.html.erb
index df816fa995e..0463ec16202 100644
--- a/sonar-server/src/main/webapp/WEB-INF/app/views/resource/_violation.html.erb
+++ b/sonar-server/src/main/webapp/WEB-INF/app/views/resource/_violation.html.erb
@@ -129,6 +129,11 @@
<% unless violation.review && violation.review.resolved? %>
<li><%= link_to_function message('reviews.change_severity'), "sCSF(#{violation.id})", :name => 'bChangeSeverity' -%></li>
<li><%= link_to_function message('reviews.link_to_action_plan'), "sAPF(#{violation.id})", :name => 'bLinkActionPlan' -%></li>
+
+ <% Review.available_link_actions(violation.review).each do |action| %>
+ <li><%= link_to_function action.getName(), "sCF(#{violation.id}, '#{action.getId()}')", :name => 'bComment' -%></li>
+ <% end %>
+
<% end %>
</ul>
</div>
diff --git a/sonar-server/src/main/webapp/WEB-INF/app/views/reviews/_violation_comment_form.html.erb b/sonar-server/src/main/webapp/WEB-INF/app/views/reviews/_violation_comment_form.html.erb
index 51ac1848fba..8c6c899a03c 100644
--- a/sonar-server/src/main/webapp/WEB-INF/app/views/reviews/_violation_comment_form.html.erb
+++ b/sonar-server/src/main/webapp/WEB-INF/app/views/reviews/_violation_comment_form.html.erb
@@ -1,5 +1,9 @@
<%
- button_label=(@comment ? message('reviews.update_comment_submit') : message('reviews.comment_submit'))
+ if @review_action
+ button_label = @review_action.getName()
+ else
+ button_label=(@comment ? message('reviews.update_comment_submit') : message('reviews.comment_submit'))
+ end
%>
<form method="POST"
onsubmit="new Ajax.Updater('vId<%= params[:id] -%>', '<%= url_for :action => 'violation_save_comment' -%>', {asynchronous:true, evalScripts:true, parameters:Form.serialize(this)});return false;">
@@ -7,11 +11,18 @@
<% if @comment %>
<input type="hidden" name="comment_id" value="<%= @comment.id -%>"/>
<% end %>
+ <% if @review_action %>
+ <input type="hidden" name="review_action_id" value="<%= @review_action.getId() -%>"/>
+ <% end %>
<table class="width100">
<tr>
<td style="vertical-align:top">
- <textarea id="commentText<%= params[:id] -%>" rows="4" name="text" style="width: 100%" onkeyup="if (this.value=='') $('submit_btn<%= params[:id] -%>').disabled='true'; else $('submit_btn<%= params[:id] -%>').disabled='';"><%= @comment.text if @comment -%></textarea>
+ <textarea id="commentText<%= params[:id] -%>"
+ <% unless @review_action -%>
+ onkeyup="if (this.value=='') $('submit_btn<%= params[:id] -%>').disabled='true'; else $('submit_btn<%= params[:id] -%>').disabled='';"
+ <% end %>
+ rows="4" name="text" style="width: 100%"><%= @comment.text if @comment -%></textarea>
</td>
<td class="sep"></td>
<td style="vertical-align:top;width: 90px">
@@ -25,7 +36,7 @@
<%= submit_to_remote "submit_btn"+params[:id],
button_label,
:url => {:action => 'violation_save_comment'},
- :html => {:id => "submit_btn"+params[:id], :disabled => "true"},
+ :html => {:id => "submit_btn"+params[:id]}.merge(@review_action ? {} : {:disabled => "true"}),
:update => 'vId'+params[:id] -%>
&nbsp;
<%= link_to_function message('cancel'), "cancelViolationAction(#{params[:id]})" -%>
diff --git a/sonar-server/src/main/webapp/WEB-INF/db/migrate/301_add_review_data.rb b/sonar-server/src/main/webapp/WEB-INF/db/migrate/301_add_review_data.rb
new file mode 100644
index 00000000000..e38e1981081
--- /dev/null
+++ b/sonar-server/src/main/webapp/WEB-INF/db/migrate/301_add_review_data.rb
@@ -0,0 +1,31 @@
+#
+# Sonar, open source software quality management tool.
+# Copyright (C) 2008-2012 SonarSource
+# 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
+#
+class AddReviewData < ActiveRecord::Migration
+
+ def self.up
+ create_table :review_data do |t|
+ t.column 'kee', :string, :null => true, :limit => 200
+ t.column :review_id, :integer, :null => true
+ t.column :data, :binary, :null => true
+ end
+ add_index :review_data, :review_id, :name => 'review_data_review_id'
+ end
+
+end \ No newline at end of file
diff --git a/sonar-server/src/main/webapp/javascripts/resource.js b/sonar-server/src/main/webapp/javascripts/resource.js
index 1223897743a..7b64d3a74a3 100644
--- a/sonar-server/src/main/webapp/javascripts/resource.js
+++ b/sonar-server/src/main/webapp/javascripts/resource.js
@@ -40,10 +40,11 @@ function hideMoreViolationActions(violation_id) {
}
// show the form to comment violation
-function sCF(violation_id) {
+function sCF(violation_id, review_action_id) {
hideMoreViolationActions(violation_id);
new Ajax.Updater('reviewForm' + violation_id,
- baseUrl + '/reviews/violation_comment_form/' + violation_id,
+ baseUrl + '/reviews/violation_comment_form/' + violation_id
+ + (review_action_id==null ? "" : "?review_action_id=" + review_action_id),
{
asynchronous:true,
evalScripts:true,
diff --git a/sonar-server/src/test/java/org/sonar/server/reviews/ReviewActionsManagerTest.java b/sonar-server/src/test/java/org/sonar/server/reviews/ReviewActionsManagerTest.java
new file mode 100644
index 00000000000..3d71fb549d6
--- /dev/null
+++ b/sonar-server/src/test/java/org/sonar/server/reviews/ReviewActionsManagerTest.java
@@ -0,0 +1,63 @@
+package org.sonar.server.reviews;
+
+import org.junit.Before;
+import org.junit.Test;
+import org.sonar.api.reviews.LinkReviewAction;
+import org.sonar.api.reviews.ReviewAction;
+
+import java.util.Collection;
+import java.util.Map;
+
+import static org.hamcrest.Matchers.hasItem;
+import static org.hamcrest.Matchers.is;
+import static org.junit.Assert.assertThat;
+
+public class ReviewActionsManagerTest {
+
+ private ReviewAction fakeLinkReviewAction = new FakeLinkReviewAction();
+ private ReviewAction simpleReviewAction = new SimpleReviewAction();
+ private ReviewActionsManager manager;
+
+ @Before
+ public void init() throws Exception {
+ manager = new ReviewActionsManager(new ReviewAction[] {fakeLinkReviewAction, simpleReviewAction});
+ }
+
+ @Test
+ public void shouldReturnActionsById() throws Exception {
+ assertThat(manager.getAction("fake-link-review"), is(fakeLinkReviewAction));
+ assertThat(manager.getAction("simple-review-action"), is(simpleReviewAction));
+ }
+
+ @Test
+ public void shouldReturnActionsByInterfaceName() throws Exception {
+ Collection<ReviewAction> reviewActions = manager.getActions("org.sonar.api.reviews.LinkReviewAction");
+ assertThat(reviewActions.size(), is(1));
+ assertThat(reviewActions, hasItem(fakeLinkReviewAction));
+ }
+
+ class FakeLinkReviewAction implements LinkReviewAction {
+ public String getId() {
+ return "fake-link-review";
+ }
+
+ public String getName() {
+ return "Fake action";
+ }
+
+ public void execute(Map<String, String> reviewContext) {
+ }
+ }
+ class SimpleReviewAction implements ReviewAction {
+ public String getId() {
+ return "simple-review-action";
+ }
+
+ public String getName() {
+ return "Simple action";
+ }
+
+ public void execute(Map<String, String> reviewContext) {
+ }
+ }
+}