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.

ApplicationConfiguration.java 30KB

преди 11 години
преди 12 години
преди 12 години
преди 12 години
преди 12 години
преди 12 години
преди 12 години
преди 12 години
преди 12 години
преди 12 години
преди 12 години
преди 12 години
преди 12 години
преди 12 години
преди 12 години
преди 12 години
преди 12 години
преди 12 години
преди 11 години
преди 12 години
преди 12 години
преди 11 години
преди 12 години
преди 11 години
преди 12 години
преди 12 години
преди 12 години
преди 12 години
преди 12 години
преди 12 години
преди 12 години
123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877
  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.ArrayList;
  18. import java.util.HashMap;
  19. import java.util.LinkedList;
  20. import java.util.List;
  21. import java.util.Map;
  22. import java.util.logging.Handler;
  23. import java.util.logging.Level;
  24. import java.util.logging.Logger;
  25. import com.google.gwt.core.client.EntryPoint;
  26. import com.google.gwt.core.client.GWT;
  27. import com.google.gwt.core.client.GWT.UncaughtExceptionHandler;
  28. import com.google.gwt.core.client.JavaScriptObject;
  29. import com.google.gwt.core.client.JsArrayString;
  30. import com.google.gwt.core.client.RunAsyncCallback;
  31. import com.google.gwt.core.client.Scheduler;
  32. import com.google.gwt.core.client.Scheduler.ScheduledCommand;
  33. import com.google.gwt.core.client.ScriptInjector;
  34. import com.google.gwt.dom.client.Element;
  35. import com.google.gwt.logging.client.LogConfiguration;
  36. import com.google.gwt.user.client.Command;
  37. import com.google.gwt.user.client.Window;
  38. import com.vaadin.client.debug.internal.ErrorNotificationHandler;
  39. import com.vaadin.client.debug.internal.HierarchySection;
  40. import com.vaadin.client.debug.internal.InfoSection;
  41. import com.vaadin.client.debug.internal.LogSection;
  42. import com.vaadin.client.debug.internal.NetworkSection;
  43. import com.vaadin.client.debug.internal.ProfilerSection;
  44. import com.vaadin.client.debug.internal.Section;
  45. import com.vaadin.client.debug.internal.TestBenchSection;
  46. import com.vaadin.client.debug.internal.VDebugWindow;
  47. import com.vaadin.client.debug.internal.theme.DebugWindowStyles;
  48. import com.vaadin.client.event.PointerEventSupport;
  49. import com.vaadin.client.metadata.BundleLoadCallback;
  50. import com.vaadin.client.metadata.ConnectorBundleLoader;
  51. import com.vaadin.client.metadata.NoDataException;
  52. import com.vaadin.client.metadata.TypeData;
  53. import com.vaadin.client.ui.UnknownComponentConnector;
  54. import com.vaadin.client.ui.ui.UIConnector;
  55. import com.vaadin.shared.ApplicationConstants;
  56. import com.vaadin.shared.ui.ui.UIConstants;
  57. public class ApplicationConfiguration implements EntryPoint {
  58. /**
  59. * Helper class for reading configuration options from the bootstap
  60. * javascript
  61. *
  62. * @since 7.0
  63. */
  64. private static class JsoConfiguration extends JavaScriptObject {
  65. protected JsoConfiguration() {
  66. // JSO Constructor
  67. }
  68. /**
  69. * Reads a configuration parameter as a string. Please note that the
  70. * javascript value of the parameter should also be a string, or else an
  71. * undefined exception may be thrown.
  72. *
  73. * @param name
  74. * name of the configuration parameter
  75. * @return value of the configuration parameter, or <code>null</code> if
  76. * not defined
  77. */
  78. private native String getConfigString(String name)
  79. /*-{
  80. var value = this.getConfig(name);
  81. if (value === null || value === undefined) {
  82. return null;
  83. } else {
  84. return value +"";
  85. }
  86. }-*/;
  87. /**
  88. * Reads a configuration parameter as a boolean object. Please note that
  89. * the javascript value of the parameter should also be a boolean, or
  90. * else an undefined exception may be thrown.
  91. *
  92. * @param name
  93. * name of the configuration parameter
  94. * @return boolean value of the configuration paramter, or
  95. * <code>null</code> if no value is defined
  96. */
  97. private native Boolean getConfigBoolean(String name)
  98. /*-{
  99. var value = this.getConfig(name);
  100. if (value === null || value === undefined) {
  101. return null;
  102. } else {
  103. // $entry not needed as function is not exported
  104. return @java.lang.Boolean::valueOf(Z)(value);
  105. }
  106. }-*/;
  107. /**
  108. * Reads a configuration parameter as an integer object. Please note
  109. * that the javascript value of the parameter should also be an integer,
  110. * or else an undefined exception may be thrown.
  111. *
  112. * @param name
  113. * name of the configuration parameter
  114. * @return integer value of the configuration paramter, or
  115. * <code>null</code> if no value is defined
  116. */
  117. private native Integer getConfigInteger(String name)
  118. /*-{
  119. var value = this.getConfig(name);
  120. if (value === null || value === undefined) {
  121. return null;
  122. } else {
  123. // $entry not needed as function is not exported
  124. return @java.lang.Integer::valueOf(I)(value);
  125. }
  126. }-*/;
  127. /**
  128. * Reads a configuration parameter as an {@link ErrorMessage} object.
  129. * Please note that the javascript value of the parameter should also be
  130. * an object with appropriate fields, or else an undefined exception may
  131. * be thrown when calling this method or when calling methods on the
  132. * returned object.
  133. *
  134. * @param name
  135. * name of the configuration parameter
  136. * @return error message with the given name, or <code>null</code> if no
  137. * value is defined
  138. */
  139. private native ErrorMessage getConfigError(String name)
  140. /*-{
  141. return this.getConfig(name);
  142. }-*/;
  143. /**
  144. * Returns a native javascript object containing version information
  145. * from the server.
  146. *
  147. * @return a javascript object with the version information
  148. */
  149. private native JavaScriptObject getVersionInfoJSObject()
  150. /*-{
  151. return this.getConfig("versionInfo");
  152. }-*/;
  153. /**
  154. * Gets the version of the Vaadin framework used on the server.
  155. *
  156. * @return a string with the version
  157. *
  158. * @see com.vaadin.server.VaadinServlet#VERSION
  159. */
  160. private native String getVaadinVersion()
  161. /*-{
  162. return this.getConfig("versionInfo").vaadinVersion;
  163. }-*/;
  164. /**
  165. * Gets the version of the Atmosphere framework.
  166. *
  167. * @return a string with the version
  168. *
  169. * @see org.atmosphere.util#getRawVersion()
  170. */
  171. private native String getAtmosphereVersion()
  172. /*-{
  173. return this.getConfig("versionInfo").atmosphereVersion;
  174. }-*/;
  175. /**
  176. * Gets the JS version used in the Atmosphere framework.
  177. *
  178. * @return a string with the version
  179. */
  180. private native String getAtmosphereJSVersion()
  181. /*-{
  182. if ($wnd.vaadinPush && $wnd.vaadinPush.atmosphere) {
  183. return $wnd.vaadinPush.atmosphere.version;
  184. } else {
  185. return null;
  186. }
  187. }-*/;
  188. private native String getUIDL()
  189. /*-{
  190. return this.getConfig("uidl");
  191. }-*/;
  192. }
  193. /**
  194. * Wraps a native javascript object containing fields for an error message
  195. *
  196. * @since 7.0
  197. */
  198. public static final class ErrorMessage extends JavaScriptObject {
  199. protected ErrorMessage() {
  200. // JSO constructor
  201. }
  202. public final native String getCaption()
  203. /*-{
  204. return this.caption;
  205. }-*/;
  206. public final native String getMessage()
  207. /*-{
  208. return this.message;
  209. }-*/;
  210. public final native String getUrl()
  211. /*-{
  212. return this.url;
  213. }-*/;
  214. }
  215. private static WidgetSet widgetSet = GWT.create(WidgetSet.class);
  216. private String id;
  217. /**
  218. * The URL to the VAADIN directory containing themes and widgetsets. Should
  219. * always end with a slash (/).
  220. */
  221. private String vaadinDirUrl;
  222. private String serviceUrl;
  223. private int uiId;
  224. private boolean standalone;
  225. private ErrorMessage communicationError;
  226. private ErrorMessage authorizationError;
  227. private ErrorMessage sessionExpiredError;
  228. private int heartbeatInterval;
  229. private HashMap<Integer, String> unknownComponents;
  230. private Map<Integer, Class<? extends ServerConnector>> classes = new HashMap<Integer, Class<? extends ServerConnector>>();
  231. private boolean widgetsetVersionSent = false;
  232. private static boolean moduleLoaded = false;
  233. static// TODO consider to make this hashmap per application
  234. LinkedList<Command> callbacks = new LinkedList<Command>();
  235. private static int dependenciesLoading;
  236. private static ArrayList<ApplicationConnection> runningApplications = new ArrayList<ApplicationConnection>();
  237. private Map<Integer, Integer> componentInheritanceMap = new HashMap<Integer, Integer>();
  238. private Map<Integer, String> tagToServerSideClassName = new HashMap<Integer, String>();
  239. /**
  240. * Checks whether path info in requests to the server-side service should be
  241. * in a request parameter (named <code>v-resourcePath</code>) or appended to
  242. * the end of the service URL.
  243. *
  244. * @see #getServiceUrl()
  245. *
  246. * @return <code>true</code> if path info should be a request parameter;
  247. * <code>false</code> if the path info goes after the service URL
  248. */
  249. public boolean useServiceUrlPathParam() {
  250. return getServiceUrlParameterName() != null;
  251. }
  252. /**
  253. * Return the name of the parameter used to to send data to the service url.
  254. * This method should only be called if {@link #useServiceUrlPathParam()} is
  255. * true.
  256. *
  257. * @since 7.1.6
  258. * @return The parameter name, by default <code>v-resourcePath</code>
  259. */
  260. public String getServiceUrlParameterName() {
  261. return getJsoConfiguration(id).getConfigString(
  262. ApplicationConstants.SERVICE_URL_PARAMETER_NAME);
  263. }
  264. public String getRootPanelId() {
  265. return id;
  266. }
  267. /**
  268. * Gets the URL to the server-side VaadinService. If
  269. * {@link #useServiceUrlPathParam()} return <code>true</code>, the requested
  270. * path info should be in the <code>v-resourcePath</code> query parameter;
  271. * else the path info should be appended to the end of the URL.
  272. *
  273. * @see #useServiceUrlPathParam()
  274. *
  275. * @return the URL to the server-side service as a string
  276. */
  277. public String getServiceUrl() {
  278. return serviceUrl;
  279. }
  280. /**
  281. * @return the theme name used when initializing the application
  282. * @deprecated as of 7.3. Use {@link UIConnector#getActiveTheme()} to get
  283. * the theme currently in use
  284. */
  285. @Deprecated
  286. public String getThemeName() {
  287. return getJsoConfiguration(id).getConfigString("theme");
  288. }
  289. /**
  290. * Gets the URL of the VAADIN directory on the server.
  291. *
  292. * @return the URL of the VAADIN directory
  293. */
  294. public String getVaadinDirUrl() {
  295. return vaadinDirUrl;
  296. }
  297. public void setAppId(String appId) {
  298. id = appId;
  299. }
  300. /**
  301. * Gets the initial UIDL from the DOM, if it was provided during the init
  302. * process.
  303. *
  304. * @return
  305. */
  306. public String getUIDL() {
  307. return getJsoConfiguration(id).getUIDL();
  308. }
  309. /**
  310. * @return true if the application is served by std. Vaadin servlet and is
  311. * considered to be the only or main content of the host page.
  312. */
  313. public boolean isStandalone() {
  314. return standalone;
  315. }
  316. /**
  317. * Gets the UI id of the server-side UI associated with this client-side
  318. * instance. The UI id should be included in every request originating from
  319. * this instance in order to associate the request with the right UI
  320. * instance on the server.
  321. *
  322. * @return the UI id
  323. */
  324. public int getUIId() {
  325. return uiId;
  326. }
  327. /**
  328. * @return The interval in seconds between heartbeat requests, or a
  329. * non-positive number if heartbeat is disabled.
  330. */
  331. public int getHeartbeatInterval() {
  332. return heartbeatInterval;
  333. }
  334. public JavaScriptObject getVersionInfoJSObject() {
  335. return getJsoConfiguration(id).getVersionInfoJSObject();
  336. }
  337. public ErrorMessage getCommunicationError() {
  338. return communicationError;
  339. }
  340. public ErrorMessage getAuthorizationError() {
  341. return authorizationError;
  342. }
  343. public ErrorMessage getSessionExpiredError() {
  344. return sessionExpiredError;
  345. }
  346. /**
  347. * Reads the configuration values defined by the bootstrap javascript.
  348. */
  349. private void loadFromDOM() {
  350. JsoConfiguration jsoConfiguration = getJsoConfiguration(id);
  351. serviceUrl = jsoConfiguration
  352. .getConfigString(ApplicationConstants.SERVICE_URL);
  353. if (serviceUrl == null || "".equals(serviceUrl)) {
  354. /*
  355. * Use the current url without query parameters and fragment as the
  356. * default value.
  357. */
  358. serviceUrl = Window.Location.getHref().replaceFirst("[?#].*", "");
  359. } else {
  360. /*
  361. * Resolve potentially relative URLs to ensure they point to the
  362. * desired locations even if the base URL of the page changes later
  363. * (e.g. with pushState)
  364. */
  365. serviceUrl = WidgetUtil.getAbsoluteUrl(serviceUrl);
  366. }
  367. // Ensure there's an ending slash (to make appending e.g. UIDL work)
  368. if (!useServiceUrlPathParam() && !serviceUrl.endsWith("/")) {
  369. serviceUrl += '/';
  370. }
  371. vaadinDirUrl = WidgetUtil.getAbsoluteUrl(jsoConfiguration
  372. .getConfigString(ApplicationConstants.VAADIN_DIR_URL));
  373. uiId = jsoConfiguration.getConfigInteger(UIConstants.UI_ID_PARAMETER)
  374. .intValue();
  375. // null -> false
  376. standalone = jsoConfiguration
  377. .getConfigBoolean("standalone") == Boolean.TRUE;
  378. heartbeatInterval = jsoConfiguration
  379. .getConfigInteger("heartbeatInterval");
  380. communicationError = jsoConfiguration.getConfigError("comErrMsg");
  381. authorizationError = jsoConfiguration.getConfigError("authErrMsg");
  382. sessionExpiredError = jsoConfiguration.getConfigError("sessExpMsg");
  383. }
  384. /**
  385. * Starts the application with a given id by reading the configuration
  386. * options stored by the bootstrap javascript.
  387. *
  388. * @param applicationId
  389. * id of the application to load, this is also the id of the html
  390. * element into which the application should be rendered.
  391. */
  392. public static void startApplication(final String applicationId) {
  393. Scheduler.get().scheduleDeferred(new ScheduledCommand() {
  394. @Override
  395. public void execute() {
  396. Profiler.enter("ApplicationConfiguration.startApplication");
  397. ApplicationConfiguration appConf = getConfigFromDOM(
  398. applicationId);
  399. ApplicationConnection a = GWT
  400. .create(ApplicationConnection.class);
  401. a.init(widgetSet, appConf);
  402. runningApplications.add(a);
  403. Profiler.leave("ApplicationConfiguration.startApplication");
  404. a.start();
  405. }
  406. });
  407. }
  408. public static List<ApplicationConnection> getRunningApplications() {
  409. return runningApplications;
  410. }
  411. /**
  412. * Gets the configuration object for a specific application from the
  413. * bootstrap javascript.
  414. *
  415. * @param appId
  416. * the id of the application to get configuration data for
  417. * @return a native javascript object containing the configuration data
  418. */
  419. private native static JsoConfiguration getJsoConfiguration(String appId)
  420. /*-{
  421. return $wnd.vaadin.getApp(appId);
  422. }-*/;
  423. public static ApplicationConfiguration getConfigFromDOM(String appId) {
  424. ApplicationConfiguration conf = new ApplicationConfiguration();
  425. conf.setAppId(appId);
  426. conf.loadFromDOM();
  427. return conf;
  428. }
  429. public String getServletVersion() {
  430. return getJsoConfiguration(id).getVaadinVersion();
  431. }
  432. /**
  433. * Return Atmosphere version.
  434. *
  435. * @since 7.4
  436. *
  437. * @return Atmosphere version.
  438. */
  439. public String getAtmosphereVersion() {
  440. return getJsoConfiguration(id).getAtmosphereVersion();
  441. }
  442. /**
  443. * Return Atmosphere JS version.
  444. *
  445. * @since 7.4
  446. *
  447. * @return Atmosphere JS version.
  448. */
  449. public String getAtmosphereJSVersion() {
  450. return getJsoConfiguration(id).getAtmosphereJSVersion();
  451. }
  452. public Class<? extends ServerConnector> getConnectorClassByEncodedTag(
  453. int tag) {
  454. Class<? extends ServerConnector> type = classes.get(tag);
  455. if (type == null && !classes.containsKey(tag)) {
  456. // Initialize if not already loaded
  457. Integer currentTag = Integer.valueOf(tag);
  458. while (type == null && currentTag != null) {
  459. String serverSideClassNameForTag = getServerSideClassNameForTag(
  460. currentTag);
  461. if (TypeData.hasIdentifier(serverSideClassNameForTag)) {
  462. try {
  463. type = (Class<? extends ServerConnector>) TypeData
  464. .getClass(serverSideClassNameForTag);
  465. } catch (NoDataException e) {
  466. throw new RuntimeException(e);
  467. }
  468. }
  469. currentTag = getParentTag(currentTag.intValue());
  470. }
  471. if (type == null) {
  472. type = UnknownComponentConnector.class;
  473. if (unknownComponents == null) {
  474. unknownComponents = new HashMap<Integer, String>();
  475. }
  476. unknownComponents.put(tag, getServerSideClassNameForTag(tag));
  477. }
  478. classes.put(tag, type);
  479. }
  480. return type;
  481. }
  482. public void addComponentInheritanceInfo(ValueMap valueMap) {
  483. JsArrayString keyArray = valueMap.getKeyArray();
  484. for (int i = 0; i < keyArray.length(); i++) {
  485. String key = keyArray.get(i);
  486. int value = valueMap.getInt(key);
  487. componentInheritanceMap.put(Integer.parseInt(key), value);
  488. }
  489. }
  490. public void addComponentMappings(ValueMap valueMap, WidgetSet widgetSet) {
  491. JsArrayString keyArray = valueMap.getKeyArray();
  492. for (int i = 0; i < keyArray.length(); i++) {
  493. String key = keyArray.get(i).intern();
  494. int value = valueMap.getInt(key);
  495. tagToServerSideClassName.put(value, key);
  496. }
  497. for (int i = 0; i < keyArray.length(); i++) {
  498. String key = keyArray.get(i).intern();
  499. int value = valueMap.getInt(key);
  500. widgetSet.ensureConnectorLoaded(value, this);
  501. }
  502. }
  503. /**
  504. * Returns all tags for given class. Tags are used in
  505. * {@link ApplicationConfiguration} to keep track of different classes and
  506. * their hierarchy
  507. *
  508. * @since 7.2
  509. * @param classname
  510. * name of class which tags we want
  511. * @return Integer array of tags pointing to this classname
  512. */
  513. public Integer[] getTagsForServerSideClassName(String classname) {
  514. List<Integer> tags = new ArrayList<Integer>();
  515. for (Map.Entry<Integer, String> entry : tagToServerSideClassName
  516. .entrySet()) {
  517. if (classname.equals(entry.getValue())) {
  518. tags.add(entry.getKey());
  519. }
  520. }
  521. Integer[] out = new Integer[tags.size()];
  522. return tags.toArray(out);
  523. }
  524. public Integer getParentTag(int tag) {
  525. return componentInheritanceMap.get(tag);
  526. }
  527. public String getServerSideClassNameForTag(Integer tag) {
  528. return tagToServerSideClassName.get(tag);
  529. }
  530. String getUnknownServerClassNameByTag(int tag) {
  531. if (unknownComponents != null) {
  532. String className = unknownComponents.get(tag);
  533. if (className == null) {
  534. className = "unknown class with id " + tag;
  535. }
  536. return className;
  537. }
  538. return null;
  539. }
  540. /**
  541. * @since 7.6
  542. * @param c
  543. */
  544. public static void runWhenDependenciesLoaded(Command c) {
  545. if (dependenciesLoading == 0) {
  546. c.execute();
  547. } else {
  548. callbacks.add(c);
  549. }
  550. }
  551. static void startDependencyLoading() {
  552. dependenciesLoading++;
  553. }
  554. static void endDependencyLoading() {
  555. dependenciesLoading--;
  556. if (dependenciesLoading == 0 && !callbacks.isEmpty()) {
  557. for (Command cmd : callbacks) {
  558. cmd.execute();
  559. }
  560. callbacks.clear();
  561. } else if (dependenciesLoading == 0 && !ConnectorBundleLoader.get()
  562. .isBundleLoaded(ConnectorBundleLoader.DEFERRED_BUNDLE_NAME)) {
  563. ConnectorBundleLoader.get().loadBundle(
  564. ConnectorBundleLoader.DEFERRED_BUNDLE_NAME,
  565. new BundleLoadCallback() {
  566. @Override
  567. public void loaded() {
  568. // Nothing to do
  569. }
  570. @Override
  571. public void failed(Throwable reason) {
  572. getLogger().log(Level.SEVERE,
  573. "Error loading deferred bundle", reason);
  574. }
  575. });
  576. }
  577. }
  578. private boolean vaadinBootstrapLoaded() {
  579. Element window = ScriptInjector.TOP_WINDOW.cast();
  580. return window.getPropertyJSO("vaadin") != null;
  581. }
  582. @Override
  583. public void onModuleLoad() {
  584. // Don't run twice if the module has been inherited several times,
  585. // and don't continue if vaadinBootstrap was not executed.
  586. if (moduleLoaded || !vaadinBootstrapLoaded()) {
  587. getLogger().log(Level.WARNING,
  588. "vaadinBootstrap.js was not loaded, skipping vaadin application configuration.");
  589. return;
  590. }
  591. moduleLoaded = true;
  592. Profiler.initialize();
  593. Profiler.enter("ApplicationConfiguration.onModuleLoad");
  594. BrowserInfo browserInfo = BrowserInfo.get();
  595. // Enable iOS6 cast fix (see #10460)
  596. if (browserInfo.isIOS6() && browserInfo.isWebkit()) {
  597. enableIOS6castFix();
  598. }
  599. // Enable IE prompt fix (#13367)
  600. if (browserInfo.isIE() && browserInfo.getBrowserMajorVersion() >= 10) {
  601. enableIEPromptFix();
  602. }
  603. // Register pointer events (must be done before any events are used)
  604. PointerEventSupport.init();
  605. // Prepare the debugging window
  606. if (isDebugMode()) {
  607. /*
  608. * XXX Lots of implementation details here right now. This should be
  609. * cleared up when an API for extending the debug window is
  610. * implemented.
  611. */
  612. VDebugWindow window = VDebugWindow.get();
  613. if (LogConfiguration.loggingIsEnabled()) {
  614. window.addSection((Section) GWT.create(LogSection.class));
  615. }
  616. window.addSection((Section) GWT.create(InfoSection.class));
  617. window.addSection((Section) GWT.create(HierarchySection.class));
  618. window.addSection((Section) GWT.create(NetworkSection.class));
  619. window.addSection((Section) GWT.create(TestBenchSection.class));
  620. if (Profiler.isEnabled()) {
  621. window.addSection((Section) GWT.create(ProfilerSection.class));
  622. }
  623. if (isQuietDebugMode()) {
  624. window.close();
  625. } else {
  626. // Load debug window styles asynchronously
  627. GWT.runAsync(new RunAsyncCallback() {
  628. @Override
  629. public void onSuccess() {
  630. DebugWindowStyles dws = GWT
  631. .create(DebugWindowStyles.class);
  632. dws.css().ensureInjected();
  633. }
  634. @Override
  635. public void onFailure(Throwable reason) {
  636. Window.alert(
  637. "Failed to load Vaadin debug window styles");
  638. }
  639. });
  640. window.init();
  641. }
  642. // Connect to the legacy API
  643. VConsole.setImplementation(window);
  644. Handler errorNotificationHandler = GWT
  645. .create(ErrorNotificationHandler.class);
  646. Logger.getLogger("").addHandler(errorNotificationHandler);
  647. }
  648. if (LogConfiguration.loggingIsEnabled()) {
  649. GWT.setUncaughtExceptionHandler(new UncaughtExceptionHandler() {
  650. @Override
  651. public void onUncaughtException(Throwable e) {
  652. /*
  653. * If the debug window is not enabled (?debug), this will
  654. * not show anything to normal users. "a1 is not an object"
  655. * style errors helps nobody, especially end user. It does
  656. * not work tells just as much.
  657. */
  658. getLogger().log(Level.SEVERE, e.getMessage(), e);
  659. }
  660. });
  661. if (isProductionMode()) {
  662. // Disable all logging if in production mode
  663. Logger.getLogger("").setLevel(Level.OFF);
  664. }
  665. }
  666. Profiler.leave("ApplicationConfiguration.onModuleLoad");
  667. if (SuperDevMode.enableBasedOnParameter()) {
  668. // Do not start any application as super dev mode will refresh the
  669. // page once done compiling
  670. return;
  671. }
  672. registerCallback(GWT.getModuleName());
  673. }
  674. /**
  675. * Fix to iOS6 failing when comparing with 0 directly after the kind of
  676. * comparison done by GWT when a double or float is cast to an int. Forcing
  677. * another trivial operation (other than a compare to 0) after the dangerous
  678. * comparison makes the issue go away. See #10460.
  679. */
  680. private static native void enableIOS6castFix()
  681. /*-{
  682. Math.max = function(a,b) {return (a > b === 1 < 2)? a : b}
  683. Math.min = function(a,b) {return (a < b === 1 < 2)? a : b}
  684. }-*/;
  685. /**
  686. * Make Metro versions of IE suggest switching to the desktop when
  687. * window.prompt is called.
  688. */
  689. private static native void enableIEPromptFix()
  690. /*-{
  691. var prompt = $wnd.prompt;
  692. $wnd.prompt = function () {
  693. var result = prompt.apply($wnd, Array.prototype.slice.call(arguments));
  694. if (result === undefined) {
  695. // force the browser to suggest desktop mode
  696. showModalDialog();
  697. return null;
  698. } else {
  699. return result;
  700. }
  701. };
  702. }-*/;
  703. /**
  704. * Registers that callback that the bootstrap javascript uses to start
  705. * applications once the widgetset is loaded and all required information is
  706. * available
  707. *
  708. * @param widgetsetName
  709. * the name of this widgetset
  710. */
  711. public native static void registerCallback(String widgetsetName)
  712. /*-{
  713. var callbackHandler = $entry(@com.vaadin.client.ApplicationConfiguration::startApplication(Ljava/lang/String;));
  714. $wnd.vaadin.registerWidgetset(widgetsetName, callbackHandler);
  715. }-*/;
  716. /**
  717. * Checks if client side is in debug mode. Practically this is invoked by
  718. * adding ?debug parameter to URI. Please note that debug mode is always
  719. * disabled if production mode is enabled, but disabling production mode
  720. * does not automatically enable debug mode.
  721. *
  722. * @see #isProductionMode()
  723. *
  724. * @return true if client side is currently been debugged
  725. */
  726. public static boolean isDebugMode() {
  727. return isDebugAvailable()
  728. && Window.Location.getParameter("debug") != null;
  729. }
  730. /**
  731. * Checks if production mode is enabled. When production mode is enabled,
  732. * client-side logging is disabled. There may also be other performance
  733. * optimizations.
  734. *
  735. * @since 7.1.2
  736. * @return <code>true</code> if production mode is enabled; otherwise
  737. * <code>false</code>.
  738. */
  739. public static boolean isProductionMode() {
  740. return !isDebugAvailable();
  741. }
  742. private native static boolean isDebugAvailable()
  743. /*-{
  744. if($wnd.vaadin.debug) {
  745. return true;
  746. } else {
  747. return false;
  748. }
  749. }-*/;
  750. /**
  751. * Checks whether debug logging should be quiet
  752. *
  753. * @return <code>true</code> if debug logging should be quiet
  754. */
  755. public static boolean isQuietDebugMode() {
  756. String debugParameter = Window.Location.getParameter("debug");
  757. return isDebugAvailable() && debugParameter != null
  758. && debugParameter.startsWith("q");
  759. }
  760. /**
  761. * Checks whether the widget set version has been sent to the server. It is
  762. * sent in the first UIDL request.
  763. *
  764. * @return <code>true</code> if browser information has already been sent
  765. */
  766. public boolean isWidgetsetVersionSent() {
  767. return widgetsetVersionSent;
  768. }
  769. /**
  770. * Registers that the widget set version has been sent to the server.
  771. */
  772. public void setWidgetsetVersionSent() {
  773. widgetsetVersionSent = true;
  774. }
  775. private static final Logger getLogger() {
  776. return Logger.getLogger(ApplicationConfiguration.class.getName());
  777. }
  778. }