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

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