log('Fetching root config');
var url = getConfig('browserDetailsUrl');
if (!url) {
- // No special url defined, use the default URL
- url = getConfig('appUri');
- // Add a slash to the end, because ApplicationConiguration.loadFromDOM does so...
- if (url.length == 0 || url.substr(url.length-1) !== "/") {
- url += '/';
- }
+ // No special url defined, use the same URL that loaded this page (without the fragment)
+ url = window.location.href.replace(/#.*/,'');
}
url += ((/\?/).test(url) ? "&" : "?") + "browserDetails=1";
var rootId = getConfig("rootId");
url += "&rootId=" + rootId;
}
- var initialPath = getConfig("initialPath");
- if (initialPath !== undefined) {
- url += '&initialPath=' + encodeURIComponent(initialPath);
+ // Tell the UI what theme it is configured to use
+ var theme = getConfig('theme');
+ if (theme !== undefined) {
+ url += '&theme=' + encodeURIComponent(theme);
}
- url += '&initialParams=' + encodeURIComponent(JSON.stringify(getConfig("initialParams")));
url += '&' + vaadin.getBrowserDetailsParameters(appId);
}
var bootstrapApp = function(mayDefer) {
- var themeUri = getConfig('themeUri');
+ var vaadinDir = getConfig('vaadinDir');
+
+ var themeUri = vaadinDir + 'themes/' + getConfig('theme')
loadTheme(themeUri);
- var widgetsetBase = getConfig('widgetsetBase');
var widgetset = getConfig('widgetset');
- loadWidgetset(widgetsetBase, widgetset);
+ loadWidgetset(vaadinDir + 'widgetsets/', widgetset);
if (getConfig('uidl') === undefined) {
if (mayDefer) {
<servlet-class>com.vaadin.server.LegacyVaadinServlet</servlet-class>
<init-param>
<param-name>application</param-name>
- <param-value>com.vaadin.tests.components.absolutelayout.AbsoluteLayoutClipping</param-value>
+ <param-value>com.vaadin.tests.components.button.Buttons</param-value>
</init-param>
</servlet>
<servlet>
private static WidgetSet widgetSet = GWT.create(WidgetSet.class);
private String id;
- private String themeUri;
- private String appUri;
+ /**
+ * The URL to the VAADIN directory containing themes and widgetsets. Should
+ * always end with a slash (/).
+ */
+ private String vaadinDirUrl;
+ private String serviceUrl;
private int uiId;
private boolean standalone;
private ErrorMessage communicationError;
private Map<Integer, Integer> componentInheritanceMap = new HashMap<Integer, Integer>();
private Map<Integer, String> tagToServerSideClassName = new HashMap<Integer, String>();
- public boolean usePortletURLs() {
- return getPortletResourceUrl() != null;
- }
-
- public String getPortletResourceUrl() {
- return getJsoConfiguration(id).getConfigString(
- ApplicationConstants.PORTLET_RESOUCE_URL_BASE);
+ /**
+ * Checks whether path info in requests to the server-side service should be
+ * in a request parameter (named
+ * {@value ApplicationConstants#V_RESOURCE_PATH}) or appended to the end of
+ * the service URL.
+ *
+ * @see #getServiceUrl()
+ *
+ * @return <code>true</code> if path info should be a request parameter;
+ * <code>false</code> if the path info goes after the service URL
+ */
+ public boolean useServiceUrlPathParam() {
+ return getJsoConfiguration(id).getConfigBoolean(
+ ApplicationConstants.SERVICE_URL_PATH_AS_PARAMETER) == Boolean.TRUE;
}
public String getRootPanelId() {
}
/**
- * Gets the application base URI. Using this other than as the download
- * action URI can cause problems in Portlet 2.0 deployments.
+ * Gets the URL to the server-side VaadinService. If
+ * {@link #useServiceUrlPathParam()} return <code>true</code>, the requested
+ * path info should be in the {@value ApplicationConstants#V_RESOURCE_PATH}
+ * query parameter; else the path info should be appended to the end of the
+ * URL.
+ *
+ * @see #useServiceUrlPathParam()
*
- * @return application base URI
+ * @return the URL to the server-side service as a string
*/
- public String getApplicationUri() {
- return appUri;
+ public String getServiceUrl() {
+ return serviceUrl;
}
public String getThemeName() {
- String uri = getThemeUri();
- String themeName = uri.substring(uri.lastIndexOf('/'));
+ String themeName = getJsoConfiguration(id).getConfigString("theme");
themeName = themeName.replaceAll("[^a-zA-Z0-9]", "");
return themeName;
}
public String getThemeUri() {
- return themeUri;
+ return vaadinDirUrl + "themes/" + getThemeName();
}
public void setAppId(String appId) {
*/
private void loadFromDOM() {
JsoConfiguration jsoConfiguration = getJsoConfiguration(id);
- appUri = jsoConfiguration.getConfigString("appUri");
- if (appUri != null && !appUri.endsWith("/")) {
- appUri += '/';
+ serviceUrl = jsoConfiguration
+ .getConfigString(ApplicationConstants.SERVICE_URL);
+ if (serviceUrl == null || "".equals(serviceUrl)) {
+ /*
+ * Use the current url without query parameters and fragment as the
+ * default value.
+ */
+ serviceUrl = Window.Location.getHref().replaceFirst("[?#].*", "");
+ } else {
+ /*
+ * Resolve potentially relative URLs to ensure they point to the
+ * desired locations even if the base URL of the page changes later
+ * (e.g. with pushState)
+ */
+ serviceUrl = Util.getAbsoluteUrl(serviceUrl);
+ }
+ // Ensure there's an ending slash (to make appending e.g. UIDL work)
+ if (!useServiceUrlPathParam() && !serviceUrl.endsWith("/")) {
+ serviceUrl += '/';
}
- themeUri = jsoConfiguration.getConfigString("themeUri");
+
+ vaadinDirUrl = Util.getAbsoluteUrl(jsoConfiguration
+ .getConfigString(ApplicationConstants.VAADIN_DIR_URL));
uiId = jsoConfiguration.getConfigInteger(UIConstants.UI_ID_PARAMETER)
.intValue();
}
}-*/;
- /**
- * Gets the application base URI. Using this other than as the download
- * action URI can cause problems in Portlet 2.0 deployments.
- *
- * @return application base URI
- */
- public String getAppUri() {
- return configuration.getApplicationUri();
- };
-
/**
* Indicates whether or not there are currently active UIDL requests. Used
* internally to sequence requests properly, seldom needed in Widgets.
String relativeUrl = uidlUri
.substring(ApplicationConstants.APP_PROTOCOL_PREFIX
.length());
- if (getConfiguration().usePortletURLs()) {
+ ApplicationConfiguration conf = getConfiguration();
+ String serviceUrl = conf.getServiceUrl();
+ if (conf.useServiceUrlPathParam()) {
// Should put path in v-resourcePath parameter and append query
// params to base portlet url
String[] parts = relativeUrl.split("\\?", 2);
String path = parts[0];
- String url = getConfiguration().getPortletResourceUrl();
-
// If there's a "?" followed by something, append it as a query
// string to the base URL
if (parts.length > 1) {
String appUrlParams = parts[1];
- url = addGetParameters(url, appUrlParams);
+ serviceUrl = addGetParameters(serviceUrl, appUrlParams);
}
if (!path.startsWith("/")) {
path = '/' + path;
}
String pathParam = ApplicationConstants.V_RESOURCE_PATH + "="
+ URL.encodeQueryString(path);
- url = addGetParameters(url, pathParam);
- uidlUri = url;
+ serviceUrl = addGetParameters(serviceUrl, pathParam);
+ uidlUri = serviceUrl;
} else {
- uidlUri = getAppUri() + relativeUrl;
+ uidlUri = serviceUrl + relativeUrl;
}
}
return uidlUri;
import com.google.gwt.core.client.GWT;
import com.google.gwt.core.client.Scheduler;
import com.google.gwt.core.client.Scheduler.RepeatingCommand;
-import com.google.gwt.dom.client.AnchorElement;
import com.google.gwt.dom.client.Document;
import com.google.gwt.dom.client.Element;
import com.google.gwt.dom.client.LinkElement;
*/
public void loadScript(final String scriptUrl,
final ResourceLoadListener resourceLoadListener) {
- final String url = getAbsoluteUrl(scriptUrl);
+ final String url = Util.getAbsoluteUrl(scriptUrl);
ResourceLoadEvent event = new ResourceLoadEvent(this, url, false);
if (loadedResources.contains(url)) {
if (resourceLoadListener != null) {
}
}
- private static String getAbsoluteUrl(String url) {
- AnchorElement a = Document.get().createAnchorElement();
- a.setHref(url);
- return a.getHref();
- }
-
/**
* Download a resource and notify a listener when the resource is loaded
* without attempting to interpret the resource. When a resource has been
*/
public void preloadResource(String url,
ResourceLoadListener resourceLoadListener) {
- url = getAbsoluteUrl(url);
+ url = Util.getAbsoluteUrl(url);
ResourceLoadEvent event = new ResourceLoadEvent(this, url, true);
if (loadedResources.contains(url) || preloadedResources.contains(url)) {
// Already loaded or preloaded -> just fire listener
*/
public void loadStylesheet(final String stylesheetUrl,
final ResourceLoadListener resourceLoadListener) {
- final String url = getAbsoluteUrl(stylesheetUrl);
+ final String url = Util.getAbsoluteUrl(stylesheetUrl);
final ResourceLoadEvent event = new ResourceLoadEvent(this, url, false);
if (loadedResources.contains(url)) {
if (resourceLoadListener != null) {
import com.google.gwt.core.client.Scheduler;
import com.google.gwt.core.client.Scheduler.ScheduledCommand;
+import com.google.gwt.dom.client.AnchorElement;
import com.google.gwt.dom.client.Document;
import com.google.gwt.dom.client.NativeEvent;
import com.google.gwt.dom.client.Node;
}
return getSimpleName(p) + " (" + p.getConnectorId() + ")";
}
+
+ /**
+ * Resolve a relative URL to an absolute URL based on the current document's
+ * location.
+ *
+ * @param url
+ * a string with the relative URL to resolve
+ * @return the corresponding absolute URL as a string
+ */
+ public static String getAbsoluteUrl(String url) {
+ AnchorElement a = Document.get().createAnchorElement();
+ a.setHref(url);
+ return a.getHref();
+ }
}
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;
public String getAppId() {
if (appId == null) {
- appId = getApplicationId(this);
+ appId = getRequest().getService().getMainDivId(getSession(),
+ getRequest(), getUIClass());
}
return appId;
}
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();
String themeName = context.getThemeName();
if (themeName != null) {
- appConfig.put("themeUri", getThemeUri(context, themeName));
+ appConfig.put("theme", themeName);
}
JSONObject versionInfo = new JSONObject();
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());
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);
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.
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
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
*/
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
@Override
public String getRequestPathInfo() {
- return secondRequest.getParameter("initialPath");
+ return secondRequest.getRequestPathInfo();
}
@Override
package com.vaadin.server;
import java.io.InputStream;
-import java.net.MalformedURLException;
-import java.net.URL;
import javax.servlet.ServletContext;
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
}
private boolean isCleanupRequest(HttpServletRequest request) {
- String path = getRequestPathInfo(request);
+ String path = request.getPathInfo();
if (path != null && path.equals(CLEANUP_PATH)) {
return true;
}
}
@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) {
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;
}
import javax.portlet.PortletRequest;
import com.vaadin.server.VaadinPortlet.RequestType;
+import com.vaadin.ui.UI;
public class VaadinPortletService extends VaadinService {
private final VaadinPortlet portlet;
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();
+ }
+}
}
}
+
+ /**
+ * 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);
}
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;
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;
}
// 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
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;
+ }
+}
@Deprecated
public static final String UPDATE_VARIABLE_METHOD = "v";
- public static final String PORTLET_RESOUCE_URL_BASE = "portletAppURLBase";
+ public static final String SERVICE_URL = "serviceUrl";
+
+ public static final String SERVICE_URL_PATH_AS_PARAMETER = "usePathParameter";
public static final String V_RESOURCE_PATH = "v-resourcePath";
* changes.
*/
public static final String URL_PARAMETER_REPAINT_ALL = "repaintAll";
+
+ /**
+ * 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
+ * vaadinBootstrap.js.
+ * </p>
+ */
+ public static final String VAADIN_DIR_URL = "vaadinDir";
}
mapping problem) -->
<dependency org="org.eclipse.jetty" name="jetty-server"
rev="7.4.5.v20110725" conf="build-provided, ide, jetty-run->default" />
+ <dependency org="org.eclipse.jetty" name="jetty-servlets"
+ rev="7.4.5.v20110725" conf="build-provided, ide, jetty-run->default" />
<!-- <dependency org="org.mortbay.jetty" name="jetty-util" -->
<!-- rev="8.1.5.v20120716" conf="build,ide,jetty-run->default" /> -->
<dependency org="org.eclipse.jetty" name="jetty-webapp"
import javax.servlet.http.HttpServletResponse;
import com.vaadin.LegacyApplication;
-import com.vaadin.server.DeploymentConfiguration;
import com.vaadin.server.LegacyVaadinServlet;
import com.vaadin.server.ServiceException;
import com.vaadin.server.SessionInitEvent;
import com.vaadin.server.VaadinRequest;
import com.vaadin.server.VaadinServiceSession;
import com.vaadin.server.VaadinServletRequest;
-import com.vaadin.server.VaadinServletService;
import com.vaadin.tests.components.TestBase;
import com.vaadin.ui.UI;
return getApplicationRunnerURIs(request).applicationClassname;
}
+ // TODO Don't need to use a data object now that there's only one field
private static class URIS {
- String staticFilesPath;
+ // String staticFilesPath;
// String applicationURI;
// String context;
// String runner;
private static URIS getApplicationRunnerURIs(HttpServletRequest request) {
final String[] urlParts = request.getRequestURI().toString()
.split("\\/");
- String context = null;
// String runner = null;
URIS uris = new URIS();
String applicationClassname = null;
String contextPath = request.getContextPath();
if (urlParts[1].equals(contextPath.replaceAll("\\/", ""))) {
// class name comes after web context and runner application
- context = urlParts[1];
// runner = urlParts[2];
if (urlParts.length == 3) {
throw new IllegalArgumentException("No application specified");
}
applicationClassname = urlParts[3];
- uris.staticFilesPath = "/" + context;
// uris.applicationURI = "/" + context + "/" + runner + "/"
// + applicationClassname;
// uris.context = context;
uris.applicationClassname = applicationClassname;
} else {
// no context
- context = "";
// runner = urlParts[1];
if (urlParts.length == 2) {
throw new IllegalArgumentException("No application specified");
}
applicationClassname = urlParts[2];
- uris.staticFilesPath = "/";
// uris.applicationURI = "/" + runner + "/" + applicationClassname;
// uris.context = context;
// uris.runner = runner;
throw new ClassNotFoundException();
}
- @Override
- protected String getRequestPathInfo(HttpServletRequest request) {
- String path = request.getPathInfo();
- if (path == null) {
- return null;
- }
-
- path = path.substring(1 + getApplicationRunnerApplicationClassName(
- request).length());
- return path;
- }
-
- @Override
- protected VaadinServletService createServletService(
- DeploymentConfiguration deploymentConfiguration) {
- return new VaadinServletService(this, deploymentConfiguration) {
- @Override
- public String getStaticFileLocation(VaadinRequest request) {
- URIS uris = getApplicationRunnerURIs(VaadinServletRequest
- .cast(request));
- String staticFilesPath = uris.staticFilesPath;
- if (staticFilesPath.equals("/")) {
- staticFilesPath = "";
- }
-
- return staticFilesPath;
- }
- };
- }
-
- @Override
- protected VaadinServletRequest createVaadinRequest(
- HttpServletRequest request) {
- return new VaadinServletRequest(request, getService()) {
- @Override
- public String getRequestPathInfo() {
- return ApplicationRunnerServlet.this.getRequestPathInfo(this);
- }
- };
- }
-
private Logger getLogger() {
return Logger.getLogger(ApplicationRunnerServlet.class.getName());
}
--- /dev/null
+<?xml version="1.0" encoding="UTF-8"?>
+<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
+<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en" lang="en">
+<head profile="http://selenium-ide.openqa.org/profiles/test-case">
+<meta http-equiv="Content-Type" content="text/html; charset=UTF-8" />
+<link rel="selenium.base" href="" />
+<title>AddAndRemoveTabs</title>
+</head>
+<body>
+<table cellpadding="1" cellspacing="1" border="1">
+<thead>
+<tr><td rowspan="1" colspan="3">AddAndRemoveTabs</td></tr>
+</thead><tbody>
+<tr>
+ <td>open</td>
+ <td>/run/com.vaadin.tests.integration.ProxyTest?restartApplication</td>
+ <td></td>
+</tr>
+<tr>
+ <td>click</td>
+ <td>vaadin=runcomvaadintestsintegrationProxyTest::/VVerticalLayout[0]/VOrderedLayout$Slot[1]/VVerticalLayout[0]/VOrderedLayout$Slot[0]/VButton[0]/domChild[0]/domChild[0]</td>
+ <td></td>
+</tr>
+<tr>
+ <td>click</td>
+ <td>vaadin=runcomvaadintestsintegrationProxyTest::/VVerticalLayout[0]/VOrderedLayout$Slot[1]/VVerticalLayout[0]/VOrderedLayout$Slot[2]/VVerticalLayout[0]/VOrderedLayout$Slot[0]/VLink[0]/domChild[0]/domChild[0]</td>
+ <td></td>
+</tr>
+<tr>
+ <td>pause</td>
+ <td></td>
+ <td>2000</td>
+</tr>
+<tr>
+ <td>assertText</td>
+ <td>vaadin=embed1::/VVerticalLayout[0]/VOrderedLayout$Slot[0]/VLabel[0]</td>
+ <td>A generic test for Buttons in different configurations</td>
+</tr>
+<tr>
+ <td>mouseClick</td>
+ <td>vaadin=embed1::/VVerticalLayout[0]/VOrderedLayout$Slot[1]/VVerticalLayout[0]/VOrderedLayout$Slot[0]/VHorizontalLayout[0]/VOrderedLayout$Slot[0]/VCheckBox[0]/domChild[0]</td>
+ <td>5,5</td>
+</tr>
+<tr>
+ <td>assertCSSClass</td>
+ <td>vaadin=embed1::/VVerticalLayout[0]/VOrderedLayout$Slot[1]/VVerticalLayout[0]/VOrderedLayout$Slot[1]/VButton[0]</td>
+ <td>v-disabled</td>
+</tr>
+<tr>
+ <td>open</td>
+ <td>/run/com.vaadin.tests.integration.ProxyTest</td>
+ <td></td>
+</tr>
+<tr>
+ <td>click</td>
+ <td>vaadin=runcomvaadintestsintegrationProxyTest::/VVerticalLayout[0]/VOrderedLayout$Slot[1]/VVerticalLayout[0]/VOrderedLayout$Slot[2]/VVerticalLayout[0]/VOrderedLayout$Slot[1]/VLink[0]/domChild[0]/domChild[0]</td>
+ <td></td>
+</tr>
+<tr>
+ <td>pause</td>
+ <td></td>
+ <td>2000</td>
+</tr>
+<tr>
+ <td>mouseClick</td>
+ <td>vaadin=embed1::/VVerticalLayout[0]/VOrderedLayout$Slot[1]/VVerticalLayout[0]/VOrderedLayout$Slot[0]/VHorizontalLayout[0]/VOrderedLayout$Slot[0]/VCheckBox[0]/domChild[0]</td>
+ <td>7,5</td>
+</tr>
+<tr>
+ <td>assertNotCSSClass</td>
+ <td>vaadin=embed1::/VVerticalLayout[0]/VOrderedLayout$Slot[1]/VVerticalLayout[0]/VOrderedLayout$Slot[1]/VButton[0]</td>
+ <td>v-disabled</td>
+</tr>
+<tr>
+ <td>open</td>
+ <td>/run/com.vaadin.tests.integration.ProxyTest</td>
+ <td></td>
+</tr>
+<tr>
+ <td>click</td>
+ <td>vaadin=runcomvaadintestsintegrationProxyTest::/VVerticalLayout[0]/VOrderedLayout$Slot[1]/VVerticalLayout[0]/VOrderedLayout$Slot[2]/VVerticalLayout[0]/VOrderedLayout$Slot[2]/VLink[0]/domChild[0]/domChild[0]</td>
+ <td></td>
+</tr>
+<tr>
+ <td>pause</td>
+ <td></td>
+ <td>2000</td>
+</tr>
+<tr>
+ <td>mouseClick</td>
+ <td>vaadin=runcomvaadintestscomponentsbuttonButtons::/VVerticalLayout[0]/VOrderedLayout$Slot[1]/VVerticalLayout[0]/VOrderedLayout$Slot[0]/VHorizontalLayout[0]/VOrderedLayout$Slot[0]/VCheckBox[0]/domChild[0]</td>
+ <td>35,7</td>
+</tr>
+<tr>
+ <td>assertCSSClass</td>
+ <td>vaadin=runcomvaadintestscomponentsbuttonButtons::/VVerticalLayout[0]/VOrderedLayout$Slot[1]/VVerticalLayout[0]/VOrderedLayout$Slot[1]/VButton[0]</td>
+ <td>v-disabled</td>
+</tr>
+<tr>
+ <td>open</td>
+ <td>/run/com.vaadin.tests.integration.ProxyTest</td>
+ <td></td>
+</tr>
+<tr>
+ <td>click</td>
+ <td>vaadin=runcomvaadintestsintegrationProxyTest::/VVerticalLayout[0]/VOrderedLayout$Slot[1]/VVerticalLayout[0]/VOrderedLayout$Slot[1]/VButton[0]/domChild[0]/domChild[0]</td>
+ <td></td>
+</tr>
+</tbody></table>
+</body>
+</html>
--- /dev/null
+/*
+ * Copyright 2011 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.integration;
+
+import javax.servlet.http.HttpServletRequest;
+
+import org.eclipse.jetty.server.Connector;
+import org.eclipse.jetty.server.Server;
+import org.eclipse.jetty.server.nio.SelectChannelConnector;
+import org.eclipse.jetty.servlet.ServletContextHandler;
+import org.eclipse.jetty.servlet.ServletHolder;
+import org.eclipse.jetty.servlets.ProxyServlet;
+
+import com.vaadin.annotations.PreserveOnRefresh;
+import com.vaadin.server.ExternalResource;
+import com.vaadin.server.VaadinRequest;
+import com.vaadin.server.VaadinServletService;
+import com.vaadin.tests.components.AbstractTestUI;
+import com.vaadin.ui.Button;
+import com.vaadin.ui.Button.ClickEvent;
+import com.vaadin.ui.Link;
+import com.vaadin.ui.VerticalLayout;
+
+@PreserveOnRefresh
+public class ProxyTest extends AbstractTestUI {
+
+ private Server server;
+
+ private final Button startButton = new Button("Start proxy",
+ new Button.ClickListener() {
+ @Override
+ public void buttonClick(ClickEvent event) {
+ startProxy();
+ stopButton.setEnabled(true);
+ }
+ });
+ private final Button stopButton = new Button("Stop proxy",
+ new Button.ClickListener() {
+ @Override
+ public void buttonClick(ClickEvent event) {
+ stopProxy();
+ startButton.setEnabled(true);
+ }
+ });
+ private VerticalLayout linkHolder = new VerticalLayout();
+
+ @Override
+ protected void setup(VaadinRequest request) {
+ stopButton.setDisableOnClick(true);
+ stopButton.setEnabled(false);
+ startButton.setDisableOnClick(true);
+
+ addCleanupListener(new CleanupListener() {
+ @Override
+ public void cleanup(CleanupEvent event) {
+ if (server != null && server.isRunning()) {
+ try {
+ server.stop();
+ } catch (Exception e) {
+ throw new RuntimeException(e);
+ }
+ }
+ }
+ });
+
+ addComponent(startButton);
+ addComponent(stopButton);
+ addComponent(linkHolder);
+ }
+
+ private void startProxy() {
+ HttpServletRequest request = VaadinServletService
+ .getCurrentServletRequest();
+
+ // Set up a server
+ server = new Server();
+ SelectChannelConnector connector = new SelectChannelConnector();
+ // Uses random available port by default, uncomment this to make local
+ // testing easier (you can just reload old tab after restarting proxy)
+ // connector.setPort(8889);
+ server.setConnectors(new Connector[] { connector });
+
+ // Create root context and add the ProxyServlet.Transparent to it
+ ServletContextHandler contextHandler = new ServletContextHandler();
+ server.setHandler(contextHandler);
+ contextHandler.setContextPath("/");
+ ServletHolder servletHolder = contextHandler.addServlet(
+ ProxyServlet.Transparent.class, "/*");
+
+ // Configure servlet to forward to the root of the original server
+ servletHolder.setInitParameter(
+ "ProxyTo",
+ "http://" + request.getLocalAddr() + ":"
+ + request.getLocalPort() + "/");
+ // Configure servlet to strip beginning of paths
+ servletHolder.setInitParameter("Prefix", "/proxypath/");
+
+ // Start the server
+ try {
+ server.start();
+ } catch (Exception e) {
+ throw new RuntimeException(e);
+ }
+
+ // Add links to some proxied urls to tests
+ String linkBase = "http://" + request.getLocalName() + ":"
+ + connector.getLocalPort() + "/proxypath/";
+
+ linkHolder.removeAllComponents();
+ linkHolder.addComponent(new Link("Open embed1 in proxy",
+ new ExternalResource(linkBase + "embed1")));
+ linkHolder.addComponent(new Link("Open embed1/ in proxy",
+ new ExternalResource(linkBase + "embed1/")));
+ linkHolder.addComponent(new Link("Open Buttons in proxy",
+ new ExternalResource(linkBase
+ + "run/com.vaadin.tests.components.button.Buttons")));
+
+ }
+
+ private void stopProxy() {
+ linkHolder.removeAllComponents();
+ try {
+ server.stop();
+ } catch (Exception e) {
+ throw new RuntimeException(e);
+ }
+ server.destroy();
+ server = null;
+ }
+
+ @Override
+ protected String getTestDescription() {
+ return "Test UI for starting an embedded Jetty on a different port that proxies requests back to the original server using a different path.";
+ }
+
+ @Override
+ protected Integer getTicketNumber() {
+ return Integer.valueOf(6771);
+ }
+
+}