aboutsummaryrefslogtreecommitdiffstats
path: root/sonar-server/src
diff options
context:
space:
mode:
Diffstat (limited to 'sonar-server/src')
-rw-r--r--sonar-server/src/dev/web.xml10
-rw-r--r--sonar-server/src/main/java/org/sonar/server/issue/JRubyApiIssues.java (renamed from sonar-server/src/main/java/org/sonar/server/issue/DefaultJRubyIssues.java)13
-rw-r--r--sonar-server/src/main/java/org/sonar/server/issue/JRubyInternalIssues.java (renamed from sonar-server/src/main/java/org/sonar/server/ui/JRubyFacades.java)33
-rw-r--r--sonar-server/src/main/java/org/sonar/server/issue/ServerIssueActions.java17
-rw-r--r--sonar-server/src/main/java/org/sonar/server/platform/Platform.java25
-rw-r--r--sonar-server/src/main/java/org/sonar/server/platform/UserSession.java66
-rw-r--r--sonar-server/src/main/java/org/sonar/server/platform/UserSessionFilter.java53
-rw-r--r--sonar-server/src/main/java/org/sonar/server/rule/JRubyRules.java (renamed from sonar-server/src/main/java/org/sonar/server/rule/DefaultJRubyRules.java)9
-rw-r--r--sonar-server/src/main/java/org/sonar/server/text/JRubyText.java51
-rw-r--r--sonar-server/src/main/java/org/sonar/server/text/Macro.java (renamed from sonar-server/src/main/java/org/sonar/server/macro/Macro.java)2
-rw-r--r--sonar-server/src/main/java/org/sonar/server/text/MacroInterpreter.java (renamed from sonar-server/src/main/java/org/sonar/server/macro/MacroInterpreter.java)22
-rw-r--r--sonar-server/src/main/java/org/sonar/server/text/RuleMacro.java (renamed from sonar-server/src/main/java/org/sonar/server/macro/RuleMacro.java)8
-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/api/authentication_controller.rb2
-rw-r--r--sonar-server/src/main/webapp/WEB-INF/app/controllers/api/issues_controller.rb59
-rw-r--r--sonar-server/src/main/webapp/WEB-INF/app/controllers/issues_controller.rb9
-rw-r--r--sonar-server/src/main/webapp/WEB-INF/app/helpers/application_helper.rb1
-rw-r--r--sonar-server/src/main/webapp/WEB-INF/app/helpers/source_helper.rb2
-rw-r--r--sonar-server/src/main/webapp/WEB-INF/app/models/api.rb9
-rw-r--r--sonar-server/src/main/webapp/WEB-INF/app/models/api/utils.rb4
-rw-r--r--sonar-server/src/main/webapp/WEB-INF/app/models/internal.rb (renamed from sonar-server/src/main/webapp/WEB-INF/app/models/macro_interpreter.rb)24
-rw-r--r--sonar-server/src/main/webapp/WEB-INF/app/models/snapshot.rb4
-rw-r--r--sonar-server/src/main/webapp/WEB-INF/app/views/issue/_issue.html.erb2
-rw-r--r--sonar-server/src/main/webapp/WEB-INF/app/views/rules/_show.html.erb4
-rw-r--r--sonar-server/src/main/webapp/WEB-INF/app/views/rules/show.html.erb4
-rw-r--r--sonar-server/src/main/webapp/WEB-INF/app/views/rules_configuration/_rule_note.html.erb4
-rw-r--r--sonar-server/src/main/webapp/WEB-INF/lib/authenticated_system.rb21
-rw-r--r--sonar-server/src/main/webapp/WEB-INF/web.xml8
-rw-r--r--sonar-server/src/test/java/org/sonar/server/issue/JRubyApiIssuesTest.java (renamed from sonar-server/src/test/java/org/sonar/server/issue/DefaultJRubyIssuesTest.java)31
-rw-r--r--sonar-server/src/test/java/org/sonar/server/platform/UserSessionFilterTest.java107
-rw-r--r--sonar-server/src/test/java/org/sonar/server/rule/JRubyRulesTest.java (renamed from sonar-server/src/test/java/org/sonar/server/rule/DefaultJRubyRulesTest.java)10
-rw-r--r--sonar-server/src/test/java/org/sonar/server/text/JRubyTextTest.java59
-rw-r--r--sonar-server/src/test/java/org/sonar/server/text/MacroInterpreterTest.java (renamed from sonar-server/src/test/java/org/sonar/server/ui/MacroInterpreterTest.java)30
-rw-r--r--sonar-server/src/test/java/org/sonar/server/ui/JRubyFacadesTest.java36
34 files changed, 545 insertions, 222 deletions
diff --git a/sonar-server/src/dev/web.xml b/sonar-server/src/dev/web.xml
index fbf1d357710..d1b0b8a7b18 100644
--- a/sonar-server/src/dev/web.xml
+++ b/sonar-server/src/dev/web.xml
@@ -40,7 +40,11 @@
<filter-name>DatabaseSessionFilter</filter-name>
<filter-class>org.sonar.server.ui.DatabaseSessionFilter</filter-class>
</filter>
- <filter>
+ <filter>
+ <filter-name>UserSessionFilter</filter-name>
+ <filter-class>org.sonar.server.platform.UserSessionFilter</filter-class>
+ </filter>
+ <filter>
<filter-name>RackFilter</filter-name>
<filter-class>org.jruby.rack.RackFilter</filter-class>
</filter>
@@ -49,6 +53,10 @@
<filter-name>DatabaseSessionFilter</filter-name>
<url-pattern>/*</url-pattern>
</filter-mapping>
+ <filter-mapping>
+ <filter-name>UserSessionFilter</filter-name>
+ <url-pattern>/*</url-pattern>
+ </filter-mapping>
<filter-mapping>
<filter-name>ServletFilters</filter-name>
<url-pattern>/*</url-pattern>
diff --git a/sonar-server/src/main/java/org/sonar/server/issue/DefaultJRubyIssues.java b/sonar-server/src/main/java/org/sonar/server/issue/JRubyApiIssues.java
index 4c72fe8385d..513820ea099 100644
--- a/sonar-server/src/main/java/org/sonar/server/issue/DefaultJRubyIssues.java
+++ b/sonar-server/src/main/java/org/sonar/server/issue/JRubyApiIssues.java
@@ -30,7 +30,7 @@ import org.sonar.api.issue.JRubyIssues;
import org.sonar.api.rule.RuleKey;
import org.sonar.api.utils.DateUtils;
import org.sonar.api.web.UserRole;
-import org.sonar.server.ui.JRubyFacades;
+import org.sonar.server.platform.UserSession;
import javax.annotation.Nullable;
import java.util.Collection;
@@ -43,24 +43,21 @@ import java.util.Map;
*
* @since 3.6
*/
-public class DefaultJRubyIssues implements JRubyIssues {
+public class JRubyApiIssues implements JRubyIssues {
private final IssueFinder finder;
- private final ServerIssueActions changes;
- public DefaultJRubyIssues(IssueFinder f, ServerIssueActions changes) {
+ public JRubyApiIssues(IssueFinder f) {
this.finder = f;
- this.changes = changes;
- JRubyFacades.setIssues(this);
}
/**
* Requires the role {@link org.sonar.api.web.UserRole#CODEVIEWER}
*/
@Override
- public IssueFinder.Results find(Map<String, Object> params, @Nullable Integer currentUserId) {
+ public IssueFinder.Results find(Map<String, Object> params) {
// TODO move the role to IssueFinder
- return finder.find(toQuery(params), currentUserId, UserRole.CODEVIEWER);
+ return finder.find(toQuery(params), UserSession.get().userId(), UserRole.CODEVIEWER);
}
IssueQuery toQuery(Map<String, Object> props) {
diff --git a/sonar-server/src/main/java/org/sonar/server/ui/JRubyFacades.java b/sonar-server/src/main/java/org/sonar/server/issue/JRubyInternalIssues.java
index 0cd75620df2..aa4c4b63cea 100644
--- a/sonar-server/src/main/java/org/sonar/server/ui/JRubyFacades.java
+++ b/sonar-server/src/main/java/org/sonar/server/issue/JRubyInternalIssues.java
@@ -17,36 +17,27 @@
* 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.ui;
+package org.sonar.server.issue;
import org.sonar.api.ServerComponent;
-import org.sonar.api.issue.JRubyIssues;
-import org.sonar.api.rule.JRubyRules;
+import org.sonar.core.issue.workflow.Transition;
+import org.sonar.server.platform.UserSession;
+
+import java.util.List;
/**
- * All the facades to Java components
- *
- * @since 3.6
+ * All the issue features that are not published to public API
*/
-public class JRubyFacades implements ServerComponent {
-
- private static JRubyIssues issues = null;
- private static JRubyRules rules = null;
+public class JRubyInternalIssues implements ServerComponent {
- public static void setIssues(JRubyIssues i) {
- JRubyFacades.issues = i;
- }
-
- public static JRubyIssues issues() {
- return issues;
- }
+ private final ServerIssueActions actions;
- public static void setRules(JRubyRules rules) {
- JRubyFacades.rules = rules;
+ public JRubyInternalIssues(ServerIssueActions actions) {
+ this.actions = actions;
}
- public static JRubyRules rules() {
- return rules;
+ public List<Transition> listTransitions(String issueKey) {
+ return actions.listTransitions(issueKey, UserSession.get().userId());
}
}
diff --git a/sonar-server/src/main/java/org/sonar/server/issue/ServerIssueActions.java b/sonar-server/src/main/java/org/sonar/server/issue/ServerIssueActions.java
index 7e6db78a103..969e04e17f1 100644
--- a/sonar-server/src/main/java/org/sonar/server/issue/ServerIssueActions.java
+++ b/sonar-server/src/main/java/org/sonar/server/issue/ServerIssueActions.java
@@ -21,14 +21,18 @@ package org.sonar.server.issue;
import org.sonar.api.ServerComponent;
import org.sonar.api.issue.Issue;
+import org.sonar.api.issue.IssueFinder;
import org.sonar.api.web.UserRole;
import org.sonar.core.issue.DefaultIssue;
import org.sonar.core.issue.db.IssueDao;
import org.sonar.core.issue.db.IssueDto;
import org.sonar.core.issue.workflow.IssueWorkflow;
+import org.sonar.core.issue.workflow.Transition;
import org.sonar.core.user.AuthorizationDao;
import javax.annotation.Nullable;
+import java.util.Collections;
+import java.util.List;
/**
* @since 3.6
@@ -36,15 +40,26 @@ import javax.annotation.Nullable;
public class ServerIssueActions implements ServerComponent {
private final IssueWorkflow workflow;
+ private final IssueFinder finder;
private final IssueDao issueDao;
private final AuthorizationDao authorizationDao;
- public ServerIssueActions(IssueWorkflow workflow, IssueDao issueDao, AuthorizationDao authorizationDao) {
+ public ServerIssueActions(IssueWorkflow workflow, IssueFinder finder, IssueDao issueDao, AuthorizationDao authorizationDao) {
this.workflow = workflow;
+ this.finder = finder;
this.issueDao = issueDao;
this.authorizationDao = authorizationDao;
}
+ public List<Transition> listTransitions(String issueKey, @Nullable Integer userId) {
+ Issue issue = finder.findByKey(issueKey /*, userId */);
+ // TODO check authorization
+ if (issue == null) {
+ return Collections.emptyList();
+ }
+ return workflow.outManualTransitions(issue);
+ }
+
public Issue executeAction(String issueKey, String action, @Nullable Integer userId) {
if (userId == null) {
// must be logged
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 e2f6e298c35..c02d1a7e1cd 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
@@ -69,19 +69,21 @@ import org.sonar.server.charts.ChartFactory;
import org.sonar.server.configuration.Backup;
import org.sonar.server.configuration.ProfilesManager;
import org.sonar.server.database.EmbeddedDatabaseFactory;
-import org.sonar.server.issue.DefaultJRubyIssues;
+import org.sonar.server.issue.JRubyApiIssues;
+import org.sonar.server.issue.JRubyInternalIssues;
import org.sonar.server.issue.ServerIssueActions;
import org.sonar.server.issue.ServerIssueFinder;
-import org.sonar.server.macro.MacroInterpreter;
import org.sonar.server.notifications.NotificationCenter;
import org.sonar.server.notifications.NotificationService;
import org.sonar.server.notifications.reviews.ReviewsNotificationManager;
import org.sonar.server.plugins.*;
import org.sonar.server.qualitymodel.DefaultModelManager;
-import org.sonar.server.rule.DefaultJRubyRules;
+import org.sonar.server.rule.JRubyRules;
import org.sonar.server.rules.ProfilesConsole;
import org.sonar.server.rules.RulesConsole;
import org.sonar.server.startup.*;
+import org.sonar.server.text.JRubyText;
+import org.sonar.server.text.MacroInterpreter;
import org.sonar.server.ui.*;
import javax.servlet.ServletContext;
@@ -185,7 +187,6 @@ public final class Platform {
coreContainer.addSingleton(ThreadLocalDatabaseSessionFactory.class);
coreContainer.addPicoAdapter(new DatabaseSessionProvider());
coreContainer.addSingleton(ServerMetadataPersister.class);
- coreContainer.addSingleton(MacroInterpreter.class);
coreContainer.startComponents();
}
@@ -242,10 +243,15 @@ public final class Platform {
servicesContainer.addSingleton(IssueWorkflow.class);
servicesContainer.addSingleton(ServerIssueActions.class);
servicesContainer.addSingleton(ServerIssueFinder.class);
- servicesContainer.addSingleton(DefaultJRubyIssues.class);
+ servicesContainer.addSingleton(JRubyApiIssues.class);
+ servicesContainer.addSingleton(JRubyInternalIssues.class);
// rules
- servicesContainer.addSingleton(DefaultJRubyRules.class);
+ servicesContainer.addSingleton(JRubyRules.class);
+
+ // text
+ servicesContainer.addSingleton(MacroInterpreter.class);
+ servicesContainer.addSingleton(JRubyText.class);
// Notifications
servicesContainer.addSingleton(EmailSettings.class);
@@ -329,4 +335,11 @@ public final class Platform {
public static Server getServer() {
return (Server) getInstance().getComponent(Server.class);
}
+
+ /**
+ * Used by ruby code
+ */
+ public static <T> T component(Class<T> type) {
+ return getInstance().getContainer().getComponentByType(type);
+ }
}
diff --git a/sonar-server/src/main/java/org/sonar/server/platform/UserSession.java b/sonar-server/src/main/java/org/sonar/server/platform/UserSession.java
new file mode 100644
index 00000000000..0fb7dd8ddbb
--- /dev/null
+++ b/sonar-server/src/main/java/org/sonar/server/platform/UserSession.java
@@ -0,0 +1,66 @@
+/*
+ * SonarQube, open source software quality management tool.
+ * Copyright (C) 2008-2013 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.platform;
+
+import com.google.common.base.Objects;
+
+import javax.annotation.CheckForNull;
+import javax.annotation.Nullable;
+
+public class UserSession {
+
+ private static final ThreadLocal<UserSession> threadLocal = new ThreadLocal<UserSession>();
+ private static final UserSession ANONYMOUS = new UserSession(null, null);
+
+ private final Integer userId;
+ private final String login;
+
+ public UserSession(@Nullable Integer userId, @Nullable String login) {
+ this.userId = userId;
+ this.login = login;
+ }
+
+ @CheckForNull
+ public String login() {
+ return login;
+ }
+
+ @CheckForNull
+ public Integer userId() {
+ return userId;
+ }
+
+ public boolean isLoggedIn() {
+ return userId != null;
+ }
+
+ /**
+ * @return never null
+ */
+ public static UserSession get() {
+ return Objects.firstNonNull(threadLocal.get(), ANONYMOUS);
+ }
+
+ static void set(@Nullable UserSession session) {
+ threadLocal.set(session);
+ }
+
+}
+
diff --git a/sonar-server/src/main/java/org/sonar/server/platform/UserSessionFilter.java b/sonar-server/src/main/java/org/sonar/server/platform/UserSessionFilter.java
new file mode 100644
index 00000000000..a63923c5139
--- /dev/null
+++ b/sonar-server/src/main/java/org/sonar/server/platform/UserSessionFilter.java
@@ -0,0 +1,53 @@
+/*
+ * SonarQube, open source software quality management tool.
+ * Copyright (C) 2008-2013 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.platform;
+
+import javax.servlet.*;
+import javax.servlet.http.HttpServletRequest;
+import javax.servlet.http.HttpSession;
+import java.io.IOException;
+
+public class UserSessionFilter implements Filter {
+ public void init(FilterConfig filterConfig) throws ServletException {
+ }
+
+ public void destroy() {
+ }
+
+ public void doFilter(ServletRequest servletRequest, ServletResponse servletResponse, FilterChain filterChain) throws IOException, ServletException {
+ try {
+ HttpServletRequest request = (HttpServletRequest) servletRequest;
+ HttpSession httpSession = request.getSession(true);
+
+ // See available attributes in authenticated_system.rb, methods
+ // current_user= and logout_keeping_session!
+ String login = (String) httpSession.getAttribute("login");
+ Long userId = (Long) httpSession.getAttribute("user_id");
+
+ UserSession.set(new UserSession(userId != null ? userId.intValue() : null, login));
+
+ filterChain.doFilter(servletRequest, servletResponse);
+
+ } finally {
+ UserSession.set(null);
+ }
+ }
+
+}
diff --git a/sonar-server/src/main/java/org/sonar/server/rule/DefaultJRubyRules.java b/sonar-server/src/main/java/org/sonar/server/rule/JRubyRules.java
index 7323d0a2d3c..30d6c3a0e26 100644
--- a/sonar-server/src/main/java/org/sonar/server/rule/DefaultJRubyRules.java
+++ b/sonar-server/src/main/java/org/sonar/server/rule/JRubyRules.java
@@ -19,9 +19,7 @@
*/
package org.sonar.server.rule;
-import org.sonar.api.rule.JRubyRules;
import org.sonar.api.rule.RuleKey;
-import org.sonar.server.ui.JRubyFacades;
import org.sonar.server.ui.JRubyI18n;
/**
@@ -29,17 +27,16 @@ import org.sonar.server.ui.JRubyI18n;
*
* @since 3.6
*/
-public class DefaultJRubyRules implements JRubyRules {
+public class JRubyRules {
private final JRubyI18n jRubyI18n;
- public DefaultJRubyRules(JRubyI18n jRubyI18n) {
+ public JRubyRules(JRubyI18n jRubyI18n) {
this.jRubyI18n = jRubyI18n;
- JRubyFacades.setRules(this);
}
public String ruleName(String rubyLocale, RuleKey ruleKey) {
- String l18n = jRubyI18n.getRuleName(rubyLocale, ruleKey.repository(), ruleKey.rule());
+ String l18n = jRubyI18n.getRuleName(rubyLocale, ruleKey.repository(), ruleKey.rule());
if (l18n != null) {
return l18n;
} else {
diff --git a/sonar-server/src/main/java/org/sonar/server/text/JRubyText.java b/sonar-server/src/main/java/org/sonar/server/text/JRubyText.java
new file mode 100644
index 00000000000..7c8fd2a5dc4
--- /dev/null
+++ b/sonar-server/src/main/java/org/sonar/server/text/JRubyText.java
@@ -0,0 +1,51 @@
+/*
+ * SonarQube, open source software quality management tool.
+ * Copyright (C) 2008-2013 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.text;
+
+import org.apache.commons.lang.StringEscapeUtils;
+import org.sonar.api.ServerComponent;
+import org.sonar.core.source.HtmlSourceDecorator;
+import org.sonar.markdown.Markdown;
+
+import java.util.List;
+
+public class JRubyText implements ServerComponent {
+
+ private final MacroInterpreter macroInterpreter;
+ private final HtmlSourceDecorator sourceDecorator;
+
+ public JRubyText(MacroInterpreter macroInterpreter, HtmlSourceDecorator sourceDecorator) {
+ this.macroInterpreter = macroInterpreter;
+ this.sourceDecorator = sourceDecorator;
+ }
+
+ public String interpretMacros(String text) {
+ return macroInterpreter.interpret(text);
+ }
+
+ public String markdownToHtml(String markdown) {
+ // TODO move HTML escaping to sonar-markdown
+ return Markdown.convertToHtml(StringEscapeUtils.escapeHtml(markdown));
+ }
+
+ public List<String> highlightedSourceLines(long snapshotId) {
+ return sourceDecorator.getDecoratedSourceAsHtml(snapshotId);
+ }
+}
diff --git a/sonar-server/src/main/java/org/sonar/server/macro/Macro.java b/sonar-server/src/main/java/org/sonar/server/text/Macro.java
index 91bd8410655..8b0a10fd75f 100644
--- a/sonar-server/src/main/java/org/sonar/server/macro/Macro.java
+++ b/sonar-server/src/main/java/org/sonar/server/text/Macro.java
@@ -18,7 +18,7 @@
* Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
*/
-package org.sonar.server.macro;
+package org.sonar.server.text;
public interface Macro {
diff --git a/sonar-server/src/main/java/org/sonar/server/macro/MacroInterpreter.java b/sonar-server/src/main/java/org/sonar/server/text/MacroInterpreter.java
index 6c85ff35777..9f55e385b4b 100644
--- a/sonar-server/src/main/java/org/sonar/server/macro/MacroInterpreter.java
+++ b/sonar-server/src/main/java/org/sonar/server/text/MacroInterpreter.java
@@ -18,33 +18,27 @@
* Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
*/
-package org.sonar.server.macro;
+package org.sonar.server.text;
+import com.google.common.collect.ImmutableList;
import org.sonar.api.ServerComponent;
import javax.servlet.ServletContext;
-
import java.util.List;
-import static com.google.common.collect.Lists.newArrayList;
-
public class MacroInterpreter implements ServerComponent {
- private ServletContext servletContext;
- private List<Macro> macroList;
+ private final List<Macro> macros;
public MacroInterpreter(ServletContext servletContext) {
- this.servletContext = servletContext;
- this.macroList = newArrayList();
- }
-
- public void start(){
- macroList.add(new RuleMacro(servletContext.getContextPath()));
+ this.macros = ImmutableList.<Macro>of(
+ new RuleMacro(servletContext.getContextPath())
+ );
}
- public String interpret(String text){
+ public String interpret(String text) {
String textReplaced = text;
- for (Macro macro : macroList) {
+ for (Macro macro : macros) {
textReplaced = textReplaced.replaceAll(macro.getRegex(), macro.getReplacement());
}
return textReplaced;
diff --git a/sonar-server/src/main/java/org/sonar/server/macro/RuleMacro.java b/sonar-server/src/main/java/org/sonar/server/text/RuleMacro.java
index df48a37d626..e0209ef5699 100644
--- a/sonar-server/src/main/java/org/sonar/server/macro/RuleMacro.java
+++ b/sonar-server/src/main/java/org/sonar/server/text/RuleMacro.java
@@ -18,13 +18,13 @@
* Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
*/
-package org.sonar.server.macro;
+package org.sonar.server.text;
-public class RuleMacro implements Macro{
+class RuleMacro implements Macro {
private final String contextPath;
- public RuleMacro(String contextPath){
+ RuleMacro(String contextPath) {
this.contextPath = contextPath;
}
@@ -35,7 +35,7 @@ public class RuleMacro implements Macro{
return "\\{rule:([a-zA-Z0-9._-]++):([a-zA-Z0-9._-]++)\\}";
}
- public String getReplacement(){
+ public String getReplacement() {
return "<a class='open-modal rule-modal' modal-width='800' href='" + contextPath + "/rules/show/$1:$2?modal=true&layout=false'>$1:$2</a>";
}
}
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 0e16d6329d7..fc5a1d470d8 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
@@ -56,13 +56,10 @@ import org.sonar.core.persistence.DryRunDatabaseFactory;
import org.sonar.core.purge.PurgeDao;
import org.sonar.core.resource.ResourceIndexerDao;
import org.sonar.core.resource.ResourceKeyUpdaterDao;
-import org.sonar.core.source.HtmlSourceDecorator;
import org.sonar.core.timemachine.Periods;
import org.sonar.core.workflow.WorkflowEngine;
-import org.sonar.markdown.Markdown;
import org.sonar.server.configuration.Backup;
import org.sonar.server.configuration.ProfilesManager;
-import org.sonar.server.macro.MacroInterpreter;
import org.sonar.server.notifications.reviews.ReviewsNotificationManager;
import org.sonar.server.platform.*;
import org.sonar.server.plugins.*;
@@ -73,7 +70,6 @@ import org.sonar.updatecenter.common.UpdateCenter;
import org.sonar.updatecenter.common.Version;
import javax.annotation.Nullable;
-
import java.net.InetAddress;
import java.sql.Connection;
import java.util.*;
@@ -89,11 +85,7 @@ public final class JRubyFacade {
return SINGLETON;
}
- public static String markdownToHtml(String input) {
- return Markdown.convertToHtml(input);
- }
-
- private <T> T get(Class<T> componentType) {
+ <T> T get(Class<T> componentType) {
return getContainer().getComponentByType(componentType);
}
@@ -317,7 +309,7 @@ public final class JRubyFacade {
public void ruleSeverityChanged(int parentProfileId, int activeRuleId, int oldSeverityId, int newSeverityId, String userName) {
getProfilesManager().ruleSeverityChanged(parentProfileId, activeRuleId, RulePriority.values()[oldSeverityId],
- RulePriority.values()[newSeverityId], userName);
+ RulePriority.values()[newSeverityId], userName);
}
public void ruleDeactivated(int parentProfileId, int deactivatedRuleId, String userName) {
@@ -513,10 +505,10 @@ public final class JRubyFacade {
// notifier is null when creating the administrator in the migration script 011.
if (notifier != null) {
notifier.onNewUser(NewUserHandler.Context.builder()
- .setLogin(fields.get("login"))
- .setName(fields.get("name"))
- .setEmail(fields.get("email"))
- .build());
+ .setLogin(fields.get("login"))
+ .setName(fields.get("name"))
+ .setEmail(fields.get("email"))
+ .build());
}
}
@@ -555,12 +547,4 @@ public final class JRubyFacade {
public Testable testable(String componentKey) {
return get(SnapshotPerspectives.class).as(MutableTestable.class, componentKey);
}
-
- public MacroInterpreter getMacroInterpreter(){
- return get(MacroInterpreter.class);
- }
-
- public Collection<String> getHighlightedSourceLines(long snapshotId) {
- return get(HtmlSourceDecorator.class).getDecoratedSourceAsHtml(snapshotId);
- }
}
diff --git a/sonar-server/src/main/webapp/WEB-INF/app/controllers/api/authentication_controller.rb b/sonar-server/src/main/webapp/WEB-INF/app/controllers/api/authentication_controller.rb
index 78f30d8e632..a27a930cdc5 100644
--- a/sonar-server/src/main/webapp/WEB-INF/app/controllers/api/authentication_controller.rb
+++ b/sonar-server/src/main/webapp/WEB-INF/app/controllers/api/authentication_controller.rb
@@ -55,7 +55,7 @@ class Api::AuthenticationController < Api::ApiController
end
def anonymous?
- !session.has_key?(:user_id)
+ !session.has_key?('user_id')
end
def set_cache_buster
diff --git a/sonar-server/src/main/webapp/WEB-INF/app/controllers/api/issues_controller.rb b/sonar-server/src/main/webapp/WEB-INF/app/controllers/api/issues_controller.rb
index d5350a804f1..b73e015ec80 100644
--- a/sonar-server/src/main/webapp/WEB-INF/app/controllers/api/issues_controller.rb
+++ b/sonar-server/src/main/webapp/WEB-INF/app/controllers/api/issues_controller.rb
@@ -22,13 +22,31 @@ class Api::IssuesController < Api::ApiController
# GET /api/issues/search?<parameters>
def search
- user_id = current_user ? current_user.id : nil
- results = Api.issues.find(params, user_id)
- render :json => jsonp(results_to_json(results))
+ results = Api.issues.find(params)
+ render :json => jsonp(
+ {
+ :securityExclusions => results.securityExclusions,
+ :paging => paging_to_json(results.paging),
+ :issues => results.issues.map { |issue| issue_to_json(issue) }
+ }
+ )
end
- # POST /api/issues/change?key=<issue key>&<newSeverity=xxx>&<newResolution=xxx>...
- def change
+ # GET /api/issues/transitions?issue=<key>
+ def transitions
+ # TODO deal with errors (404, ...)
+ require_parameters :issue
+ issue_key = params[:issue]
+ transitions = Internal.issues.listTransitions(issue_key)
+ render :json => jsonp(
+ {
+ :transitions => transitions.map { |t| t.key() }
+ }
+ )
+ end
+
+ # POST /api/issues/transition?issue=<key>&transition=<key>&comment=<optional comment>
+ def transition
verify_post_request
access_denied unless logged_in?
@@ -47,21 +65,13 @@ class Api::IssuesController < Api::ApiController
private
- def results_to_json(results)
- json = {}
- json[:issues] = results.issues.map { |issue| issue_to_json(issue) }
- json[:paging] = pagination_to_json(results.paging)
- json[:securityExclusions] = results.securityExclusions
- json
- end
-
def issue_to_json(issue)
json = {
- :key => issue.key,
- :component => issue.componentKey,
- :rule => issue.ruleKey.toString(),
- :resolution => issue.resolution,
- :status => issue.status
+ :key => issue.key,
+ :component => issue.componentKey,
+ :rule => issue.ruleKey.toString(),
+ :resolution => issue.resolution,
+ :status => issue.status
}
json[:severity] = issue.severity if issue.severity
json[:desc] = issue.description if issue.description
@@ -76,14 +86,13 @@ class Api::IssuesController < Api::ApiController
json
end
- def pagination_to_json(paging)
- json = {
- :pageIndex => paging.pageIndex,
- :pageSize => paging.pageSize,
- :total => paging.total,
- :pages => paging.pages
+ def paging_to_json(paging)
+ {
+ :pageIndex => paging.pageIndex,
+ :pageSize => paging.pageSize,
+ :total => paging.total,
+ :pages => paging.pages
}
- json
end
def format_java_datetime(java_date)
diff --git a/sonar-server/src/main/webapp/WEB-INF/app/controllers/issues_controller.rb b/sonar-server/src/main/webapp/WEB-INF/app/controllers/issues_controller.rb
index af2ad7ab831..3a19d5890e5 100644
--- a/sonar-server/src/main/webapp/WEB-INF/app/controllers/issues_controller.rb
+++ b/sonar-server/src/main/webapp/WEB-INF/app/controllers/issues_controller.rb
@@ -22,16 +22,9 @@ class IssuesController < ApplicationController
def index
page_index = params[:page_index] || 1
- issues_result = find_issues({'pageSize' => 25, 'pageIndex' => page_index})
+ issues_result = Api.issues.find({'pageSize' => 25, 'pageIndex' => page_index})
@paging = issues_result.paging
@issues = issues_result.issues.collect {|issue| issue}
end
- protected
-
- def find_issues(map)
- user = current_user ? current_user.id : nil
- Api.issues.find(map, user)
- end
-
end \ No newline at end of file
diff --git a/sonar-server/src/main/webapp/WEB-INF/app/helpers/application_helper.rb b/sonar-server/src/main/webapp/WEB-INF/app/helpers/application_helper.rb
index a16f41d5098..450f07d2257 100644
--- a/sonar-server/src/main/webapp/WEB-INF/app/helpers/application_helper.rb
+++ b/sonar-server/src/main/webapp/WEB-INF/app/helpers/application_helper.rb
@@ -828,6 +828,7 @@ module ApplicationHelper
html
end
+ # TODO move to Api
def to_date(java_date)
java_date ? Time.at(java_date.time/1000) : nil
end
diff --git a/sonar-server/src/main/webapp/WEB-INF/app/helpers/source_helper.rb b/sonar-server/src/main/webapp/WEB-INF/app/helpers/source_helper.rb
index 2b50ec23f6c..3a56cd84f10 100644
--- a/sonar-server/src/main/webapp/WEB-INF/app/helpers/source_helper.rb
+++ b/sonar-server/src/main/webapp/WEB-INF/app/helpers/source_helper.rb
@@ -73,7 +73,7 @@ module SourceHelper
end
panel.html_lines=[]
- html_source_lines = snapshot.highlighting_data || snapshot.source.syntax_highlighted_lines()
+ html_source_lines = snapshot.highlighted_source_lines || snapshot.source.syntax_highlighted_lines()
line_range=sanitize_range(options[:line_range], 1..html_source_lines.length)
html_source_lines.each_with_index do |source, index|
diff --git a/sonar-server/src/main/webapp/WEB-INF/app/models/api.rb b/sonar-server/src/main/webapp/WEB-INF/app/models/api.rb
index 478d9a3a591..101ef78aa3d 100644
--- a/sonar-server/src/main/webapp/WEB-INF/app/models/api.rb
+++ b/sonar-server/src/main/webapp/WEB-INF/app/models/api.rb
@@ -18,16 +18,13 @@
# Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
#
+# Entry points to Java API. All other Ruby classes are not considered
+# as an API and can evolve through time.
class Api
# since 3.6
def self.issues
- Java::OrgSonarServerUi::JRubyFacades.issues()
- end
-
- # since 3.6
- def self.rules
- Java::OrgSonarServerUi::JRubyFacades.rules()
+ Internal.issues_api
end
end
diff --git a/sonar-server/src/main/webapp/WEB-INF/app/models/api/utils.rb b/sonar-server/src/main/webapp/WEB-INF/app/models/api/utils.rb
index d22f095e580..14eae5135c0 100644
--- a/sonar-server/src/main/webapp/WEB-INF/app/models/api/utils.rb
+++ b/sonar-server/src/main/webapp/WEB-INF/app/models/api/utils.rb
@@ -52,8 +52,8 @@ class Api::Utils
false
end
- def self.markdown_to_html(markdown)
- markdown ? Java::OrgSonarServerUi::JRubyFacade.markdownToHtml(ERB::Util.html_escape(markdown)) : ''
+ def self.markdown_to_html(markdown='')
+ Internal.text.markdownToHtml(markdown)
end
# Splits a string into an array of lines
diff --git a/sonar-server/src/main/webapp/WEB-INF/app/models/macro_interpreter.rb b/sonar-server/src/main/webapp/WEB-INF/app/models/internal.rb
index 852ed29c2a7..332bc95fdc2 100644
--- a/sonar-server/src/main/webapp/WEB-INF/app/models/macro_interpreter.rb
+++ b/sonar-server/src/main/webapp/WEB-INF/app/models/internal.rb
@@ -18,10 +18,28 @@
# Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
#
-class MacroInterpreter
+# All the Java components that are not published to public plugin API.
+# Must NOT be used by plugins. Forward-compatibility is NOT guaranteed.
+class Internal
- def self.interpret_macro(text)
- Java::OrgSonarServerUi::JRubyFacade.getInstance().getMacroInterpreter().interpret(text)
+ def self.issues
+ component(Java::OrgSonarServerIssue::JRubyInternalIssues.java_class)
end
+ def self.issues_api
+ component(Java::OrgSonarApiIssue::JRubyIssues.java_class)
+ end
+
+ def self.text
+ component(Java::OrgSonarServerText::JRubyText.java_class)
+ end
+
+ def self.rules
+ component(Java::OrgSonarServerRule::JRubyRules.java_class)
+ end
+
+ private
+ def self.component(component_java_class)
+ Java::OrgSonarServerPlatform::Platform.component(component_java_class)
+ end
end \ No newline at end of file
diff --git a/sonar-server/src/main/webapp/WEB-INF/app/models/snapshot.rb b/sonar-server/src/main/webapp/WEB-INF/app/models/snapshot.rb
index a59ce9f9d25..ec55b8a46d2 100644
--- a/sonar-server/src/main/webapp/WEB-INF/app/models/snapshot.rb
+++ b/sonar-server/src/main/webapp/WEB-INF/app/models/snapshot.rb
@@ -252,8 +252,8 @@ class Snapshot < ActiveRecord::Base
end
end
- def highlighting_data
- Java::OrgSonarServerUi::JRubyFacade.getInstance().getHighlightedSourceLines(id)
+ def highlighted_source_lines
+ Internal.text.highlightedSourceLines(id)
end
def has_source
diff --git a/sonar-server/src/main/webapp/WEB-INF/app/views/issue/_issue.html.erb b/sonar-server/src/main/webapp/WEB-INF/app/views/issue/_issue.html.erb
index d32da0dc041..fb18dabbf95 100644
--- a/sonar-server/src/main/webapp/WEB-INF/app/views/issue/_issue.html.erb
+++ b/sonar-server/src/main/webapp/WEB-INF/app/views/issue/_issue.html.erb
@@ -59,7 +59,7 @@
</tr>
<% # TODO action plan %>
<% if rule %>
- <% rule_name = Api.rules.rule_name(I18n.locale, rule.rule_key) %>
+ <% rule_name = Internal.rules.ruleName(I18n.locale, rule.rule_key) %>
<tr>
<td class="key">
<%= message('rule') -%>:
diff --git a/sonar-server/src/main/webapp/WEB-INF/app/views/rules/_show.html.erb b/sonar-server/src/main/webapp/WEB-INF/app/views/rules/_show.html.erb
index c4e6d9b174a..1d4a91542d3 100644
--- a/sonar-server/src/main/webapp/WEB-INF/app/views/rules/_show.html.erb
+++ b/sonar-server/src/main/webapp/WEB-INF/app/views/rules/_show.html.erb
@@ -19,9 +19,9 @@
<div class="modal-body rule_detail">
<% if @rule.description.strip.start_with?('<p>') %>
- <%= MacroInterpreter.interpret_macro @rule.description %>
+ <%= Internal.text.interpretMacros(@rule.description) %>
<% else %>
- <p><%= MacroInterpreter.interpret_macro @rule.description %></p>
+ <p><%= Internal.text.interpretMacros(@rule.description) %></p>
<% end %>
<% if @rule.note && !@rule.note.text.strip.blank? %>
diff --git a/sonar-server/src/main/webapp/WEB-INF/app/views/rules/show.html.erb b/sonar-server/src/main/webapp/WEB-INF/app/views/rules/show.html.erb
index bbb02e8141f..ab37ce9e1df 100644
--- a/sonar-server/src/main/webapp/WEB-INF/app/views/rules/show.html.erb
+++ b/sonar-server/src/main/webapp/WEB-INF/app/views/rules/show.html.erb
@@ -17,9 +17,9 @@
<div class="rule_detail">
<% if @rule.description.strip.start_with?('<p>') %>
- <%= MacroInterpreter.interpret_macro @rule.description %>
+ <%= Internal.text.interpretMacros(@rule.description) %>
<% else %>
- <p><%= MacroInterpreter.interpret_macro @rule.description %></p>
+ <p><%= Internal.text.interpretMacros(@rule.description) %></p>
<% end %>
<% if @rule.note && !@rule.note.text.strip.blank? %>
diff --git a/sonar-server/src/main/webapp/WEB-INF/app/views/rules_configuration/_rule_note.html.erb b/sonar-server/src/main/webapp/WEB-INF/app/views/rules_configuration/_rule_note.html.erb
index 86c598fc31b..cd389daecca 100644
--- a/sonar-server/src/main/webapp/WEB-INF/app/views/rules_configuration/_rule_note.html.erb
+++ b/sonar-server/src/main/webapp/WEB-INF/app/views/rules_configuration/_rule_note.html.erb
@@ -10,9 +10,9 @@
<div id="<%= note_detail_div_id -%>">
<div>
<% if rule.description.strip.start_with?('<p>') %>
- <%= MacroInterpreter.interpret_macro rule.description %>
+ <%= Internal.text.interpretMacros(rule.description) %>
<% else %>
- <p><%= MacroInterpreter.interpret_macro rule.description %></p>
+ <p><%= Internal.text.interpretMacros(rule.description) %></p>
<% end %>
</div>
diff --git a/sonar-server/src/main/webapp/WEB-INF/lib/authenticated_system.rb b/sonar-server/src/main/webapp/WEB-INF/lib/authenticated_system.rb
index dd97c70bac5..f8b17a9ac6a 100644
--- a/sonar-server/src/main/webapp/WEB-INF/lib/authenticated_system.rb
+++ b/sonar-server/src/main/webapp/WEB-INF/lib/authenticated_system.rb
@@ -13,8 +13,17 @@ module AuthenticatedSystem
# Store the given user id in the session.
def current_user=(new_user)
- session[:user_id] = (new_user ? new_user.id : nil)
- @current_user = new_user || false
+ # Do not use ruby symbols, else they can't be accessed from Java Servlet Filter
+ # (see UserSessionFilter
+ if new_user
+ session['user_id'] = new_user.id
+ session['login'] = new_user.login
+ @current_user = new_user
+ else
+ session['user_id'] = nil
+ session['login'] = nil
+ @current_user = false
+ end
end
# Check if the user is authorized
@@ -107,7 +116,7 @@ module AuthenticatedSystem
# Called from #current_user. First attempt to login by the user id stored in the session.
def login_from_session
- self.current_user = User.find_by_id(session[:user_id]) if session[:user_id]
+ self.current_user = User.find_by_id(session['user_id']) if session['user_id']
end
# Called from #current_user. Now, attempt to login by basic authentication information.
@@ -140,7 +149,11 @@ module AuthenticatedSystem
@current_user.forget_me if @current_user.is_a? User
@current_user = false # not logged in, and don't do it for me
kill_remember_cookie! # Kill client-side auth cookie
- session[:user_id] = nil # keeps the session but kill our variable
+
+ # Do not use ruby symbols, else they can't be accessed from Java Servlet Filter
+ # (see UserSessionFilter)
+ session['user_id'] = nil # keeps the session but kill our variable
+ session['login'] = nil # keeps the session but kill our variable
# explicitly kill any other session variables you set
end
diff --git a/sonar-server/src/main/webapp/WEB-INF/web.xml b/sonar-server/src/main/webapp/WEB-INF/web.xml
index b2683b72a0c..55b93f2f7da 100644
--- a/sonar-server/src/main/webapp/WEB-INF/web.xml
+++ b/sonar-server/src/main/webapp/WEB-INF/web.xml
@@ -41,6 +41,10 @@
<filter-class>org.sonar.server.ui.DatabaseSessionFilter</filter-class>
</filter>
<filter>
+ <filter-name>UserSessionFilter</filter-name>
+ <filter-class>org.sonar.server.platform.UserSessionFilter</filter-class>
+ </filter>
+ <filter>
<filter-name>RackFilter</filter-name>
<filter-class>org.jruby.rack.RackFilter</filter-class>
</filter>
@@ -65,6 +69,10 @@
<url-pattern>/*</url-pattern>
</filter-mapping>
<filter-mapping>
+ <filter-name>UserSessionFilter</filter-name>
+ <url-pattern>/*</url-pattern>
+ </filter-mapping>
+ <filter-mapping>
<filter-name>ServletFilters</filter-name>
<url-pattern>/*</url-pattern>
</filter-mapping>
diff --git a/sonar-server/src/test/java/org/sonar/server/issue/DefaultJRubyIssuesTest.java b/sonar-server/src/test/java/org/sonar/server/issue/JRubyApiIssuesTest.java
index 38b7d784aa6..b8468d72427 100644
--- a/sonar-server/src/test/java/org/sonar/server/issue/DefaultJRubyIssuesTest.java
+++ b/sonar-server/src/test/java/org/sonar/server/issue/JRubyApiIssuesTest.java
@@ -39,21 +39,20 @@ import static org.mockito.Matchers.argThat;
import static org.mockito.Matchers.eq;
import static org.mockito.Mockito.*;
-public class DefaultJRubyIssuesTest {
+public class JRubyApiIssuesTest {
IssueFinder finder = mock(IssueFinder.class);
- ServerIssueActions changes = mock(ServerIssueActions.class);
- DefaultJRubyIssues facade = new DefaultJRubyIssues(finder, changes);
+ JRubyApiIssues facade = new JRubyApiIssues(finder);
@Test
public void test_find() throws Exception {
- facade.find(ImmutableMap.<String, Object>of("keys", Lists.newArrayList("ABCDE")), 123);
+ facade.find(ImmutableMap.<String, Object>of("keys", Lists.newArrayList("ABCDE")));
verify(finder).find(argThat(new ArgumentMatcher<IssueQuery>() {
@Override
public boolean matches(Object o) {
return ((IssueQuery) o).keys().contains("ABCDE");
}
- }), eq(123), eq(UserRole.CODEVIEWER));
+ }), anyInt(), eq(UserRole.CODEVIEWER));
}
@Test
@@ -73,7 +72,7 @@ public class DefaultJRubyIssuesTest {
map.put("pageSize", 10l);
map.put("pageIndex", 50);
- IssueQuery query = new DefaultJRubyIssues(finder, changes).toQuery(map);
+ IssueQuery query = new JRubyApiIssues(finder).toQuery(map);
assertThat(query.keys()).containsOnly("ABCDE1234");
assertThat(query.severities()).containsOnly("MAJOR", "MINOR");
assertThat(query.statuses()).containsOnly("CLOSED");
@@ -91,20 +90,20 @@ public class DefaultJRubyIssuesTest {
@Test
public void should_parse_list_of_rules() {
- assertThat(DefaultJRubyIssues.toRules(null)).isNull();
- assertThat(DefaultJRubyIssues.toRules("")).isEmpty();
- assertThat(DefaultJRubyIssues.toRules("squid:AvoidCycle")).containsOnly(RuleKey.of("squid", "AvoidCycle"));
- assertThat(DefaultJRubyIssues.toRules("squid:AvoidCycle,findbugs:NullRef")).containsOnly(RuleKey.of("squid", "AvoidCycle"), RuleKey.of("findbugs", "NullRef"));
- assertThat(DefaultJRubyIssues.toRules(asList("squid:AvoidCycle", "findbugs:NullRef"))).containsOnly(RuleKey.of("squid", "AvoidCycle"), RuleKey.of("findbugs", "NullRef"));
+ assertThat(JRubyApiIssues.toRules(null)).isNull();
+ assertThat(JRubyApiIssues.toRules("")).isEmpty();
+ assertThat(JRubyApiIssues.toRules("squid:AvoidCycle")).containsOnly(RuleKey.of("squid", "AvoidCycle"));
+ assertThat(JRubyApiIssues.toRules("squid:AvoidCycle,findbugs:NullRef")).containsOnly(RuleKey.of("squid", "AvoidCycle"), RuleKey.of("findbugs", "NullRef"));
+ assertThat(JRubyApiIssues.toRules(asList("squid:AvoidCycle", "findbugs:NullRef"))).containsOnly(RuleKey.of("squid", "AvoidCycle"), RuleKey.of("findbugs", "NullRef"));
}
@Test
public void should_parse_list_of_strings() {
- assertThat(DefaultJRubyIssues.toStrings(null)).isNull();
- assertThat(DefaultJRubyIssues.toStrings("")).isEmpty();
- assertThat(DefaultJRubyIssues.toStrings("foo")).containsOnly("foo");
- assertThat(DefaultJRubyIssues.toStrings("foo,bar")).containsOnly("foo", "bar");
- assertThat(DefaultJRubyIssues.toStrings(asList("foo", "bar"))).containsOnly("foo", "bar");
+ assertThat(JRubyApiIssues.toStrings(null)).isNull();
+ assertThat(JRubyApiIssues.toStrings("")).isEmpty();
+ assertThat(JRubyApiIssues.toStrings("foo")).containsOnly("foo");
+ assertThat(JRubyApiIssues.toStrings("foo,bar")).containsOnly("foo", "bar");
+ assertThat(JRubyApiIssues.toStrings(asList("foo", "bar"))).containsOnly("foo", "bar");
}
diff --git a/sonar-server/src/test/java/org/sonar/server/platform/UserSessionFilterTest.java b/sonar-server/src/test/java/org/sonar/server/platform/UserSessionFilterTest.java
new file mode 100644
index 00000000000..55399dada36
--- /dev/null
+++ b/sonar-server/src/test/java/org/sonar/server/platform/UserSessionFilterTest.java
@@ -0,0 +1,107 @@
+/*
+ * SonarQube, open source software quality management tool.
+ * Copyright (C) 2008-2013 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.platform;
+
+import org.junit.Before;
+import org.junit.Test;
+import org.mockito.invocation.InvocationOnMock;
+import org.mockito.stubbing.Answer;
+
+import javax.servlet.FilterChain;
+import javax.servlet.FilterConfig;
+import javax.servlet.ServletResponse;
+import javax.servlet.http.HttpServletRequest;
+import javax.servlet.http.HttpSession;
+
+import static org.fest.assertions.Assertions.assertThat;
+import static org.mockito.Mockito.*;
+
+public class UserSessionFilterTest {
+
+ @Before
+ public void setUp() {
+ // for test isolation
+ UserSession.set(null);
+ }
+
+ @Test
+ public void should_load_user_session() throws Exception {
+ HttpSession httpSession = mock(HttpSession.class);
+ // JRuby sets a long but not an integer
+ when(httpSession.getAttribute("user_id")).thenReturn(123L);
+ when(httpSession.getAttribute("login")).thenReturn("karadoc");
+ HttpServletRequest httpRequest = mock(HttpServletRequest.class);
+ when(httpRequest.getSession(true)).thenReturn(httpSession);
+ ServletResponse httpResponse = mock(ServletResponse.class);
+
+ FilterChain chain = mock(FilterChain.class);
+ doAnswer(new Answer() {
+ @Override
+ public Object answer(InvocationOnMock invocation) throws Throwable {
+ assertThat(UserSession.get()).isNotNull();
+ assertThat(UserSession.get().login()).isEqualTo("karadoc");
+ assertThat(UserSession.get().userId()).isEqualTo(123);
+ assertThat(UserSession.get().isLoggedIn()).isTrue();
+ return null;
+ }
+ }).when(chain).doFilter(httpRequest, httpResponse);
+
+ UserSessionFilter filter = new UserSessionFilter();
+ filter.doFilter(httpRequest, httpResponse, chain);
+
+ verify(chain).doFilter(httpRequest, httpResponse);
+ }
+
+ /**
+ * UserSession should always be set, even when end-user is not logged in.
+ */
+ @Test
+ public void should_load_anonymous_session() throws Exception {
+ HttpSession httpSession = mock(HttpSession.class);
+ HttpServletRequest httpRequest = mock(HttpServletRequest.class);
+ when(httpRequest.getSession(true)).thenReturn(httpSession);
+ ServletResponse httpResponse = mock(ServletResponse.class);
+
+ FilterChain chain = mock(FilterChain.class);
+ doAnswer(new Answer() {
+ @Override
+ public Object answer(InvocationOnMock invocation) throws Throwable {
+ assertThat(UserSession.get()).isNotNull();
+ assertThat(UserSession.get().login()).isNull();
+ assertThat(UserSession.get().userId()).isNull();
+ assertThat(UserSession.get().isLoggedIn()).isFalse();
+ return null;
+ }
+ }).when(chain).doFilter(httpRequest, httpResponse);
+
+ UserSessionFilter filter = new UserSessionFilter();
+ filter.doFilter(httpRequest, httpResponse, chain);
+
+ verify(chain).doFilter(httpRequest, httpResponse);
+ }
+
+ @Test
+ public void just_for_fun_and_coverage() throws Exception {
+ UserSessionFilter filter = new UserSessionFilter();
+ filter.init(mock(FilterConfig.class));
+ filter.destroy();
+ // do not fail
+ }
+}
diff --git a/sonar-server/src/test/java/org/sonar/server/rule/DefaultJRubyRulesTest.java b/sonar-server/src/test/java/org/sonar/server/rule/JRubyRulesTest.java
index 67820369694..ef68be157b7 100644
--- a/sonar-server/src/test/java/org/sonar/server/rule/DefaultJRubyRulesTest.java
+++ b/sonar-server/src/test/java/org/sonar/server/rule/JRubyRulesTest.java
@@ -28,15 +28,15 @@ import static org.fest.assertions.Assertions.assertThat;
import static org.mockito.Mockito.mock;
import static org.mockito.Mockito.when;
-public class DefaultJRubyRulesTest {
+public class JRubyRulesTest {
- private DefaultJRubyRules defaultJRubyRules;
+ private JRubyRules JRubyRules;
private JRubyI18n jRubyI18n;
@Before
public void before() {
jRubyI18n = mock(JRubyI18n.class);
- defaultJRubyRules = new DefaultJRubyRules(jRubyI18n);
+ JRubyRules = new JRubyRules(jRubyI18n);
}
@Test
@@ -45,7 +45,7 @@ public class DefaultJRubyRulesTest {
String locale = "en";
RuleKey ruleKey = RuleKey.of("squid", "AvoidCycle");
when(jRubyI18n.getRuleName(locale, "squid", "AvoidCycle")).thenReturn(ruleName);
- assertThat(defaultJRubyRules.ruleName(locale, ruleKey)).isEqualTo(ruleName);
+ assertThat(JRubyRules.ruleName(locale, ruleKey)).isEqualTo(ruleName);
}
@Test
@@ -54,7 +54,7 @@ public class DefaultJRubyRulesTest {
RuleKey ruleKey = RuleKey.of("squid", "AvoidCycle");
when(jRubyI18n.getRuleName("fr", "squid", "AvoidCycle")).thenReturn(null);
when(jRubyI18n.getRuleName("en", "squid", "AvoidCycle")).thenReturn(englishRuleName);
- assertThat(defaultJRubyRules.ruleName("fr", ruleKey)).isEqualTo(englishRuleName);
+ assertThat(JRubyRules.ruleName("fr", ruleKey)).isEqualTo(englishRuleName);
}
}
diff --git a/sonar-server/src/test/java/org/sonar/server/text/JRubyTextTest.java b/sonar-server/src/test/java/org/sonar/server/text/JRubyTextTest.java
new file mode 100644
index 00000000000..feb71d9972d
--- /dev/null
+++ b/sonar-server/src/test/java/org/sonar/server/text/JRubyTextTest.java
@@ -0,0 +1,59 @@
+/*
+ * SonarQube, open source software quality management tool.
+ * Copyright (C) 2008-2013 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.text;
+
+import org.junit.Test;
+import org.sonar.core.source.HtmlSourceDecorator;
+
+import static org.fest.assertions.Assertions.assertThat;
+import static org.mockito.Mockito.*;
+
+public class JRubyTextTest {
+
+ MacroInterpreter macroInterpreter = mock(MacroInterpreter.class);
+ HtmlSourceDecorator sourceDecorator = mock(HtmlSourceDecorator.class);
+ JRubyText text = new JRubyText(macroInterpreter, sourceDecorator);
+
+ @Test
+ public void interpretMacros() throws Exception {
+ text.interpretMacros("text with macros");
+ verify(macroInterpreter, times(1)).interpret("text with macros");
+ verifyZeroInteractions(sourceDecorator);
+ }
+
+ @Test
+ public void markdownToHtml() throws Exception {
+ String html = text.markdownToHtml("some *markdown*");
+ assertThat(html).isEqualTo("some <em>markdown</em>");
+ }
+
+ @Test
+ public void should_escape_markdown_input() throws Exception {
+ String html = text.markdownToHtml("a > b");
+ assertThat(html).isEqualTo("a &gt; b");
+ }
+
+ @Test
+ public void highlightedSourceLines() throws Exception {
+ text.highlightedSourceLines(123L);
+ verify(sourceDecorator, times(1)).getDecoratedSourceAsHtml(123L);
+ verifyZeroInteractions(macroInterpreter);
+ }
+}
diff --git a/sonar-server/src/test/java/org/sonar/server/ui/MacroInterpreterTest.java b/sonar-server/src/test/java/org/sonar/server/text/MacroInterpreterTest.java
index 218fee698be..b23f84c0741 100644
--- a/sonar-server/src/test/java/org/sonar/server/ui/MacroInterpreterTest.java
+++ b/sonar-server/src/test/java/org/sonar/server/text/MacroInterpreterTest.java
@@ -18,11 +18,10 @@
* Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
*/
-package org.sonar.server.ui;
+package org.sonar.server.text;
import org.junit.Before;
import org.junit.Test;
-import org.sonar.server.macro.MacroInterpreter;
import javax.servlet.ServletContext;
@@ -32,12 +31,11 @@ import static org.mockito.Mockito.when;
public class MacroInterpreterTest {
- private MacroInterpreter interpreter;
- private String path;
+ String path = "http://sonar";
+ MacroInterpreter interpreter;
@Before
- public void before() {
- path = "http://sonar";
+ public void setUp() {
ServletContext servletContext = mock(ServletContext.class);
when(servletContext.getContextPath()).thenReturn(path);
interpreter = new MacroInterpreter(servletContext);
@@ -46,16 +44,6 @@ public class MacroInterpreterTest {
@Test
public void should_do_nothing_if_no_macro_detected() {
String origin = "nothing to do";
- interpreter.start();
- String result = interpreter.interpret(origin);
- assertThat(result).isEqualTo(origin);
- }
-
- @Test
- public void should_do_nothing_if_not_started() {
- String ruleKey = "repo:key";
- String origin = "{rule:"+ ruleKey + "}";
-
String result = interpreter.interpret(origin);
assertThat(result).isEqualTo(origin);
}
@@ -63,18 +51,16 @@ public class MacroInterpreterTest {
@Test
public void should_replace_rule_macro() {
String ruleKey = "repo:key";
- String origin = "See {rule:"+ ruleKey + "} for detail.";
- interpreter.start();
+ String origin = "See {rule:" + ruleKey + "} for detail.";
String result = interpreter.interpret(origin);
- assertThat(result).isEqualTo("See <a class='open-modal rule-modal' modal-width='800' href='"+ path + "/rules/show/"+ ruleKey + "?modal=true&layout=false'>" + ruleKey +"</a> for detail.");
+ assertThat(result).isEqualTo("See <a class='open-modal rule-modal' modal-width='800' href='" + path + "/rules/show/" + ruleKey + "?modal=true&layout=false'>" + ruleKey + "</a> for detail.");
}
@Test
public void should_replace_rule_macro_containing_digit_and_dash() {
String ruleKey = "my-repo1:my-key1";
- String origin = "See {rule:"+ ruleKey + "} for detail.";
- interpreter.start();
+ String origin = "See {rule:" + ruleKey + "} for detail.";
String result = interpreter.interpret(origin);
- assertThat(result).isEqualTo("See <a class='open-modal rule-modal' modal-width='800' href='"+ path + "/rules/show/"+ ruleKey + "?modal=true&layout=false'>" + ruleKey +"</a> for detail.");
+ assertThat(result).isEqualTo("See <a class='open-modal rule-modal' modal-width='800' href='" + path + "/rules/show/" + ruleKey + "?modal=true&layout=false'>" + ruleKey + "</a> for detail.");
}
}
diff --git a/sonar-server/src/test/java/org/sonar/server/ui/JRubyFacadesTest.java b/sonar-server/src/test/java/org/sonar/server/ui/JRubyFacadesTest.java
deleted file mode 100644
index c4b34d7a4e3..00000000000
--- a/sonar-server/src/test/java/org/sonar/server/ui/JRubyFacadesTest.java
+++ /dev/null
@@ -1,36 +0,0 @@
-/*
- * SonarQube, open source software quality management tool.
- * Copyright (C) 2008-2013 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.ui;
-
-import org.junit.Test;
-import org.sonar.server.issue.DefaultJRubyIssues;
-
-import static org.fest.assertions.Assertions.assertThat;
-import static org.mockito.Mockito.mock;
-
-public class JRubyFacadesTest {
-
- @Test
- public void register_issues_facade_on_creation() throws Exception {
- DefaultJRubyIssues issues = mock(DefaultJRubyIssues.class);
- JRubyFacades.setIssues(issues);
- assertThat(JRubyFacades.issues()).isSameAs(issues);
- }
-}