]> source.dussan.org Git - sonarqube.git/commitdiff
SONAR-5334 Create WS to serialize all bundles for a given language
authorJean-Baptiste Lievremont <jean-baptiste.lievremont@sonarsource.com>
Thu, 22 May 2014 15:34:22 +0000 (17:34 +0200)
committerJean-Baptiste Lievremont <jean-baptiste.lievremont@sonarsource.com>
Thu, 22 May 2014 15:34:22 +0000 (17:34 +0200)
sonar-core/src/main/java/org/sonar/core/i18n/DefaultI18n.java
sonar-server/src/main/java/org/sonar/server/platform/ServerComponents.java
sonar-server/src/main/java/org/sonar/server/platform/ws/L10nWs.java [new file with mode: 0644]
sonar-server/src/test/java/org/sonar/server/platform/ws/L10nWsTest.java [new file with mode: 0644]

index 0ce77a1baec77e0baf58599f85a9188cdbb1ed49..dc6de022b0039a21bea26ae606f66c4cadb7b79c 100644 (file)
@@ -206,8 +206,7 @@ public class DefaultI18n implements I18n, ServerExtension, BatchExtension, Start
     return result;
   }
 
-  @VisibleForTesting
-  Set<String> getPropertyKeys() {
+  public Set<String> getPropertyKeys() {
     return propertyToBundles.keySet();
   }
 
index 42eb906dcccaa1b8a74deab74f7f51922d79487e..68df4edaf9e2714cefd2dc00db322487ccaeab79 100644 (file)
@@ -52,13 +52,7 @@ import org.sonar.core.measure.db.MeasureFilterDao;
 import org.sonar.core.metric.DefaultMetricFinder;
 import org.sonar.core.notification.DefaultNotificationManager;
 import org.sonar.core.permission.PermissionFacade;
-import org.sonar.core.persistence.DaoUtils;
-import org.sonar.core.persistence.DatabaseVersion;
-import org.sonar.core.persistence.DefaultDatabase;
-import org.sonar.core.persistence.MyBatis;
-import org.sonar.core.persistence.PreviewDatabaseFactory;
-import org.sonar.core.persistence.SemaphoreUpdater;
-import org.sonar.core.persistence.SemaphoresImpl;
+import org.sonar.core.persistence.*;
 import org.sonar.core.preview.PreviewCache;
 import org.sonar.core.profiling.Profiling;
 import org.sonar.core.purge.PurgeProfiler;
@@ -92,33 +86,11 @@ import org.sonar.server.db.DbClient;
 import org.sonar.server.db.EmbeddedDatabaseFactory;
 import org.sonar.server.db.migrations.DatabaseMigrations;
 import org.sonar.server.db.migrations.DatabaseMigrator;
-import org.sonar.server.debt.DebtCharacteristicsXMLImporter;
-import org.sonar.server.debt.DebtModelBackup;
-import org.sonar.server.debt.DebtModelLookup;
-import org.sonar.server.debt.DebtModelOperations;
-import org.sonar.server.debt.DebtModelPluginRepository;
-import org.sonar.server.debt.DebtModelService;
-import org.sonar.server.debt.DebtModelXMLExporter;
-import org.sonar.server.debt.DebtRulesXMLImporter;
+import org.sonar.server.debt.*;
 import org.sonar.server.duplication.ws.DuplicationsWriter;
 import org.sonar.server.duplication.ws.DuplicationsWs;
 import org.sonar.server.es.ESNode;
-import org.sonar.server.issue.ActionService;
-import org.sonar.server.issue.AssignAction;
-import org.sonar.server.issue.CommentAction;
-import org.sonar.server.issue.DefaultIssueFinder;
-import org.sonar.server.issue.InternalRubyIssueService;
-import org.sonar.server.issue.IssueBulkChangeService;
-import org.sonar.server.issue.IssueChangelogFormatter;
-import org.sonar.server.issue.IssueChangelogService;
-import org.sonar.server.issue.IssueCommentService;
-import org.sonar.server.issue.IssueService;
-import org.sonar.server.issue.IssueStatsFinder;
-import org.sonar.server.issue.PlanAction;
-import org.sonar.server.issue.PublicRubyIssueService;
-import org.sonar.server.issue.ServerIssueStorage;
-import org.sonar.server.issue.SetSeverityAction;
-import org.sonar.server.issue.TransitionAction;
+import org.sonar.server.issue.*;
 import org.sonar.server.issue.actionplan.ActionPlanService;
 import org.sonar.server.issue.actionplan.ActionPlanWs;
 import org.sonar.server.issue.filter.IssueFilterService;
@@ -137,75 +109,27 @@ import org.sonar.server.permission.InternalPermissionService;
 import org.sonar.server.permission.InternalPermissionTemplateService;
 import org.sonar.server.permission.PermissionFinder;
 import org.sonar.server.permission.ws.PermissionsWs;
+import org.sonar.server.platform.ws.L10nWs;
 import org.sonar.server.platform.ws.RestartHandler;
 import org.sonar.server.platform.ws.ServerWs;
 import org.sonar.server.platform.ws.SystemWs;
-import org.sonar.server.plugins.BatchWs;
-import org.sonar.server.plugins.InstalledPluginReferentialFactory;
-import org.sonar.server.plugins.PluginDownloader;
-import org.sonar.server.plugins.ServerExtensionInstaller;
-import org.sonar.server.plugins.ServerPluginJarInstaller;
-import org.sonar.server.plugins.ServerPluginJarsInstaller;
-import org.sonar.server.plugins.ServerPluginRepository;
-import org.sonar.server.plugins.UpdateCenterClient;
-import org.sonar.server.plugins.UpdateCenterMatrixFactory;
+import org.sonar.server.plugins.*;
 import org.sonar.server.qualitygate.QgateProjectFinder;
 import org.sonar.server.qualitygate.QualityGates;
 import org.sonar.server.qualitygate.RegisterQualityGates;
-import org.sonar.server.qualitygate.ws.QGatesAppAction;
-import org.sonar.server.qualitygate.ws.QGatesCopyAction;
-import org.sonar.server.qualitygate.ws.QGatesCreateAction;
-import org.sonar.server.qualitygate.ws.QGatesCreateConditionAction;
-import org.sonar.server.qualitygate.ws.QGatesDeleteConditionAction;
-import org.sonar.server.qualitygate.ws.QGatesDeselectAction;
-import org.sonar.server.qualitygate.ws.QGatesDestroyAction;
-import org.sonar.server.qualitygate.ws.QGatesListAction;
-import org.sonar.server.qualitygate.ws.QGatesRenameAction;
-import org.sonar.server.qualitygate.ws.QGatesSearchAction;
-import org.sonar.server.qualitygate.ws.QGatesSelectAction;
-import org.sonar.server.qualitygate.ws.QGatesSetAsDefaultAction;
-import org.sonar.server.qualitygate.ws.QGatesShowAction;
-import org.sonar.server.qualitygate.ws.QGatesUnsetDefaultAction;
-import org.sonar.server.qualitygate.ws.QGatesUpdateConditionAction;
-import org.sonar.server.qualitygate.ws.QGatesWs;
-import org.sonar.server.qualityprofile.ActiveRuleService;
-import org.sonar.server.qualityprofile.DefaultProfilesCache;
-import org.sonar.server.qualityprofile.ProfilesManager;
-import org.sonar.server.qualityprofile.QProfileActiveRuleOperations;
-import org.sonar.server.qualityprofile.QProfileBackup;
-import org.sonar.server.qualityprofile.QProfileLookup;
-import org.sonar.server.qualityprofile.QProfileOperations;
-import org.sonar.server.qualityprofile.QProfileProjectLookup;
-import org.sonar.server.qualityprofile.QProfileProjectOperations;
-import org.sonar.server.qualityprofile.QProfileRepositoryExporter;
-import org.sonar.server.qualityprofile.QProfiles;
-import org.sonar.server.qualityprofile.QualityProfileService;
-import org.sonar.server.qualityprofile.RegisterQualityProfiles;
-import org.sonar.server.qualityprofile.RuleActivationContextFactory;
+import org.sonar.server.qualitygate.ws.*;
+import org.sonar.server.qualityprofile.*;
 import org.sonar.server.qualityprofile.index.ActiveRuleIndex;
 import org.sonar.server.qualityprofile.index.ActiveRuleNormalizer;
 import org.sonar.server.qualityprofile.persistence.ActiveRuleDao;
-import org.sonar.server.qualityprofile.ws.BulkRuleActivationActions;
-import org.sonar.server.qualityprofile.ws.ProfilesWs;
-import org.sonar.server.qualityprofile.ws.QProfileRecreateBuiltInAction;
-import org.sonar.server.qualityprofile.ws.QProfilesWs;
-import org.sonar.server.qualityprofile.ws.RuleActivationActions;
-import org.sonar.server.rule.DeprecatedRulesDefinition;
-import org.sonar.server.rule.RubyRuleService;
-import org.sonar.server.rule.RuleDefinitionsLoader;
-import org.sonar.server.rule.RuleOperations;
-import org.sonar.server.rule.RuleRepositories;
+import org.sonar.server.qualityprofile.ws.*;
+import org.sonar.server.rule.*;
 import org.sonar.server.rule2.RegisterRules;
 import org.sonar.server.rule2.RuleService;
 import org.sonar.server.rule2.index.RuleIndex;
 import org.sonar.server.rule2.index.RuleNormalizer;
 import org.sonar.server.rule2.persistence.RuleDao;
-import org.sonar.server.rule2.ws.RuleMapping;
-import org.sonar.server.rule2.ws.RulesWebService;
-import org.sonar.server.rule2.ws.SearchAction;
-import org.sonar.server.rule2.ws.SetNoteAction;
-import org.sonar.server.rule2.ws.SetTagsAction;
-import org.sonar.server.rule2.ws.TagsAction;
+import org.sonar.server.rule2.ws.*;
 import org.sonar.server.search.IndexClient;
 import org.sonar.server.search.IndexQueue;
 import org.sonar.server.search.IndexQueueWorker;
@@ -217,20 +141,7 @@ import org.sonar.server.source.ws.ScmAction;
 import org.sonar.server.source.ws.ScmWriter;
 import org.sonar.server.source.ws.ShowAction;
 import org.sonar.server.source.ws.SourcesWs;
-import org.sonar.server.startup.CleanPreviewAnalysisCache;
-import org.sonar.server.startup.CopyRequirementsFromCharacteristicsToRules;
-import org.sonar.server.startup.GeneratePluginIndex;
-import org.sonar.server.startup.GwtPublisher;
-import org.sonar.server.startup.JdbcDriverDeployer;
-import org.sonar.server.startup.LogServerId;
-import org.sonar.server.startup.RegisterDashboards;
-import org.sonar.server.startup.RegisterDebtModel;
-import org.sonar.server.startup.RegisterMetrics;
-import org.sonar.server.startup.RegisterNewMeasureFilters;
-import org.sonar.server.startup.RegisterPermissionTemplates;
-import org.sonar.server.startup.RegisterServletFilters;
-import org.sonar.server.startup.RenameDeprecatedPropertyKeys;
-import org.sonar.server.startup.ServerMetadataPersister;
+import org.sonar.server.startup.*;
 import org.sonar.server.test.CoverageService;
 import org.sonar.server.test.ws.CoverageShowAction;
 import org.sonar.server.test.ws.CoverageWs;
@@ -242,20 +153,9 @@ import org.sonar.server.ui.JRubyProfiling;
 import org.sonar.server.ui.PageDecorations;
 import org.sonar.server.ui.Views;
 import org.sonar.server.updatecenter.ws.UpdateCenterWs;
-import org.sonar.server.user.DefaultUserService;
-import org.sonar.server.user.DoPrivileged;
-import org.sonar.server.user.GroupMembershipFinder;
-import org.sonar.server.user.GroupMembershipService;
-import org.sonar.server.user.NewUserNotifier;
-import org.sonar.server.user.SecurityRealmFactory;
+import org.sonar.server.user.*;
 import org.sonar.server.user.ws.UsersWs;
-import org.sonar.server.util.BooleanTypeValidation;
-import org.sonar.server.util.FloatTypeValidation;
-import org.sonar.server.util.IntegerTypeValidation;
-import org.sonar.server.util.StringListTypeValidation;
-import org.sonar.server.util.StringTypeValidation;
-import org.sonar.server.util.TextTypeValidation;
-import org.sonar.server.util.TypeValidations;
+import org.sonar.server.util.*;
 import org.sonar.server.ws.ListingWs;
 import org.sonar.server.ws.WebServiceEngine;
 
@@ -473,6 +373,9 @@ class ServerComponents {
     pico.addSingleton(WebServiceEngine.class);
     pico.addSingleton(ListingWs.class);
 
+    // localization
+    pico.addSingleton(L10nWs.class);
+
     // authentication
     pico.addSingleton(AuthenticationWs.class);
 
diff --git a/sonar-server/src/main/java/org/sonar/server/platform/ws/L10nWs.java b/sonar-server/src/main/java/org/sonar/server/platform/ws/L10nWs.java
new file mode 100644 (file)
index 0000000..f267b4a
--- /dev/null
@@ -0,0 +1,72 @@
+/*
+ * 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.platform.ws;
+
+import org.apache.commons.lang.LocaleUtils;
+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.core.i18n.DefaultI18n;
+import org.sonar.server.user.UserSession;
+
+import java.util.Locale;
+
+public class L10nWs implements WebService {
+
+  private final DefaultI18n i18n;
+
+  public L10nWs(DefaultI18n i18n) {
+    this.i18n = i18n;
+  }
+
+  @Override
+  public void define(Context context) {
+    NewController l10n = context.createController("api/l10n");
+    l10n.setDescription("Localization")
+      .setSince("4.4")
+      .createAction("index")
+        .setInternal(true)
+        .setDescription("Get all localization messages for a given locale")
+        .setHandler(new RequestHandler() {
+          @Override
+          public void handle(Request request, Response response) throws Exception {
+            serializeMessages(request, response);
+          }
+        }).createParam("locale")
+          .setDescription("BCP47 language tag, used to override the browser Accept-Language header")
+          .setExampleValue("fr-CH");
+    l10n.done();
+  }
+
+  protected void serializeMessages(Request request, Response response) {
+    Locale locale = UserSession.get().locale();
+    String localeParam = request.param("locale");
+    if (localeParam != null) {
+      locale = LocaleUtils.toLocale(localeParam);
+    }
+    JsonWriter json = response.newJsonWriter().beginObject();
+    for (String messageKey: i18n.getPropertyKeys()) {
+      json.prop(messageKey, i18n.message(locale, messageKey, messageKey));
+    }
+    json.endObject().close();
+  }
+}
diff --git a/sonar-server/src/test/java/org/sonar/server/platform/ws/L10nWsTest.java b/sonar-server/src/test/java/org/sonar/server/platform/ws/L10nWsTest.java
new file mode 100644 (file)
index 0000000..2194058
--- /dev/null
@@ -0,0 +1,89 @@
+/*
+ * 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.platform.ws;
+
+import com.google.common.collect.ImmutableSet;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.mockito.Mock;
+import org.mockito.runners.MockitoJUnitRunner;
+import org.sonar.core.i18n.DefaultI18n;
+import org.sonar.server.user.MockUserSession;
+import org.sonar.server.ws.WsTester;
+import org.sonar.server.ws.WsTester.Result;
+
+import java.util.Locale;
+
+import static org.mockito.Mockito.verify;
+import static org.mockito.Mockito.when;
+
+@RunWith(MockitoJUnitRunner.class)
+public class L10nWsTest {
+
+  @Mock
+  DefaultI18n i18n;
+
+  @Test
+  public void should_return_all_l10n_messages_using_accept_header() throws Exception {
+    Locale locale = Locale.PRC;
+    MockUserSession.set().setLocale(locale);
+
+    String key1 = "key1";
+    String key2 = "key2";
+    String key3 = "key3";
+
+    when(i18n.getPropertyKeys()).thenReturn(ImmutableSet.of(key1, key2, key3));
+    when(i18n.message(locale, key1, key1)).thenReturn(key1);
+    when(i18n.message(locale, key2, key2)).thenReturn(key2);
+    when(i18n.message(locale, key3, key3)).thenReturn(key3);
+
+    Result result = new WsTester(new L10nWs(i18n)).newGetRequest("api/l10n", "index").execute();
+    verify(i18n).getPropertyKeys();
+    verify(i18n).message(locale, key1, key1);
+    verify(i18n).message(locale, key2, key2);
+    verify(i18n).message(locale, key3, key3);
+
+    result.assertJson("{key1:'key1',key2:'key2',key3:'key3'}");
+  }
+
+  @Test
+  public void should_override_locale_when_locale_param_is_set() throws Exception {
+    Locale locale = Locale.PRC;
+    MockUserSession.set().setLocale(locale);
+    Locale override = Locale.JAPANESE;
+
+    String key1 = "key1";
+    String key2 = "key2";
+    String key3 = "key3";
+
+    when(i18n.getPropertyKeys()).thenReturn(ImmutableSet.of(key1, key2, key3));
+    when(i18n.message(override, key1, key1)).thenReturn(key1);
+    when(i18n.message(override, key2, key2)).thenReturn(key2);
+    when(i18n.message(override, key3, key3)).thenReturn(key3);
+
+    Result result = new WsTester(new L10nWs(i18n)).newGetRequest("api/l10n", "index").setParam("locale", override.toString()).execute();
+    verify(i18n).getPropertyKeys();
+    verify(i18n).message(override, key1, key1);
+    verify(i18n).message(override, key2, key2);
+    verify(i18n).message(override, key3, key3);
+
+    result.assertJson("{key1:'key1',key2:'key2',key3:'key3'}");
+  }
+}