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

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697989910010110210310410510610710810911011111211311411511611711811912012112212312412512612712812913013113213313413513613713813914014114214314414514614714814915015115215315415515615715815916016116216316416516616716816917017117217317417517617717817918018118218318418518618718818919019119219319419519619719819920020120220320420520620720820921021121221321421521621721821922022122222322422522622722822923023123223323423523623723823924024124224324424524624724824925025125225325425525625725825926026126226326426526626726826927027127227327427527627727827928028128228328428528628728828929029129229329429529629729829930030130230330430530630730830931031131231331431531631731831932032132232332432532632732832933033133233333433533633733833934034134234334434534634734834935035135235335435535635735835936036136236336436536636736836937037137237337437537637737837938038138238338438538638738838939039139239339439539639739839940040140240340440540640740840941041141241341441541641741841942042142242342442542642742842943043143243343443543643743843944044144244344444544644744844945045145245345445545645745845946046146246346446546646746846947047147247347447547647747847948048148248348448548648748848949049149249349449549649749849950050150250350450550650750850951051151251351451551651751851952052152252352452552652752852953053153253353453553653753853954054154254354454554654754854955055155255355455555655755855956056156256356456556656756856957057157257357457557657757857958058158258358458558658758858959059159259359459559659759859960060160260360460560660760860961061161261361461561661761861962062162262362462562662762862963063163263363463563663763863964064164264364464564664764864965065165265365465565665765865966066166266366466566666766866967067167267367467567667767867968068168268368468568668768868969069169269369469569669769869970070170270370470570670770870971071171271371471571671771871972072172272372472572672772872973073173273373473573673773873974074174274374474574674774874975075175275375475575675775875976076176276376476576676776876977077177277377477577677777877978078178278378478578678778878979079179279379479579679779879980080180280380480580680780880981081181281381481581681781881982082182282382482582682782882983083183283383483583683783883984084184284384484584684784884985085185285385485585685785885986086186286386486586686786886987087187287387487587687787887988088188288388488588688788888989089189289389489589689789889990090190290390490590690790890991091191291391491591691791891992092192292392492592692792892993093193293393493593693793893994094194294394494594694794894995095195295395495595695795895996096196296396496596696796896997097197297397497597697797897998098198298398498598698798898999099199299399499599699799899910001001100210031004100510061007100810091010101110121013101410151016101710181019102010211022102310241025102610271028102910301031103210331034103510361037103810391040104110421043104410451046104710481049105010511052105310541055105610571058105910601061106210631064106510661067106810691070107110721073107410751076107710781079108010811082108310841085108610871088108910901091109210931094109510961097109810991100110111021103110411051106110711081109111011111112111311141115111611171118111911201121112211231124112511261127112811291130113111321133113411351136113711381139114011411142114311441145114611471148114911501151115211531154115511561157115811591160116111621163116411651166116711681169117011711172117311741175117611771178117911801181118211831184118511861187118811891190119111921193119411951196119711981199120012011202120312041205120612071208120912101211121212131214121512161217121812191220122112221223122412251226122712281229123012311232123312341235123612371238123912401241124212431244124512461247124812491250125112521253125412551256125712581259126012611262126312641265126612671268126912701271127212731274127512761277127812791280128112821283128412851286128712881289129012911292129312941295129612971298129913001301130213031304130513061307130813091310131113121313131413151316131713181319132013211322132313241325132613271328132913301331133213331334133513361337133813391340134113421343134413451346134713481349135013511352135313541355135613571358135913601361136213631364136513661367136813691370137113721373137413751376137713781379138013811382138313841385138613871388138913901391139213931394139513961397139813991400140114021403140414051406140714081409141014111412141314141415141614171418141914201421142214231424142514261427142814291430143114321433143414351436143714381439144014411442144314441445144614471448144914501451145214531454145514561457145814591460146114621463146414651466146714681469147014711472147314741475147614771478147914801481148214831484148514861487148814891490149114921493149414951496149714981499150015011502150315041505150615071508150915101511151215131514151515161517151815191520152115221523152415251526152715281529153015311532153315341535153615371538153915401541154215431544154515461547154815491550155115521553155415551556155715581559156015611562156315641565156615671568156915701571157215731574157515761577157815791580158115821583158415851586158715881589
  1. /*
  2. * Copyright 2000-2021 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. if (cnf.getRootElement() != null) {
  337. uIConnector.init(cnf.getRootElement(), this);
  338. } else {
  339. uIConnector.init(cnf.getRootPanelId(), this);
  340. }
  341. // Connection state handler preloads the reconnect dialog, which uses
  342. // overlay container. This in turn depends on VUI being attached
  343. // (done in uiConnector.init)
  344. connectionStateHandler.setConnection(this);
  345. tooltip.setOwner(uIConnector.getWidget());
  346. getLoadingIndicator().show();
  347. heartbeat.init(this);
  348. // Ensure the overlay container is added to the dom and set as a live
  349. // area for assistive devices
  350. Element overlayContainer = VOverlay.getOverlayContainer(this);
  351. Roles.getAlertRole().setAriaLiveProperty(overlayContainer,
  352. LiveValue.ASSERTIVE);
  353. VOverlay.setOverlayContainerLabel(this,
  354. getUIConnector().getState().overlayContainerLabel);
  355. Roles.getAlertRole().setAriaRelevantProperty(overlayContainer,
  356. RelevantValue.ADDITIONS);
  357. }
  358. /**
  359. * Starts this application. Don't call this method directly - it's called by
  360. * {@link ApplicationConfiguration#startNextApplication()}, which should be
  361. * called once this application has started (first response received) or
  362. * failed to start. This ensures that the applications are started in order,
  363. * to avoid session-id problems.
  364. *
  365. */
  366. public void start() {
  367. String jsonText = configuration.getUIDL();
  368. if (jsonText == null) {
  369. // initial UIDL not in DOM, request from server
  370. getMessageSender().resynchronize();
  371. } else {
  372. // initial UIDL provided in DOM, continue as if returned by request
  373. // Hack to avoid logging an error in endRequest()
  374. getMessageSender().startRequest();
  375. getMessageHandler()
  376. .handleMessage(MessageHandler.parseJson(jsonText));
  377. }
  378. // Tooltip can't be created earlier because the
  379. // necessary fields are not setup to add it in the
  380. // correct place in the DOM
  381. if (!tooltipInitialized) {
  382. tooltipInitialized = true;
  383. ApplicationConfiguration.runWhenDependenciesLoaded(
  384. () -> getVTooltip().initializeAssistiveTooltips());
  385. }
  386. }
  387. /**
  388. * Checks if there is some work to be done on the client side
  389. *
  390. * @return true if the client has some work to be done, false otherwise
  391. */
  392. private boolean isActive() {
  393. return !getMessageHandler().isInitialUidlHandled() || isWorkPending()
  394. || getMessageSender().hasActiveRequest()
  395. || isExecutingDeferredCommands();
  396. }
  397. private native void initializeTestbenchHooks(
  398. ComponentLocator componentLocator, String ttAppId)
  399. /*-{
  400. var ap = this;
  401. var client = {};
  402. client.isActive = $entry(function() {
  403. return ap.@com.vaadin.client.ApplicationConnection::isActive()();
  404. });
  405. var vi = ap.@com.vaadin.client.ApplicationConnection::getVersionInfo()();
  406. if (vi) {
  407. client.getVersionInfo = function() {
  408. return vi;
  409. }
  410. }
  411. client.getProfilingData = $entry(function() {
  412. var smh = ap.@com.vaadin.client.ApplicationConnection::getMessageHandler()();
  413. var pd = [
  414. smh.@com.vaadin.client.communication.MessageHandler::lastProcessingTime,
  415. smh.@com.vaadin.client.communication.MessageHandler::totalProcessingTime
  416. ];
  417. if (null != smh.@com.vaadin.client.communication.MessageHandler::serverTimingInfo) {
  418. pd = pd.concat(smh.@com.vaadin.client.communication.MessageHandler::serverTimingInfo);
  419. } else {
  420. pd = pd.concat(-1, -1);
  421. }
  422. pd[pd.length] = smh.@com.vaadin.client.communication.MessageHandler::bootstrapTime;
  423. return pd;
  424. });
  425. client.getElementByPath = $entry(function(id) {
  426. return componentLocator.@com.vaadin.client.componentlocator.ComponentLocator::getElementByPath(Ljava/lang/String;)(id);
  427. });
  428. client.getElementByPathStartingAt = $entry(function(id, element) {
  429. return componentLocator.@com.vaadin.client.componentlocator.ComponentLocator::getElementByPathStartingAt(Ljava/lang/String;Lcom/google/gwt/dom/client/Element;)(id, element);
  430. });
  431. client.getElementsByPath = $entry(function(id) {
  432. return componentLocator.@com.vaadin.client.componentlocator.ComponentLocator::getElementsByPath(Ljava/lang/String;)(id);
  433. });
  434. client.getElementsByPathStartingAt = $entry(function(id, element) {
  435. return componentLocator.@com.vaadin.client.componentlocator.ComponentLocator::getElementsByPathStartingAt(Ljava/lang/String;Lcom/google/gwt/dom/client/Element;)(id, element);
  436. });
  437. client.getPathForElement = $entry(function(element) {
  438. return componentLocator.@com.vaadin.client.componentlocator.ComponentLocator::getPathForElement(Lcom/google/gwt/dom/client/Element;)(element);
  439. });
  440. client.initializing = false;
  441. $wnd.vaadin.clients[ttAppId] = client;
  442. }-*/;
  443. /**
  444. * Helper for tt initialization
  445. */
  446. private JavaScriptObject getVersionInfo() {
  447. return configuration.getVersionInfoJSObject();
  448. }
  449. /**
  450. * Publishes a JavaScript API for mash-up applications.
  451. * <ul>
  452. * <li><code>vaadin.forceSync()</code> sends pending variable changes, in
  453. * effect synchronizing the server and client state. This is done for all
  454. * applications on host page.</li>
  455. * <li><code>vaadin.postRequestHooks</code> is a map of functions which gets
  456. * called after each XHR made by vaadin application. Note, that it is
  457. * attaching js functions responsibility to create the variable like this:
  458. *
  459. * <code><pre>
  460. * if (!vaadin.postRequestHooks) {vaadin.postRequestHooks = new Object();}
  461. * postRequestHooks.myHook = function(appId) {
  462. * if (appId == "MyAppOfInterest") {
  463. * // do the staff you need on xhr activity
  464. * }
  465. * }
  466. * </pre></code> First parameter passed to these functions is the identifier
  467. * of Vaadin application that made the request.
  468. * </ul>
  469. *
  470. * TODO make this multi-app aware
  471. */
  472. private native void initializeClientHooks()
  473. /*-{
  474. var app = this;
  475. var oldSync;
  476. if ($wnd.vaadin.forceSync) {
  477. oldSync = $wnd.vaadin.forceSync;
  478. }
  479. $wnd.vaadin.forceSync = $entry(function() {
  480. if (oldSync) {
  481. oldSync();
  482. }
  483. var sender = app.@com.vaadin.client.ApplicationConnection::messageSender;
  484. sender.@com.vaadin.client.communication.MessageSender::resynchronize()();
  485. });
  486. var oldForceLayout;
  487. if ($wnd.vaadin.forceLayout) {
  488. oldForceLayout = $wnd.vaadin.forceLayout;
  489. }
  490. $wnd.vaadin.forceLayout = $entry(function() {
  491. if (oldForceLayout) {
  492. oldForceLayout();
  493. }
  494. app.@com.vaadin.client.ApplicationConnection::forceLayout()();
  495. });
  496. }-*/;
  497. /**
  498. * Requests an analyze of layouts, to find inconsistencies. Exclusively used
  499. * for debugging during development.
  500. *
  501. * @deprecated as of 7.1. Replaced by {@link UIConnector#analyzeLayouts()}
  502. */
  503. @Deprecated
  504. public void analyzeLayouts() {
  505. getUIConnector().analyzeLayouts();
  506. }
  507. /**
  508. * Sends a request to the server to print details to console that will help
  509. * the developer to locate the corresponding server-side connector in the
  510. * source code.
  511. *
  512. * @param serverConnector
  513. * @deprecated as of 7.1. Replaced by
  514. * {@link UIConnector#showServerDebugInfo(ServerConnector)}
  515. */
  516. @Deprecated
  517. void highlightConnector(ServerConnector serverConnector) {
  518. getUIConnector().showServerDebugInfo(serverConnector);
  519. }
  520. int cssWaits = 0;
  521. protected ServerRpcQueue serverRpcQueue;
  522. protected ConnectionStateHandler connectionStateHandler;
  523. protected MessageHandler messageHandler;
  524. protected MessageSender messageSender;
  525. static final int MAX_CSS_WAITS = 100;
  526. public void executeWhenCSSLoaded(final Command c) {
  527. if (!isCSSLoaded() && cssWaits < MAX_CSS_WAITS) {
  528. (new Timer() {
  529. @Override
  530. public void run() {
  531. executeWhenCSSLoaded(c);
  532. }
  533. }).schedule(50);
  534. // Show this message just once
  535. if (cssWaits++ == 0) {
  536. getLogger().warning("Assuming CSS loading is not complete, "
  537. + "postponing render phase. "
  538. + "(.v-loading-indicator height == 0)");
  539. }
  540. } else {
  541. cssLoaded = true;
  542. if (cssWaits >= MAX_CSS_WAITS) {
  543. getLogger().severe("CSS files may have not loaded properly.");
  544. }
  545. c.execute();
  546. }
  547. }
  548. /**
  549. * Checks whether or not the CSS is loaded. By default checks the size of
  550. * the loading indicator element.
  551. *
  552. * @return
  553. */
  554. protected boolean isCSSLoaded() {
  555. return cssLoaded
  556. || getLoadingIndicator().getElement().getOffsetHeight() != 0;
  557. }
  558. /**
  559. * Shows the communication error notification.
  560. *
  561. * @param details
  562. * Optional details.
  563. * @param statusCode
  564. * The status code returned for the request
  565. *
  566. */
  567. public void showCommunicationError(String details, int statusCode) {
  568. getLogger().severe("Communication error: " + details);
  569. showError(details, configuration.getCommunicationError());
  570. }
  571. /**
  572. * Shows the authentication error notification.
  573. *
  574. * @param details
  575. * Optional details.
  576. */
  577. public void showAuthenticationError(String details) {
  578. getLogger().severe("Authentication error: " + details);
  579. showError(details, configuration.getAuthorizationError());
  580. }
  581. /**
  582. * Shows the session expiration notification.
  583. *
  584. * @param details
  585. * Optional details.
  586. */
  587. public void showSessionExpiredError(String details) {
  588. getLogger().severe("Session expired: " + details);
  589. showError(details, configuration.getSessionExpiredError());
  590. }
  591. /**
  592. * Shows an error notification.
  593. *
  594. * @param details
  595. * Optional details.
  596. * @param message
  597. * An ErrorMessage describing the error.
  598. */
  599. protected void showError(String details, ErrorMessage message) {
  600. VNotification.showError(this, message.getCaption(),
  601. message.getMessage(), details, message.getUrl());
  602. }
  603. /**
  604. * Checks if the client has running or scheduled commands
  605. */
  606. private boolean isWorkPending() {
  607. ConnectorMap connectorMap = getConnectorMap();
  608. JsArrayObject<ServerConnector> connectors = connectorMap
  609. .getConnectorsAsJsArray();
  610. int size = connectors.size();
  611. for (int i = 0; i < size; i++) {
  612. ServerConnector conn = connectors.get(i);
  613. if (isWorkPending(conn)) {
  614. return true;
  615. }
  616. if (conn instanceof ComponentConnector) {
  617. ComponentConnector compConn = (ComponentConnector) conn;
  618. if (isWorkPending(compConn.getWidget())) {
  619. return true;
  620. }
  621. }
  622. }
  623. return false;
  624. }
  625. private static boolean isWorkPending(Object object) {
  626. return object instanceof DeferredWorker
  627. && ((DeferredWorker) object).isWorkPending();
  628. }
  629. /**
  630. * Checks if deferred commands are (potentially) still being executed as a
  631. * result of an update from the server. Returns true if a deferred command
  632. * might still be executing, false otherwise. This will not work correctly
  633. * if a deferred command is added in another deferred command.
  634. * <p>
  635. * Used by the native "client.isActive" function.
  636. * </p>
  637. *
  638. * @return true if deferred commands are (potentially) being executed, false
  639. * otherwise
  640. */
  641. private boolean isExecutingDeferredCommands() {
  642. Scheduler s = Scheduler.get();
  643. if (s instanceof VSchedulerImpl) {
  644. return ((VSchedulerImpl) s).hasWorkQueued();
  645. } else {
  646. return false;
  647. }
  648. }
  649. /**
  650. * Returns the loading indicator used by this ApplicationConnection.
  651. *
  652. * @return The loading indicator for this ApplicationConnection
  653. */
  654. public VLoadingIndicator getLoadingIndicator() {
  655. return loadingIndicator;
  656. }
  657. /**
  658. * Determines whether or not the loading indicator is showing.
  659. *
  660. * @return true if the loading indicator is visible
  661. * @deprecated As of 7.1. Use {@link #getLoadingIndicator()} and
  662. * {@link VLoadingIndicator#isVisible()}.isVisible() instead.
  663. */
  664. @Deprecated
  665. public boolean isLoadingIndicatorVisible() {
  666. return getLoadingIndicator().isVisible();
  667. }
  668. private void addVariableToQueue(String connectorId, String variableName,
  669. Object value, boolean immediate) {
  670. boolean lastOnly = !immediate;
  671. // note that type is now deduced from value
  672. serverRpcQueue.add(new LegacyChangeVariablesInvocation(connectorId,
  673. variableName, value), lastOnly);
  674. if (immediate) {
  675. serverRpcQueue.flush();
  676. }
  677. }
  678. /**
  679. * @deprecated as of 7.6, use {@link ServerRpcQueue#flush()}
  680. */
  681. @Deprecated
  682. public void sendPendingVariableChanges() {
  683. serverRpcQueue.flush();
  684. }
  685. /**
  686. * Sends a new value for the given paintables given variable to the server.
  687. * <p>
  688. * The update is actually queued to be sent at a suitable time. If immediate
  689. * is true, the update is sent as soon as possible. If immediate is false,
  690. * the update will be sent along with the next immediate update.
  691. * </p>
  692. *
  693. * @param paintableId
  694. * the id of the paintable that owns the variable
  695. * @param variableName
  696. * the name of the variable
  697. * @param newValue
  698. * the new value to be sent
  699. * @param immediate
  700. * true if the update is to be sent as soon as possible
  701. */
  702. public void updateVariable(String paintableId, String variableName,
  703. ServerConnector newValue, boolean immediate) {
  704. addVariableToQueue(paintableId, variableName, newValue, immediate);
  705. }
  706. /**
  707. * Sends a new value for the given paintables given variable to the server.
  708. * <p>
  709. * The update is actually queued to be sent at a suitable time. If immediate
  710. * is true, the update is sent as soon as possible. If immediate is false,
  711. * the update will be sent along with the next immediate update.
  712. * </p>
  713. *
  714. * @param paintableId
  715. * the id of the paintable that owns the variable
  716. * @param variableName
  717. * the name of the variable
  718. * @param newValue
  719. * the new value to be sent
  720. * @param immediate
  721. * true if the update is to be sent as soon as possible
  722. */
  723. public void updateVariable(String paintableId, String variableName,
  724. String newValue, boolean immediate) {
  725. addVariableToQueue(paintableId, variableName, newValue, immediate);
  726. }
  727. /**
  728. * Sends a new value for the given paintables given variable to the server.
  729. * <p>
  730. * The update is actually queued to be sent at a suitable time. If immediate
  731. * is true, the update is sent as soon as possible. If immediate is false,
  732. * the update will be sent along with the next immediate update.
  733. * </p>
  734. *
  735. * @param paintableId
  736. * the id of the paintable that owns the variable
  737. * @param variableName
  738. * the name of the variable
  739. * @param newValue
  740. * the new value to be sent
  741. * @param immediate
  742. * true if the update is to be sent as soon as possible
  743. */
  744. public void updateVariable(String paintableId, String variableName,
  745. int newValue, boolean immediate) {
  746. addVariableToQueue(paintableId, variableName, newValue, immediate);
  747. }
  748. /**
  749. * Sends a new value for the given paintables given variable to the server.
  750. * <p>
  751. * The update is actually queued to be sent at a suitable time. If immediate
  752. * is true, the update is sent as soon as possible. If immediate is false,
  753. * the update will be sent along with the next immediate update.
  754. * </p>
  755. *
  756. * @param paintableId
  757. * the id of the paintable that owns the variable
  758. * @param variableName
  759. * the name of the variable
  760. * @param newValue
  761. * the new value to be sent
  762. * @param immediate
  763. * true if the update is to be sent as soon as possible
  764. */
  765. public void updateVariable(String paintableId, String variableName,
  766. long newValue, boolean immediate) {
  767. addVariableToQueue(paintableId, variableName, newValue, immediate);
  768. }
  769. /**
  770. * Sends a new value for the given paintables given variable to the server.
  771. * <p>
  772. * The update is actually queued to be sent at a suitable time. If immediate
  773. * is true, the update is sent as soon as possible. If immediate is false,
  774. * the update will be sent along with the next immediate update.
  775. * </p>
  776. *
  777. * @param paintableId
  778. * the id of the paintable that owns the variable
  779. * @param variableName
  780. * the name of the variable
  781. * @param newValue
  782. * the new value to be sent
  783. * @param immediate
  784. * true if the update is to be sent as soon as possible
  785. */
  786. public void updateVariable(String paintableId, String variableName,
  787. float newValue, boolean immediate) {
  788. addVariableToQueue(paintableId, variableName, newValue, immediate);
  789. }
  790. /**
  791. * Sends a new value for the given paintables given variable to the server.
  792. * <p>
  793. * The update is actually queued to be sent at a suitable time. If immediate
  794. * is true, the update is sent as soon as possible. If immediate is false,
  795. * the update will be sent along with the next immediate update.
  796. * </p>
  797. *
  798. * @param paintableId
  799. * the id of the paintable that owns the variable
  800. * @param variableName
  801. * the name of the variable
  802. * @param newValue
  803. * the new value to be sent
  804. * @param immediate
  805. * true if the update is to be sent as soon as possible
  806. */
  807. public void updateVariable(String paintableId, String variableName,
  808. double newValue, boolean immediate) {
  809. addVariableToQueue(paintableId, variableName, newValue, immediate);
  810. }
  811. /**
  812. * Sends a new value for the given paintables given variable to the server.
  813. * <p>
  814. * The update is actually queued to be sent at a suitable time. If immediate
  815. * is true, the update is sent as soon as possible. If immediate is false,
  816. * the update will be sent along with the next immediate update.
  817. * </p>
  818. *
  819. * @param paintableId
  820. * the id of the paintable that owns the variable
  821. * @param variableName
  822. * the name of the variable
  823. * @param newValue
  824. * the new value to be sent
  825. * @param immediate
  826. * true if the update is to be sent as soon as possible
  827. */
  828. public void updateVariable(String paintableId, String variableName,
  829. boolean newValue, boolean immediate) {
  830. addVariableToQueue(paintableId, variableName, newValue, immediate);
  831. }
  832. /**
  833. * Sends a new value for the given paintables given variable to the server.
  834. * <p>
  835. * The update is actually queued to be sent at a suitable time. If immediate
  836. * is true, the update is sent as soon as possible. If immediate is false,
  837. * the update will be sent along with the next immediate update.
  838. * </p>
  839. *
  840. * @param paintableId
  841. * the id of the paintable that owns the variable
  842. * @param variableName
  843. * the name of the variable
  844. * @param map
  845. * the new values to be sent
  846. * @param immediate
  847. * true if the update is to be sent as soon as possible
  848. */
  849. public void updateVariable(String paintableId, String variableName,
  850. Map<String, Object> map, boolean immediate) {
  851. addVariableToQueue(paintableId, variableName, map, immediate);
  852. }
  853. /**
  854. * Sends a new value for the given paintables given variable to the server.
  855. * <p>
  856. * The update is actually queued to be sent at a suitable time. If immediate
  857. * is true, the update is sent as soon as possible. If immediate is false,
  858. * the update will be sent along with the next immediate update.
  859. * <p>
  860. * A null array is sent as an empty array.
  861. *
  862. * @param paintableId
  863. * the id of the paintable that owns the variable
  864. * @param variableName
  865. * the name of the variable
  866. * @param values
  867. * the new value to be sent
  868. * @param immediate
  869. * true if the update is to be sent as soon as possible
  870. */
  871. public void updateVariable(String paintableId, String variableName,
  872. String[] values, boolean immediate) {
  873. addVariableToQueue(paintableId, variableName, values, immediate);
  874. }
  875. /**
  876. * Sends a new value for the given paintables given variable to the server.
  877. * <p>
  878. * The update is actually queued to be sent at a suitable time. If immediate
  879. * is true, the update is sent as soon as possible. If immediate is false,
  880. * the update will be sent along with the next immediate update.
  881. * <p>
  882. * A null array is sent as an empty array.
  883. *
  884. * @param paintableId
  885. * the id of the paintable that owns the variable
  886. * @param variableName
  887. * the name of the variable
  888. * @param values
  889. * the new value to be sent
  890. * @param immediate
  891. * true if the update is to be sent as soon as possible
  892. */
  893. public void updateVariable(String paintableId, String variableName,
  894. Object[] values, boolean immediate) {
  895. addVariableToQueue(paintableId, variableName, values, immediate);
  896. }
  897. /**
  898. * Does absolutely nothing. Replaced by {@link LayoutManager}.
  899. *
  900. * @param container
  901. * @deprecated As of 7.0, serves no purpose
  902. */
  903. @Deprecated
  904. public void runDescendentsLayout(HasWidgets container) {
  905. }
  906. /**
  907. * This will cause re-layouting of all components. Mainly used for
  908. * development. Published to JavaScript.
  909. */
  910. public void forceLayout() {
  911. Duration duration = new Duration();
  912. layoutManager.forceLayout();
  913. getLogger().info("forceLayout in " + duration.elapsedMillis() + " ms");
  914. }
  915. /**
  916. * Returns false
  917. *
  918. * @param paintable
  919. * @return false, always
  920. * @deprecated As of 7.0, serves no purpose
  921. */
  922. @Deprecated
  923. private boolean handleComponentRelativeSize(ComponentConnector paintable) {
  924. return false;
  925. }
  926. /**
  927. * Returns false.
  928. *
  929. * @param paintable
  930. * @return false, always
  931. * @deprecated As of 7.0, serves no purpose
  932. */
  933. @Deprecated
  934. public boolean handleComponentRelativeSize(Widget widget) {
  935. return handleComponentRelativeSize(connectorMap.getConnector(widget));
  936. }
  937. @Deprecated
  938. public ComponentConnector getPaintable(UIDL uidl) {
  939. // Non-component connectors shouldn't be painted from legacy connectors
  940. return (ComponentConnector) getConnector(uidl.getId(),
  941. Integer.parseInt(uidl.getTag()));
  942. }
  943. /**
  944. * Get either an existing ComponentConnector or create a new
  945. * ComponentConnector with the given type and id.
  946. *
  947. * If a ComponentConnector with the given id already exists, returns it.
  948. * Otherwise creates and registers a new ComponentConnector of the given
  949. * type.
  950. *
  951. * @param connectorId
  952. * Id of the paintable
  953. * @param connectorType
  954. * Type of the connector, as passed from the server side
  955. *
  956. * @return Either an existing ComponentConnector or a new ComponentConnector
  957. * of the given type
  958. */
  959. public ServerConnector getConnector(String connectorId, int connectorType) {
  960. if (!connectorMap.hasConnector(connectorId)) {
  961. return createAndRegisterConnector(connectorId, connectorType);
  962. }
  963. return connectorMap.getConnector(connectorId);
  964. }
  965. /**
  966. * Creates a new ServerConnector with the given type and id.
  967. *
  968. * Creates and registers a new ServerConnector of the given type. Should
  969. * never be called with the connector id of an existing connector.
  970. *
  971. * @param connectorId
  972. * Id of the new connector
  973. * @param connectorType
  974. * Type of the connector, as passed from the server side
  975. *
  976. * @return A new ServerConnector of the given type
  977. */
  978. private ServerConnector createAndRegisterConnector(String connectorId,
  979. int connectorType) {
  980. Profiler.enter("ApplicationConnection.createAndRegisterConnector");
  981. // Create and register a new connector with the given type
  982. ServerConnector p = widgetSet.createConnector(connectorType,
  983. configuration);
  984. connectorMap.registerConnector(connectorId, p);
  985. p.doInit(connectorId, this);
  986. Profiler.leave("ApplicationConnection.createAndRegisterConnector");
  987. return p;
  988. }
  989. /**
  990. * Gets a resource that has been pre-loaded via UIDL, such as custom
  991. * layouts.
  992. *
  993. * @param name
  994. * identifier of the resource to get
  995. * @return the resource
  996. */
  997. public String getResource(String name) {
  998. return resourcesMap.get(name);
  999. }
  1000. /**
  1001. * Sets a resource that has been pre-loaded via UIDL, such as custom
  1002. * layouts.
  1003. *
  1004. * @since 7.6
  1005. * @param name
  1006. * identifier of the resource to Set
  1007. * @param resource
  1008. * the resource
  1009. */
  1010. public void setResource(String name, String resource) {
  1011. resourcesMap.put(name, resource);
  1012. }
  1013. /**
  1014. * Singleton method to get instance of app's context menu.
  1015. *
  1016. * @return VContextMenu object
  1017. */
  1018. public VContextMenu getContextMenu() {
  1019. if (contextMenu == null) {
  1020. contextMenu = new VContextMenu();
  1021. contextMenu.setOwner(uIConnector.getWidget());
  1022. DOM.setElementProperty(contextMenu.getElement(), "id",
  1023. "PID_VAADIN_CM");
  1024. }
  1025. return contextMenu;
  1026. }
  1027. /**
  1028. * Gets an {@link Icon} instance corresponding to a URI.
  1029. *
  1030. * @since 7.2
  1031. * @param uri
  1032. * @return Icon object
  1033. */
  1034. public Icon getIcon(String uri) {
  1035. Icon icon;
  1036. if (uri == null) {
  1037. return null;
  1038. } else if (FontIcon.isFontIconUri(uri)) {
  1039. icon = GWT.create(FontIcon.class);
  1040. } else {
  1041. icon = GWT.create(ImageIcon.class);
  1042. }
  1043. icon.setUri(translateVaadinUri(uri));
  1044. return icon;
  1045. }
  1046. /**
  1047. * Translates custom protocols in UIDL URI's to be recognizable by browser.
  1048. * All uri's from UIDL should be routed via this method before giving them
  1049. * to browser due URI's in UIDL may contain custom protocols like theme://.
  1050. *
  1051. * @param uidlUri
  1052. * Vaadin URI from uidl
  1053. * @return translated URI ready for browser
  1054. */
  1055. public String translateVaadinUri(String uidlUri) {
  1056. return uriResolver.resolveVaadinUri(uidlUri);
  1057. }
  1058. /**
  1059. * Gets the URI for the current theme. Can be used to reference theme
  1060. * resources.
  1061. *
  1062. * @return URI to the current theme
  1063. */
  1064. public String getThemeUri() {
  1065. return configuration.getVaadinDirUrl() + "themes/"
  1066. + getUIConnector().getActiveTheme();
  1067. }
  1068. /* Extended title handling */
  1069. private final VTooltip tooltip;
  1070. private ConnectorMap connectorMap = GWT.create(ConnectorMap.class);
  1071. private final DependencyLoader dependencyLoader = GWT
  1072. .create(DependencyLoader.class);
  1073. /**
  1074. * Use to notify that the given component's caption has changed; layouts may
  1075. * have to be recalculated.
  1076. *
  1077. * @param widget
  1078. * The Widget whose caption has changed
  1079. * @deprecated As of 7.0.2, has not had any effect for a long time
  1080. */
  1081. @Deprecated
  1082. public void captionSizeUpdated(Widget widget) {
  1083. // This doesn't do anything, it's just kept here for compatibility
  1084. }
  1085. /**
  1086. * Gets the main view.
  1087. *
  1088. * @return the main view
  1089. */
  1090. public UIConnector getUIConnector() {
  1091. return uIConnector;
  1092. }
  1093. /**
  1094. * Gets the {@link ApplicationConfiguration} for the current application.
  1095. *
  1096. * @see ApplicationConfiguration
  1097. * @return the configuration for this application
  1098. */
  1099. public ApplicationConfiguration getConfiguration() {
  1100. return configuration;
  1101. }
  1102. /**
  1103. * Checks if there is a registered server side listener for the event. The
  1104. * list of events which has server side listeners is updated automatically
  1105. * before the component is updated so the value is correct if called from
  1106. * updatedFromUIDL.
  1107. *
  1108. * @param connector
  1109. * The connector to register event listeners for
  1110. * @param eventIdentifier
  1111. * The identifier for the event
  1112. * @return true if at least one listener has been registered on server side
  1113. * for the event identified by eventIdentifier.
  1114. * @deprecated As of 7.0. Use
  1115. * {@link AbstractConnector#hasEventListener(String)} instead
  1116. */
  1117. @Deprecated
  1118. public boolean hasEventListeners(ComponentConnector connector,
  1119. String eventIdentifier) {
  1120. return connector.hasEventListener(eventIdentifier);
  1121. }
  1122. /**
  1123. * Adds the get parameters to the uri and returns the new uri that contains
  1124. * the parameters.
  1125. *
  1126. * @param uri
  1127. * The uri to which the parameters should be added.
  1128. * @param extraParams
  1129. * One or more parameters in the format "a=b" or "c=d&e=f". An
  1130. * empty string is allowed but will not modify the url.
  1131. * @return The modified URI with the get parameters in extraParams added.
  1132. * @deprecated Use {@link SharedUtil#addGetParameters(String,String)}
  1133. * instead
  1134. */
  1135. @Deprecated
  1136. public static String addGetParameters(String uri, String extraParams) {
  1137. return SharedUtil.addGetParameters(uri, extraParams);
  1138. }
  1139. ConnectorMap getConnectorMap() {
  1140. return connectorMap;
  1141. }
  1142. /**
  1143. * @deprecated As of 7.0. No longer serves any purpose.
  1144. */
  1145. @Deprecated
  1146. public void unregisterPaintable(ServerConnector p) {
  1147. getLogger().info("unregisterPaintable (unnecessarily) called for "
  1148. + Util.getConnectorString(p));
  1149. }
  1150. /**
  1151. * Get VTooltip instance related to application connection.
  1152. *
  1153. * @return VTooltip instance
  1154. */
  1155. public VTooltip getVTooltip() {
  1156. return tooltip;
  1157. }
  1158. /**
  1159. * Method provided for backwards compatibility. Duties previously done by
  1160. * this method is now handled by the state change event handler in
  1161. * AbstractComponentConnector. The only function this method has is to
  1162. * return true if the UIDL is a "cached" update.
  1163. *
  1164. * @param component
  1165. * @param uidl
  1166. * @param manageCaption
  1167. * @deprecated As of 7.0, no longer serves any purpose
  1168. * @return
  1169. */
  1170. @Deprecated
  1171. public boolean updateComponent(Widget component, UIDL uidl,
  1172. boolean manageCaption) {
  1173. ComponentConnector connector = getConnectorMap()
  1174. .getConnector(component);
  1175. if (!AbstractComponentConnector.isRealUpdate(uidl)) {
  1176. return true;
  1177. }
  1178. if (!manageCaption) {
  1179. getLogger().warning(Util.getConnectorString(connector)
  1180. + " 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.");
  1181. }
  1182. return false;
  1183. }
  1184. /**
  1185. * @deprecated As of 7.0. Use
  1186. * {@link AbstractComponentConnector#hasEventListener(String)}
  1187. * instead
  1188. */
  1189. @Deprecated
  1190. public boolean hasEventListeners(Widget widget, String eventIdentifier) {
  1191. ComponentConnector connector = getConnectorMap().getConnector(widget);
  1192. if (connector == null) {
  1193. /*
  1194. * No connector will exist in cases where Vaadin widgets have been
  1195. * re-used without implementing server<->client communication.
  1196. */
  1197. return false;
  1198. }
  1199. return hasEventListeners(connector, eventIdentifier);
  1200. }
  1201. LayoutManager getLayoutManager() {
  1202. return layoutManager;
  1203. }
  1204. /**
  1205. * Schedules a heartbeat request to occur after the configured heartbeat
  1206. * interval elapses if the interval is a positive number. Otherwise, does
  1207. * nothing.
  1208. *
  1209. * @deprecated as of 7.2, use {@link Heartbeat#schedule()} instead
  1210. */
  1211. @Deprecated
  1212. protected void scheduleHeartbeat() {
  1213. heartbeat.schedule();
  1214. }
  1215. /**
  1216. * Sends a heartbeat request to the server.
  1217. * <p>
  1218. * Heartbeat requests are used to inform the server that the client-side is
  1219. * still alive. If the client page is closed or the connection lost, the
  1220. * server will eventually close the inactive UI.
  1221. *
  1222. * @deprecated as of 7.2, use {@link Heartbeat#send()} instead
  1223. */
  1224. @Deprecated
  1225. protected void sendHeartbeat() {
  1226. heartbeat.send();
  1227. }
  1228. public void handleCommunicationError(String details, int statusCode) {
  1229. boolean handled = false;
  1230. if (communicationErrorDelegate != null) {
  1231. handled = communicationErrorDelegate.onError(details, statusCode);
  1232. }
  1233. if (!handled) {
  1234. showCommunicationError(details, statusCode);
  1235. }
  1236. }
  1237. /**
  1238. * Sets the delegate that is called whenever a communication error occurrs.
  1239. *
  1240. * @param delegate
  1241. * the delegate.
  1242. */
  1243. public void setCommunicationErrorDelegate(
  1244. CommunicationErrorHandler delegate) {
  1245. communicationErrorDelegate = delegate;
  1246. }
  1247. public void setApplicationRunning(boolean applicationRunning) {
  1248. if (getApplicationState() == ApplicationState.TERMINATED) {
  1249. if (applicationRunning) {
  1250. getLogger().severe(
  1251. "Tried to restart a terminated application. This is not supported");
  1252. } else {
  1253. getLogger().warning(
  1254. "Tried to stop a terminated application. This should not be done");
  1255. }
  1256. return;
  1257. } else if (getApplicationState() == ApplicationState.INITIALIZING) {
  1258. if (applicationRunning) {
  1259. applicationState = ApplicationState.RUNNING;
  1260. } else {
  1261. getLogger().warning(
  1262. "Tried to stop the application before it has started. This should not be done");
  1263. }
  1264. } else if (getApplicationState() == ApplicationState.RUNNING) {
  1265. if (!applicationRunning) {
  1266. applicationState = ApplicationState.TERMINATED;
  1267. eventBus.fireEvent(new ApplicationStoppedEvent());
  1268. } else {
  1269. getLogger().warning(
  1270. "Tried to start an already running application. This should not be done");
  1271. }
  1272. }
  1273. }
  1274. /**
  1275. * Checks if the application is in the {@link ApplicationState#RUNNING}
  1276. * state.
  1277. *
  1278. * @since 7.6
  1279. * @return true if the application is in the running state, false otherwise
  1280. */
  1281. public boolean isApplicationRunning() {
  1282. return applicationState == ApplicationState.RUNNING;
  1283. }
  1284. public <H extends EventHandler> HandlerRegistration addHandler(
  1285. GwtEvent.Type<H> type, H handler) {
  1286. return eventBus.addHandler(type, handler);
  1287. }
  1288. @Override
  1289. public void fireEvent(GwtEvent<?> event) {
  1290. eventBus.fireEvent(event);
  1291. }
  1292. /**
  1293. * Calls {@link ComponentConnector#flush()} on the active connector. Does
  1294. * nothing if there is no active (focused) connector.
  1295. */
  1296. public void flushActiveConnector() {
  1297. ComponentConnector activeConnector = getActiveConnector();
  1298. if (activeConnector == null) {
  1299. return;
  1300. }
  1301. activeConnector.flush();
  1302. }
  1303. /**
  1304. * Gets the active connector for the focused element in the browser.
  1305. *
  1306. * @return the connector for the focused element or <code>null</code> if
  1307. * none found or no element is focused.
  1308. */
  1309. private ComponentConnector getActiveConnector() {
  1310. Element focusedElement = WidgetUtil.getFocusedElement();
  1311. if (focusedElement == null) {
  1312. return null;
  1313. }
  1314. return Util.getConnectorForElement(this, RootPanel.get(),
  1315. focusedElement);
  1316. }
  1317. private static Logger getLogger() {
  1318. return Logger.getLogger(ApplicationConnection.class.getName());
  1319. }
  1320. /**
  1321. * Returns the hearbeat instance.
  1322. */
  1323. public Heartbeat getHeartbeat() {
  1324. return heartbeat;
  1325. }
  1326. /**
  1327. * Returns the state of this application. An application state goes from
  1328. * "initializing" to "running" to "stopped". There is no way for an
  1329. * application to go back to a previous state, i.e. a stopped application
  1330. * can never be re-started
  1331. *
  1332. * @since 7.6
  1333. * @return the current state of this application
  1334. */
  1335. public ApplicationState getApplicationState() {
  1336. return applicationState;
  1337. }
  1338. /**
  1339. * Gets the server RPC queue for this application.
  1340. *
  1341. * @since 7.6
  1342. * @return the server RPC queue
  1343. */
  1344. public ServerRpcQueue getServerRpcQueue() {
  1345. return serverRpcQueue;
  1346. }
  1347. /**
  1348. * Gets the communication error handler for this application.
  1349. *
  1350. * @since 7.6
  1351. * @return the server RPC queue
  1352. */
  1353. public ConnectionStateHandler getConnectionStateHandler() {
  1354. return connectionStateHandler;
  1355. }
  1356. /**
  1357. * Gets the (server to client) message handler for this application.
  1358. *
  1359. * @since 7.6
  1360. * @return the message handler
  1361. */
  1362. public MessageHandler getMessageHandler() {
  1363. return messageHandler;
  1364. }
  1365. /**
  1366. * Gets the server rpc manager for this application.
  1367. *
  1368. * @since 7.6
  1369. * @return the server rpc manager
  1370. */
  1371. public RpcManager getRpcManager() {
  1372. return rpcManager;
  1373. }
  1374. /**
  1375. * Gets the (client to server) message sender for this application.
  1376. *
  1377. * @since 7.6
  1378. * @return the message sender
  1379. */
  1380. public MessageSender getMessageSender() {
  1381. return messageSender;
  1382. }
  1383. /**
  1384. * @since 7.6
  1385. * @return the widget set
  1386. */
  1387. public WidgetSet getWidgetSet() {
  1388. return widgetSet;
  1389. }
  1390. public int getLastSeenServerSyncId() {
  1391. return getMessageHandler().getLastSeenServerSyncId();
  1392. }
  1393. /**
  1394. * Gets the instance which handles loading of dependencies.
  1395. *
  1396. * @return the dependency loader for this connection
  1397. */
  1398. public DependencyLoader getDependencyLoader() {
  1399. return dependencyLoader;
  1400. }
  1401. }