]> source.dussan.org Git - vaadin-framework.git/commitdiff
Add Page.getLocation() (#9249) 63/63/2
authorJohannes Dahlström <johannesd@vaadin.com>
Thu, 4 Oct 2012 15:21:03 +0000 (18:21 +0300)
committerJohannes Dahlström <johannesd@vaadin.com>
Fri, 5 Oct 2012 11:10:03 +0000 (14:10 +0300)
* Send the whole window location, not just fragment, in bootstrap and when the fragment changes
* BrowserDetails now has URI getLocation() instead of String getUriFragment()
* Keep FragmentChangeListeners as-is, should perhaps change to LocationChangeListeners at some point
* Implement Page.getFragment() by means of Page.getLocation()
* Differentiate between no fragment (null) and empty fragment ("") as java.net.URI does

Change-Id: I1da1ea0664304d0c121a57e85d127fe48605e940

15 files changed:
WebContent/VAADIN/vaadinBootstrap.js
client/src/com/vaadin/client/ui/ui/UIConnector.java
client/src/com/vaadin/client/ui/ui/VUI.java
server/src/com/vaadin/navigator/Navigator.java
server/src/com/vaadin/server/AbstractCommunicationManager.java
server/src/com/vaadin/server/CombinedRequest.java
server/src/com/vaadin/server/Page.java
server/src/com/vaadin/server/VaadinPortletRequest.java
server/src/com/vaadin/server/VaadinRequest.java
server/src/com/vaadin/server/VaadinServletRequest.java
server/src/com/vaadin/ui/UI.java
shared/src/com/vaadin/shared/ui/ui/UIConstants.java
uitest/src/com/vaadin/tests/components/ui/LazyInitUIs.java
uitest/src/com/vaadin/tests/minitutorials/v7a1/UsingUriFragments.java
uitest/src/com/vaadin/tests/navigator/NavigatorTest.java

index fc1de31bc814e127eb6b94dcd8ac867308612c34..3fff0bd8292f69a657de6abe5389554d129cc6a8 100644 (file)
                                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);
index 3b4e4e1c7c9eb95b53f8da8d9ba2e057d2ff7ad5..2a728769246fe028648786076829093e8579c59f 100644 (file)
@@ -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) {
index 096b0b60ba2a85e2dcc014c9ff548edc108030fd..d650b1734c1a6cd0643cf04b37a6a581d92637c5 100644 (file)
@@ -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);
             }
         }
     };
index df9e5059fad11276005a38ffcd038f1777819669..e4704bce6a5b52478198410f3c8b5bc8278042f0 100644 (file)
@@ -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);
             }
         }
 
index b7b97cbefdc9eaf8eab0b595f17e0f0acb5f5e80..19b53c8a7a2b1645ddaa541aa6264eedac711418 100644 (file)
@@ -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();
index 2487957e24f86d4abe4a82d845187c22375c9419..34ac0b6a6f0c6445eb3ae6e992d80a42ca81070c 100644 (file)
@@ -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);
+                    }
                 }
             }
 
index b6a2b2f7768d8cf4971067bda800ad40a1f3ade1..ff0980d5fb5abc777b73c3e481685eebffed9924 100644 (file)
@@ -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,24 +601,65 @@ 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>
index cb55262b062341e9715c57d1b0e49990f6717a3b..08e809eed276daeb373ba9d9a5bfbfc59e0b6440 100644 (file)
@@ -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;
             }
 
index 7e2ae75850ff6ceb9c59a83daf75ab76f74c0ff6..650b5ad82b2047bcf4dc618b892c68ac4384a148 100644 (file)
@@ -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
index d1fd87f9c407b85c231910bc47ac499d595893cc..5a7e96763b06077040b5b91d40ba50a87197971c 100644 (file)
@@ -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;
             }
 
index ba87eb1424c1f1d28ce083c5dac4a7dd56076d0c..3cacf5c497c7b13bd51a1eb1f6e07f548d6ad22b 100644 (file)
@@ -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);
         }
     }
 
index 76413628a41dc51ab70baa75331b9e10abf6720d..06a4afae98c1f10e799b3ef2bad01611f6b51e13 100644 (file)
@@ -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";
index 4d4d96a465c66f2ac5ce7b18ee5a3a1ef70e95ec..4648529db79307771282d2f0d0b8cc0bc3928b43 100644 (file)
@@ -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);
     }
 
index 9d494f78581dba75a632c17d745b2ef61939f9f0..db8b2616283dc84231a67497a0c80e3460277905 100644 (file)
@@ -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() {
index 146b4df02fbce1326270c7f072eb18e1c55fa896..97c4e9fd4fcb3491a1f96b37c752eccc0f718a1b 100644 (file)
@@ -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);
         }
     }
 }