diff options
15 files changed, 144 insertions, 69 deletions
diff --git a/WebContent/VAADIN/vaadinBootstrap.js b/WebContent/VAADIN/vaadinBootstrap.js index fc1de31bc8..3fff0bd829 100644 --- a/WebContent/VAADIN/vaadinBootstrap.js +++ b/WebContent/VAADIN/vaadinBootstrap.js @@ -249,11 +249,9 @@ url += '&vh=' + pe.offsetHeight; } - // Uri fragment - if (location.hash) { - //Remove initial # - url += '&fr=' + encodeURIComponent(location.hash.replace(/^#/, "")); - } + // Location + url += '&loc=' + encodeURIComponent(location.href); + // Window name if (window.name) { url += '&wn=' + encodeURIComponent(window.name); diff --git a/client/src/com/vaadin/client/ui/ui/UIConnector.java b/client/src/com/vaadin/client/ui/ui/UIConnector.java index 3b4e4e1c7c..2a72876924 100644 --- a/client/src/com/vaadin/client/ui/ui/UIConnector.java +++ b/client/src/com/vaadin/client/ui/ui/UIConnector.java @@ -264,21 +264,17 @@ public class UIConnector extends AbstractComponentContainerConnector implements scrollIntoView(connector); } - if (uidl.hasAttribute(UIConstants.FRAGMENT_VARIABLE)) { - getWidget().currentFragment = uidl - .getStringAttribute(UIConstants.FRAGMENT_VARIABLE); + if (uidl.hasAttribute(UIConstants.LOCATION_VARIABLE)) { + String location = uidl + .getStringAttribute(UIConstants.LOCATION_VARIABLE); + int fragmentIndex = location.indexOf('#'); + if (fragmentIndex >= 0) { + getWidget().currentFragment = location + .substring(fragmentIndex + 1); + } if (!getWidget().currentFragment.equals(History.getToken())) { History.newItem(getWidget().currentFragment, true); } - } else { - // Initial request for which the server doesn't yet have a fragment - // (and haven't shown any interest in getting one) - getWidget().currentFragment = History.getToken(); - - // Include current fragment in the next request - client.updateVariable(getWidget().id, - UIConstants.FRAGMENT_VARIABLE, getWidget().currentFragment, - false); } if (firstPaint) { diff --git a/client/src/com/vaadin/client/ui/ui/VUI.java b/client/src/com/vaadin/client/ui/ui/VUI.java index 096b0b60ba..d650b1734c 100644 --- a/client/src/com/vaadin/client/ui/ui/VUI.java +++ b/client/src/com/vaadin/client/ui/ui/VUI.java @@ -128,11 +128,11 @@ public class VUI extends SimplePanel implements ResizeHandler, public void onValueChange(ValueChangeEvent<String> event) { String newFragment = event.getValue(); - // Send the new fragment to the server if it has changed + // Send the location to the server if the fragment has changed if (!newFragment.equals(currentFragment) && connection != null) { currentFragment = newFragment; - connection.updateVariable(id, UIConstants.FRAGMENT_VARIABLE, - newFragment, true); + connection.updateVariable(id, UIConstants.LOCATION_VARIABLE, + Window.Location.getHref(), true); } } }; diff --git a/server/src/com/vaadin/navigator/Navigator.java b/server/src/com/vaadin/navigator/Navigator.java index df9e5059fa..e4704bce6a 100644 --- a/server/src/com/vaadin/navigator/Navigator.java +++ b/server/src/com/vaadin/navigator/Navigator.java @@ -109,10 +109,10 @@ public class Navigator implements Serializable { @Override public String getState() { String fragment = getFragment(); - if (fragment.startsWith("!")) { - return fragment.substring(1); - } else { + if (fragment == null || !fragment.startsWith("!")) { return ""; + } else { + return fragment.substring(1); } } diff --git a/server/src/com/vaadin/server/AbstractCommunicationManager.java b/server/src/com/vaadin/server/AbstractCommunicationManager.java index b7b97cbefd..19b53c8a7a 100644 --- a/server/src/com/vaadin/server/AbstractCommunicationManager.java +++ b/server/src/com/vaadin/server/AbstractCommunicationManager.java @@ -2498,7 +2498,7 @@ public abstract class AbstractCommunicationManager implements Serializable { // Check for an existing UI based on window.name BrowserDetails browserDetails = request.getBrowserDetails(); boolean hasBrowserDetails = browserDetails != null - && browserDetails.getUriFragment() != null; + && browserDetails.getLocation() != null; Map<String, Integer> retainOnRefreshUIs = session .getPreserveOnRefreshUIs(); diff --git a/server/src/com/vaadin/server/CombinedRequest.java b/server/src/com/vaadin/server/CombinedRequest.java index 2487957e24..34ac0b6a6f 100644 --- a/server/src/com/vaadin/server/CombinedRequest.java +++ b/server/src/com/vaadin/server/CombinedRequest.java @@ -18,6 +18,8 @@ package com.vaadin.server; import java.io.IOException; import java.io.InputStream; +import java.net.URI; +import java.net.URISyntaxException; import java.util.Collections; import java.util.HashMap; import java.util.Iterator; @@ -131,12 +133,17 @@ public class CombinedRequest implements VaadinRequest { public BrowserDetails getBrowserDetails() { return new BrowserDetails() { @Override - public String getUriFragment() { - String fragment = secondRequest.getParameter("fr"); - if (fragment == null) { - return ""; + public URI getLocation() { + String location = secondRequest.getParameter("loc"); + if (location == null) { + return null; } else { - return fragment; + try { + return new URI(location); + } catch (URISyntaxException e) { + throw new RuntimeException( + "Invalid location URI received from client", e); + } } } diff --git a/server/src/com/vaadin/server/Page.java b/server/src/com/vaadin/server/Page.java index b6a2b2f776..ff0980d5fb 100644 --- a/server/src/com/vaadin/server/Page.java +++ b/server/src/com/vaadin/server/Page.java @@ -18,6 +18,8 @@ package com.vaadin.server; import java.io.Serializable; import java.lang.reflect.Method; +import java.net.URI; +import java.net.URISyntaxException; import java.util.EventObject; import java.util.Iterator; import java.util.LinkedList; @@ -293,11 +295,6 @@ public class Page implements Serializable { private EventRouter eventRouter; - /** - * The current URI fragment. - */ - private String fragment; - private final UI uI; private int browserWindowWidth = -1; @@ -305,6 +302,11 @@ public class Page implements Serializable { private JavaScript javaScript; + /** + * The current browser location. + */ + private URI location; + public Page(UI uI) { this.uI = uI; } @@ -352,21 +354,40 @@ public class Page implements Serializable { } /** - * Sets URI fragment. Optionally fires a {@link FragmentChangedEvent} + * Sets the fragment part in the current location URI. Optionally fires a + * {@link FragmentChangedEvent}. + * <p> + * The fragment is the optional last component of a URI, prefixed with a + * hash sign ("#"). + * <p> + * Passing <code>null</code> as <code>newFragment</code> clears the fragment + * (no "#" in the URI); passing an empty string sets an empty fragment (a + * trailing "#" in the URI.) This is consistent with the semantics of + * {@link java.net.URI}. * * @param newFragment - * id of the new fragment + * The new fragment. * @param fireEvent * true to fire event + * + * @see #getFragment() + * @see #setLocation(URI) * @see FragmentChangedEvent * @see Page.FragmentChangedListener + * */ public void setFragment(String newFragment, boolean fireEvents) { - if (newFragment == null) { - throw new NullPointerException("The fragment may not be null"); - } - if (!newFragment.equals(fragment)) { - fragment = newFragment; + String oldFragment = location.getFragment(); + if (newFragment == null && oldFragment != null + || !newFragment.equals(oldFragment)) { + try { + location = new URI(location.getScheme(), + location.getSchemeSpecificPart(), newFragment); + } catch (URISyntaxException e) { + // This should not actually happen as the fragment syntax is not + // constrained + throw new RuntimeException(e); + } if (fireEvents) { fireEvent(new FragmentChangedEvent(this, newFragment)); } @@ -393,21 +414,28 @@ public class Page implements Serializable { } /** - * Gets currently set URI fragment. + * Gets the currently set URI fragment. * <p> - * To listen changes in fragment, hook a + * Returns <code>null</code> if there is no fragment and an empty string if + * there is an empty fragment. + * <p> + * To listen to changes in fragment, hook a * {@link Page.FragmentChangedListener}. * - * @return the current fragment in browser uri or null if not known + * @return the current fragment in browser location URI. + * + * @see #getLocation() + * @see #setFragment(String) + * @see #addFragmentChangedListener(FragmentChangedListener) */ public String getFragment() { - return fragment; + return location.getFragment(); } public void init(VaadinRequest request) { BrowserDetails browserDetails = request.getBrowserDetails(); if (browserDetails != null) { - fragment = browserDetails.getUriFragment(); + location = browserDetails.getLocation(); } } @@ -573,25 +601,66 @@ public class Page implements Serializable { notifications = null; } - if (fragment != null) { - target.addAttribute(UIConstants.FRAGMENT_VARIABLE, fragment); + if (location != null) { + target.addAttribute(UIConstants.LOCATION_VARIABLE, + location.toString()); } } /** - * Navigates this page to the given URL. The contents of this page in the - * browser is replaced with whatever is returned for the given URL. + * Navigates this page to the given URI. The contents of this page in the + * browser is replaced with whatever is returned for the given URI. * - * @param url - * the URL to show + * @param uri + * the URI to show */ - public void setLocation(String url) { - openList.add(new OpenResource(url, null, -1, -1, BORDER_DEFAULT)); + public void setLocation(String uri) { + openList.add(new OpenResource(uri, null, -1, -1, BORDER_DEFAULT)); uI.markAsDirty(); } /** + * Navigates this page to the given URI. The contents of this page in the + * browser is replaced with whatever is returned for the given URI. + * + * @param uri + * the URI to show + */ + public void setLocation(URI uri) { + setLocation(uri.toString()); + } + + /** + * Returns the location URI of this page, as reported by the browser. Note + * that this may not be consistent with the server URI the application is + * deployed in due to potential proxies, redirections and similar. + * + * @return The browser location URI. + */ + public URI getLocation() { + return location; + } + + /** + * For internal use only. Used to update the server-side location when the + * client-side location changes. + */ + public void updateLocation(String location) { + try { + String oldFragment = this.location.getFragment(); + this.location = new URI(location); + String newFragment = this.location.getFragment(); + if (newFragment == null && oldFragment != null + || !newFragment.equals(oldFragment)) { + fireEvent(new FragmentChangedEvent(this, newFragment)); + } + } catch (URISyntaxException e) { + throw new RuntimeException(e); + } + } + + /** * Opens the given URL in a window with the given name. * <p> * The supplied {@code windowName} is used as the target name in a diff --git a/server/src/com/vaadin/server/VaadinPortletRequest.java b/server/src/com/vaadin/server/VaadinPortletRequest.java index cb55262b06..08e809eed2 100644 --- a/server/src/com/vaadin/server/VaadinPortletRequest.java +++ b/server/src/com/vaadin/server/VaadinPortletRequest.java @@ -18,6 +18,7 @@ package com.vaadin.server; import java.io.IOException; import java.io.InputStream; +import java.net.URI; import java.util.Locale; import java.util.Map; @@ -151,7 +152,7 @@ public class VaadinPortletRequest implements VaadinRequest { public BrowserDetails getBrowserDetails() { return new BrowserDetails() { @Override - public String getUriFragment() { + public URI getLocation() { return null; } diff --git a/server/src/com/vaadin/server/VaadinRequest.java b/server/src/com/vaadin/server/VaadinRequest.java index 7e2ae75850..650b5ad82b 100644 --- a/server/src/com/vaadin/server/VaadinRequest.java +++ b/server/src/com/vaadin/server/VaadinRequest.java @@ -19,6 +19,7 @@ package com.vaadin.server; import java.io.IOException; import java.io.InputStream; import java.io.Serializable; +import java.net.URI; import java.util.Locale; import java.util.Map; @@ -46,12 +47,12 @@ public interface VaadinRequest extends Serializable { @Deprecated public interface BrowserDetails extends Serializable { /** - * Gets the URI hash fragment for the request. This is typically used to - * encode navigation within an application. + * Gets the URI in the browser address bar, including the fragment + * (Javascript window.location) * - * @return the URI hash fragment + * @return the browser location URI */ - public String getUriFragment(); + public URI getLocation(); /** * Gets the value of window.name from the browser. This can be used to diff --git a/server/src/com/vaadin/server/VaadinServletRequest.java b/server/src/com/vaadin/server/VaadinServletRequest.java index d1fd87f9c4..5a7e96763b 100644 --- a/server/src/com/vaadin/server/VaadinServletRequest.java +++ b/server/src/com/vaadin/server/VaadinServletRequest.java @@ -16,6 +16,8 @@ package com.vaadin.server; +import java.net.URI; + import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletRequestWrapper; import javax.servlet.http.HttpSession; @@ -86,7 +88,7 @@ public class VaadinServletRequest extends HttpServletRequestWrapper implements public BrowserDetails getBrowserDetails() { return new BrowserDetails() { @Override - public String getUriFragment() { + public URI getLocation() { return null; } diff --git a/server/src/com/vaadin/ui/UI.java b/server/src/com/vaadin/ui/UI.java index ba87eb1424..3cacf5c497 100644 --- a/server/src/com/vaadin/ui/UI.java +++ b/server/src/com/vaadin/ui/UI.java @@ -680,10 +680,10 @@ public abstract class UI extends AbstractComponentContainer implements actionManager.handleActions(variables, this); } - if (variables.containsKey(UIConstants.FRAGMENT_VARIABLE)) { - String fragment = (String) variables - .get(UIConstants.FRAGMENT_VARIABLE); - getPage().setFragment(fragment, true); + if (variables.containsKey(UIConstants.LOCATION_VARIABLE)) { + String location = (String) variables + .get(UIConstants.LOCATION_VARIABLE); + getPage().updateLocation(location); } } diff --git a/shared/src/com/vaadin/shared/ui/ui/UIConstants.java b/shared/src/com/vaadin/shared/ui/ui/UIConstants.java index 76413628a4..06a4afae98 100644 --- a/shared/src/com/vaadin/shared/ui/ui/UIConstants.java +++ b/shared/src/com/vaadin/shared/ui/ui/UIConstants.java @@ -26,7 +26,7 @@ public class UIConstants { public static final String NOTIFICATION_HTML_CONTENT_NOT_ALLOWED = "useplain"; @Deprecated - public static final String FRAGMENT_VARIABLE = "fragment"; + public static final String LOCATION_VARIABLE = "location"; @Deprecated public static final String ATTRIBUTE_NOTIFICATION_STYLE = "style"; diff --git a/uitest/src/com/vaadin/tests/components/ui/LazyInitUIs.java b/uitest/src/com/vaadin/tests/components/ui/LazyInitUIs.java index 4d4d96a465..4648529db7 100644 --- a/uitest/src/com/vaadin/tests/components/ui/LazyInitUIs.java +++ b/uitest/src/com/vaadin/tests/components/ui/LazyInitUIs.java @@ -78,7 +78,7 @@ public class LazyInitUIs extends AbstractTestUIProvider { info += "<br />pathInfo: " + request.getRequestPathInfo(); info += "<br />parameters: " + request.getParameterMap().keySet(); info += "<br />uri fragment: " - + request.getBrowserDetails().getUriFragment(); + + request.getBrowserDetails().getLocation().getFragment(); return new Label(info, ContentMode.HTML); } diff --git a/uitest/src/com/vaadin/tests/minitutorials/v7a1/UsingUriFragments.java b/uitest/src/com/vaadin/tests/minitutorials/v7a1/UsingUriFragments.java index 9d494f7858..db8b261628 100644 --- a/uitest/src/com/vaadin/tests/minitutorials/v7a1/UsingUriFragments.java +++ b/uitest/src/com/vaadin/tests/minitutorials/v7a1/UsingUriFragments.java @@ -36,7 +36,7 @@ public class UsingUriFragments extends UI { @Override protected void init(VaadinRequest request) { Label label = new Label("Hello, your fragment is " - + request.getBrowserDetails().getUriFragment()); + + request.getBrowserDetails().getLocation().getFragment()); getContent().addComponent(label); // React to fragment changes @@ -48,7 +48,7 @@ public class UsingUriFragments extends UI { }); // Handle the fragment received in the initial request - handleFragment(request.getBrowserDetails().getUriFragment()); + handleFragment(request.getBrowserDetails().getLocation().getFragment()); addComponent(new Button("Show and set fragment", new Button.ClickListener() { diff --git a/uitest/src/com/vaadin/tests/navigator/NavigatorTest.java b/uitest/src/com/vaadin/tests/navigator/NavigatorTest.java index 146b4df02f..97c4e9fd4f 100644 --- a/uitest/src/com/vaadin/tests/navigator/NavigatorTest.java +++ b/uitest/src/com/vaadin/tests/navigator/NavigatorTest.java @@ -135,7 +135,8 @@ public class NavigatorTest extends UI { addComponent(log); addComponent(naviLayout); } catch (Exception e) { - log.log("Exception: " + e.getMessage()); + e.printStackTrace(); + log.log("Exception: " + e); } } } |