aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorArtur <artur@vaadin.com>2017-02-22 10:35:44 +0200
committerIlia Motornyi <elmot@vaadin.com>2017-02-22 10:35:44 +0200
commitbba4e4037bbfa7bfd5f71718806a92bb351e2fe8 (patch)
tree75c5481b87f1a477ffac07bd1b77c009586abae8
parentaf1412adad6131a9603dc6854186ec896fb90f61 (diff)
downloadvaadin-framework-bba4e4037bbfa7bfd5f71718806a92bb351e2fe8.tar.gz
vaadin-framework-bba4e4037bbfa7bfd5f71718806a92bb351e2fe8.zip
Translate "context://" to the context root of the web app
Fixes #2523
-rw-r--r--client/src/main/java/com/vaadin/client/ApplicationConfiguration.java13
-rw-r--r--client/src/main/java/com/vaadin/client/ApplicationConnection.java12
-rw-r--r--server/src/main/java/com/vaadin/server/BootstrapHandler.java13
-rw-r--r--server/src/main/java/com/vaadin/server/VaadinServletService.java26
-rw-r--r--server/src/main/java/com/vaadin/server/communication/PortletBootstrapHandler.java6
-rw-r--r--server/src/main/java/com/vaadin/server/communication/ServletBootstrapHandler.java7
-rw-r--r--server/src/test/java/com/vaadin/server/VaadinServletServiceTest.java127
-rw-r--r--shared/src/main/java/com/vaadin/shared/ApplicationConstants.java10
-rw-r--r--shared/src/main/java/com/vaadin/shared/VaadinUriResolver.java14
-rw-r--r--uitest/src/main/java/com/vaadin/tests/applicationservlet/ContextProtocol.java37
-rw-r--r--uitest/src/main/webapp/statictestfiles/image.pngbin0 -> 17005 bytes
-rw-r--r--uitest/src/main/webapp/statictestfiles/sayHello.js1
-rw-r--r--uitest/src/test/java/com/vaadin/tests/applicationservlet/ContextProtocolTest.java36
13 files changed, 299 insertions, 3 deletions
diff --git a/client/src/main/java/com/vaadin/client/ApplicationConfiguration.java b/client/src/main/java/com/vaadin/client/ApplicationConfiguration.java
index e599eef61b..cde31cbd40 100644
--- a/client/src/main/java/com/vaadin/client/ApplicationConfiguration.java
+++ b/client/src/main/java/com/vaadin/client/ApplicationConfiguration.java
@@ -241,6 +241,7 @@ public class ApplicationConfiguration implements EntryPoint {
*/
private String vaadinDirUrl;
private String serviceUrl;
+ private String contextRootUrl;
private int uiId;
private boolean standalone;
private ErrorMessage communicationError;
@@ -311,6 +312,15 @@ public class ApplicationConfiguration implements EntryPoint {
}
/**
+ * Gets the URL to the context root of the web application
+ *
+ * @return the URL to the server-side context root as a string
+ */
+ public String getContextRootUrl() {
+ return contextRootUrl;
+ }
+
+ /**
* @return the theme name used when initializing the application
* @deprecated as of 7.3. Use {@link UIConnector#getActiveTheme()} to get
* the theme currently in use
@@ -413,6 +423,8 @@ public class ApplicationConfiguration implements EntryPoint {
serviceUrl += '/';
}
+ contextRootUrl = jsoConfiguration
+ .getConfigString(ApplicationConstants.CONTEXT_ROOT_URL);
vaadinDirUrl = WidgetUtil.getAbsoluteUrl(jsoConfiguration
.getConfigString(ApplicationConstants.VAADIN_DIR_URL));
uiId = jsoConfiguration.getConfigInteger(UIConstants.UI_ID_PARAMETER)
@@ -897,4 +909,5 @@ public class ApplicationConfiguration implements EntryPoint {
private static final Logger getLogger() {
return Logger.getLogger(ApplicationConfiguration.class.getName());
}
+
}
diff --git a/client/src/main/java/com/vaadin/client/ApplicationConnection.java b/client/src/main/java/com/vaadin/client/ApplicationConnection.java
index b9288d68c6..e94195cd37 100644
--- a/client/src/main/java/com/vaadin/client/ApplicationConnection.java
+++ b/client/src/main/java/com/vaadin/client/ApplicationConnection.java
@@ -41,6 +41,7 @@ import com.google.gwt.user.client.Timer;
import com.google.gwt.user.client.ui.HasWidgets;
import com.google.gwt.user.client.ui.Widget;
import com.vaadin.client.ApplicationConfiguration.ErrorMessage;
+import com.vaadin.client.ApplicationConnection.ApplicationStoppedEvent;
import com.vaadin.client.communication.ConnectionStateHandler;
import com.vaadin.client.communication.Heartbeat;
import com.vaadin.client.communication.MessageHandler;
@@ -328,6 +329,11 @@ public class ApplicationConnection implements HasHandlers {
protected String encodeQueryStringParameterValue(String queryString) {
return URL.encodeQueryString(queryString);
}
+
+ @Override
+ protected String getContextRootUrl() {
+ return getConfiguration().getContextRootUrl();
+ }
};
public static class MultiStepDuration extends Duration {
@@ -481,7 +487,7 @@ public class ApplicationConnection implements HasHandlers {
return vi;
}
}
-
+
client.getProfilingData = $entry(function() {
var smh = ap.@com.vaadin.client.ApplicationConnection::getMessageHandler()();
var pd = [
@@ -496,7 +502,7 @@ public class ApplicationConnection implements HasHandlers {
pd[pd.length] = smh.@com.vaadin.client.communication.MessageHandler::bootstrapTime;
return pd;
});
-
+
client.getElementByPath = $entry(function(id) {
return componentLocator.@com.vaadin.client.componentlocator.ComponentLocator::getElementByPath(Ljava/lang/String;)(id);
});
@@ -513,7 +519,7 @@ public class ApplicationConnection implements HasHandlers {
return componentLocator.@com.vaadin.client.componentlocator.ComponentLocator::getPathForElement(Lcom/google/gwt/dom/client/Element;)(element);
});
client.initializing = false;
-
+
$wnd.vaadin.clients[TTAppId] = client;
}-*/;
diff --git a/server/src/main/java/com/vaadin/server/BootstrapHandler.java b/server/src/main/java/com/vaadin/server/BootstrapHandler.java
index d94101152e..02a8d7ba84 100644
--- a/server/src/main/java/com/vaadin/server/BootstrapHandler.java
+++ b/server/src/main/java/com/vaadin/server/BootstrapHandler.java
@@ -242,6 +242,14 @@ public abstract class BootstrapHandler extends SynchronizedRequestHandler {
}
return encodedString;
}
+
+ @Override
+ protected String getContextRootUrl() {
+ String root = context.getApplicationParameters()
+ .getString(ApplicationConstants.CONTEXT_ROOT_URL);
+ assert root.endsWith("/");
+ return root;
+ }
}
@Override
@@ -691,6 +699,9 @@ public abstract class BootstrapHandler extends SynchronizedRequestHandler {
appConfig.put("sessExpMsg", sessExpMsg);
}
+ appConfig.put(ApplicationConstants.CONTEXT_ROOT_URL,
+ getContextRootPath(context));
+
// getStaticFileLocation documented to never end with a slash
// vaadinDir should always end with a slash
String vaadinDir = vaadinService.getStaticFileLocation(request)
@@ -722,6 +733,8 @@ public abstract class BootstrapHandler extends SynchronizedRequestHandler {
return appConfig;
}
+ protected abstract String getContextRootPath(BootstrapContext context);
+
protected abstract String getServiceUrl(BootstrapContext context);
/**
diff --git a/server/src/main/java/com/vaadin/server/VaadinServletService.java b/server/src/main/java/com/vaadin/server/VaadinServletService.java
index 2adea189f7..242966f8cf 100644
--- a/server/src/main/java/com/vaadin/server/VaadinServletService.java
+++ b/server/src/main/java/com/vaadin/server/VaadinServletService.java
@@ -114,6 +114,32 @@ public class VaadinServletService extends VaadinService {
return sb.toString();
}
+ /**
+ * Gets a relative path you can use to refer to the context root.
+ *
+ * @param request
+ * the request for which the location should be determined
+ * @return A relative path to the context root. Never ends with a slash (/).
+ */
+ public static String getContextRootRelativePath(VaadinRequest request) {
+ VaadinServletRequest servletRequest = (VaadinServletRequest) request;
+ // Generate location from the request by finding how many "../" should
+ // be added to the servlet path before we get to the context root
+
+ String servletPath = servletRequest.getServletPath();
+ if (servletPath == null) {
+ // Not allowed by the spec but servers are servers...
+ servletPath = "";
+ }
+
+ String pathInfo = servletRequest.getPathInfo();
+ if (pathInfo != null && !"".equals(pathInfo)) {
+ servletPath += pathInfo;
+ }
+
+ return getCancelingRelativePath(servletPath);
+ }
+
@Override
public String getConfiguredWidgetset(VaadinRequest request) {
return getDeploymentConfiguration()
diff --git a/server/src/main/java/com/vaadin/server/communication/PortletBootstrapHandler.java b/server/src/main/java/com/vaadin/server/communication/PortletBootstrapHandler.java
index 490fbb81f0..535cd7646e 100644
--- a/server/src/main/java/com/vaadin/server/communication/PortletBootstrapHandler.java
+++ b/server/src/main/java/com/vaadin/server/communication/PortletBootstrapHandler.java
@@ -119,4 +119,10 @@ public class PortletBootstrapHandler extends BootstrapHandler {
return parameters;
}
+
+ @Override
+ protected String getContextRootPath(BootstrapContext context) {
+ // Not really supported in portlet environments
+ return ".";
+ }
}
diff --git a/server/src/main/java/com/vaadin/server/communication/ServletBootstrapHandler.java b/server/src/main/java/com/vaadin/server/communication/ServletBootstrapHandler.java
index 0365914ff1..28bda1b42c 100644
--- a/server/src/main/java/com/vaadin/server/communication/ServletBootstrapHandler.java
+++ b/server/src/main/java/com/vaadin/server/communication/ServletBootstrapHandler.java
@@ -45,4 +45,11 @@ public class ServletBootstrapHandler extends BootstrapHandler {
}
return themeName;
}
+
+ @Override
+ protected String getContextRootPath(BootstrapContext context) {
+ return VaadinServletService
+ .getContextRootRelativePath(context.getRequest()) + "/";
+ }
+
}
diff --git a/server/src/test/java/com/vaadin/server/VaadinServletServiceTest.java b/server/src/test/java/com/vaadin/server/VaadinServletServiceTest.java
new file mode 100644
index 0000000000..24bb800a12
--- /dev/null
+++ b/server/src/test/java/com/vaadin/server/VaadinServletServiceTest.java
@@ -0,0 +1,127 @@
+package com.vaadin.server;
+
+import static org.easymock.EasyMock.createMock;
+import static org.easymock.EasyMock.expect;
+import static org.easymock.EasyMock.replay;
+
+import java.net.MalformedURLException;
+import java.net.URL;
+
+import javax.servlet.ServletException;
+import javax.servlet.http.HttpServletRequest;
+
+import org.junit.Assert;
+import org.junit.Before;
+import org.junit.Test;
+
+public class VaadinServletServiceTest {
+ VaadinServlet servlet;
+
+ @Before
+ public void setup() throws ServletException {
+ servlet = new VaadinServlet();
+ servlet.init(new MockServletConfig());
+ }
+
+ @Test
+ public void testServletToContextRootRelativePath() throws Exception {
+ String location;
+
+ /* SERVLETS */
+ // http://dummy.host:8080/contextpath/servlet
+ // should return . (relative url resolving to /contextpath)
+ location = testLocation("http://dummy.host:8080", "/contextpath",
+ "/servlet", "");
+ Assert.assertEquals(".", location);
+
+ // http://dummy.host:8080/contextpath/servlet/
+ // should return ./.. (relative url resolving to /contextpath)
+ location = testLocation("http://dummy.host:8080", "/contextpath",
+ "/servlet", "/");
+ Assert.assertEquals("./..", location);
+
+ // http://dummy.host:8080/servlet
+ // should return "."
+ location = testLocation("http://dummy.host:8080", "", "/servlet", "");
+ Assert.assertEquals(".", location);
+
+ // http://dummy.host/contextpath/servlet/extra/stuff
+ // should return ./../.. (relative url resolving to /contextpath)
+ location = testLocation("http://dummy.host", "/contextpath", "/servlet",
+ "/extra/stuff");
+ Assert.assertEquals("./../..", location);
+
+ // http://dummy.host/contextpath/servlet/extra/stuff/
+ // should return ./../.. (relative url resolving to /contextpath)
+ location = testLocation("http://dummy.host", "/contextpath", "/servlet",
+ "/extra/stuff/");
+ Assert.assertEquals("./../../..", location);
+
+ // http://dummy.host/context/path/servlet/extra/stuff
+ // should return ./../.. (relative url resolving to /context/path)
+ location = testLocation("http://dummy.host", "/context/path",
+ "/servlet", "/extra/stuff");
+ Assert.assertEquals("./../..", location);
+
+ }
+
+ private String testLocation(String base, String contextPath,
+ String servletPath, String pathInfo) throws Exception {
+
+ HttpServletRequest request = createNonIncludeRequest(base, contextPath,
+ servletPath, pathInfo);
+ // Set request into replay mode
+ replay(request);
+
+ String location = VaadinServletService.getContextRootRelativePath(
+ servlet.createVaadinRequest(request));
+ return location;
+ }
+
+ private HttpServletRequest createNonIncludeRequest(String base,
+ String realContextPath, String realServletPath, String pathInfo)
+ throws Exception {
+ HttpServletRequest request = createRequest(base, realContextPath,
+ realServletPath, pathInfo);
+ expect(request.getAttribute("javax.servlet.include.context_path"))
+ .andReturn(null).anyTimes();
+ expect(request.getAttribute("javax.servlet.include.servlet_path"))
+ .andReturn(null).anyTimes();
+
+ return request;
+ }
+
+ /**
+ * Creates a HttpServletRequest mock using the supplied parameters.
+ *
+ * @param base
+ * The base url, e.g. http://localhost:8080
+ * @param contextPath
+ * The context path where the application is deployed, e.g.
+ * /mycontext
+ * @param servletPath
+ * The servlet path to the servlet we are testing, e.g. /myapp
+ * @param pathInfo
+ * Any text following the servlet path in the request, not
+ * including query parameters, e.g. /UIDL/
+ * @return A mock HttpServletRequest object useful for testing
+ * @throws MalformedURLException
+ */
+ private HttpServletRequest createRequest(String base, String contextPath,
+ String servletPath, String pathInfo) throws MalformedURLException {
+ URL url = new URL(base + contextPath + pathInfo);
+ HttpServletRequest request = createMock(HttpServletRequest.class);
+ expect(request.isSecure())
+ .andReturn(url.getProtocol().equalsIgnoreCase("https"))
+ .anyTimes();
+ expect(request.getServerName()).andReturn(url.getHost()).anyTimes();
+ expect(request.getServerPort()).andReturn(url.getPort()).anyTimes();
+ expect(request.getRequestURI()).andReturn(url.getPath()).anyTimes();
+ expect(request.getContextPath()).andReturn(contextPath).anyTimes();
+ expect(request.getPathInfo()).andReturn(pathInfo).anyTimes();
+ expect(request.getServletPath()).andReturn(servletPath).anyTimes();
+
+ return request;
+ }
+
+}
diff --git a/shared/src/main/java/com/vaadin/shared/ApplicationConstants.java b/shared/src/main/java/com/vaadin/shared/ApplicationConstants.java
index 166e75e94f..8cf30e43b5 100644
--- a/shared/src/main/java/com/vaadin/shared/ApplicationConstants.java
+++ b/shared/src/main/java/com/vaadin/shared/ApplicationConstants.java
@@ -35,6 +35,10 @@ public class ApplicationConstants implements Serializable {
public static final String APP_PROTOCOL_PREFIX = "app://";
public static final String VAADIN_PROTOCOL_PREFIX = "vaadin://";
+ /**
+ * An internal protocol used for referencing the application context path.
+ */
+ public static final String CONTEXT_PROTOCOL_PREFIX = "context://";
public static final String FONTICON_PROTOCOL_PREFIX = "fonticon://";
public static final String PUBLISHED_PROTOCOL_NAME = "published";
public static final String PUBLISHED_PROTOCOL_PREFIX = PUBLISHED_PROTOCOL_NAME
@@ -73,6 +77,12 @@ public class ApplicationConstants implements Serializable {
/**
* Configuration parameter giving the (in some cases relative) URL to the
+ * web application context root.
+ */
+ public static final String CONTEXT_ROOT_URL = "contextRootUrl";
+
+ /**
+ * Configuration parameter giving the (in some cases relative) URL to the
* VAADIN folder from where themes and widgetsets are loaded.
* <p>
* <b>Refactor warning:</b> This value is also hardcoded in
diff --git a/shared/src/main/java/com/vaadin/shared/VaadinUriResolver.java b/shared/src/main/java/com/vaadin/shared/VaadinUriResolver.java
index 169b1ce768..78bf0de598 100644
--- a/shared/src/main/java/com/vaadin/shared/VaadinUriResolver.java
+++ b/shared/src/main/java/com/vaadin/shared/VaadinUriResolver.java
@@ -110,6 +110,13 @@ public abstract class VaadinUriResolver implements Serializable {
ApplicationConstants.VAADIN_PROTOCOL_PREFIX.length());
vaadinUri = vaadinDirUri + relativeUrl;
}
+ if (vaadinUri
+ .startsWith(ApplicationConstants.CONTEXT_PROTOCOL_PREFIX)) {
+ final String contextRoot = getContextRootUrl();
+ String relativeUrl = vaadinUri.substring(
+ ApplicationConstants.CONTEXT_PROTOCOL_PREFIX.length());
+ vaadinUri = contextRoot + relativeUrl;
+ }
return vaadinUri;
}
@@ -141,6 +148,13 @@ public abstract class VaadinUriResolver implements Serializable {
protected abstract String getServiceUrl();
/**
+ * Gets the URL pointing to the context root.
+ *
+ * @return the context root URL
+ */
+ protected abstract String getContextRootUrl();
+
+ /**
* Gets the URI of the directory of the current theme.
*
* @return the URI of the current theme directory
diff --git a/uitest/src/main/java/com/vaadin/tests/applicationservlet/ContextProtocol.java b/uitest/src/main/java/com/vaadin/tests/applicationservlet/ContextProtocol.java
new file mode 100644
index 0000000000..64fd47a3be
--- /dev/null
+++ b/uitest/src/main/java/com/vaadin/tests/applicationservlet/ContextProtocol.java
@@ -0,0 +1,37 @@
+/*
+ * Copyright 2000-2016 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.tests.applicationservlet;
+
+import com.vaadin.annotations.JavaScript;
+import com.vaadin.annotations.Widgetset;
+import com.vaadin.server.ExternalResource;
+import com.vaadin.server.VaadinRequest;
+import com.vaadin.tests.components.AbstractTestUI;
+import com.vaadin.ui.Image;
+
+@JavaScript("context://statictestfiles/sayHello.js")
+@Widgetset("com.vaadin.DefaultWidgetSet")
+public class ContextProtocol extends AbstractTestUI {
+
+ @Override
+ protected void setup(VaadinRequest request) {
+ Image image = new Image("Image from context root",
+ new ExternalResource("context://statictestfiles/image.png"));
+ image.setId("image");
+ addComponent(image);
+ }
+
+}
diff --git a/uitest/src/main/webapp/statictestfiles/image.png b/uitest/src/main/webapp/statictestfiles/image.png
new file mode 100644
index 0000000000..f52011183c
--- /dev/null
+++ b/uitest/src/main/webapp/statictestfiles/image.png
Binary files differ
diff --git a/uitest/src/main/webapp/statictestfiles/sayHello.js b/uitest/src/main/webapp/statictestfiles/sayHello.js
new file mode 100644
index 0000000000..b1f3e9274c
--- /dev/null
+++ b/uitest/src/main/webapp/statictestfiles/sayHello.js
@@ -0,0 +1 @@
+window.hello="said"; \ No newline at end of file
diff --git a/uitest/src/test/java/com/vaadin/tests/applicationservlet/ContextProtocolTest.java b/uitest/src/test/java/com/vaadin/tests/applicationservlet/ContextProtocolTest.java
new file mode 100644
index 0000000000..a4bd0b5f85
--- /dev/null
+++ b/uitest/src/test/java/com/vaadin/tests/applicationservlet/ContextProtocolTest.java
@@ -0,0 +1,36 @@
+/*
+ * Copyright 2000-2016 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.tests.applicationservlet;
+
+import org.junit.Assert;
+import org.junit.Test;
+
+import com.vaadin.testbench.By;
+import com.vaadin.tests.tb3.SingleBrowserTest;
+
+public class ContextProtocolTest extends SingleBrowserTest {
+
+ @Test
+ public void contextPathCorrect() {
+ openTestURL();
+ // Added by bootstrap
+ Assert.assertEquals("said", executeScript("return window.hello"));
+ // Added by client side
+ Assert.assertEquals(getBaseURL() + "/statictestfiles/image.png",
+ findElement(By.id("image")).getAttribute("src"));
+ }
+
+}