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 54KB

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