aboutsummaryrefslogtreecommitdiffstats
path: root/src/com/vaadin/terminal/gwt/client/ApplicationConnection.java
diff options
context:
space:
mode:
Diffstat (limited to 'src/com/vaadin/terminal/gwt/client/ApplicationConnection.java')
-rw-r--r--src/com/vaadin/terminal/gwt/client/ApplicationConnection.java250
1 files changed, 143 insertions, 107 deletions
diff --git a/src/com/vaadin/terminal/gwt/client/ApplicationConnection.java b/src/com/vaadin/terminal/gwt/client/ApplicationConnection.java
index f0470c8ee8..fb7af1404c 100644
--- a/src/com/vaadin/terminal/gwt/client/ApplicationConnection.java
+++ b/src/com/vaadin/terminal/gwt/client/ApplicationConnection.java
@@ -27,6 +27,7 @@ import com.google.gwt.http.client.RequestBuilder;
import com.google.gwt.http.client.RequestCallback;
import com.google.gwt.http.client.RequestException;
import com.google.gwt.http.client.Response;
+import com.google.gwt.http.client.URL;
import com.google.gwt.json.client.JSONArray;
import com.google.gwt.json.client.JSONObject;
import com.google.gwt.json.client.JSONString;
@@ -35,21 +36,23 @@ import com.google.gwt.regexp.shared.RegExp;
import com.google.gwt.user.client.Command;
import com.google.gwt.user.client.DOM;
import com.google.gwt.user.client.Element;
-import com.google.gwt.user.client.Event;
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.shared.ComponentState;
+import com.vaadin.shared.communication.MethodInvocation;
+import com.vaadin.shared.communication.SharedState;
+import com.vaadin.shared.communication.UidlValue;
import com.vaadin.terminal.gwt.client.ApplicationConfiguration.ErrorMessage;
+import com.vaadin.terminal.gwt.client.ResourceLoader.ResourceLoadEvent;
+import com.vaadin.terminal.gwt.client.ResourceLoader.ResourceLoadListener;
import com.vaadin.terminal.gwt.client.communication.HasJavaScriptConnectorHelper;
import com.vaadin.terminal.gwt.client.communication.JsonDecoder;
import com.vaadin.terminal.gwt.client.communication.JsonEncoder;
-import com.vaadin.terminal.gwt.client.communication.MethodInvocation;
import com.vaadin.terminal.gwt.client.communication.RpcManager;
import com.vaadin.terminal.gwt.client.communication.SerializerMap;
-import com.vaadin.terminal.gwt.client.communication.SharedState;
import com.vaadin.terminal.gwt.client.communication.StateChangeEvent;
import com.vaadin.terminal.gwt.client.communication.Type;
-import com.vaadin.terminal.gwt.client.communication.UidlValue;
import com.vaadin.terminal.gwt.client.extensions.AbstractExtensionConnector;
import com.vaadin.terminal.gwt.client.ui.AbstractComponentConnector;
import com.vaadin.terminal.gwt.client.ui.VContextMenu;
@@ -75,6 +78,19 @@ import com.vaadin.terminal.gwt.server.AbstractCommunicationManager;
* Entry point classes (widgetsets) define <code>onModuleLoad()</code>.
*/
public class ApplicationConnection {
+ public static final String APP_REQUEST_PATH = "APP/";
+
+ public static final String UIDL_REQUEST_PATH = "UIDL/";
+
+ public static final String APP_PROTOCOL_PREFIX = "app://";
+
+ public static final String V_RESOURCE_PATH = "v-resourcePath";
+
+ public static final String CONNECTOR_PROTOCOL_PREFIX = "connector://";
+
+ public static final String CONNECTOR_RESOURCE_PREFIX = APP_REQUEST_PATH
+ + "CONNECTOR";
+
// This indicates the whole page is generated by us (not embedded)
public static final String GENERATED_BODY_CLASSNAME = "v-generated-body";
@@ -131,7 +147,7 @@ public class ApplicationConnection {
*/
public static final String UIDL_REFRESH_TOKEN = "Vaadin-Refresh";
- private final boolean debugLogging = false;
+ private final boolean debugLogging = true || false;
// will hold the UIDL security key (for XSS protection) once received
private String uidlSecurityKey = "init";
@@ -506,12 +522,7 @@ public class ApplicationConnection {
final String payload = uidlSecurityKey + VAR_BURST_SEPARATOR
+ requestData;
VConsole.log("Making UIDL Request with params: " + payload);
- String uri;
- if (configuration.usePortletURLs()) {
- uri = configuration.getPortletUidlURLBase();
- } else {
- uri = getAppUri() + "UIDL";
- }
+ String uri = translateVaadinUri(APP_PROTOCOL_PREFIX + UIDL_REQUEST_PATH);
if (extraParams != null && extraParams.length() > 0) {
uri = addGetParameters(uri, extraParams);
@@ -538,11 +549,13 @@ public class ApplicationConnection {
final boolean synchronous) {
if (!synchronous) {
RequestCallback requestCallback = new RequestCallback() {
+ @Override
public void onError(Request request, Throwable exception) {
showCommunicationError(exception.getMessage(), -1);
endRequest();
}
+ @Override
public void onResponseReceived(Request request,
Response response) {
VConsole.log("Server visit took "
@@ -868,6 +881,7 @@ public class ApplicationConnection {
}
// deferring to avoid flickering
Scheduler.get().scheduleDeferred(new Command() {
+ @Override
public void execute() {
if (!hasActiveRequest()) {
hideLoadingIndicator();
@@ -1067,6 +1081,14 @@ public class ApplicationConnection {
json.getValueMap("typeMappings"), widgetSet);
}
+ VConsole.log("Handling resource dependencies");
+ if (json.containsKey("scriptDependencies")) {
+ loadScriptDependencies(json.getJSStringArray("scriptDependencies"));
+ }
+ if (json.containsKey("styleDependencies")) {
+ loadStyleDependencies(json.getJSStringArray("styleDependencies"));
+ }
+
handleUIDLDuration.logDuration(
" * Handling type mappings from server completed", 10);
/*
@@ -1077,6 +1099,7 @@ public class ApplicationConnection {
}
Command c = new Command() {
+ @Override
public void execute() {
handleUIDLDuration.logDuration(" * Loading widgets completed",
10);
@@ -1608,7 +1631,72 @@ public class ApplicationConnection {
}
};
- ApplicationConfiguration.runWhenWidgetsLoaded(c);
+ ApplicationConfiguration.runWhenDependenciesLoaded(c);
+ }
+
+ private void loadStyleDependencies(JsArrayString dependencies) {
+ // Assuming no reason to interpret in a defined order
+ ResourceLoadListener resourceLoadListener = new ResourceLoadListener() {
+ @Override
+ public void onLoad(ResourceLoadEvent event) {
+ ApplicationConfiguration.endDependencyLoading();
+ }
+
+ @Override
+ public void onError(ResourceLoadEvent event) {
+ VConsole.error(event.getResourceUrl()
+ + " could not be loaded, or the load detection failed because the stylesheet is empty.");
+ // The show must go on
+ onLoad(event);
+ }
+ };
+ ResourceLoader loader = ResourceLoader.get();
+ for (int i = 0; i < dependencies.length(); i++) {
+ String url = translateVaadinUri(dependencies.get(i));
+ ApplicationConfiguration.startDependencyLoading();
+ loader.loadStylesheet(url, resourceLoadListener);
+ }
+ }
+
+ private void loadScriptDependencies(final JsArrayString dependencies) {
+ if (dependencies.length() == 0) {
+ return;
+ }
+
+ // Listener that loads the next when one is completed
+ ResourceLoadListener resourceLoadListener = new ResourceLoadListener() {
+ @Override
+ public void onLoad(ResourceLoadEvent event) {
+ if (dependencies.length() != 0) {
+ String url = translateVaadinUri(dependencies.shift());
+ ApplicationConfiguration.startDependencyLoading();
+ // Load next in chain (hopefully already preloaded)
+ event.getResourceLoader().loadScript(url, this);
+ }
+ // Call start for next before calling end for current
+ ApplicationConfiguration.endDependencyLoading();
+ }
+
+ @Override
+ public void onError(ResourceLoadEvent event) {
+ VConsole.error(event.getResourceUrl() + " could not be loaded.");
+ // The show must go on
+ onLoad(event);
+ }
+ };
+
+ ResourceLoader loader = ResourceLoader.get();
+
+ // Start chain by loading first
+ String url = translateVaadinUri(dependencies.shift());
+ ApplicationConfiguration.startDependencyLoading();
+ loader.loadScript(url, resourceLoadListener);
+
+ // Preload all remaining
+ for (int i = 0; i < dependencies.length(); i++) {
+ String preloadUrl = translateVaadinUri(dependencies.get(i));
+ loader.preloadResource(preloadUrl, null);
+ }
}
// Redirect browser, null reloads current page
@@ -1669,6 +1757,7 @@ public class ApplicationConnection {
}
private final ScheduledCommand sendPendingCommand = new ScheduledCommand() {
+ @Override
public void execute() {
deferedSendPending = false;
doSendPendingVariableChanges();
@@ -2214,8 +2303,42 @@ public class ApplicationConnection {
}
uidlUri = themeUri + uidlUri.substring(7);
}
- if (uidlUri.startsWith("app://")) {
- uidlUri = getAppUri() + uidlUri.substring(6);
+
+ if (uidlUri.startsWith(CONNECTOR_PROTOCOL_PREFIX)) {
+ // getAppUri *should* always end with /
+ // substring *should* always start with / (connector:///foo.bar
+ // without connector://)
+ uidlUri = APP_PROTOCOL_PREFIX + CONNECTOR_RESOURCE_PREFIX
+ + uidlUri.substring(CONNECTOR_PROTOCOL_PREFIX.length());
+ // Let translation of app:// urls take care of the rest
+ }
+ if (uidlUri.startsWith(APP_PROTOCOL_PREFIX)) {
+ String relativeUrl = uidlUri
+ .substring(APP_PROTOCOL_PREFIX.length());
+ if (getConfiguration().usePortletURLs()) {
+ // 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);
+ }
+ if (!path.startsWith("/")) {
+ path = '/' + path;
+ }
+ String pathParam = V_RESOURCE_PATH + "="
+ + URL.encodeQueryString(path);
+ url = addGetParameters(url, pathParam);
+ uidlUri = url;
+ } else {
+ uidlUri = getAppUri() + relativeUrl;
+ }
}
return uidlUri;
}
@@ -2242,6 +2365,7 @@ public class ApplicationConnection {
this.url = url;
}
+ @Override
public void notificationHidden(HideEvent event) {
redirect(url);
}
@@ -2250,57 +2374,8 @@ public class ApplicationConnection {
/* Extended title handling */
- /**
- * Data showed in tooltips are stored centrilized as it may be needed in
- * varios place: caption, layouts, and in owner components themselves.
- *
- * Updating TooltipInfo is done in updateComponent method.
- *
- */
- public TooltipInfo getTooltipTitleInfo(ComponentConnector titleOwner,
- Object key) {
- if (null == titleOwner) {
- return null;
- }
- return connectorMap.getTooltipInfo(titleOwner, key);
- }
-
private final VTooltip tooltip = new VTooltip(this);
- /**
- * Component may want to delegate Tooltip handling to client. Layouts add
- * Tooltip (description, errors) to caption, but some components may want
- * them to appear one other elements too.
- *
- * Events wanted by this handler are same as in Tooltip.TOOLTIP_EVENTS
- *
- * @param event
- * @param owner
- */
- public void handleTooltipEvent(Event event, ComponentConnector owner) {
- tooltip.handleTooltipEvent(event, owner, null);
-
- }
-
- /**
- * Component may want to delegate Tooltip handling to client. Layouts add
- * Tooltip (description, errors) to caption, but some components may want
- * them to appear one other elements too.
- *
- * Events wanted by this handler are same as in Tooltip.TOOLTIP_EVENTS
- *
- * @param event
- * @param owner
- * @param key
- * the key for tooltip if this is "additional" tooltip, null for
- * components "main tooltip"
- */
- public void handleTooltipEvent(Event event, ComponentConnector owner,
- Object key) {
- tooltip.handleTooltipEvent(event, owner, key);
-
- }
-
private ConnectorMap connectorMap = GWT.create(ConnectorMap.class);
protected String getUidlSecurityKey() {
@@ -2328,34 +2403,6 @@ public class ApplicationConnection {
}
/**
- * If component has several tooltips in addition to the one provided by
- * {@link com.vaadin.ui.AbstractComponent}, component can register them with
- * this method.
- * <p>
- * Component must also pipe events to
- * {@link #handleTooltipEvent(Event, ComponentConnector, Object)} method.
- * <p>
- * This method can also be used to deregister tooltips by using null as
- * tooltip
- *
- * @param paintable
- * Paintable "owning" this tooltip
- * @param key
- * key assosiated with given tooltip. Can be any object. For
- * example a related dom element. Same key must be given for
- * {@link #handleTooltipEvent(Event, ComponentConnector, Object)}
- * method.
- *
- * @param tooltip
- * the TooltipInfo object containing details shown in tooltip,
- * null if deregistering tooltip
- */
- public void registerTooltip(ComponentConnector paintable, Object key,
- TooltipInfo tooltip) {
- connectorMap.registerTooltip(paintable, key, tooltip);
- }
-
- /**
* Gets the {@link ApplicationConfiguration} for the current application.
*
* @see ApplicationConfiguration
@@ -2437,15 +2484,15 @@ public class ApplicationConnection {
// connectorMap.unregisterConnector(p);
}
+ /**
+ * Get VTooltip instance related to application connection
+ *
+ * @return VTooltip instance
+ */
public VTooltip getVTooltip() {
return tooltip;
}
- @Deprecated
- public void handleTooltipEvent(Event event, Widget owner, Object key) {
- handleTooltipEvent(event, getConnectorMap().getConnector(owner), key);
- }
-
/**
* Method provided for backwards compatibility. Duties previously done by
* this method is now handled by the state change event handler in
@@ -2474,17 +2521,6 @@ public class ApplicationConnection {
}
@Deprecated
- public void handleTooltipEvent(Event event, Widget owner) {
- handleTooltipEvent(event, getConnectorMap().getConnector(owner));
-
- }
-
- @Deprecated
- public void registerTooltip(Widget owner, Object key, TooltipInfo info) {
- registerTooltip(getConnectorMap().getConnector(owner), key, info);
- }
-
- @Deprecated
public boolean hasEventListeners(Widget widget, String eventIdentifier) {
return hasEventListeners(getConnectorMap().getConnector(widget),
eventIdentifier);