diff options
Diffstat (limited to 'src/com/vaadin/terminal')
22 files changed, 332 insertions, 92 deletions
diff --git a/src/com/vaadin/terminal/gwt/client/ApplicationConnection.java b/src/com/vaadin/terminal/gwt/client/ApplicationConnection.java index be6d578112..739c232a72 100644 --- a/src/com/vaadin/terminal/gwt/client/ApplicationConnection.java +++ b/src/com/vaadin/terminal/gwt/client/ApplicationConnection.java @@ -272,7 +272,7 @@ public class ApplicationConnection { ap.@com.vaadin.terminal.gwt.client.ApplicationConnection::lastProcessingTime, ap.@com.vaadin.terminal.gwt.client.ApplicationConnection::totalProcessingTime ]; - pd = pd.concat(ap.@com.vaadin.terminal.gwt.client.ApplicationConnection::testBenchServerStatus); + pd = pd.concat(ap.@com.vaadin.terminal.gwt.client.ApplicationConnection::serverTimingInfo); return pd; }); @@ -698,7 +698,7 @@ public class ApplicationConnection { * servicing the session so far. These values are always one request behind, * since they cannot be measured before the request is finished. */ - private ValueMap testBenchServerStatus; + private ValueMap serverTimingInfo; static final int MAX_CSS_WAITS = 100; @@ -1037,10 +1037,10 @@ public class ApplicationConnection { handleUIDLDuration.logDuration( " * Handling type mappings from server completed", 10); /* - * Hook for TestBench to get details about server status + * Hook for e.g. TestBench to get details about server peformance */ - if (json.containsKey("tbss")) { - testBenchServerStatus = json.getValueMap("tbss"); + if (json.containsKey("timings")) { + serverTimingInfo = json.getValueMap("timings"); } Command c = new Command() { diff --git a/src/com/vaadin/terminal/gwt/client/BrowserInfo.java b/src/com/vaadin/terminal/gwt/client/BrowserInfo.java index ef1dc481b1..064f175301 100644 --- a/src/com/vaadin/terminal/gwt/client/BrowserInfo.java +++ b/src/com/vaadin/terminal/gwt/client/BrowserInfo.java @@ -28,6 +28,8 @@ public class BrowserInfo { private static final String OS_WINDOWS = "win"; private static final String OS_LINUX = "lin"; private static final String OS_MACOSX = "mac"; + private static final String OS_ANDROID = "android"; + private static final String OS_IOS = "ios"; private static BrowserInfo instance; @@ -167,13 +169,18 @@ public class BrowserInfo { if (osClass != null) { cssClass = cssClass + " " + prefix + osClass; } + } return cssClass; } private String getOperatingSystemClass() { - if (browserDetails.isWindows()) { + if (browserDetails.isAndroid()) { + return OS_ANDROID; + } else if (browserDetails.isIOS()) { + return OS_IOS; + } else if (browserDetails.isWindows()) { return OS_WINDOWS; } else if (browserDetails.isLinux()) { return OS_LINUX; @@ -312,4 +319,59 @@ public class BrowserInfo { && Util.getNativeScrollbarSize() > 0; } + /** + * Checks if the browser is run on iOS + * + * @return true if the browser is run on iOS, false otherwise + */ + public boolean isIOS() { + return browserDetails.isIOS(); + } + + /** + * Checks if the browser is run on Android + * + * @return true if the browser is run on Android, false otherwise + */ + public boolean isAndroid() { + return browserDetails.isAndroid(); + } + + /** + * Checks if the browser is capable of handling scrolling natively or if a + * touch scroll helper is needed for scrolling. + * + * @return true if browser needs a touch scroll helper, false if the browser + * can handle scrolling natively + */ + public boolean requiresTouchScrollDelegate() { + if (!isTouchDevice()) { + return false; + } + + if (isAndroid() && isWebkit() && getWebkitVersion() < 534) { + return true; + } + // if (isIOS() && isWebkit() && getWebkitVersion() < ???) { + // return true; + // } + + return false; + } + + /** + * Tests if this is an Android devices with a broken scrollTop + * implementation + * + * @return true if scrollTop cannot be trusted on this device, false + * otherwise + */ + public boolean isAndroidWithBrokenScrollTop() { + return isAndroid() + && (getOperatingSystemMajorVersion() == 3 || getOperatingSystemMajorVersion() == 4); + } + + private int getOperatingSystemMajorVersion() { + return browserDetails.getOperatingSystemMajorVersion(); + } } diff --git a/src/com/vaadin/terminal/gwt/client/CSSRule.java b/src/com/vaadin/terminal/gwt/client/CSSRule.java index 4d9196c8d6..c36b0611e8 100644 --- a/src/com/vaadin/terminal/gwt/client/CSSRule.java +++ b/src/com/vaadin/terminal/gwt/client/CSSRule.java @@ -33,6 +33,7 @@ public class CSSRule { for(var i = 0; i < sheets.length; i++) { var sheet = sheets[i]; if(sheet.href && sheet.href.indexOf("VAADIN/themes")>-1) { + // $entry not needed as function is not exported this.@com.vaadin.terminal.gwt.client.CSSRule::rules = @com.vaadin.terminal.gwt.client.CSSRule::searchForRule(Lcom/google/gwt/core/client/JavaScriptObject;Ljava/lang/String;Z)(sheet, selector, deep); return; } @@ -58,6 +59,7 @@ public class CSSRule { // IE handles imported sheet differently if(deep && sheet.imports && sheet.imports.length > 0) { for(var i=0; i < sheet.imports.length; i++) { + // $entry not needed as function is not exported var imports = @com.vaadin.terminal.gwt.client.CSSRule::searchForRule(Lcom/google/gwt/core/client/JavaScriptObject;Ljava/lang/String;Z)(sheet.imports[i], selector, deep); allMatches.concat(imports); } @@ -83,6 +85,7 @@ public class CSSRule { } } else if(deep && r.type == 3) { // Search @import stylesheet + // $entry not needed as function is not exported var imports = @com.vaadin.terminal.gwt.client.CSSRule::searchForRule(Lcom/google/gwt/core/client/JavaScriptObject;Ljava/lang/String;Z)(r.styleSheet, selector, deep); allMatches = allMatches.concat(imports); } @@ -102,6 +105,7 @@ public class CSSRule { /*-{ var j = this.@com.vaadin.terminal.gwt.client.CSSRule::rules.length; for(var i=0; i<j; i++) { + // $entry not needed as function is not exported var value = this.@com.vaadin.terminal.gwt.client.CSSRule::rules[i].style[propertyName]; if(value) return value; diff --git a/src/com/vaadin/terminal/gwt/client/ComponentDetailMap.java b/src/com/vaadin/terminal/gwt/client/ComponentDetailMap.java index 3405d838a7..dfbcf9d38b 100644 --- a/src/com/vaadin/terminal/gwt/client/ComponentDetailMap.java +++ b/src/com/vaadin/terminal/gwt/client/ComponentDetailMap.java @@ -62,6 +62,7 @@ final class ComponentDetailMap extends JavaScriptObject { private final native void fillWithValues(Collection<ComponentDetail> list) /*-{ for(var key in this) { + // $entry not needed as function is not exported list.@java.util.Collection::add(Ljava/lang/Object;)(this[key]); } }-*/; diff --git a/src/com/vaadin/terminal/gwt/client/ComputedStyle.java b/src/com/vaadin/terminal/gwt/client/ComputedStyle.java index bedb217c63..29b02b4dde 100644 --- a/src/com/vaadin/terminal/gwt/client/ComputedStyle.java +++ b/src/com/vaadin/terminal/gwt/client/ComputedStyle.java @@ -179,6 +179,7 @@ public class ComputedStyle { if (isNaN(number)) return null; else + // $entry not needed as function is not exported return @java.lang.Integer::valueOf(I)(number); }-*/; diff --git a/src/com/vaadin/terminal/gwt/client/Util.java b/src/com/vaadin/terminal/gwt/client/Util.java index bfe63caefd..c392a0ba9c 100644 --- a/src/com/vaadin/terminal/gwt/client/Util.java +++ b/src/com/vaadin/terminal/gwt/client/Util.java @@ -978,6 +978,19 @@ public class Util { */ final Element target = getElementFromPoint(touch.getClientX(), touch.getClientY()); + + /* + * Fixes infocusable form fields in Safari of iOS 5.x and some Android + * browsers. + */ + Widget targetWidget = findWidget(target, null); + if (targetWidget instanceof com.google.gwt.user.client.ui.Focusable) { + final com.google.gwt.user.client.ui.Focusable toBeFocusedWidget = (com.google.gwt.user.client.ui.Focusable) targetWidget; + toBeFocusedWidget.setFocus(true); + } else if (targetWidget instanceof Focusable) { + ((Focusable) targetWidget).focus(); + } + Scheduler.get().scheduleDeferred(new ScheduledCommand() { public void execute() { try { diff --git a/src/com/vaadin/terminal/gwt/client/VBrowserDetails.java b/src/com/vaadin/terminal/gwt/client/VBrowserDetails.java index 89e106f063..6e0417149c 100644 --- a/src/com/vaadin/terminal/gwt/client/VBrowserDetails.java +++ b/src/com/vaadin/terminal/gwt/client/VBrowserDetails.java @@ -31,14 +31,19 @@ public class VBrowserDetails implements Serializable { private boolean isOpera = false; private boolean isIE = false; - private boolean isWindows = false; - private boolean isMacOSX = false; - private boolean isLinux = false; + private OperatingSystem os = OperatingSystem.UNKNOWN; + + public enum OperatingSystem { + UNKNOWN, WINDOWS, MACOSX, LINUX, IOS, ANDROID; + } private float browserEngineVersion = -1; private int browserMajorVersion = -1; private int browserMinorVersion = -1; + private int osMajorVersion = -1; + private int osMinorVersion = -1; + /** * Create an instance based on the given user agent. * @@ -122,14 +127,80 @@ public class VBrowserDetails implements Serializable { // Operating system if (userAgent.contains("windows ")) { - isWindows = true; + os = OperatingSystem.WINDOWS; } else if (userAgent.contains("linux")) { - isLinux = true; + if (userAgent.contains("android")) { + os = OperatingSystem.ANDROID; + parseAndroidVersion(userAgent); + } else { + os = OperatingSystem.LINUX; + + } } else if (userAgent.contains("macintosh") || userAgent.contains("mac osx") || userAgent.contains("mac os x")) { - isMacOSX = true; + if (userAgent.contains("ipad") || userAgent.contains("ipod") + || userAgent.contains("iphone")) { + os = OperatingSystem.IOS; + parseIOSVersion(userAgent); + } else { + os = OperatingSystem.MACOSX; + } + } + } + + private void parseAndroidVersion(String userAgent) { + // Android 5.1; + if (!userAgent.contains("android")) { + return; + } + + String osVersionString = safeSubstring(userAgent, + userAgent.indexOf("android ") + "android ".length(), + userAgent.length()); + osVersionString = safeSubstring(osVersionString, 0, + osVersionString.indexOf(";")); + String[] parts = osVersionString.split("\\."); + parseOsVersion(parts); + } + + private void parseIOSVersion(String userAgent) { + // OS 5_1 like Mac OS X + if (!userAgent.contains("os ") || !userAgent.contains(" like mac")) { + return; + } + + String osVersionString = safeSubstring(userAgent, + userAgent.indexOf("os ") + 3, userAgent.indexOf(" like mac")); + String[] parts = osVersionString.split("_"); + parseOsVersion(parts); + } + + private void parseOsVersion(String[] parts) { + osMajorVersion = -1; + osMinorVersion = -1; + + if (parts.length >= 1) { + try { + osMajorVersion = Integer.parseInt(parts[0]); + } catch (Exception e) { + } + } + if (parts.length >= 2) { + try { + osMinorVersion = Integer.parseInt(parts[1]); + } catch (Exception e) { + } + // Some Androids report version numbers as "2.1-update1" + if (osMinorVersion == -1 && parts[1].contains("-")) { + try { + osMinorVersion = Integer.parseInt(parts[1].substring(0, + parts[1].indexOf('-'))); + } catch (Exception ee) { + } + } } + } private void parseVersionString(String versionString) { @@ -306,7 +377,7 @@ public class VBrowserDetails implements Serializable { * @return true if run on Windows, false otherwise */ public boolean isWindows() { - return isWindows; + return os == OperatingSystem.WINDOWS; } /** @@ -315,7 +386,7 @@ public class VBrowserDetails implements Serializable { * @return true if run on Mac OSX, false otherwise */ public boolean isMacOSX() { - return isMacOSX; + return os == OperatingSystem.MACOSX; } /** @@ -324,7 +395,45 @@ public class VBrowserDetails implements Serializable { * @return true if run on Linux, false otherwise */ public boolean isLinux() { - return isLinux; + return os == OperatingSystem.LINUX; + } + + /** + * Tests if the browser is run on Android. + * + * @return true if run on Android, false otherwise + */ + public boolean isAndroid() { + return os == OperatingSystem.ANDROID; + } + + /** + * Tests if the browser is run in iOS. + * + * @return true if run in iOS, false otherwise + */ + public boolean isIOS() { + return os == OperatingSystem.IOS; + } + + /** + * Returns the major version of the operating system. Currently only + * supported for mobile devices (iOS/Android) + * + * @return The major version or -1 if unknown + */ + public int getOperatingSystemMajorVersion() { + return osMajorVersion; + } + + /** + * Returns the minor version of the operating system. Currently only + * supported for mobile devices (iOS/Android) + * + * @return The minor version or -1 if unknown + */ + public int getOperatingSystemMinorVersion() { + return osMinorVersion; } /** diff --git a/src/com/vaadin/terminal/gwt/client/ui/FocusableScrollPanel.java b/src/com/vaadin/terminal/gwt/client/ui/FocusableScrollPanel.java index 533d6a78ae..62697c4d98 100644 --- a/src/com/vaadin/terminal/gwt/client/ui/FocusableScrollPanel.java +++ b/src/com/vaadin/terminal/gwt/client/ui/FocusableScrollPanel.java @@ -153,7 +153,7 @@ public class FocusableScrollPanel extends SimpleFocusablePanel implements * the new vertical scroll position, in pixels */ public void setScrollPosition(int position) { - if (isAndroidWithBrokenScrollTop()) { + if (BrowserInfo.get().isAndroidWithBrokenScrollTop()) { ArrayList<com.google.gwt.dom.client.Element> elements = TouchScrollDelegate .getElements(getElement()); for (com.google.gwt.dom.client.Element el : elements) { @@ -167,11 +167,6 @@ public class FocusableScrollPanel extends SimpleFocusablePanel implements } } - private boolean isAndroidWithBrokenScrollTop() { - return BrowserInfo.getBrowserString().contains("Android 3") - || BrowserInfo.getBrowserString().contains("Android 4"); - } - public void onScroll(ScrollEvent event) { Scheduler.get().scheduleDeferred(new ScheduledCommand() { public void execute() { diff --git a/src/com/vaadin/terminal/gwt/client/ui/TouchScrollDelegate.java b/src/com/vaadin/terminal/gwt/client/ui/TouchScrollDelegate.java index d4b59ed23a..8b2248aff6 100644 --- a/src/com/vaadin/terminal/gwt/client/ui/TouchScrollDelegate.java +++ b/src/com/vaadin/terminal/gwt/client/ui/TouchScrollDelegate.java @@ -83,9 +83,8 @@ public class TouchScrollDelegate implements NativePreviewHandler { private static TouchScrollDelegate activeScrollDelegate; - private static final boolean androidWithBrokenScrollTop = BrowserInfo - .getBrowserString().contains("Android 3") - || BrowserInfo.getBrowserString().contains("Android 4"); + private static final boolean androidWithBrokenScrollTop = BrowserInfo.get() + .isAndroidWithBrokenScrollTop(); public TouchScrollDelegate(Element... elements) { scrollableElements = elements; diff --git a/src/com/vaadin/terminal/gwt/client/ui/button/ButtonConnector.java b/src/com/vaadin/terminal/gwt/client/ui/button/ButtonConnector.java index 62a5e8ac8b..a555ecd392 100644 --- a/src/com/vaadin/terminal/gwt/client/ui/button/ButtonConnector.java +++ b/src/com/vaadin/terminal/gwt/client/ui/button/ButtonConnector.java @@ -57,7 +57,11 @@ public class ButtonConnector extends AbstractComponentConnector implements blurHandlerRegistration = EventHelper.updateBlurHandler(this, blurHandlerRegistration); // Set text - getWidget().setText(getState().getCaption()); + if (getState().isHtmlContentAllowed()) { + getWidget().setHtml(getState().getCaption()); + } else { + getWidget().setText(getState().getCaption()); + } // handle error if (null != getState().getErrorMessage()) { diff --git a/src/com/vaadin/terminal/gwt/client/ui/button/ButtonState.java b/src/com/vaadin/terminal/gwt/client/ui/button/ButtonState.java index f26cdae0c6..fdc053b3ae 100644 --- a/src/com/vaadin/terminal/gwt/client/ui/button/ButtonState.java +++ b/src/com/vaadin/terminal/gwt/client/ui/button/ButtonState.java @@ -17,6 +17,10 @@ import com.vaadin.ui.Button; public class ButtonState extends ComponentState { private boolean disableOnClick = false; private int clickShortcutKeyCode = 0; + /** + * If caption should be rendered in HTML + */ + private boolean htmlContentAllowed = false; /** * Checks whether the button should be disabled on the client side on next @@ -62,4 +66,30 @@ public class ButtonState extends ComponentState { this.clickShortcutKeyCode = clickShortcutKeyCode; } + /** + * Set whether the caption text is rendered as HTML or not. You might need + * to retheme button to allow higher content than the original text style. + * + * If set to true, the captions are passed to the browser as html and the + * developer is responsible for ensuring no harmful html is used. If set to + * false, the content is passed to the browser as plain text. + * + * @param htmlContentAllowed + * <code>true</code> if caption is rendered as HTML, + * <code>false</code> otherwise + */ + public void setHtmlContentAllowed(boolean htmlContentAllowed) { + this.htmlContentAllowed = htmlContentAllowed; + } + + /** + * Return HTML rendering setting. + * + * @return <code>true</code> if the caption text is to be rendered as HTML, + * <code>false</code> otherwise + */ + public boolean isHtmlContentAllowed() { + return htmlContentAllowed; + } + } diff --git a/src/com/vaadin/terminal/gwt/client/ui/button/VButton.java b/src/com/vaadin/terminal/gwt/client/ui/button/VButton.java index f7d73d3b5e..e5e7dbba8b 100644 --- a/src/com/vaadin/terminal/gwt/client/ui/button/VButton.java +++ b/src/com/vaadin/terminal/gwt/client/ui/button/VButton.java @@ -98,6 +98,10 @@ public class VButton extends FocusWidget implements ClickHandler { captionElement.setInnerText(text); } + public void setHtml(String html) { + captionElement.setInnerHTML(html); + } + @SuppressWarnings("deprecation") @Override /* diff --git a/src/com/vaadin/terminal/gwt/client/ui/datefield/VDateFieldCalendar.java b/src/com/vaadin/terminal/gwt/client/ui/datefield/VDateFieldCalendar.java index 21e0e0820d..84b3c678eb 100644 --- a/src/com/vaadin/terminal/gwt/client/ui/datefield/VDateFieldCalendar.java +++ b/src/com/vaadin/terminal/gwt/client/ui/datefield/VDateFieldCalendar.java @@ -45,6 +45,13 @@ public class VDateFieldCalendar extends VDateField { */ @SuppressWarnings("deprecation") protected void updateValueFromPanel() { + + // If field is invisible at the beginning, client can still be null when + // this function is called. + if (getClient() == null) { + return; + } + Date date2 = calendarPanel.getDate(); Date currentDate = getCurrentDate(); if (currentDate == null || date2.getTime() != currentDate.getTime()) { diff --git a/src/com/vaadin/terminal/gwt/client/ui/nativebutton/NativeButtonConnector.java b/src/com/vaadin/terminal/gwt/client/ui/nativebutton/NativeButtonConnector.java index 801c405826..84d3b73285 100644 --- a/src/com/vaadin/terminal/gwt/client/ui/nativebutton/NativeButtonConnector.java +++ b/src/com/vaadin/terminal/gwt/client/ui/nativebutton/NativeButtonConnector.java @@ -58,7 +58,11 @@ public class NativeButtonConnector extends AbstractComponentConnector implements blurHandlerRegistration); // Set text - getWidget().setText(getState().getCaption()); + if (getState().isHtmlContentAllowed()) { + getWidget().setHTML(getState().getCaption()); + } else { + getWidget().setText(getState().getCaption()); + } // handle error if (null != getState().getErrorMessage()) { diff --git a/src/com/vaadin/terminal/gwt/client/ui/nativebutton/VNativeButton.java b/src/com/vaadin/terminal/gwt/client/ui/nativebutton/VNativeButton.java index d0b8f73eb1..01ac4fab6a 100644 --- a/src/com/vaadin/terminal/gwt/client/ui/nativebutton/VNativeButton.java +++ b/src/com/vaadin/terminal/gwt/client/ui/nativebutton/VNativeButton.java @@ -65,6 +65,11 @@ public class VNativeButton extends Button implements ClickHandler { } @Override + public void setHTML(String html) { + captionElement.setInnerHTML(html); + } + + @Override public void onBrowserEvent(Event event) { super.onBrowserEvent(event); diff --git a/src/com/vaadin/terminal/gwt/client/ui/notification/VNotification.java b/src/com/vaadin/terminal/gwt/client/ui/notification/VNotification.java index eb97160f52..0d222044ba 100644 --- a/src/com/vaadin/terminal/gwt/client/ui/notification/VNotification.java +++ b/src/com/vaadin/terminal/gwt/client/ui/notification/VNotification.java @@ -160,6 +160,13 @@ public class VNotification extends VOverlay { } super.show(); setPosition(position); + /** + * Android 4 fails to render notifications correctly without a little + * nudge (#8551) + */ + if (BrowserInfo.get().isAndroid()) { + Util.setStyleTemporarily(getElement(), "display", "none"); + } } @Override diff --git a/src/com/vaadin/terminal/gwt/client/ui/root/VRoot.java b/src/com/vaadin/terminal/gwt/client/ui/root/VRoot.java index 13fc55d7ea..12a69d5556 100644 --- a/src/com/vaadin/terminal/gwt/client/ui/root/VRoot.java +++ b/src/com/vaadin/terminal/gwt/client/ui/root/VRoot.java @@ -306,6 +306,7 @@ public class VRoot extends SimplePanel implements ResizeHandler, /*-{ var j; for(j in $wnd.vaadin.vaadinConfigurations) { + // $entry not needed as function is not exported list.@java.util.Collection::add(Ljava/lang/Object;)(j); } }-*/; diff --git a/src/com/vaadin/terminal/gwt/server/AbstractApplicationPortlet.java b/src/com/vaadin/terminal/gwt/server/AbstractApplicationPortlet.java index 58d6a18592..77698805de 100644 --- a/src/com/vaadin/terminal/gwt/server/AbstractApplicationPortlet.java +++ b/src/com/vaadin/terminal/gwt/server/AbstractApplicationPortlet.java @@ -509,6 +509,9 @@ public abstract class AbstractApplicationPortlet extends GenericPortlet protected void handleRequest(PortletRequest request, PortletResponse response) throws PortletException, IOException { + RequestTimer requestTimer = new RequestTimer(); + requestTimer.start(); + AbstractApplicationPortletWrapper portletWrapper = new AbstractApplicationPortletWrapper( this); @@ -530,9 +533,6 @@ public abstract class AbstractApplicationPortlet extends GenericPortlet WrappedPortletResponse wrappedResponse = new WrappedPortletResponse( response, getDeploymentConfiguration()); - RequestTimer requestTimer = RequestTimer.get(wrappedRequest); - requestTimer.start(wrappedRequest); - RequestType requestType = getRequestType(request); if (requestType == RequestType.UNKNOWN) { @@ -721,10 +721,11 @@ public abstract class AbstractApplicationPortlet extends GenericPortlet } finally { Root.setCurrentRoot(null); Application.setCurrentApplication(null); - } - requestTimer.stop(); - RequestTimer.set(wrappedRequest, requestTimer); + requestTimer + .stop((AbstractWebApplicationContext) application + .getContext()); + } } } } diff --git a/src/com/vaadin/terminal/gwt/server/AbstractApplicationServlet.java b/src/com/vaadin/terminal/gwt/server/AbstractApplicationServlet.java index 799271b979..6ab2748332 100644 --- a/src/com/vaadin/terminal/gwt/server/AbstractApplicationServlet.java +++ b/src/com/vaadin/terminal/gwt/server/AbstractApplicationServlet.java @@ -400,12 +400,12 @@ public abstract class AbstractApplicationServlet extends HttpServlet implements private void service(WrappedHttpServletRequest request, WrappedHttpServletResponse response) throws ServletException, IOException { + RequestTimer requestTimer = new RequestTimer(); + requestTimer.start(); + AbstractApplicationServletWrapper servletWrapper = new AbstractApplicationServletWrapper( this); - RequestTimer requestTimer = RequestTimer.get(request); - requestTimer.start(request); - RequestType requestType = getRequestType(request); if (!ensureCookiesEnabled(requestType, request, response)) { return; @@ -540,10 +540,11 @@ public abstract class AbstractApplicationServlet extends HttpServlet implements } finally { Root.setCurrentRoot(null); Application.setCurrentApplication(null); - } - requestTimer.stop(); - RequestTimer.set(request, requestTimer); + requestTimer + .stop((AbstractWebApplicationContext) application + .getContext()); + } } } diff --git a/src/com/vaadin/terminal/gwt/server/AbstractCommunicationManager.java b/src/com/vaadin/terminal/gwt/server/AbstractCommunicationManager.java index b780f66a23..c57e7d8bc1 100644 --- a/src/com/vaadin/terminal/gwt/server/AbstractCommunicationManager.java +++ b/src/com/vaadin/terminal/gwt/server/AbstractCommunicationManager.java @@ -1097,19 +1097,18 @@ public abstract class AbstractCommunicationManager implements Serializable { dragAndDropService.printJSONResponse(outWriter); } - writePerformanceDataForTestBench(request, outWriter); + writePerformanceData(outWriter); } /** - * Adds the performance timing data used by TestBench 3 to the UIDL + * Adds the performance timing data (used by TestBench 3) to the UIDL * response. */ - private void writePerformanceDataForTestBench(final WrappedRequest request, - final PrintWriter outWriter) { - Long totalTime = (Long) request.getAttribute("TOTAL"); - Long lastRequestTime = (Long) request.getAttribute("LASTREQUEST"); - outWriter.write(String.format(", \"tbss\":[%d, %d]", totalTime, - lastRequestTime)); + private void writePerformanceData(final PrintWriter outWriter) { + AbstractWebApplicationContext ctx = (AbstractWebApplicationContext) application + .getContext(); + outWriter.write(String.format(", \"timings\":[%d, %d]", + ctx.getTotalSessionTime(), ctx.getLastRequestTime())); } private void legacyPaint(PaintTarget paintTarget, diff --git a/src/com/vaadin/terminal/gwt/server/AbstractWebApplicationContext.java b/src/com/vaadin/terminal/gwt/server/AbstractWebApplicationContext.java index c8335a8607..c0ae0afc26 100644 --- a/src/com/vaadin/terminal/gwt/server/AbstractWebApplicationContext.java +++ b/src/com/vaadin/terminal/gwt/server/AbstractWebApplicationContext.java @@ -44,6 +44,10 @@ public abstract class AbstractWebApplicationContext implements protected HashMap<Application, AbstractCommunicationManager> applicationToAjaxAppMgrMap = new HashMap<Application, AbstractCommunicationManager>(); + private long totalSessionTime = 0; + + private long lastRequestTime = -1; + public void addTransactionListener(TransactionListener listener) { if (listener != null) { listeners.add(listener); @@ -222,4 +226,30 @@ public abstract class AbstractWebApplicationContext implements return relativeUri.substring(index + 1, next); } + /** + * @return The total time spent servicing requests in this session. + */ + public long getTotalSessionTime() { + return totalSessionTime; + } + + /** + * Sets the time spent servicing the last request in the session and updates + * the total time spent servicing requests in this session. + * + * @param time + * the time spent in the last request. + */ + public void setLastRequestTime(long time) { + lastRequestTime = time; + totalSessionTime += time; + } + + /** + * @return the time spent servicing the last request in this session. + */ + public long getLastRequestTime() { + return lastRequestTime; + } + }
\ No newline at end of file diff --git a/src/com/vaadin/terminal/gwt/server/RequestTimer.java b/src/com/vaadin/terminal/gwt/server/RequestTimer.java index d47f444bef..6c0edec466 100644 --- a/src/com/vaadin/terminal/gwt/server/RequestTimer.java +++ b/src/com/vaadin/terminal/gwt/server/RequestTimer.java @@ -4,7 +4,7 @@ package com.vaadin.terminal.gwt.server; -import com.vaadin.terminal.WrappedRequest; +import java.io.Serializable; /** * Times the handling of requests and stores the information as an attribute in @@ -14,67 +14,30 @@ import com.vaadin.terminal.WrappedRequest; * * @author Jonatan Kronqvist / Vaadin Ltd */ -public class RequestTimer { - public static final String SESSION_ATTR_ID = "REQUESTTIMER"; - +public class RequestTimer implements Serializable { private long requestStartTime = 0; - private long totalSessionTime = 0; - private long lastRequestTime = -1; /** * Starts the timing of a request. This should be called before any * processing of the request. - * - * @param request - * the request. */ - public void start(WrappedRequest request) { + public void start() { requestStartTime = System.nanoTime(); - request.setAttribute("TOTAL", totalSessionTime); - request.setAttribute("LASTREQUEST", lastRequestTime); } /** * Stops the timing of a request. This should be called when all processing * of a request has finished. + * + * @param context */ - public void stop() { + public void stop(AbstractWebApplicationContext context) { // Measure and store the total handling time. This data can be // used in TestBench 3 tests. long time = (System.nanoTime() - requestStartTime) / 1000000; - lastRequestTime = time; - totalSessionTime += time; - } - - /** - * Returns a valid request timer for the specified request. Timers are - * session bound. - * - * @param request - * the request for which to get a valid timer. - * @return a valid timer. - */ - public static RequestTimer get(WrappedRequest request) { - RequestTimer timer = (RequestTimer) request - .getSessionAttribute(SESSION_ATTR_ID); - if (timer == null) { - timer = new RequestTimer(); - } - return timer; - } - /** - * Associates the specified request timer with the specified request. Since - * {@link #get(RequestWrapper)} will, at one point or another, return a new - * instance, this method should be called to keep the request <-> timer - * association updated. - * - * @param request - * the request for which to set the timer. - * @param requestTimer - * the timer. - */ - public static void set(WrappedRequest request, RequestTimer requestTimer) { - request.setSessionAttribute(RequestTimer.SESSION_ATTR_ID, requestTimer); + // The timings must be stored in the context, since a new + // RequestTimer is created for every request. + context.setLastRequestTime(time); } } |