You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

ApplicationConnection.java 53KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036103710381039104010411042104310441045104610471048104910501051105210531054105510561057105810591060106110621063106410651066106710681069107010711072107310741075107610771078107910801081108210831084108510861087108810891090109110921093109410951096109710981099110011011102110311041105110611071108110911101111111211131114111511161117111811191120112111221123112411251126112711281129113011311132113311341135113611371138113911401141114211431144114511461147114811491150115111521153115411551156115711581159116011611162116311641165116611671168116911701171117211731174117511761177117811791180118111821183118411851186118711881189119011911192119311941195119611971198119912001201120212031204120512061207120812091210121112121213121412151216121712181219122012211222122312241225122612271228122912301231123212331234123512361237123812391240124112421243124412451246124712481249125012511252125312541255125612571258125912601261126212631264126512661267126812691270127112721273127412751276127712781279128012811282128312841285128612871288128912901291129212931294129512961297129812991300130113021303130413051306130713081309131013111312131313141315131613171318131913201321132213231324132513261327132813291330133113321333133413351336133713381339134013411342134313441345134613471348134913501351135213531354135513561357135813591360136113621363136413651366136713681369137013711372137313741375137613771378137913801381138213831384138513861387138813891390139113921393139413951396139713981399140014011402140314041405140614071408140914101411141214131414141514161417141814191420142114221423142414251426142714281429143014311432143314341435143614371438143914401441144214431444144514461447144814491450145114521453145414551456145714581459146014611462146314641465146614671468146914701471147214731474147514761477147814791480148114821483148414851486148714881489149014911492149314941495149614971498149915001501150215031504150515061507150815091510151115121513151415151516151715181519152015211522152315241525152615271528152915301531153215331534153515361537153815391540154115421543154415451546154715481549155015511552155315541555155615571558155915601561156215631564156515661567156815691570157115721573157415751576157715781579158015811582158315841585
  1. /*
  2. * Copyright 2000-2018 Vaadin Ltd.
  3. *
  4. * Licensed under the Apache License, Version 2.0 (the "License"); you may not
  5. * use this file except in compliance with the License. You may obtain a copy of
  6. * the License at
  7. *
  8. * http://www.apache.org/licenses/LICENSE-2.0
  9. *
  10. * Unless required by applicable law or agreed to in writing, software
  11. * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
  12. * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
  13. * License for the specific language governing permissions and limitations under
  14. * the License.
  15. */
  16. package com.vaadin.client;
  17. import java.util.HashMap;
  18. import java.util.Map;
  19. import java.util.logging.Logger;
  20. import com.google.gwt.aria.client.LiveValue;
  21. import com.google.gwt.aria.client.RelevantValue;
  22. import com.google.gwt.aria.client.Roles;
  23. import com.google.gwt.core.client.Duration;
  24. import com.google.gwt.core.client.GWT;
  25. import com.google.gwt.core.client.JavaScriptObject;
  26. import com.google.gwt.core.client.Scheduler;
  27. import com.google.gwt.dom.client.Element;
  28. import com.google.gwt.event.shared.EventBus;
  29. import com.google.gwt.event.shared.EventHandler;
  30. import com.google.gwt.event.shared.GwtEvent;
  31. import com.google.gwt.event.shared.HandlerRegistration;
  32. import com.google.gwt.event.shared.HasHandlers;
  33. import com.google.gwt.event.shared.SimpleEventBus;
  34. import com.google.gwt.http.client.URL;
  35. import com.google.gwt.user.client.Command;
  36. import com.google.gwt.user.client.DOM;
  37. import com.google.gwt.user.client.Timer;
  38. import com.google.gwt.user.client.ui.HasWidgets;
  39. import com.google.gwt.user.client.ui.RootPanel;
  40. import com.google.gwt.user.client.ui.Widget;
  41. import com.vaadin.client.ApplicationConfiguration.ErrorMessage;
  42. import com.vaadin.client.communication.ConnectionStateHandler;
  43. import com.vaadin.client.communication.Heartbeat;
  44. import com.vaadin.client.communication.MessageHandler;
  45. import com.vaadin.client.communication.MessageSender;
  46. import com.vaadin.client.communication.RpcManager;
  47. import com.vaadin.client.communication.ServerRpcQueue;
  48. import com.vaadin.client.componentlocator.ComponentLocator;
  49. import com.vaadin.client.metadata.ConnectorBundleLoader;
  50. import com.vaadin.client.ui.AbstractComponentConnector;
  51. import com.vaadin.client.ui.AbstractConnector;
  52. import com.vaadin.client.ui.FontIcon;
  53. import com.vaadin.client.ui.Icon;
  54. import com.vaadin.client.ui.ImageIcon;
  55. import com.vaadin.client.ui.VContextMenu;
  56. import com.vaadin.client.ui.VNotification;
  57. import com.vaadin.client.ui.VOverlay;
  58. import com.vaadin.client.ui.ui.UIConnector;
  59. import com.vaadin.shared.VaadinUriResolver;
  60. import com.vaadin.shared.Version;
  61. import com.vaadin.shared.communication.LegacyChangeVariablesInvocation;
  62. import com.vaadin.shared.util.SharedUtil;
  63. /**
  64. * This is the client side communication "engine", managing client-server
  65. * communication with its server side counterpart
  66. * com.vaadin.server.VaadinService.
  67. *
  68. * Client-side connectors receive updates from the corresponding server-side
  69. * connector (typically component) as state updates or RPC calls. The connector
  70. * has the possibility to communicate back with its server side counter part
  71. * through RPC calls.
  72. *
  73. * TODO document better
  74. *
  75. * Entry point classes (widgetsets) define <code>onModuleLoad()</code>.
  76. */
  77. public class ApplicationConnection implements HasHandlers {
  78. @Deprecated
  79. public static final String MODIFIED_CLASSNAME = StyleConstants.MODIFIED;
  80. @Deprecated
  81. public static final String DISABLED_CLASSNAME = StyleConstants.DISABLED;
  82. @Deprecated
  83. public static final String REQUIRED_CLASSNAME = StyleConstants.REQUIRED;
  84. @Deprecated
  85. public static final String REQUIRED_CLASSNAME_EXT = StyleConstants.REQUIRED_EXT;
  86. @Deprecated
  87. public static final String ERROR_CLASSNAME_EXT = StyleConstants.ERROR_EXT;
  88. /**
  89. * A string that, if found in a non-JSON response to a UIDL request, will
  90. * cause the browser to refresh the page. If followed by a colon, optional
  91. * whitespace, and a URI, causes the browser to synchronously load the URI.
  92. *
  93. * <p>
  94. * This allows, for instance, a servlet filter to redirect the application
  95. * to a custom login page when the session expires. For example:
  96. * </p>
  97. *
  98. * <pre>
  99. * if (sessionExpired) {
  100. * response.setHeader(&quot;Content-Type&quot;, &quot;text/html&quot;);
  101. * response.getWriter().write(myLoginPageHtml + &quot;&lt;!-- Vaadin-Refresh: &quot;
  102. * + request.getContextPath() + &quot; --&gt;&quot;);
  103. * }
  104. * </pre>
  105. */
  106. public static final String UIDL_REFRESH_TOKEN = "Vaadin-Refresh";
  107. private final Map<String, String> resourcesMap = new HashMap<>();
  108. private WidgetSet widgetSet;
  109. private VContextMenu contextMenu = null;
  110. private final UIConnector uIConnector;
  111. protected boolean cssLoaded = false;
  112. /** Parameters for this application connection loaded from the web-page */
  113. private ApplicationConfiguration configuration;
  114. private final LayoutManager layoutManager;
  115. private final RpcManager rpcManager;
  116. /** Event bus for communication events */
  117. private EventBus eventBus = GWT.create(SimpleEventBus.class);
  118. public enum ApplicationState {
  119. INITIALIZING, RUNNING, TERMINATED;
  120. }
  121. private ApplicationState applicationState = ApplicationState.INITIALIZING;
  122. /**
  123. * The communication handler methods are called at certain points during
  124. * communication with the server. This allows for making add-ons that keep
  125. * track of different aspects of the communication.
  126. */
  127. public interface CommunicationHandler extends EventHandler {
  128. void onRequestStarting(RequestStartingEvent e);
  129. void onResponseHandlingStarted(ResponseHandlingStartedEvent e);
  130. void onResponseHandlingEnded(ResponseHandlingEndedEvent e);
  131. }
  132. public static class RequestStartingEvent
  133. extends ApplicationConnectionEvent {
  134. public static Type<CommunicationHandler> TYPE = new Type<>();
  135. public RequestStartingEvent(ApplicationConnection connection) {
  136. super(connection);
  137. }
  138. @Override
  139. public Type<CommunicationHandler> getAssociatedType() {
  140. return TYPE;
  141. }
  142. @Override
  143. protected void dispatch(CommunicationHandler handler) {
  144. handler.onRequestStarting(this);
  145. }
  146. }
  147. public static class ResponseHandlingEndedEvent
  148. extends ApplicationConnectionEvent {
  149. public static Type<CommunicationHandler> TYPE = new Type<>();
  150. public ResponseHandlingEndedEvent(ApplicationConnection connection) {
  151. super(connection);
  152. }
  153. @Override
  154. public Type<CommunicationHandler> getAssociatedType() {
  155. return TYPE;
  156. }
  157. @Override
  158. protected void dispatch(CommunicationHandler handler) {
  159. handler.onResponseHandlingEnded(this);
  160. }
  161. }
  162. public abstract static class ApplicationConnectionEvent
  163. extends GwtEvent<CommunicationHandler> {
  164. private ApplicationConnection connection;
  165. protected ApplicationConnectionEvent(ApplicationConnection connection) {
  166. this.connection = connection;
  167. }
  168. public ApplicationConnection getConnection() {
  169. return connection;
  170. }
  171. }
  172. public static class ResponseHandlingStartedEvent
  173. extends ApplicationConnectionEvent {
  174. public ResponseHandlingStartedEvent(ApplicationConnection connection) {
  175. super(connection);
  176. }
  177. public static Type<CommunicationHandler> TYPE = new Type<>();
  178. @Override
  179. public Type<CommunicationHandler> getAssociatedType() {
  180. return TYPE;
  181. }
  182. @Override
  183. protected void dispatch(CommunicationHandler handler) {
  184. handler.onResponseHandlingStarted(this);
  185. }
  186. }
  187. /**
  188. * Event triggered when a application is stopped by calling
  189. * {@link ApplicationConnection#setApplicationRunning(false)}.
  190. *
  191. * To listen for the event add a {@link ApplicationStoppedHandler} by
  192. * invoking
  193. * {@link ApplicationConnection#addHandler(GwtEvent.Type, ApplicationStoppedHandler)}
  194. * to the {@link ApplicationConnection}
  195. *
  196. * @since 7.1.8
  197. * @author Vaadin Ltd
  198. */
  199. public static class ApplicationStoppedEvent
  200. extends GwtEvent<ApplicationStoppedHandler> {
  201. public static Type<ApplicationStoppedHandler> TYPE = new Type<>();
  202. @Override
  203. public Type<ApplicationStoppedHandler> getAssociatedType() {
  204. return TYPE;
  205. }
  206. @Override
  207. protected void dispatch(ApplicationStoppedHandler listener) {
  208. listener.onApplicationStopped(this);
  209. }
  210. }
  211. /**
  212. * Allows custom handling of communication errors.
  213. */
  214. public interface CommunicationErrorHandler {
  215. /**
  216. * Called when a communication error has occurred. Returning
  217. * <code>true</code> from this method suppresses error handling.
  218. *
  219. * @param details
  220. * A string describing the error.
  221. * @param statusCode
  222. * The HTTP status code (e.g. 404, etc).
  223. * @return true if the error reporting should be suppressed, false to
  224. * perform normal error reporting.
  225. */
  226. public boolean onError(String details, int statusCode);
  227. }
  228. /**
  229. * A listener for listening to application stopped events. The listener can
  230. * be added to a {@link ApplicationConnection} by invoking
  231. * {@link ApplicationConnection#addHandler(GwtEvent.Type, ApplicationStoppedHandler)}
  232. *
  233. * @since 7.1.8
  234. * @author Vaadin Ltd
  235. */
  236. public interface ApplicationStoppedHandler extends EventHandler {
  237. /**
  238. * Triggered when the {@link ApplicationConnection} marks a previously
  239. * running application as stopped by invoking
  240. * {@link ApplicationConnection#setApplicationRunning(false)}.
  241. *
  242. * @param event
  243. * the event triggered by the {@link ApplicationConnection}
  244. */
  245. void onApplicationStopped(ApplicationStoppedEvent event);
  246. }
  247. private CommunicationErrorHandler communicationErrorDelegate = null;
  248. private VLoadingIndicator loadingIndicator;
  249. private Heartbeat heartbeat = GWT.create(Heartbeat.class);
  250. private boolean tooltipInitialized = false;
  251. private final VaadinUriResolver uriResolver = new VaadinUriResolver() {
  252. @Override
  253. protected String getVaadinDirUrl() {
  254. return getConfiguration().getVaadinDirUrl();
  255. }
  256. @Override
  257. protected String getServiceUrlParameterName() {
  258. return getConfiguration().getServiceUrlParameterName();
  259. }
  260. @Override
  261. protected String getServiceUrl() {
  262. return getConfiguration().getServiceUrl();
  263. }
  264. @Override
  265. protected String getThemeUri() {
  266. return ApplicationConnection.this.getThemeUri();
  267. }
  268. @Override
  269. protected String encodeQueryStringParameterValue(String queryString) {
  270. return URL.encodeQueryString(queryString);
  271. }
  272. @Override
  273. protected String getContextRootUrl() {
  274. return getConfiguration().getContextRootUrl();
  275. }
  276. @Override
  277. protected String getFrontendUrl() {
  278. String url = getConfiguration().getFrontendUrl();
  279. assert url.endsWith("/");
  280. return url;
  281. }
  282. };
  283. public static class MultiStepDuration extends Duration {
  284. private int previousStep = elapsedMillis();
  285. public void logDuration(String message) {
  286. logDuration(message, 0);
  287. }
  288. public void logDuration(String message, int minDuration) {
  289. int currentTime = elapsedMillis();
  290. int stepDuration = currentTime - previousStep;
  291. if (stepDuration >= minDuration) {
  292. getLogger().info(message + ": " + stepDuration + " ms");
  293. }
  294. previousStep = currentTime;
  295. }
  296. }
  297. public ApplicationConnection() {
  298. // Assuming UI data is eagerly loaded
  299. ConnectorBundleLoader.get()
  300. .loadBundle(ConnectorBundleLoader.EAGER_BUNDLE_NAME, null);
  301. uIConnector = GWT.create(UIConnector.class);
  302. rpcManager = GWT.create(RpcManager.class);
  303. layoutManager = GWT.create(LayoutManager.class);
  304. tooltip = GWT.create(VTooltip.class);
  305. loadingIndicator = GWT.create(VLoadingIndicator.class);
  306. serverRpcQueue = GWT.create(ServerRpcQueue.class);
  307. connectionStateHandler = GWT.create(ConnectionStateHandler.class);
  308. messageHandler = GWT.create(MessageHandler.class);
  309. messageSender = GWT.create(MessageSender.class);
  310. }
  311. public void init(WidgetSet widgetSet, ApplicationConfiguration cnf) {
  312. getLogger().info("Starting application " + cnf.getRootPanelId());
  313. getLogger().info("Using theme: " + cnf.getThemeName());
  314. getLogger().info("Vaadin application servlet version: "
  315. + cnf.getServletVersion());
  316. if (!cnf.getServletVersion().equals(Version.getFullVersion())) {
  317. getLogger().severe(
  318. "Warning: your widget set seems to be built with a different "
  319. + "version than the one used on server. Unexpected "
  320. + "behavior may occur.");
  321. }
  322. this.widgetSet = widgetSet;
  323. configuration = cnf;
  324. layoutManager.setConnection(this);
  325. loadingIndicator.setConnection(this);
  326. serverRpcQueue.setConnection(this);
  327. messageHandler.setConnection(this);
  328. messageSender.setConnection(this);
  329. dependencyLoader.setConnection(this);
  330. ComponentLocator componentLocator = new ComponentLocator(this);
  331. String appRootPanelName = cnf.getRootPanelId();
  332. // remove the end (window name) of autogenerated rootpanel id
  333. appRootPanelName = appRootPanelName.replaceFirst("-\\d+$", "");
  334. initializeTestbenchHooks(componentLocator, appRootPanelName);
  335. initializeClientHooks();
  336. uIConnector.init(cnf.getRootPanelId(), this);
  337. // Connection state handler preloads the reconnect dialog, which uses
  338. // overlay container. This in turn depends on VUI being attached
  339. // (done in uiConnector.init)
  340. connectionStateHandler.setConnection(this);
  341. tooltip.setOwner(uIConnector.getWidget());
  342. getLoadingIndicator().show();
  343. heartbeat.init(this);
  344. // Ensure the overlay container is added to the dom and set as a live
  345. // area for assistive devices
  346. Element overlayContainer = VOverlay.getOverlayContainer(this);
  347. Roles.getAlertRole().setAriaLiveProperty(overlayContainer,
  348. LiveValue.ASSERTIVE);
  349. VOverlay.setOverlayContainerLabel(this,
  350. getUIConnector().getState().overlayContainerLabel);
  351. Roles.getAlertRole().setAriaRelevantProperty(overlayContainer,
  352. RelevantValue.ADDITIONS);
  353. }
  354. /**
  355. * Starts this application. Don't call this method directly - it's called by
  356. * {@link ApplicationConfiguration#startNextApplication()}, which should be
  357. * called once this application has started (first response received) or
  358. * failed to start. This ensures that the applications are started in order,
  359. * to avoid session-id problems.
  360. *
  361. */
  362. public void start() {
  363. String jsonText = configuration.getUIDL();
  364. if (jsonText == null) {
  365. // initial UIDL not in DOM, request from server
  366. getMessageSender().resynchronize();
  367. } else {
  368. // initial UIDL provided in DOM, continue as if returned by request
  369. // Hack to avoid logging an error in endRequest()
  370. getMessageSender().startRequest();
  371. getMessageHandler()
  372. .handleMessage(MessageHandler.parseJson(jsonText));
  373. }
  374. // Tooltip can't be created earlier because the
  375. // necessary fields are not setup to add it in the
  376. // correct place in the DOM
  377. if (!tooltipInitialized) {
  378. tooltipInitialized = true;
  379. ApplicationConfiguration.runWhenDependenciesLoaded(
  380. () -> getVTooltip().initializeAssistiveTooltips());
  381. }
  382. }
  383. /**
  384. * Checks if there is some work to be done on the client side
  385. *
  386. * @return true if the client has some work to be done, false otherwise
  387. */
  388. private boolean isActive() {
  389. return !getMessageHandler().isInitialUidlHandled() || isWorkPending()
  390. || getMessageSender().hasActiveRequest()
  391. || isExecutingDeferredCommands();
  392. }
  393. private native void initializeTestbenchHooks(
  394. ComponentLocator componentLocator, String ttAppId)
  395. /*-{
  396. var ap = this;
  397. var client = {};
  398. client.isActive = $entry(function() {
  399. return ap.@com.vaadin.client.ApplicationConnection::isActive()();
  400. });
  401. var vi = ap.@com.vaadin.client.ApplicationConnection::getVersionInfo()();
  402. if (vi) {
  403. client.getVersionInfo = function() {
  404. return vi;
  405. }
  406. }
  407. client.getProfilingData = $entry(function() {
  408. var smh = ap.@com.vaadin.client.ApplicationConnection::getMessageHandler()();
  409. var pd = [
  410. smh.@com.vaadin.client.communication.MessageHandler::lastProcessingTime,
  411. smh.@com.vaadin.client.communication.MessageHandler::totalProcessingTime
  412. ];
  413. if (null != smh.@com.vaadin.client.communication.MessageHandler::serverTimingInfo) {
  414. pd = pd.concat(smh.@com.vaadin.client.communication.MessageHandler::serverTimingInfo);
  415. } else {
  416. pd = pd.concat(-1, -1);
  417. }
  418. pd[pd.length] = smh.@com.vaadin.client.communication.MessageHandler::bootstrapTime;
  419. return pd;
  420. });
  421. client.getElementByPath = $entry(function(id) {
  422. return componentLocator.@com.vaadin.client.componentlocator.ComponentLocator::getElementByPath(Ljava/lang/String;)(id);
  423. });
  424. client.getElementByPathStartingAt = $entry(function(id, element) {
  425. return componentLocator.@com.vaadin.client.componentlocator.ComponentLocator::getElementByPathStartingAt(Ljava/lang/String;Lcom/google/gwt/dom/client/Element;)(id, element);
  426. });
  427. client.getElementsByPath = $entry(function(id) {
  428. return componentLocator.@com.vaadin.client.componentlocator.ComponentLocator::getElementsByPath(Ljava/lang/String;)(id);
  429. });
  430. client.getElementsByPathStartingAt = $entry(function(id, element) {
  431. return componentLocator.@com.vaadin.client.componentlocator.ComponentLocator::getElementsByPathStartingAt(Ljava/lang/String;Lcom/google/gwt/dom/client/Element;)(id, element);
  432. });
  433. client.getPathForElement = $entry(function(element) {
  434. return componentLocator.@com.vaadin.client.componentlocator.ComponentLocator::getPathForElement(Lcom/google/gwt/dom/client/Element;)(element);
  435. });
  436. client.initializing = false;
  437. $wnd.vaadin.clients[ttAppId] = client;
  438. }-*/;
  439. /**
  440. * Helper for tt initialization
  441. */
  442. private JavaScriptObject getVersionInfo() {
  443. return configuration.getVersionInfoJSObject();
  444. }
  445. /**
  446. * Publishes a JavaScript API for mash-up applications.
  447. * <ul>
  448. * <li><code>vaadin.forceSync()</code> sends pending variable changes, in
  449. * effect synchronizing the server and client state. This is done for all
  450. * applications on host page.</li>
  451. * <li><code>vaadin.postRequestHooks</code> is a map of functions which gets
  452. * called after each XHR made by vaadin application. Note, that it is
  453. * attaching js functions responsibility to create the variable like this:
  454. *
  455. * <code><pre>
  456. * if (!vaadin.postRequestHooks) {vaadin.postRequestHooks = new Object();}
  457. * postRequestHooks.myHook = function(appId) {
  458. * if (appId == "MyAppOfInterest") {
  459. * // do the staff you need on xhr activity
  460. * }
  461. * }
  462. * </pre></code> First parameter passed to these functions is the identifier
  463. * of Vaadin application that made the request.
  464. * </ul>
  465. *
  466. * TODO make this multi-app aware
  467. */
  468. private native void initializeClientHooks()
  469. /*-{
  470. var app = this;
  471. var oldSync;
  472. if ($wnd.vaadin.forceSync) {
  473. oldSync = $wnd.vaadin.forceSync;
  474. }
  475. $wnd.vaadin.forceSync = $entry(function() {
  476. if (oldSync) {
  477. oldSync();
  478. }
  479. var sender = app.@com.vaadin.client.ApplicationConnection::messageSender;
  480. sender.@com.vaadin.client.communication.MessageSender::resynchronize()();
  481. });
  482. var oldForceLayout;
  483. if ($wnd.vaadin.forceLayout) {
  484. oldForceLayout = $wnd.vaadin.forceLayout;
  485. }
  486. $wnd.vaadin.forceLayout = $entry(function() {
  487. if (oldForceLayout) {
  488. oldForceLayout();
  489. }
  490. app.@com.vaadin.client.ApplicationConnection::forceLayout()();
  491. });
  492. }-*/;
  493. /**
  494. * Requests an analyze of layouts, to find inconsistencies. Exclusively used
  495. * for debugging during development.
  496. *
  497. * @deprecated as of 7.1. Replaced by {@link UIConnector#analyzeLayouts()}
  498. */
  499. @Deprecated
  500. public void analyzeLayouts() {
  501. getUIConnector().analyzeLayouts();
  502. }
  503. /**
  504. * Sends a request to the server to print details to console that will help
  505. * the developer to locate the corresponding server-side connector in the
  506. * source code.
  507. *
  508. * @param serverConnector
  509. * @deprecated as of 7.1. Replaced by
  510. * {@link UIConnector#showServerDebugInfo(ServerConnector)}
  511. */
  512. @Deprecated
  513. void highlightConnector(ServerConnector serverConnector) {
  514. getUIConnector().showServerDebugInfo(serverConnector);
  515. }
  516. int cssWaits = 0;
  517. protected ServerRpcQueue serverRpcQueue;
  518. protected ConnectionStateHandler connectionStateHandler;
  519. protected MessageHandler messageHandler;
  520. protected MessageSender messageSender;
  521. static final int MAX_CSS_WAITS = 100;
  522. public void executeWhenCSSLoaded(final Command c) {
  523. if (!isCSSLoaded() && cssWaits < MAX_CSS_WAITS) {
  524. (new Timer() {
  525. @Override
  526. public void run() {
  527. executeWhenCSSLoaded(c);
  528. }
  529. }).schedule(50);
  530. // Show this message just once
  531. if (cssWaits++ == 0) {
  532. getLogger().warning("Assuming CSS loading is not complete, "
  533. + "postponing render phase. "
  534. + "(.v-loading-indicator height == 0)");
  535. }
  536. } else {
  537. cssLoaded = true;
  538. if (cssWaits >= MAX_CSS_WAITS) {
  539. getLogger().severe("CSS files may have not loaded properly.");
  540. }
  541. c.execute();
  542. }
  543. }
  544. /**
  545. * Checks whether or not the CSS is loaded. By default checks the size of
  546. * the loading indicator element.
  547. *
  548. * @return
  549. */
  550. protected boolean isCSSLoaded() {
  551. return cssLoaded
  552. || getLoadingIndicator().getElement().getOffsetHeight() != 0;
  553. }
  554. /**
  555. * Shows the communication error notification.
  556. *
  557. * @param details
  558. * Optional details.
  559. * @param statusCode
  560. * The status code returned for the request
  561. *
  562. */
  563. public void showCommunicationError(String details, int statusCode) {
  564. getLogger().severe("Communication error: " + details);
  565. showError(details, configuration.getCommunicationError());
  566. }
  567. /**
  568. * Shows the authentication error notification.
  569. *
  570. * @param details
  571. * Optional details.
  572. */
  573. public void showAuthenticationError(String details) {
  574. getLogger().severe("Authentication error: " + details);
  575. showError(details, configuration.getAuthorizationError());
  576. }
  577. /**
  578. * Shows the session expiration notification.
  579. *
  580. * @param details
  581. * Optional details.
  582. */
  583. public void showSessionExpiredError(String details) {
  584. getLogger().severe("Session expired: " + details);
  585. showError(details, configuration.getSessionExpiredError());
  586. }
  587. /**
  588. * Shows an error notification.
  589. *
  590. * @param details
  591. * Optional details.
  592. * @param message
  593. * An ErrorMessage describing the error.
  594. */
  595. protected void showError(String details, ErrorMessage message) {
  596. VNotification.showError(this, message.getCaption(),
  597. message.getMessage(), details, message.getUrl());
  598. }
  599. /**
  600. * Checks if the client has running or scheduled commands
  601. */
  602. private boolean isWorkPending() {
  603. ConnectorMap connectorMap = getConnectorMap();
  604. JsArrayObject<ServerConnector> connectors = connectorMap
  605. .getConnectorsAsJsArray();
  606. int size = connectors.size();
  607. for (int i = 0; i < size; i++) {
  608. ServerConnector conn = connectors.get(i);
  609. if (isWorkPending(conn)) {
  610. return true;
  611. }
  612. if (conn instanceof ComponentConnector) {
  613. ComponentConnector compConn = (ComponentConnector) conn;
  614. if (isWorkPending(compConn.getWidget())) {
  615. return true;
  616. }
  617. }
  618. }
  619. return false;
  620. }
  621. private static boolean isWorkPending(Object object) {
  622. return object instanceof DeferredWorker
  623. && ((DeferredWorker) object).isWorkPending();
  624. }
  625. /**
  626. * Checks if deferred commands are (potentially) still being executed as a
  627. * result of an update from the server. Returns true if a deferred command
  628. * might still be executing, false otherwise. This will not work correctly
  629. * if a deferred command is added in another deferred command.
  630. * <p>
  631. * Used by the native "client.isActive" function.
  632. * </p>
  633. *
  634. * @return true if deferred commands are (potentially) being executed, false
  635. * otherwise
  636. */
  637. private boolean isExecutingDeferredCommands() {
  638. Scheduler s = Scheduler.get();
  639. if (s instanceof VSchedulerImpl) {
  640. return ((VSchedulerImpl) s).hasWorkQueued();
  641. } else {
  642. return false;
  643. }
  644. }
  645. /**
  646. * Returns the loading indicator used by this ApplicationConnection.
  647. *
  648. * @return The loading indicator for this ApplicationConnection
  649. */
  650. public VLoadingIndicator getLoadingIndicator() {
  651. return loadingIndicator;
  652. }
  653. /**
  654. * Determines whether or not the loading indicator is showing.
  655. *
  656. * @return true if the loading indicator is visible
  657. * @deprecated As of 7.1. Use {@link #getLoadingIndicator()} and
  658. * {@link VLoadingIndicator#isVisible()}.isVisible() instead.
  659. */
  660. @Deprecated
  661. public boolean isLoadingIndicatorVisible() {
  662. return getLoadingIndicator().isVisible();
  663. }
  664. private void addVariableToQueue(String connectorId, String variableName,
  665. Object value, boolean immediate) {
  666. boolean lastOnly = !immediate;
  667. // note that type is now deduced from value
  668. serverRpcQueue.add(new LegacyChangeVariablesInvocation(connectorId,
  669. variableName, value), lastOnly);
  670. if (immediate) {
  671. serverRpcQueue.flush();
  672. }
  673. }
  674. /**
  675. * @deprecated as of 7.6, use {@link ServerRpcQueue#flush()}
  676. */
  677. @Deprecated
  678. public void sendPendingVariableChanges() {
  679. serverRpcQueue.flush();
  680. }
  681. /**
  682. * Sends a new value for the given paintables given variable to the server.
  683. * <p>
  684. * The update is actually queued to be sent at a suitable time. If immediate
  685. * is true, the update is sent as soon as possible. If immediate is false,
  686. * the update will be sent along with the next immediate update.
  687. * </p>
  688. *
  689. * @param paintableId
  690. * the id of the paintable that owns the variable
  691. * @param variableName
  692. * the name of the variable
  693. * @param newValue
  694. * the new value to be sent
  695. * @param immediate
  696. * true if the update is to be sent as soon as possible
  697. */
  698. public void updateVariable(String paintableId, String variableName,
  699. ServerConnector newValue, boolean immediate) {
  700. addVariableToQueue(paintableId, variableName, newValue, immediate);
  701. }
  702. /**
  703. * Sends a new value for the given paintables given variable to the server.
  704. * <p>
  705. * The update is actually queued to be sent at a suitable time. If immediate
  706. * is true, the update is sent as soon as possible. If immediate is false,
  707. * the update will be sent along with the next immediate update.
  708. * </p>
  709. *
  710. * @param paintableId
  711. * the id of the paintable that owns the variable
  712. * @param variableName
  713. * the name of the variable
  714. * @param newValue
  715. * the new value to be sent
  716. * @param immediate
  717. * true if the update is to be sent as soon as possible
  718. */
  719. public void updateVariable(String paintableId, String variableName,
  720. String newValue, boolean immediate) {
  721. addVariableToQueue(paintableId, variableName, newValue, immediate);
  722. }
  723. /**
  724. * Sends a new value for the given paintables given variable to the server.
  725. * <p>
  726. * The update is actually queued to be sent at a suitable time. If immediate
  727. * is true, the update is sent as soon as possible. If immediate is false,
  728. * the update will be sent along with the next immediate update.
  729. * </p>
  730. *
  731. * @param paintableId
  732. * the id of the paintable that owns the variable
  733. * @param variableName
  734. * the name of the variable
  735. * @param newValue
  736. * the new value to be sent
  737. * @param immediate
  738. * true if the update is to be sent as soon as possible
  739. */
  740. public void updateVariable(String paintableId, String variableName,
  741. int newValue, boolean immediate) {
  742. addVariableToQueue(paintableId, variableName, newValue, immediate);
  743. }
  744. /**
  745. * Sends a new value for the given paintables given variable to the server.
  746. * <p>
  747. * The update is actually queued to be sent at a suitable time. If immediate
  748. * is true, the update is sent as soon as possible. If immediate is false,
  749. * the update will be sent along with the next immediate update.
  750. * </p>
  751. *
  752. * @param paintableId
  753. * the id of the paintable that owns the variable
  754. * @param variableName
  755. * the name of the variable
  756. * @param newValue
  757. * the new value to be sent
  758. * @param immediate
  759. * true if the update is to be sent as soon as possible
  760. */
  761. public void updateVariable(String paintableId, String variableName,
  762. long newValue, boolean immediate) {
  763. addVariableToQueue(paintableId, variableName, newValue, immediate);
  764. }
  765. /**
  766. * Sends a new value for the given paintables given variable to the server.
  767. * <p>
  768. * The update is actually queued to be sent at a suitable time. If immediate
  769. * is true, the update is sent as soon as possible. If immediate is false,
  770. * the update will be sent along with the next immediate update.
  771. * </p>
  772. *
  773. * @param paintableId
  774. * the id of the paintable that owns the variable
  775. * @param variableName
  776. * the name of the variable
  777. * @param newValue
  778. * the new value to be sent
  779. * @param immediate
  780. * true if the update is to be sent as soon as possible
  781. */
  782. public void updateVariable(String paintableId, String variableName,
  783. float newValue, boolean immediate) {
  784. addVariableToQueue(paintableId, variableName, newValue, immediate);
  785. }
  786. /**
  787. * Sends a new value for the given paintables given variable to the server.
  788. * <p>
  789. * The update is actually queued to be sent at a suitable time. If immediate
  790. * is true, the update is sent as soon as possible. If immediate is false,
  791. * the update will be sent along with the next immediate update.
  792. * </p>
  793. *
  794. * @param paintableId
  795. * the id of the paintable that owns the variable
  796. * @param variableName
  797. * the name of the variable
  798. * @param newValue
  799. * the new value to be sent
  800. * @param immediate
  801. * true if the update is to be sent as soon as possible
  802. */
  803. public void updateVariable(String paintableId, String variableName,
  804. double newValue, boolean immediate) {
  805. addVariableToQueue(paintableId, variableName, newValue, immediate);
  806. }
  807. /**
  808. * Sends a new value for the given paintables given variable to the server.
  809. * <p>
  810. * The update is actually queued to be sent at a suitable time. If immediate
  811. * is true, the update is sent as soon as possible. If immediate is false,
  812. * the update will be sent along with the next immediate update.
  813. * </p>
  814. *
  815. * @param paintableId
  816. * the id of the paintable that owns the variable
  817. * @param variableName
  818. * the name of the variable
  819. * @param newValue
  820. * the new value to be sent
  821. * @param immediate
  822. * true if the update is to be sent as soon as possible
  823. */
  824. public void updateVariable(String paintableId, String variableName,
  825. boolean newValue, boolean immediate) {
  826. addVariableToQueue(paintableId, variableName, newValue, immediate);
  827. }
  828. /**
  829. * Sends a new value for the given paintables given variable to the server.
  830. * <p>
  831. * The update is actually queued to be sent at a suitable time. If immediate
  832. * is true, the update is sent as soon as possible. If immediate is false,
  833. * the update will be sent along with the next immediate update.
  834. * </p>
  835. *
  836. * @param paintableId
  837. * the id of the paintable that owns the variable
  838. * @param variableName
  839. * the name of the variable
  840. * @param map
  841. * the new values to be sent
  842. * @param immediate
  843. * true if the update is to be sent as soon as possible
  844. */
  845. public void updateVariable(String paintableId, String variableName,
  846. Map<String, Object> map, boolean immediate) {
  847. addVariableToQueue(paintableId, variableName, map, immediate);
  848. }
  849. /**
  850. * Sends a new value for the given paintables given variable to the server.
  851. * <p>
  852. * The update is actually queued to be sent at a suitable time. If immediate
  853. * is true, the update is sent as soon as possible. If immediate is false,
  854. * the update will be sent along with the next immediate update.
  855. * <p>
  856. * A null array is sent as an empty array.
  857. *
  858. * @param paintableId
  859. * the id of the paintable that owns the variable
  860. * @param variableName
  861. * the name of the variable
  862. * @param values
  863. * the new value to be sent
  864. * @param immediate
  865. * true if the update is to be sent as soon as possible
  866. */
  867. public void updateVariable(String paintableId, String variableName,
  868. String[] values, boolean immediate) {
  869. addVariableToQueue(paintableId, variableName, values, immediate);
  870. }
  871. /**
  872. * Sends a new value for the given paintables given variable to the server.
  873. * <p>
  874. * The update is actually queued to be sent at a suitable time. If immediate
  875. * is true, the update is sent as soon as possible. If immediate is false,
  876. * the update will be sent along with the next immediate update.
  877. * <p>
  878. * A null array is sent as an empty array.
  879. *
  880. * @param paintableId
  881. * the id of the paintable that owns the variable
  882. * @param variableName
  883. * the name of the variable
  884. * @param values
  885. * the new value to be sent
  886. * @param immediate
  887. * true if the update is to be sent as soon as possible
  888. */
  889. public void updateVariable(String paintableId, String variableName,
  890. Object[] values, boolean immediate) {
  891. addVariableToQueue(paintableId, variableName, values, immediate);
  892. }
  893. /**
  894. * Does absolutely nothing. Replaced by {@link LayoutManager}.
  895. *
  896. * @param container
  897. * @deprecated As of 7.0, serves no purpose
  898. */
  899. @Deprecated
  900. public void runDescendentsLayout(HasWidgets container) {
  901. }
  902. /**
  903. * This will cause re-layouting of all components. Mainly used for
  904. * development. Published to JavaScript.
  905. */
  906. public void forceLayout() {
  907. Duration duration = new Duration();
  908. layoutManager.forceLayout();
  909. getLogger().info("forceLayout in " + duration.elapsedMillis() + " ms");
  910. }
  911. /**
  912. * Returns false
  913. *
  914. * @param paintable
  915. * @return false, always
  916. * @deprecated As of 7.0, serves no purpose
  917. */
  918. @Deprecated
  919. private boolean handleComponentRelativeSize(ComponentConnector paintable) {
  920. return false;
  921. }
  922. /**
  923. * Returns false.
  924. *
  925. * @param paintable
  926. * @return false, always
  927. * @deprecated As of 7.0, serves no purpose
  928. */
  929. @Deprecated
  930. public boolean handleComponentRelativeSize(Widget widget) {
  931. return handleComponentRelativeSize(connectorMap.getConnector(widget));
  932. }
  933. @Deprecated
  934. public ComponentConnector getPaintable(UIDL uidl) {
  935. // Non-component connectors shouldn't be painted from legacy connectors
  936. return (ComponentConnector) getConnector(uidl.getId(),
  937. Integer.parseInt(uidl.getTag()));
  938. }
  939. /**
  940. * Get either an existing ComponentConnector or create a new
  941. * ComponentConnector with the given type and id.
  942. *
  943. * If a ComponentConnector with the given id already exists, returns it.
  944. * Otherwise creates and registers a new ComponentConnector of the given
  945. * type.
  946. *
  947. * @param connectorId
  948. * Id of the paintable
  949. * @param connectorType
  950. * Type of the connector, as passed from the server side
  951. *
  952. * @return Either an existing ComponentConnector or a new ComponentConnector
  953. * of the given type
  954. */
  955. public ServerConnector getConnector(String connectorId, int connectorType) {
  956. if (!connectorMap.hasConnector(connectorId)) {
  957. return createAndRegisterConnector(connectorId, connectorType);
  958. }
  959. return connectorMap.getConnector(connectorId);
  960. }
  961. /**
  962. * Creates a new ServerConnector with the given type and id.
  963. *
  964. * Creates and registers a new ServerConnector of the given type. Should
  965. * never be called with the connector id of an existing connector.
  966. *
  967. * @param connectorId
  968. * Id of the new connector
  969. * @param connectorType
  970. * Type of the connector, as passed from the server side
  971. *
  972. * @return A new ServerConnector of the given type
  973. */
  974. private ServerConnector createAndRegisterConnector(String connectorId,
  975. int connectorType) {
  976. Profiler.enter("ApplicationConnection.createAndRegisterConnector");
  977. // Create and register a new connector with the given type
  978. ServerConnector p = widgetSet.createConnector(connectorType,
  979. configuration);
  980. connectorMap.registerConnector(connectorId, p);
  981. p.doInit(connectorId, this);
  982. Profiler.leave("ApplicationConnection.createAndRegisterConnector");
  983. return p;
  984. }
  985. /**
  986. * Gets a resource that has been pre-loaded via UIDL, such as custom
  987. * layouts.
  988. *
  989. * @param name
  990. * identifier of the resource to get
  991. * @return the resource
  992. */
  993. public String getResource(String name) {
  994. return resourcesMap.get(name);
  995. }
  996. /**
  997. * Sets a resource that has been pre-loaded via UIDL, such as custom
  998. * layouts.
  999. *
  1000. * @since 7.6
  1001. * @param name
  1002. * identifier of the resource to Set
  1003. * @param resource
  1004. * the resource
  1005. */
  1006. public void setResource(String name, String resource) {
  1007. resourcesMap.put(name, resource);
  1008. }
  1009. /**
  1010. * Singleton method to get instance of app's context menu.
  1011. *
  1012. * @return VContextMenu object
  1013. */
  1014. public VContextMenu getContextMenu() {
  1015. if (contextMenu == null) {
  1016. contextMenu = new VContextMenu();
  1017. contextMenu.setOwner(uIConnector.getWidget());
  1018. DOM.setElementProperty(contextMenu.getElement(), "id",
  1019. "PID_VAADIN_CM");
  1020. }
  1021. return contextMenu;
  1022. }
  1023. /**
  1024. * Gets an {@link Icon} instance corresponding to a URI.
  1025. *
  1026. * @since 7.2
  1027. * @param uri
  1028. * @return Icon object
  1029. */
  1030. public Icon getIcon(String uri) {
  1031. Icon icon;
  1032. if (uri == null) {
  1033. return null;
  1034. } else if (FontIcon.isFontIconUri(uri)) {
  1035. icon = GWT.create(FontIcon.class);
  1036. } else {
  1037. icon = GWT.create(ImageIcon.class);
  1038. }
  1039. icon.setUri(translateVaadinUri(uri));
  1040. return icon;
  1041. }
  1042. /**
  1043. * Translates custom protocols in UIDL URI's to be recognizable by browser.
  1044. * All uri's from UIDL should be routed via this method before giving them
  1045. * to browser due URI's in UIDL may contain custom protocols like theme://.
  1046. *
  1047. * @param uidlUri
  1048. * Vaadin URI from uidl
  1049. * @return translated URI ready for browser
  1050. */
  1051. public String translateVaadinUri(String uidlUri) {
  1052. return uriResolver.resolveVaadinUri(uidlUri);
  1053. }
  1054. /**
  1055. * Gets the URI for the current theme. Can be used to reference theme
  1056. * resources.
  1057. *
  1058. * @return URI to the current theme
  1059. */
  1060. public String getThemeUri() {
  1061. return configuration.getVaadinDirUrl() + "themes/"
  1062. + getUIConnector().getActiveTheme();
  1063. }
  1064. /* Extended title handling */
  1065. private final VTooltip tooltip;
  1066. private ConnectorMap connectorMap = GWT.create(ConnectorMap.class);
  1067. private final DependencyLoader dependencyLoader = GWT
  1068. .create(DependencyLoader.class);
  1069. /**
  1070. * Use to notify that the given component's caption has changed; layouts may
  1071. * have to be recalculated.
  1072. *
  1073. * @param widget
  1074. * The Widget whose caption has changed
  1075. * @deprecated As of 7.0.2, has not had any effect for a long time
  1076. */
  1077. @Deprecated
  1078. public void captionSizeUpdated(Widget widget) {
  1079. // This doesn't do anything, it's just kept here for compatibility
  1080. }
  1081. /**
  1082. * Gets the main view.
  1083. *
  1084. * @return the main view
  1085. */
  1086. public UIConnector getUIConnector() {
  1087. return uIConnector;
  1088. }
  1089. /**
  1090. * Gets the {@link ApplicationConfiguration} for the current application.
  1091. *
  1092. * @see ApplicationConfiguration
  1093. * @return the configuration for this application
  1094. */
  1095. public ApplicationConfiguration getConfiguration() {
  1096. return configuration;
  1097. }
  1098. /**
  1099. * Checks if there is a registered server side listener for the event. The
  1100. * list of events which has server side listeners is updated automatically
  1101. * before the component is updated so the value is correct if called from
  1102. * updatedFromUIDL.
  1103. *
  1104. * @param connector
  1105. * The connector to register event listeners for
  1106. * @param eventIdentifier
  1107. * The identifier for the event
  1108. * @return true if at least one listener has been registered on server side
  1109. * for the event identified by eventIdentifier.
  1110. * @deprecated As of 7.0. Use
  1111. * {@link AbstractConnector#hasEventListener(String)} instead
  1112. */
  1113. @Deprecated
  1114. public boolean hasEventListeners(ComponentConnector connector,
  1115. String eventIdentifier) {
  1116. return connector.hasEventListener(eventIdentifier);
  1117. }
  1118. /**
  1119. * Adds the get parameters to the uri and returns the new uri that contains
  1120. * the parameters.
  1121. *
  1122. * @param uri
  1123. * The uri to which the parameters should be added.
  1124. * @param extraParams
  1125. * One or more parameters in the format "a=b" or "c=d&e=f". An
  1126. * empty string is allowed but will not modify the url.
  1127. * @return The modified URI with the get parameters in extraParams added.
  1128. * @deprecated Use {@link SharedUtil#addGetParameters(String,String)}
  1129. * instead
  1130. */
  1131. @Deprecated
  1132. public static String addGetParameters(String uri, String extraParams) {
  1133. return SharedUtil.addGetParameters(uri, extraParams);
  1134. }
  1135. ConnectorMap getConnectorMap() {
  1136. return connectorMap;
  1137. }
  1138. /**
  1139. * @deprecated As of 7.0. No longer serves any purpose.
  1140. */
  1141. @Deprecated
  1142. public void unregisterPaintable(ServerConnector p) {
  1143. getLogger().info("unregisterPaintable (unnecessarily) called for "
  1144. + Util.getConnectorString(p));
  1145. }
  1146. /**
  1147. * Get VTooltip instance related to application connection.
  1148. *
  1149. * @return VTooltip instance
  1150. */
  1151. public VTooltip getVTooltip() {
  1152. return tooltip;
  1153. }
  1154. /**
  1155. * Method provided for backwards compatibility. Duties previously done by
  1156. * this method is now handled by the state change event handler in
  1157. * AbstractComponentConnector. The only function this method has is to
  1158. * return true if the UIDL is a "cached" update.
  1159. *
  1160. * @param component
  1161. * @param uidl
  1162. * @param manageCaption
  1163. * @deprecated As of 7.0, no longer serves any purpose
  1164. * @return
  1165. */
  1166. @Deprecated
  1167. public boolean updateComponent(Widget component, UIDL uidl,
  1168. boolean manageCaption) {
  1169. ComponentConnector connector = getConnectorMap()
  1170. .getConnector(component);
  1171. if (!AbstractComponentConnector.isRealUpdate(uidl)) {
  1172. return true;
  1173. }
  1174. if (!manageCaption) {
  1175. getLogger().warning(Util.getConnectorString(connector)
  1176. + " called updateComponent with manageCaption=false. The parameter was ignored - override delegateCaption() to return false instead. It is however not recommended to use caption this way at all.");
  1177. }
  1178. return false;
  1179. }
  1180. /**
  1181. * @deprecated As of 7.0. Use
  1182. * {@link AbstractComponentConnector#hasEventListener(String)}
  1183. * instead
  1184. */
  1185. @Deprecated
  1186. public boolean hasEventListeners(Widget widget, String eventIdentifier) {
  1187. ComponentConnector connector = getConnectorMap().getConnector(widget);
  1188. if (connector == null) {
  1189. /*
  1190. * No connector will exist in cases where Vaadin widgets have been
  1191. * re-used without implementing server<->client communication.
  1192. */
  1193. return false;
  1194. }
  1195. return hasEventListeners(connector, eventIdentifier);
  1196. }
  1197. LayoutManager getLayoutManager() {
  1198. return layoutManager;
  1199. }
  1200. /**
  1201. * Schedules a heartbeat request to occur after the configured heartbeat
  1202. * interval elapses if the interval is a positive number. Otherwise, does
  1203. * nothing.
  1204. *
  1205. * @deprecated as of 7.2, use {@link Heartbeat#schedule()} instead
  1206. */
  1207. @Deprecated
  1208. protected void scheduleHeartbeat() {
  1209. heartbeat.schedule();
  1210. }
  1211. /**
  1212. * Sends a heartbeat request to the server.
  1213. * <p>
  1214. * Heartbeat requests are used to inform the server that the client-side is
  1215. * still alive. If the client page is closed or the connection lost, the
  1216. * server will eventually close the inactive UI.
  1217. *
  1218. * @deprecated as of 7.2, use {@link Heartbeat#send()} instead
  1219. */
  1220. @Deprecated
  1221. protected void sendHeartbeat() {
  1222. heartbeat.send();
  1223. }
  1224. public void handleCommunicationError(String details, int statusCode) {
  1225. boolean handled = false;
  1226. if (communicationErrorDelegate != null) {
  1227. handled = communicationErrorDelegate.onError(details, statusCode);
  1228. }
  1229. if (!handled) {
  1230. showCommunicationError(details, statusCode);
  1231. }
  1232. }
  1233. /**
  1234. * Sets the delegate that is called whenever a communication error occurrs.
  1235. *
  1236. * @param delegate
  1237. * the delegate.
  1238. */
  1239. public void setCommunicationErrorDelegate(
  1240. CommunicationErrorHandler delegate) {
  1241. communicationErrorDelegate = delegate;
  1242. }
  1243. public void setApplicationRunning(boolean applicationRunning) {
  1244. if (getApplicationState() == ApplicationState.TERMINATED) {
  1245. if (applicationRunning) {
  1246. getLogger().severe(
  1247. "Tried to restart a terminated application. This is not supported");
  1248. } else {
  1249. getLogger().warning(
  1250. "Tried to stop a terminated application. This should not be done");
  1251. }
  1252. return;
  1253. } else if (getApplicationState() == ApplicationState.INITIALIZING) {
  1254. if (applicationRunning) {
  1255. applicationState = ApplicationState.RUNNING;
  1256. } else {
  1257. getLogger().warning(
  1258. "Tried to stop the application before it has started. This should not be done");
  1259. }
  1260. } else if (getApplicationState() == ApplicationState.RUNNING) {
  1261. if (!applicationRunning) {
  1262. applicationState = ApplicationState.TERMINATED;
  1263. eventBus.fireEvent(new ApplicationStoppedEvent());
  1264. } else {
  1265. getLogger().warning(
  1266. "Tried to start an already running application. This should not be done");
  1267. }
  1268. }
  1269. }
  1270. /**
  1271. * Checks if the application is in the {@link ApplicationState#RUNNING}
  1272. * state.
  1273. *
  1274. * @since 7.6
  1275. * @return true if the application is in the running state, false otherwise
  1276. */
  1277. public boolean isApplicationRunning() {
  1278. return applicationState == ApplicationState.RUNNING;
  1279. }
  1280. public <H extends EventHandler> HandlerRegistration addHandler(
  1281. GwtEvent.Type<H> type, H handler) {
  1282. return eventBus.addHandler(type, handler);
  1283. }
  1284. @Override
  1285. public void fireEvent(GwtEvent<?> event) {
  1286. eventBus.fireEvent(event);
  1287. }
  1288. /**
  1289. * Calls {@link ComponentConnector#flush()} on the active connector. Does
  1290. * nothing if there is no active (focused) connector.
  1291. */
  1292. public void flushActiveConnector() {
  1293. ComponentConnector activeConnector = getActiveConnector();
  1294. if (activeConnector == null) {
  1295. return;
  1296. }
  1297. activeConnector.flush();
  1298. }
  1299. /**
  1300. * Gets the active connector for the focused element in the browser.
  1301. *
  1302. * @return the connector for the focused element or <code>null</code> if
  1303. * none found or no element is focused.
  1304. */
  1305. private ComponentConnector getActiveConnector() {
  1306. Element focusedElement = WidgetUtil.getFocusedElement();
  1307. if (focusedElement == null) {
  1308. return null;
  1309. }
  1310. return Util.getConnectorForElement(this, RootPanel.get(),
  1311. focusedElement);
  1312. }
  1313. private static Logger getLogger() {
  1314. return Logger.getLogger(ApplicationConnection.class.getName());
  1315. }
  1316. /**
  1317. * Returns the hearbeat instance.
  1318. */
  1319. public Heartbeat getHeartbeat() {
  1320. return heartbeat;
  1321. }
  1322. /**
  1323. * Returns the state of this application. An application state goes from
  1324. * "initializing" to "running" to "stopped". There is no way for an
  1325. * application to go back to a previous state, i.e. a stopped application
  1326. * can never be re-started
  1327. *
  1328. * @since 7.6
  1329. * @return the current state of this application
  1330. */
  1331. public ApplicationState getApplicationState() {
  1332. return applicationState;
  1333. }
  1334. /**
  1335. * Gets the server RPC queue for this application.
  1336. *
  1337. * @since 7.6
  1338. * @return the server RPC queue
  1339. */
  1340. public ServerRpcQueue getServerRpcQueue() {
  1341. return serverRpcQueue;
  1342. }
  1343. /**
  1344. * Gets the communication error handler for this application.
  1345. *
  1346. * @since 7.6
  1347. * @return the server RPC queue
  1348. */
  1349. public ConnectionStateHandler getConnectionStateHandler() {
  1350. return connectionStateHandler;
  1351. }
  1352. /**
  1353. * Gets the (server to client) message handler for this application.
  1354. *
  1355. * @since 7.6
  1356. * @return the message handler
  1357. */
  1358. public MessageHandler getMessageHandler() {
  1359. return messageHandler;
  1360. }
  1361. /**
  1362. * Gets the server rpc manager for this application.
  1363. *
  1364. * @since 7.6
  1365. * @return the server rpc manager
  1366. */
  1367. public RpcManager getRpcManager() {
  1368. return rpcManager;
  1369. }
  1370. /**
  1371. * Gets the (client to server) message sender for this application.
  1372. *
  1373. * @since 7.6
  1374. * @return the message sender
  1375. */
  1376. public MessageSender getMessageSender() {
  1377. return messageSender;
  1378. }
  1379. /**
  1380. * @since 7.6
  1381. * @return the widget set
  1382. */
  1383. public WidgetSet getWidgetSet() {
  1384. return widgetSet;
  1385. }
  1386. public int getLastSeenServerSyncId() {
  1387. return getMessageHandler().getLastSeenServerSyncId();
  1388. }
  1389. /**
  1390. * Gets the instance which handles loading of dependencies.
  1391. *
  1392. * @return the dependency loader for this connection
  1393. */
  1394. public DependencyLoader getDependencyLoader() {
  1395. return dependencyLoader;
  1396. }
  1397. }