aboutsummaryrefslogtreecommitdiffstats
path: root/server
diff options
context:
space:
mode:
authorLeif Åstrand <leif@vaadin.com>2012-10-08 08:11:51 +0300
committerVaadin Code Review <review@vaadin.com>2012-10-08 10:35:02 +0000
commit13d5b3e98954c2ade382305f8d044b2b49fdbd0b (patch)
tree37559368471cbed3a9ea159261869bcf5c82e52a /server
parent6337f8f8ccb88014f7a3d269332661ec8183b758 (diff)
downloadvaadin-framework-13d5b3e98954c2ade382305f8d044b2b49fdbd0b.tar.gz
vaadin-framework-13d5b3e98954c2ade382305f8d044b2b49fdbd0b.zip
Bootstrap UI using relative URLs with servlets (#6771)
* Configure widgetset using URLs relative to the requested page * Provide a Util method for getting an absolute URL from a relative URL * Test by using an embedded Jetty acting as a transparent proxy * Make /embed1 use the Buttons test to enable testing UIDL requests Change-Id: I4ef9b40e3954ae16b682d743a339f4360db40d4d
Diffstat (limited to 'server')
-rw-r--r--server/src/com/vaadin/server/BootstrapHandler.java44
-rw-r--r--server/src/com/vaadin/server/CombinedRequest.java33
-rw-r--r--server/src/com/vaadin/server/CommunicationManager.java52
-rw-r--r--server/src/com/vaadin/server/GAEVaadinServlet.java2
-rw-r--r--server/src/com/vaadin/server/PortletCommunicationManager.java27
-rw-r--r--server/src/com/vaadin/server/VaadinPortletService.java15
-rw-r--r--server/src/com/vaadin/server/VaadinService.java16
-rw-r--r--server/src/com/vaadin/server/VaadinServlet.java20
-rw-r--r--server/src/com/vaadin/server/VaadinServletService.java75
9 files changed, 122 insertions, 162 deletions
diff --git a/server/src/com/vaadin/server/BootstrapHandler.java b/server/src/com/vaadin/server/BootstrapHandler.java
index c08d3bdbb1..9a0e4c2071 100644
--- a/server/src/com/vaadin/server/BootstrapHandler.java
+++ b/server/src/com/vaadin/server/BootstrapHandler.java
@@ -21,7 +21,6 @@ import java.io.IOException;
import java.io.OutputStreamWriter;
import java.io.Serializable;
import java.util.ArrayList;
-import java.util.HashMap;
import java.util.LinkedHashMap;
import java.util.List;
import java.util.Locale;
@@ -101,7 +100,8 @@ public abstract class BootstrapHandler implements RequestHandler {
public String getAppId() {
if (appId == null) {
- appId = getApplicationId(this);
+ appId = getRequest().getService().getMainDivId(getSession(),
+ getRequest(), getUIClass());
}
return appId;
}
@@ -274,16 +274,6 @@ public abstract class BootstrapHandler implements RequestHandler {
return null;
}
- /**
- * Creates and returns a unique ID for the DIV where the application is to
- * be rendered.
- *
- * @param context
- *
- * @return the id to use in the DOM
- */
- protected abstract String getApplicationId(BootstrapContext context);
-
public String getWidgetsetForUI(BootstrapContext context) {
VaadinRequest request = context.getRequest();
@@ -411,7 +401,7 @@ public abstract class BootstrapHandler implements RequestHandler {
String themeName = context.getThemeName();
if (themeName != null) {
- appConfig.put("themeUri", getThemeUri(context, themeName));
+ appConfig.put("theme", themeName);
}
JSONObject versionInfo = new JSONObject();
@@ -420,17 +410,6 @@ public abstract class BootstrapHandler implements RequestHandler {
appConfig.put("widgetset", context.getWidgetsetName());
- appConfig.put("initialPath", request.getRequestPathInfo());
-
- Map<String, String[]> parameterMap = new HashMap<String, String[]>(
- request.getParameterMap());
-
- // Include theme as a fake initial param so that UI can know its theme
- // for serving CustomLayout templates
- parameterMap.put("theme", new String[] { themeName });
-
- appConfig.put("initialParams", parameterMap);
-
// Use locale from session if set, else from the request
Locale locale = ServletPortletHelper.findLocale(null,
context.getSession(), context.getRequest());
@@ -457,11 +436,11 @@ public abstract class BootstrapHandler implements RequestHandler {
appConfig.put("authErrMsg", authErrMsg);
}
- String staticFileLocation = vaadinService
- .getStaticFileLocation(request);
- String widgetsetBase = staticFileLocation + "/"
- + VaadinServlet.WIDGETSET_DIRECTORY_PATH;
- appConfig.put("widgetsetBase", widgetsetBase);
+ // getStaticFileLocation documented to never end with a slash
+ // vaadinDir should always end with a slash
+ String vaadinDir = vaadinService.getStaticFileLocation(request)
+ + "/VAADIN/";
+ appConfig.put(ApplicationConstants.VAADIN_DIR_URL, vaadinDir);
if (!session.getConfiguration().isProductionMode()) {
appConfig.put("debug", true);
@@ -474,12 +453,15 @@ public abstract class BootstrapHandler implements RequestHandler {
appConfig.put("heartbeatInterval", vaadinService
.getDeploymentConfiguration().getHeartbeatInterval());
- appConfig.put("appUri", getAppUri(context));
+ String serviceUrl = getServiceUrl(context);
+ if (serviceUrl != null) {
+ appConfig.put(ApplicationConstants.SERVICE_URL, serviceUrl);
+ }
return appConfig;
}
- protected abstract String getAppUri(BootstrapContext context);
+ protected abstract String getServiceUrl(BootstrapContext context);
/**
* Get the URI for the application theme.
diff --git a/server/src/com/vaadin/server/CombinedRequest.java b/server/src/com/vaadin/server/CombinedRequest.java
index 34ac0b6a6f..5cb5b674b6 100644
--- a/server/src/com/vaadin/server/CombinedRequest.java
+++ b/server/src/com/vaadin/server/CombinedRequest.java
@@ -20,15 +20,10 @@ 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;
import java.util.Locale;
import java.util.Map;
-import org.json.JSONArray;
import org.json.JSONException;
-import org.json.JSONObject;
/**
* A {@link VaadinRequest} with path and parameters from one request and
@@ -42,7 +37,6 @@ import org.json.JSONObject;
public class CombinedRequest implements VaadinRequest {
private final VaadinRequest secondRequest;
- private Map<String, String[]> parameterMap;
/**
* Creates a new combined request based on the second request and some
@@ -56,37 +50,16 @@ public class CombinedRequest implements VaadinRequest {
*/
public CombinedRequest(VaadinRequest secondRequest) throws JSONException {
this.secondRequest = secondRequest;
-
- HashMap<String, String[]> map = new HashMap<String, String[]>();
- JSONObject initialParams = new JSONObject(
- secondRequest.getParameter("initialParams"));
- for (Iterator<?> keys = initialParams.keys(); keys.hasNext();) {
- String name = (String) keys.next();
- JSONArray jsonValues = initialParams.getJSONArray(name);
- String[] values = new String[jsonValues.length()];
- for (int i = 0; i < values.length; i++) {
- values[i] = jsonValues.getString(i);
- }
- map.put(name, values);
- }
-
- parameterMap = Collections.unmodifiableMap(map);
-
}
@Override
public String getParameter(String parameter) {
- String[] strings = getParameterMap().get(parameter);
- if (strings == null || strings.length == 0) {
- return null;
- } else {
- return strings[0];
- }
+ return secondRequest.getParameter(parameter);
}
@Override
public Map<String, String[]> getParameterMap() {
- return parameterMap;
+ return secondRequest.getParameterMap();
}
@Override
@@ -111,7 +84,7 @@ public class CombinedRequest implements VaadinRequest {
@Override
public String getRequestPathInfo() {
- return secondRequest.getParameter("initialPath");
+ return secondRequest.getRequestPathInfo();
}
@Override
diff --git a/server/src/com/vaadin/server/CommunicationManager.java b/server/src/com/vaadin/server/CommunicationManager.java
index 5f61079261..6cfaf37092 100644
--- a/server/src/com/vaadin/server/CommunicationManager.java
+++ b/server/src/com/vaadin/server/CommunicationManager.java
@@ -17,8 +17,6 @@
package com.vaadin.server;
import java.io.InputStream;
-import java.net.MalformedURLException;
-import java.net.URL;
import javax.servlet.ServletContext;
@@ -54,45 +52,19 @@ public class CommunicationManager extends AbstractCommunicationManager {
protected BootstrapHandler createBootstrapHandler() {
return new BootstrapHandler() {
@Override
- protected String getApplicationId(BootstrapContext context) {
- String appUrl = getAppUri(context);
-
- String appId = appUrl;
- if ("".equals(appUrl)) {
- appId = "ROOT";
- }
- appId = appId.replaceAll("[^a-zA-Z0-9]", "");
- // Add hashCode to the end, so that it is still (sort of)
- // predictable, but indicates that it should not be used in CSS
- // and
- // such:
- int hashCode = appId.hashCode();
- if (hashCode < 0) {
- hashCode = -hashCode;
- }
- appId = appId + "-" + hashCode;
- return appId;
- }
-
- @Override
- protected String getAppUri(BootstrapContext context) {
- /* Fetch relative url to application */
- // don't use server and port in uri. It may cause problems with
- // some
- // virtual server configurations which lose the server name
- URL url;
-
- try {
- url = context.getRequest().getService()
- .getApplicationUrl(context.getRequest());
- } catch (MalformedURLException e) {
- throw new RuntimeException(e);
- }
- String appUrl = url.getPath();
- if (appUrl.endsWith("/")) {
- appUrl = appUrl.substring(0, appUrl.length() - 1);
+ protected String getServiceUrl(BootstrapContext context) {
+ String pathInfo = context.getRequest().getRequestPathInfo();
+ if (pathInfo == null) {
+ return null;
+ } else {
+ /*
+ * Make a relative URL to the servlet by adding one ../ for
+ * each path segment in pathInfo (i.e. the part of the
+ * requested path that comes after the servlet mapping)
+ */
+ return VaadinServletService
+ .getCancelingRelativePath(pathInfo);
}
- return appUrl;
}
@Override
diff --git a/server/src/com/vaadin/server/GAEVaadinServlet.java b/server/src/com/vaadin/server/GAEVaadinServlet.java
index c68f25a282..d2c53c6fcb 100644
--- a/server/src/com/vaadin/server/GAEVaadinServlet.java
+++ b/server/src/com/vaadin/server/GAEVaadinServlet.java
@@ -348,7 +348,7 @@ public class GAEVaadinServlet extends VaadinServlet {
}
private boolean isCleanupRequest(HttpServletRequest request) {
- String path = getRequestPathInfo(request);
+ String path = request.getPathInfo();
if (path != null && path.equals(CLEANUP_PATH)) {
return true;
}
diff --git a/server/src/com/vaadin/server/PortletCommunicationManager.java b/server/src/com/vaadin/server/PortletCommunicationManager.java
index 8d39eee9ac..635202a074 100644
--- a/server/src/com/vaadin/server/PortletCommunicationManager.java
+++ b/server/src/com/vaadin/server/PortletCommunicationManager.java
@@ -65,19 +65,11 @@ public class PortletCommunicationManager extends AbstractCommunicationManager {
}
@Override
- protected String getApplicationId(BootstrapContext context) {
- PortletRequest portletRequest = VaadinPortletRequest.cast(
- context.getRequest()).getPortletRequest();
- /*
- * We need to generate a unique ID because some portals already
- * create a DIV with the portlet's Window ID as the DOM ID.
- */
- return "v-" + portletRequest.getWindowID();
- }
-
- @Override
- protected String getAppUri(BootstrapContext context) {
- return getRenderResponse(context).createActionURL().toString();
+ protected String getServiceUrl(BootstrapContext context) {
+ ResourceURL portletResourceUrl = getRenderResponse(context)
+ .createResourceURL();
+ portletResourceUrl.setResourceID(VaadinPortlet.RESOURCE_URL_ID);
+ return portletResourceUrl.toString();
}
private RenderResponse getRenderResponse(BootstrapContext context) {
@@ -129,11 +121,10 @@ public class PortletCommunicationManager extends AbstractCommunicationManager {
resourceURL.setResourceID("browserDetails");
parameters.put("browserDetailsUrl", resourceURL.toString());
- ResourceURL portletResourceUrl = getRenderResponse(context)
- .createResourceURL();
- portletResourceUrl.setResourceID(VaadinPortlet.RESOURCE_URL_ID);
- parameters.put(ApplicationConstants.PORTLET_RESOUCE_URL_BASE,
- portletResourceUrl.toString());
+ // Always send path info as a query parameter
+ parameters.put(
+ ApplicationConstants.SERVICE_URL_PATH_AS_PARAMETER,
+ true);
return parameters;
}
diff --git a/server/src/com/vaadin/server/VaadinPortletService.java b/server/src/com/vaadin/server/VaadinPortletService.java
index ac48900945..12bf45f43a 100644
--- a/server/src/com/vaadin/server/VaadinPortletService.java
+++ b/server/src/com/vaadin/server/VaadinPortletService.java
@@ -25,6 +25,7 @@ import javax.portlet.PortletContext;
import javax.portlet.PortletRequest;
import com.vaadin.server.VaadinPortlet.RequestType;
+import com.vaadin.ui.UI;
public class VaadinPortletService extends VaadinService {
private final VaadinPortlet portlet;
@@ -218,4 +219,16 @@ public class VaadinPortletService extends VaadinService {
public boolean preserveUIOnRefresh(UIProvider provider, UICreateEvent event) {
return true;
}
-} \ No newline at end of file
+
+ @Override
+ public String getMainDivId(VaadinServiceSession session,
+ VaadinRequest request, Class<? extends UI> uiClass) {
+ PortletRequest portletRequest = VaadinPortletRequest.cast(request)
+ .getPortletRequest();
+ /*
+ * We need to generate a unique ID because some portals already create a
+ * DIV with the portlet's Window ID as the DOM ID.
+ */
+ return "v-" + portletRequest.getWindowID();
+ }
+}
diff --git a/server/src/com/vaadin/server/VaadinService.java b/server/src/com/vaadin/server/VaadinService.java
index 28684ec8dc..d9c8b83ea4 100644
--- a/server/src/com/vaadin/server/VaadinService.java
+++ b/server/src/com/vaadin/server/VaadinService.java
@@ -730,4 +730,20 @@ public abstract class VaadinService implements Serializable {
}
}
+
+ /**
+ * Creates and returns a unique ID for the DIV where the UI is to be
+ * rendered.
+ *
+ * @param session
+ * The service session to which the bootstrapped UI will belong.
+ * @param request
+ * The request for which a div id is needed
+ * @param uiClass
+ * The class of the UI that will be bootstrapped
+ *
+ * @return the id to use in the DOM
+ */
+ public abstract String getMainDivId(VaadinServiceSession session,
+ VaadinRequest request, Class<? extends UI> uiClass);
}
diff --git a/server/src/com/vaadin/server/VaadinServlet.java b/server/src/com/vaadin/server/VaadinServlet.java
index bd724aad63..68fca7b463 100644
--- a/server/src/com/vaadin/server/VaadinServlet.java
+++ b/server/src/com/vaadin/server/VaadinServlet.java
@@ -1165,26 +1165,6 @@ public class VaadinServlet extends HttpServlet implements Constants {
return u;
}
- /**
- * Returns the path info; note that this _can_ be different than
- * request.getPathInfo(). Examples where this might be useful:
- * <ul>
- * <li>An application runner servlet that runs different Vaadin applications
- * based on an identifier.</li>
- * <li>Providing a REST interface in the context root, while serving a
- * Vaadin UI on a sub-URI using only one servlet (e.g. REST on
- * http://example.com/foo, UI on http://example.com/foo/vaadin)</li>
- *
- * @param request
- * @return
- *
- * @deprecated might be refactored or removed before 7.0.0
- */
- @Deprecated
- protected String getRequestPathInfo(HttpServletRequest request) {
- return request.getPathInfo();
- }
-
public class RequestError implements Terminal.ErrorEvent, Serializable {
private final Throwable throwable;
diff --git a/server/src/com/vaadin/server/VaadinServletService.java b/server/src/com/vaadin/server/VaadinServletService.java
index b8af3b13fb..9992b3698d 100644
--- a/server/src/com/vaadin/server/VaadinServletService.java
+++ b/server/src/com/vaadin/server/VaadinServletService.java
@@ -23,6 +23,7 @@ import java.net.URL;
import javax.servlet.http.HttpServletRequest;
import com.vaadin.server.VaadinServlet.RequestType;
+import com.vaadin.ui.UI;
public class VaadinServletService extends VaadinService {
private final VaadinServlet servlet;
@@ -50,31 +51,35 @@ public class VaadinServletService extends VaadinService {
}
// the last (but most common) option is to generate default location
- // from request
+ // from request by finding how many "../" should be added to the
+ // requested path before we get to the context root
- // if context is specified add it to widgetsetUrl
- String ctxPath = servletRequest.getContextPath();
-
- // FIXME: ctxPath.length() == 0 condition is probably unnecessary
- // and
- // might even be wrong.
-
- if (ctxPath.length() == 0
- && request.getAttribute("javax.servlet.include.context_path") != null) {
- // include request (e.g portlet), get context path from
- // attribute
- ctxPath = (String) request
- .getAttribute("javax.servlet.include.context_path");
+ String requestedPath = servletRequest.getServletPath();
+ String pathInfo = servletRequest.getPathInfo();
+ if (pathInfo != null) {
+ requestedPath += pathInfo;
}
- // Remove heading and trailing slashes from the context path
- ctxPath = VaadinServlet.removeHeadingOrTrailing(ctxPath, "/");
+ return getCancelingRelativePath(requestedPath);
+ }
- if (ctxPath.equals("")) {
- return "";
- } else {
- return "/" + ctxPath;
+ /**
+ * Gets a relative path that cancels the provided path. This essentially
+ * adds one .. for each part of the path to cancel.
+ *
+ * @param pathToCancel
+ * the path that should be canceled
+ * @return a relative path that cancels out the provided path segment
+ */
+ public static String getCancelingRelativePath(String pathToCancel) {
+ StringBuilder sb = new StringBuilder(".");
+ // Start from i = 1 to ignore first slash
+ for (int i = 1; i < pathToCancel.length(); i++) {
+ if (pathToCancel.charAt(i) == '/') {
+ sb.append("/..");
+ }
}
+ return sb.toString();
}
@Override
@@ -184,4 +189,32 @@ public class VaadinServletService extends VaadinService {
public String getServiceName() {
return getServlet().getServletName();
}
-} \ No newline at end of file
+
+ @Override
+ public String getMainDivId(VaadinServiceSession session,
+ VaadinRequest request, Class<? extends UI> uiClass) {
+ String appId = null;
+ try {
+ URL appUrl = getServlet().getApplicationUrl(
+ VaadinServletRequest.cast(request));
+ appId = appUrl.getPath();
+ } catch (MalformedURLException e) {
+ // Just ignore problem here
+ }
+
+ if (appId == null || "".equals(appId)) {
+ appId = "ROOT";
+ }
+ appId = appId.replaceAll("[^a-zA-Z0-9]", "");
+ // Add hashCode to the end, so that it is still (sort of)
+ // predictable, but indicates that it should not be used in CSS
+ // and
+ // such:
+ int hashCode = appId.hashCode();
+ if (hashCode < 0) {
+ hashCode = -hashCode;
+ }
+ appId = appId + "-" + hashCode;
+ return appId;
+ }
+}