summaryrefslogtreecommitdiffstats
path: root/server
diff options
context:
space:
mode:
authorArtur Signell <artur@vaadin.com>2013-05-28 12:00:15 +0300
committerVaadin Code Review <review@vaadin.com>2013-05-29 12:33:17 +0000
commita9afca67ba942afa287be3507eb225e0a7b954e6 (patch)
treed2ddd12b3acc2f83c3361c018717bd557454cec6 /server
parenta3ad62d947c86d3f53f333ca9bc36e4544cd5d46 (diff)
downloadvaadin-framework-a9afca67ba942afa287be3507eb225e0a7b954e6.tar.gz
vaadin-framework-a9afca67ba942afa287be3507eb225e0a7b954e6.zip
Moved Locale data handling to LocaleService (#11378)
The locale data is now tracked per UI instance and no longer sent in every request. Change-Id: I4bebd00327da6f8d812181fd76a85eb6196d0010
Diffstat (limited to 'server')
-rw-r--r--server/src/com/vaadin/server/JsonPaintTarget.java4
-rw-r--r--server/src/com/vaadin/server/LegacyCommunicationManager.java61
-rw-r--r--server/src/com/vaadin/server/LocaleService.java211
-rw-r--r--server/src/com/vaadin/server/communication/LocaleWriter.java204
-rw-r--r--server/src/com/vaadin/server/communication/UidlWriter.java4
-rw-r--r--server/src/com/vaadin/ui/AbstractComponent.java9
-rw-r--r--server/src/com/vaadin/ui/UI.java17
7 files changed, 236 insertions, 274 deletions
diff --git a/server/src/com/vaadin/server/JsonPaintTarget.java b/server/src/com/vaadin/server/JsonPaintTarget.java
index ca70391f64..cd09b2a44b 100644
--- a/server/src/com/vaadin/server/JsonPaintTarget.java
+++ b/server/src/com/vaadin/server/JsonPaintTarget.java
@@ -388,10 +388,6 @@ public class JsonPaintTarget implements PaintTarget {
getUsedResources().add("layouts/" + value + ".html");
}
- if (name.equals("locale")) {
- manager.requireLocale(value);
- }
-
}
@Override
diff --git a/server/src/com/vaadin/server/LegacyCommunicationManager.java b/server/src/com/vaadin/server/LegacyCommunicationManager.java
index c0194db243..ad662cf6df 100644
--- a/server/src/com/vaadin/server/LegacyCommunicationManager.java
+++ b/server/src/com/vaadin/server/LegacyCommunicationManager.java
@@ -16,18 +16,12 @@
package com.vaadin.server;
-import java.io.IOException;
-import java.io.PrintWriter;
import java.io.Serializable;
-import java.io.Writer;
import java.net.URI;
import java.net.URISyntaxException;
import java.security.GeneralSecurityException;
-import java.util.ArrayList;
import java.util.HashMap;
import java.util.HashSet;
-import java.util.List;
-import java.util.Locale;
import java.util.Map;
import java.util.Set;
import java.util.logging.Level;
@@ -37,7 +31,6 @@ import org.json.JSONException;
import org.json.JSONObject;
import com.vaadin.server.ClientConnector.ConnectorErrorEvent;
-import com.vaadin.server.communication.LocaleWriter;
import com.vaadin.shared.ApplicationConstants;
import com.vaadin.shared.JavaScriptConnectorState;
import com.vaadin.shared.communication.SharedState;
@@ -69,9 +62,6 @@ public class LegacyCommunicationManager implements Serializable {
*/
private final VaadinSession session;
- // TODO Refactor to UI shared state (#11378)
- private List<String> locales;
-
// TODO Move to VaadinSession (#11409)
private DragAndDropService dragAndDropService;
@@ -88,7 +78,6 @@ public class LegacyCommunicationManager implements Serializable {
*/
public LegacyCommunicationManager(VaadinSession session) {
this.session = session;
- requireLocale(session.getLocale().toString());
}
protected VaadinSession getSession() {
@@ -313,52 +302,6 @@ public class LegacyCommunicationManager implements Serializable {
}
/**
- * Prints the queued (pending) locale definitions to a {@link PrintWriter}
- * in a (UIDL) format that can be sent to the client and used there in
- * formatting dates, times etc.
- *
- * @deprecated As of 7.1. See #11378.
- *
- * @param outWriter
- */
- @Deprecated
- public void printLocaleDeclarations(Writer writer) throws IOException {
- new LocaleWriter().write(locales, writer);
- }
-
- /**
- * Queues a locale to be sent to the client (browser) for date and time
- * entry etc. All locale specific information is derived from server-side
- * {@link Locale} instances and sent to the client when needed, eliminating
- * the need to use the {@link Locale} class and all the framework behind it
- * on the client.
- *
- * @deprecated As of 7.1. See #11378.
- *
- * @see Locale#toString()
- *
- * @param value
- */
- @Deprecated
- public void requireLocale(String value) {
- if (locales == null) {
- locales = new ArrayList<String>();
- locales.add(session.getLocale().toString());
- }
- if (!locales.contains(value)) {
- locales.add(value);
- }
- }
-
- /**
- * @deprecated As of 7.1. See #11378.
- */
- @Deprecated
- public void resetLocales() {
- locales = null;
- }
-
- /**
* @deprecated As of 7.1. Will be removed in the future.
*/
@Deprecated
@@ -486,10 +429,6 @@ public class LegacyCommunicationManager implements Serializable {
getClientCache(ui).clear();
ui.getConnectorTracker().markAllConnectorsDirty();
ui.getConnectorTracker().markAllClientSidesUninitialized();
-
- // Reset sent locales
- resetLocales();
- requireLocale(session.getLocale().toString());
}
private static final Logger getLogger() {
diff --git a/server/src/com/vaadin/server/LocaleService.java b/server/src/com/vaadin/server/LocaleService.java
new file mode 100644
index 0000000000..347c4da5c6
--- /dev/null
+++ b/server/src/com/vaadin/server/LocaleService.java
@@ -0,0 +1,211 @@
+/*
+ * Copyright 2000-2013 Vaadin Ltd.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License"); you may not
+ * use this file except in compliance with the License. You may obtain a copy of
+ * the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
+ * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
+ * License for the specific language governing permissions and limitations under
+ * the License.
+ */
+
+/**
+ *
+ */
+package com.vaadin.server;
+
+import java.text.DateFormat;
+import java.text.DateFormatSymbols;
+import java.text.SimpleDateFormat;
+import java.util.GregorianCalendar;
+import java.util.Locale;
+import java.util.logging.Logger;
+
+import com.vaadin.shared.ui.ui.UIState.LocaleData;
+import com.vaadin.shared.ui.ui.UIState.LocaleServiceState;
+import com.vaadin.ui.UI;
+
+/**
+ * Server side service which handles locale and the transmission of locale date
+ * to the client side LocaleService.
+ *
+ * @since 7.1
+ * @author Vaadin Ltd
+ */
+public class LocaleService {
+
+ private UI ui;
+
+ private LocaleServiceState state;
+
+ /**
+ * Creates a LocaleService bound to the given UI
+ *
+ * @since 7.1
+ * @param ui
+ * The UI which owns the LocaleService
+ */
+ public LocaleService(UI ui, LocaleServiceState state) {
+ this.ui = ui;
+ this.state = state;
+ }
+
+ /**
+ * Retrieves the UI this service is bound to
+ *
+ * @since 7.1
+ * @return the UI for this service
+ */
+ public UI getUI() {
+ return ui;
+ }
+
+ /**
+ * Adds a locale to be sent to the client (browser) for date and time entry
+ * etc. All locale specific information is derived from server-side
+ * {@link Locale} instances and sent to the client when needed, eliminating
+ * the need to use the {@link Locale} class and all the framework behind it
+ * on the client.
+ *
+ * @param locale
+ * The locale which is required on the client side
+ */
+ public void addLocale(Locale locale) {
+ for (LocaleData data : getState(false).localeData) {
+ if (data.name.equals(locale.toString())) {
+ // Already there
+ return;
+ }
+ }
+
+ getState(true).localeData.add(createLocaleData(locale));
+ }
+
+ /**
+ * Returns the state for this service
+ * <p>
+ * The state is transmitted inside the UI state rather than as an individual
+ * entity.
+ * </p>
+ *
+ * @since 7.1
+ * @param markAsDirty
+ * true to mark the state as dirty
+ * @return a LocaleServiceState object that can be read in any case and
+ * modified if markAsDirty is true
+ */
+ private LocaleServiceState getState(boolean markAsDirty) {
+ if (markAsDirty) {
+ getUI().markAsDirty();
+ }
+
+ return state;
+ }
+
+ /**
+ * Creates a LocaleData instance for transportation to the client
+ *
+ * @since 7.1
+ * @param locale
+ * The locale for which to create a LocaleData object
+ * @return A LocaleData object with information about the given locale
+ */
+ protected LocaleData createLocaleData(Locale locale) {
+ LocaleData localeData = new LocaleData();
+ localeData.name = locale.toString();
+
+ final DateFormatSymbols dfs = new DateFormatSymbols(locale);
+ localeData.shortMonthNames = dfs.getShortMonths();
+ localeData.monthNames = dfs.getMonths();
+ // Client expects 0 based indexing, DateFormatSymbols use 1 based
+ localeData.shortDayNames = new String[7];
+ localeData.dayNames = new String[7];
+ String[] sDayNames = dfs.getShortWeekdays();
+ String[] lDayNames = dfs.getWeekdays();
+ for (int i = 0; i < 7; i++) {
+ localeData.shortDayNames[i] = sDayNames[i + 1];
+ localeData.dayNames[i] = lDayNames[i + 1];
+ }
+
+ /*
+ * First day of week (0 = sunday, 1 = monday)
+ */
+ final java.util.Calendar cal = new GregorianCalendar(locale);
+ localeData.firstDayOfWeek = cal.getFirstDayOfWeek() - 1;
+
+ /*
+ * Date formatting (MM/DD/YYYY etc.)
+ */
+
+ DateFormat dateFormat = DateFormat.getDateTimeInstance(
+ DateFormat.SHORT, DateFormat.SHORT, locale);
+ if (!(dateFormat instanceof SimpleDateFormat)) {
+ getLogger().warning(
+ "Unable to get default date pattern for locale "
+ + locale.toString());
+ dateFormat = new SimpleDateFormat();
+ }
+ final String df = ((SimpleDateFormat) dateFormat).toPattern();
+
+ int timeStart = df.indexOf("H");
+ if (timeStart < 0) {
+ timeStart = df.indexOf("h");
+ }
+ final int ampm_first = df.indexOf("a");
+ // E.g. in Korean locale AM/PM is before h:mm
+ // TODO should take that into consideration on client-side as well,
+ // now always h:mm a
+ if (ampm_first > 0 && ampm_first < timeStart) {
+ timeStart = ampm_first;
+ }
+ // Hebrew locale has time before the date
+ final boolean timeFirst = timeStart == 0;
+ String dateformat;
+ if (timeFirst) {
+ int dateStart = df.indexOf(' ');
+ if (ampm_first > dateStart) {
+ dateStart = df.indexOf(' ', ampm_first);
+ }
+ dateformat = df.substring(dateStart + 1);
+ } else {
+ dateformat = df.substring(0, timeStart - 1);
+ }
+
+ localeData.dateFormat = dateformat.trim();
+
+ /*
+ * Time formatting (24 or 12 hour clock and AM/PM suffixes)
+ */
+ final String timeformat = df.substring(timeStart, df.length());
+ /*
+ * Doesn't return second or milliseconds.
+ *
+ * We use timeformat to determine 12/24-hour clock
+ */
+ final boolean twelve_hour_clock = timeformat.indexOf("a") > -1;
+ // TODO there are other possibilities as well, like 'h' in french
+ // (ignore them, too complicated)
+ final String hour_min_delimiter = timeformat.indexOf(".") > -1 ? "."
+ : ":";
+ // outWriter.print("\"tf\":\"" + timeformat + "\",");
+ localeData.twelveHourClock = twelve_hour_clock;
+ localeData.hourMinuteDelimiter = hour_min_delimiter;
+ if (twelve_hour_clock) {
+ final String[] ampm = dfs.getAmPmStrings();
+ localeData.am = ampm[0];
+ localeData.pm = ampm[1];
+ }
+
+ return localeData;
+ }
+
+ private static Logger getLogger() {
+ return Logger.getLogger(LocaleService.class.getName());
+ }
+
+}
diff --git a/server/src/com/vaadin/server/communication/LocaleWriter.java b/server/src/com/vaadin/server/communication/LocaleWriter.java
deleted file mode 100644
index c05649da19..0000000000
--- a/server/src/com/vaadin/server/communication/LocaleWriter.java
+++ /dev/null
@@ -1,204 +0,0 @@
-/*
- * Copyright 2000-2013 Vaadin Ltd.
- *
- * Licensed under the Apache License, Version 2.0 (the "License"); you may not
- * use this file except in compliance with the License. You may obtain a copy of
- * the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
- * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
- * License for the specific language governing permissions and limitations under
- * the License.
- */
-
-package com.vaadin.server.communication;
-
-import java.io.IOException;
-import java.io.Serializable;
-import java.io.Writer;
-import java.text.DateFormat;
-import java.text.DateFormatSymbols;
-import java.text.SimpleDateFormat;
-import java.util.Calendar;
-import java.util.GregorianCalendar;
-import java.util.List;
-import java.util.Locale;
-import java.util.logging.Logger;
-
-/**
- * Serializes locale information to JSON.
- *
- * @author Vaadin Ltd
- * @since 7.1
- * @deprecated See <a href="http://dev.vaadin.com/ticket/11378">ticket
- * #11378</a>.
- */
-@Deprecated
-public class LocaleWriter implements Serializable {
-
- /**
- * Writes a JSON object containing localized strings of the given locales.
- *
- * @param locales
- * The list of {@link Locale}s to write.
- * @param writer
- * The {@link Writer} used to write the JSON.
- * @throws IOException
- * If the serialization fails.
- *
- */
- public void write(List<String> locales, Writer writer) throws IOException {
-
- // Send locale informations to client
- writer.write("[");
- // TODO locales are currently sent on each request; this will be fixed
- // by implementing #11378.
- for (int pendingLocalesIndex = 0; pendingLocalesIndex < locales.size(); pendingLocalesIndex++) {
-
- final Locale l = generateLocale(locales.get(pendingLocalesIndex));
- // Locale name
- writer.write("{\"name\":\"" + l.toString() + "\",");
-
- /*
- * Month names (both short and full)
- */
- final DateFormatSymbols dfs = new DateFormatSymbols(l);
- final String[] short_months = dfs.getShortMonths();
- final String[] months = dfs.getMonths();
- writer.write("\"smn\":[\""
- + // ShortMonthNames
- short_months[0] + "\",\"" + short_months[1] + "\",\""
- + short_months[2] + "\",\"" + short_months[3] + "\",\""
- + short_months[4] + "\",\"" + short_months[5] + "\",\""
- + short_months[6] + "\",\"" + short_months[7] + "\",\""
- + short_months[8] + "\",\"" + short_months[9] + "\",\""
- + short_months[10] + "\",\"" + short_months[11] + "\""
- + "],");
- writer.write("\"mn\":[\""
- + // MonthNames
- months[0] + "\",\"" + months[1] + "\",\"" + months[2]
- + "\",\"" + months[3] + "\",\"" + months[4] + "\",\""
- + months[5] + "\",\"" + months[6] + "\",\"" + months[7]
- + "\",\"" + months[8] + "\",\"" + months[9] + "\",\""
- + months[10] + "\",\"" + months[11] + "\"" + "],");
-
- /*
- * Weekday names (both short and full)
- */
- final String[] short_days = dfs.getShortWeekdays();
- final String[] days = dfs.getWeekdays();
- writer.write("\"sdn\":[\""
- + // ShortDayNames
- short_days[1] + "\",\"" + short_days[2] + "\",\""
- + short_days[3] + "\",\"" + short_days[4] + "\",\""
- + short_days[5] + "\",\"" + short_days[6] + "\",\""
- + short_days[7] + "\"" + "],");
- writer.write("\"dn\":[\""
- + // DayNames
- days[1] + "\",\"" + days[2] + "\",\"" + days[3] + "\",\""
- + days[4] + "\",\"" + days[5] + "\",\"" + days[6] + "\",\""
- + days[7] + "\"" + "],");
-
- /*
- * First day of week (0 = sunday, 1 = monday)
- */
- final Calendar cal = new GregorianCalendar(l);
- writer.write("\"fdow\":" + (cal.getFirstDayOfWeek() - 1) + ",");
-
- /*
- * Date formatting (MM/DD/YYYY etc.)
- */
-
- DateFormat dateFormat = DateFormat.getDateTimeInstance(
- DateFormat.SHORT, DateFormat.SHORT, l);
- if (!(dateFormat instanceof SimpleDateFormat)) {
- getLogger().warning(
- "Unable to get default date pattern for locale "
- + l.toString());
- dateFormat = new SimpleDateFormat();
- }
- final String df = ((SimpleDateFormat) dateFormat).toPattern();
-
- int timeStart = df.indexOf("H");
- if (timeStart < 0) {
- timeStart = df.indexOf("h");
- }
- final int ampm_first = df.indexOf("a");
- // E.g. in Korean locale AM/PM is before h:mm
- // TODO should take that into consideration on client-side as well,
- // now always h:mm a
- if (ampm_first > 0 && ampm_first < timeStart) {
- timeStart = ampm_first;
- }
- // Hebrew locale has time before the date
- final boolean timeFirst = timeStart == 0;
- String dateformat;
- if (timeFirst) {
- int dateStart = df.indexOf(' ');
- if (ampm_first > dateStart) {
- dateStart = df.indexOf(' ', ampm_first);
- }
- dateformat = df.substring(dateStart + 1);
- } else {
- dateformat = df.substring(0, timeStart - 1);
- }
-
- writer.write("\"df\":\"" + dateformat.trim() + "\",");
-
- /*
- * Time formatting (24 or 12 hour clock and AM/PM suffixes)
- */
- final String timeformat = df.substring(timeStart, df.length());
- /*
- * Doesn't return second or milliseconds.
- *
- * We use timeformat to determine 12/24-hour clock
- */
- final boolean twelve_hour_clock = timeformat.indexOf("a") > -1;
- // TODO there are other possibilities as well, like 'h' in french
- // (ignore them, too complicated)
- final String hour_min_delimiter = timeformat.indexOf(".") > -1 ? "."
- : ":";
- // outWriter.print("\"tf\":\"" + timeformat + "\",");
- writer.write("\"thc\":" + twelve_hour_clock + ",");
- writer.write("\"hmd\":\"" + hour_min_delimiter + "\"");
- if (twelve_hour_clock) {
- final String[] ampm = dfs.getAmPmStrings();
- writer.write(",\"ampm\":[\"" + ampm[0] + "\",\"" + ampm[1]
- + "\"]");
- }
- writer.write("}");
- if (pendingLocalesIndex < locales.size() - 1) {
- writer.write(",");
- }
- }
- writer.write("]"); // Close locales
- }
-
- /**
- * Constructs a {@link Locale} instance to be sent to the client based on a
- * short locale description string.
- *
- * @see #requireLocale(String)
- *
- * @param value
- * @return
- */
- private Locale generateLocale(String value) {
- final String[] temp = value.split("_");
- if (temp.length == 1) {
- return new Locale(temp[0]);
- } else if (temp.length == 2) {
- return new Locale(temp[0], temp[1]);
- } else {
- return new Locale(temp[0], temp[1], temp[2]);
- }
- }
-
- private static final Logger getLogger() {
- return Logger.getLogger(LocaleWriter.class.getName());
- }
-}
diff --git a/server/src/com/vaadin/server/communication/UidlWriter.java b/server/src/com/vaadin/server/communication/UidlWriter.java
index 60a884a635..f715569424 100644
--- a/server/src/com/vaadin/server/communication/UidlWriter.java
+++ b/server/src/com/vaadin/server/communication/UidlWriter.java
@@ -283,10 +283,6 @@ public class UidlWriter implements Serializable {
+ new JSONArray(styleDependencies).toString());
}
- // add any pending locale definitions requested by the client
- writer.write(", \"locales\": ");
- manager.printLocaleDeclarations(writer);
-
if (manager.getDragAndDropService() != null) {
manager.getDragAndDropService().printJSONResponse(writer);
}
diff --git a/server/src/com/vaadin/ui/AbstractComponent.java b/server/src/com/vaadin/ui/AbstractComponent.java
index 06060dbf91..9ff36a42d2 100644
--- a/server/src/com/vaadin/ui/AbstractComponent.java
+++ b/server/src/com/vaadin/ui/AbstractComponent.java
@@ -291,7 +291,10 @@ public abstract class AbstractComponent extends AbstractClientConnector
public void setLocale(Locale locale) {
this.locale = locale;
- // FIXME: Reload value if there is a converter
+ if (locale != null && isAttached()) {
+ getUI().getLocaleService().addLocale(locale);
+ }
+
markAsDirty();
}
@@ -556,6 +559,10 @@ public abstract class AbstractComponent extends AbstractClientConnector
focus();
}
setActionManagerViewer();
+ if (locale != null) {
+ getUI().getLocaleService().addLocale(locale);
+ }
+
}
/*
diff --git a/server/src/com/vaadin/ui/UI.java b/server/src/com/vaadin/ui/UI.java
index 545c2c7365..706f7c436b 100644
--- a/server/src/com/vaadin/ui/UI.java
+++ b/server/src/com/vaadin/ui/UI.java
@@ -30,6 +30,7 @@ import com.vaadin.event.ActionManager;
import com.vaadin.event.MouseEvents.ClickEvent;
import com.vaadin.event.MouseEvents.ClickListener;
import com.vaadin.navigator.Navigator;
+import com.vaadin.server.LocaleService;
import com.vaadin.server.Page;
import com.vaadin.server.PaintException;
import com.vaadin.server.PaintTarget;
@@ -494,6 +495,9 @@ public abstract class UI extends AbstractSingleComponentContainer implements
private boolean hasPendingPush = false;
+ private LocaleService localeService = new LocaleService(this,
+ getState(false).localeServiceState);
+
/**
* This method is used by Component.Focusable objects to request focus to
* themselves. Focus renders must be handled at window level (instead of
@@ -1052,6 +1056,7 @@ public abstract class UI extends AbstractSingleComponentContainer implements
@Override
public void attach() {
super.attach();
+ getLocaleService().addLocale(getLocale());
}
/**
@@ -1428,4 +1433,16 @@ public abstract class UI extends AbstractSingleComponentContainer implements
public void setOverlayContainerLabel(String overlayContainerLabel) {
getState().overlayContainerLabel = overlayContainerLabel;
}
+
+ /**
+ * Returns the locale service which handles transmission of Locale data to
+ * the client.
+ *
+ * @since 7.1
+ * @return The LocaleService for this UI
+ */
+ public LocaleService getLocaleService() {
+ return localeService;
+ }
+
}