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

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