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.

Application.java 64KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036103710381039104010411042104310441045104610471048104910501051105210531054105510561057105810591060106110621063106410651066106710681069107010711072107310741075107610771078107910801081108210831084108510861087108810891090109110921093109410951096109710981099110011011102110311041105110611071108110911101111111211131114111511161117111811191120112111221123112411251126112711281129113011311132113311341135113611371138113911401141114211431144114511461147114811491150115111521153115411551156115711581159116011611162116311641165116611671168116911701171117211731174117511761177117811791180118111821183118411851186118711881189119011911192119311941195119611971198119912001201120212031204120512061207120812091210121112121213121412151216121712181219122012211222122312241225122612271228122912301231123212331234123512361237123812391240124112421243124412451246124712481249125012511252125312541255125612571258125912601261126212631264126512661267126812691270127112721273127412751276127712781279128012811282128312841285128612871288128912901291129212931294129512961297129812991300130113021303130413051306130713081309131013111312131313141315131613171318131913201321132213231324132513261327132813291330133113321333133413351336133713381339134013411342134313441345134613471348134913501351135213531354135513561357135813591360136113621363136413651366136713681369137013711372137313741375137613771378137913801381138213831384138513861387138813891390139113921393139413951396139713981399140014011402140314041405140614071408140914101411141214131414141514161417141814191420142114221423142414251426142714281429143014311432143314341435143614371438143914401441144214431444144514461447144814491450145114521453145414551456145714581459146014611462146314641465146614671468146914701471147214731474147514761477147814791480148114821483148414851486148714881489149014911492149314941495149614971498149915001501150215031504150515061507150815091510151115121513151415151516151715181519152015211522152315241525152615271528152915301531153215331534153515361537153815391540154115421543154415451546154715481549155015511552155315541555155615571558155915601561156215631564156515661567156815691570157115721573157415751576157715781579158015811582158315841585158615871588158915901591159215931594159515961597159815991600160116021603160416051606160716081609161016111612161316141615161616171618161916201621162216231624162516261627162816291630163116321633163416351636163716381639164016411642164316441645164616471648164916501651165216531654165516561657165816591660166116621663166416651666166716681669167016711672167316741675167616771678167916801681168216831684168516861687168816891690169116921693169416951696169716981699170017011702170317041705170617071708170917101711171217131714171517161717171817191720172117221723172417251726172717281729173017311732173317341735173617371738173917401741174217431744174517461747174817491750175117521753175417551756175717581759176017611762176317641765176617671768176917701771177217731774177517761777177817791780178117821783178417851786178717881789179017911792179317941795179617971798179918001801180218031804180518061807180818091810181118121813181418151816181718181819182018211822182318241825182618271828182918301831183218331834183518361837183818391840184118421843184418451846184718481849185018511852185318541855185618571858185918601861186218631864186518661867186818691870187118721873187418751876187718781879188018811882188318841885188618871888188918901891189218931894189518961897189818991900190119021903190419051906190719081909
  1. /*
  2. @VaadinApache2LicenseForJavaFiles@
  3. */
  4. package com.vaadin;
  5. import java.io.Serializable;
  6. import java.net.SocketException;
  7. import java.net.URL;
  8. import java.util.Collection;
  9. import java.util.Collections;
  10. import java.util.Enumeration;
  11. import java.util.EventListener;
  12. import java.util.EventObject;
  13. import java.util.Hashtable;
  14. import java.util.Iterator;
  15. import java.util.LinkedList;
  16. import java.util.Locale;
  17. import java.util.Properties;
  18. import java.util.logging.Level;
  19. import java.util.logging.Logger;
  20. import com.vaadin.service.ApplicationContext;
  21. import com.vaadin.terminal.ApplicationResource;
  22. import com.vaadin.terminal.DownloadStream;
  23. import com.vaadin.terminal.ErrorMessage;
  24. import com.vaadin.terminal.ParameterHandler;
  25. import com.vaadin.terminal.SystemError;
  26. import com.vaadin.terminal.Terminal;
  27. import com.vaadin.terminal.URIHandler;
  28. import com.vaadin.terminal.VariableOwner;
  29. import com.vaadin.terminal.gwt.server.ChangeVariablesErrorEvent;
  30. import com.vaadin.terminal.gwt.server.PortletApplicationContext;
  31. import com.vaadin.terminal.gwt.server.WebApplicationContext;
  32. import com.vaadin.ui.AbstractComponent;
  33. import com.vaadin.ui.Window;
  34. /**
  35. * <p>
  36. * Base class required for all Vaadin applications. This class provides all the
  37. * basic services required by Vaadin. These services allow external discovery
  38. * and manipulation of the user, {@link com.vaadin.ui.Window windows} and
  39. * themes, and starting and stopping the application.
  40. * </p>
  41. *
  42. * <p>
  43. * As mentioned, all Vaadin applications must inherit this class. However, this
  44. * is almost all of what one needs to do to create a fully functional
  45. * application. The only thing a class inheriting the <code>Application</code>
  46. * needs to do is implement the <code>init</code> method where it creates the
  47. * windows it needs to perform its function. Note that all applications must
  48. * have at least one window: the main window. The first unnamed window
  49. * constructed by an application automatically becomes the main window which
  50. * behaves just like other windows with one exception: when accessing windows
  51. * using URLs the main window corresponds to the application URL whereas other
  52. * windows correspond to a URL gotten by catenating the window's name to the
  53. * application URL.
  54. * </p>
  55. *
  56. * <p>
  57. * See the class <code>com.vaadin.demo.HelloWorld</code> for a simple example of
  58. * a fully working application.
  59. * </p>
  60. *
  61. * <p>
  62. * <strong>Window access.</strong> <code>Application</code> provides methods to
  63. * list, add and remove the windows it contains.
  64. * </p>
  65. *
  66. * <p>
  67. * <strong>Execution control.</strong> This class includes method to start and
  68. * finish the execution of the application. Being finished means basically that
  69. * no windows will be available from the application anymore.
  70. * </p>
  71. *
  72. * <p>
  73. * <strong>Theme selection.</strong> The theme selection process allows a theme
  74. * to be specified at three different levels. When a window's theme needs to be
  75. * found out, the window itself is queried for a preferred theme. If the window
  76. * does not prefer a specific theme, the application containing the window is
  77. * queried. If neither the application prefers a theme, the default theme for
  78. * the {@link com.vaadin.terminal.Terminal terminal} is used. The terminal
  79. * always defines a default theme.
  80. * </p>
  81. *
  82. * @author Vaadin Ltd.
  83. * @version
  84. * @VERSION@
  85. * @since 3.0
  86. */
  87. @SuppressWarnings("serial")
  88. public abstract class Application implements URIHandler,
  89. Terminal.ErrorListener, Serializable {
  90. private final static Logger logger = Logger.getLogger(Application.class
  91. .getName());
  92. /**
  93. * Id use for the next window that is opened. Access to this must be
  94. * synchronized.
  95. */
  96. private int nextWindowId = 1;
  97. /**
  98. * Application context the application is running in.
  99. */
  100. private ApplicationContext context;
  101. /**
  102. * The current user or <code>null</code> if no user has logged in.
  103. */
  104. private Object user;
  105. /**
  106. * Mapping from window name to window instance.
  107. */
  108. private final Hashtable<String, Window> windows = new Hashtable<String, Window>();
  109. /**
  110. * Main window of the application.
  111. */
  112. private Window mainWindow = null;
  113. /**
  114. * The application's URL.
  115. */
  116. private URL applicationUrl;
  117. /**
  118. * Name of the theme currently used by the application.
  119. */
  120. private String theme = null;
  121. /**
  122. * Application status.
  123. */
  124. private volatile boolean applicationIsRunning = false;
  125. /**
  126. * Application properties.
  127. */
  128. private Properties properties;
  129. /**
  130. * Default locale of the application.
  131. */
  132. private Locale locale;
  133. /**
  134. * List of listeners listening user changes.
  135. */
  136. private LinkedList<UserChangeListener> userChangeListeners = null;
  137. /**
  138. * Window attach listeners.
  139. */
  140. private LinkedList<WindowAttachListener> windowAttachListeners = null;
  141. /**
  142. * Window detach listeners.
  143. */
  144. private LinkedList<WindowDetachListener> windowDetachListeners = null;
  145. /**
  146. * Application resource mapping: key <-> resource.
  147. */
  148. private final Hashtable<ApplicationResource, String> resourceKeyMap = new Hashtable<ApplicationResource, String>();
  149. private final Hashtable<String, ApplicationResource> keyResourceMap = new Hashtable<String, ApplicationResource>();
  150. private long lastResourceKeyNumber = 0;
  151. /**
  152. * URL where the user is redirected to on application close, or null if
  153. * application is just closed without redirection.
  154. */
  155. private String logoutURL = null;
  156. /**
  157. * The default SystemMessages (read-only). Change by overriding
  158. * getSystemMessages() and returning CustomizedSystemMessages
  159. */
  160. private static final SystemMessages DEFAULT_SYSTEM_MESSAGES = new SystemMessages();
  161. /**
  162. * Application wide error handler which is used by default if an error is
  163. * left unhandled.
  164. */
  165. private Terminal.ErrorListener errorHandler = this;
  166. /**
  167. * <p>
  168. * Gets a window by name. Returns <code>null</code> if the application is
  169. * not running or it does not contain a window corresponding to the name.
  170. * </p>
  171. *
  172. * <p>
  173. * All windows can be referenced by their names in url
  174. * <code>http://host:port/foo/bar/</code> where
  175. * <code>http://host:port/foo/</code> is the application url as returned by
  176. * getURL() and <code>bar</code> is the name of the window.
  177. * </p>
  178. *
  179. * <p>
  180. * One should note that this method can, as a side effect create new windows
  181. * if needed by the application. This can be achieved by overriding the
  182. * default implementation.
  183. * </p>
  184. *
  185. * <p>
  186. * If for some reason user opens another window with same url that is
  187. * already open, the name is modified by adding a "_N" postfix to the name,
  188. * where N is a running number starting from 1. One can decide to create
  189. * another window-object for those windows (recommended) or to discard the
  190. * postfix. If the user has two browser windows pointing to the same
  191. * window-object on server, synchronization errors are likely to occur.
  192. * </p>
  193. *
  194. * <p>
  195. * If no browser-level windowing is used, all defaults are fine and this
  196. * method can be left as is. In case browser-level windows are needed, it is
  197. * recommended to create new window-objects on this method from their names
  198. * if the super.getWindow() does not find existing windows. See below for
  199. * implementation example: <code><pre>
  200. // If we already have the requested window, use it
  201. Window w = super.getWindow(name);
  202. if (w == null) {
  203. // If no window found, create it
  204. w = new Window(name);
  205. // set windows name to the one requested
  206. w.setName(name);
  207. // add it to this application
  208. addWindow(w);
  209. // ensure use of window specific url
  210. w.open(new ExternalResource(w.getURL().toString()));
  211. // add some content
  212. w.addComponent(new Label("Test window"));
  213. }
  214. return w;</pre></code>
  215. * </p>
  216. *
  217. * <p>
  218. * <strong>Note</strong> that all returned Window objects must be added to
  219. * this application instance.
  220. *
  221. * <p>
  222. * The method should return null if the window does not exists (and is not
  223. * created as a side-effect) or if the application is not running anymore.
  224. * </p>
  225. *
  226. * @param name
  227. * the name of the window.
  228. * @return the window associated with the given URI or <code>null</code>
  229. */
  230. public Window getWindow(String name) {
  231. // For closed app, do not give any windows
  232. if (!isRunning()) {
  233. return null;
  234. }
  235. // Gets the window by name
  236. final Window window = windows.get(name);
  237. return window;
  238. }
  239. /**
  240. * Adds a new window to the application.
  241. *
  242. * <p>
  243. * This implicitly invokes the
  244. * {@link com.vaadin.ui.Window#setApplication(Application)} method.
  245. * </p>
  246. *
  247. * <p>
  248. * Note that all application-level windows can be accessed by their names in
  249. * url <code>http://host:port/foo/bar/</code> where
  250. * <code>http://host:port/foo/</code> is the application url as returned by
  251. * getURL() and <code>bar</code> is the name of the window. Also note that
  252. * not all windows should be added to application - one can also add windows
  253. * inside other windows - these windows show as smaller windows inside those
  254. * windows.
  255. * </p>
  256. *
  257. * @param window
  258. * the new <code>Window</code> to add. If the name of the window
  259. * is <code>null</code>, an unique name is automatically given
  260. * for the window.
  261. * @throws IllegalArgumentException
  262. * if a window with the same name as the new window already
  263. * exists in the application.
  264. * @throws NullPointerException
  265. * if the given <code>Window</code> is <code>null</code>.
  266. */
  267. public void addWindow(Window window) throws IllegalArgumentException,
  268. NullPointerException {
  269. // Nulls can not be added to application
  270. if (window == null) {
  271. return;
  272. }
  273. // Check that one is not adding a sub-window to application
  274. if (window.getParent() != null) {
  275. throw new IllegalArgumentException(
  276. "Window was already added inside another window"
  277. + " - it can not be added to application also.");
  278. }
  279. // Gets the naming proposal from window
  280. String name = window.getName();
  281. // Checks that the application does not already contain
  282. // window having the same name
  283. if (name != null && windows.containsKey(name)) {
  284. // If the window is already added
  285. if (window == windows.get(name)) {
  286. return;
  287. }
  288. // Otherwise complain
  289. throw new IllegalArgumentException("Window with name '"
  290. + window.getName()
  291. + "' is already present in the application");
  292. }
  293. // If the name of the window is null, the window is automatically named
  294. if (name == null) {
  295. boolean accepted = false;
  296. while (!accepted) {
  297. // Try another name
  298. synchronized (this) {
  299. name = String.valueOf(nextWindowId);
  300. nextWindowId++;
  301. }
  302. if (!windows.containsKey(name)) {
  303. accepted = true;
  304. }
  305. }
  306. window.setName(name);
  307. }
  308. // Adds the window to application
  309. windows.put(name, window);
  310. window.setApplication(this);
  311. fireWindowAttachEvent(window);
  312. // If no main window is set, declare the window to be main window
  313. if (getMainWindow() == null) {
  314. mainWindow = window;
  315. }
  316. }
  317. /**
  318. * Send information to all listeners about new Windows associated with this
  319. * application.
  320. *
  321. * @param window
  322. */
  323. private void fireWindowAttachEvent(Window window) {
  324. // Fires the window attach event
  325. if (windowAttachListeners != null) {
  326. final Object[] listeners = windowAttachListeners.toArray();
  327. final WindowAttachEvent event = new WindowAttachEvent(window);
  328. for (int i = 0; i < listeners.length; i++) {
  329. ((WindowAttachListener) listeners[i]).windowAttached(event);
  330. }
  331. }
  332. }
  333. /**
  334. * Removes the specified window from the application.
  335. *
  336. * <p>
  337. * Removing the main window of the Application also sets the main window to
  338. * null. One must another window to be the main window after this with
  339. * {@link #setMainWindow(Window)}.
  340. * </p>
  341. *
  342. * <p>
  343. * Note that removing window from the application does not close the browser
  344. * window - the window is only removed from the server-side.
  345. * </p>
  346. *
  347. * @param window
  348. * the window to be removed.
  349. */
  350. public void removeWindow(Window window) {
  351. if (window != null && windows.contains(window)) {
  352. // Removes the window from application
  353. windows.remove(window.getName());
  354. // If the window was main window, clear it
  355. if (getMainWindow() == window) {
  356. setMainWindow(null);
  357. }
  358. // Removes the application from window
  359. if (window.getApplication() == this) {
  360. window.setApplication(null);
  361. }
  362. fireWindowDetachEvent(window);
  363. }
  364. }
  365. private void fireWindowDetachEvent(Window window) {
  366. // Fires the window detach event
  367. if (windowDetachListeners != null) {
  368. final Object[] listeners = windowDetachListeners.toArray();
  369. final WindowDetachEvent event = new WindowDetachEvent(window);
  370. for (int i = 0; i < listeners.length; i++) {
  371. ((WindowDetachListener) listeners[i]).windowDetached(event);
  372. }
  373. }
  374. }
  375. /**
  376. * Gets the user of the application.
  377. *
  378. * <p>
  379. * Vaadin doesn't define of use user object in any way - it only provides
  380. * this getter and setter methods for convenience. The user is any object
  381. * that has been stored to the application with {@link #setUser(Object)}.
  382. * </p>
  383. *
  384. * @return the User of the application.
  385. */
  386. public Object getUser() {
  387. return user;
  388. }
  389. /**
  390. * <p>
  391. * Sets the user of the application instance. An application instance may
  392. * have a user associated to it. This can be set in login procedure or
  393. * application initialization.
  394. * </p>
  395. * <p>
  396. * A component performing the user login procedure can assign the user
  397. * property of the application and make the user object available to other
  398. * components of the application.
  399. * </p>
  400. * <p>
  401. * Vaadin doesn't define of use user object in any way - it only provides
  402. * getter and setter methods for convenience. The user reference stored to
  403. * the application can be read with {@link #getUser()}.
  404. * </p>
  405. *
  406. * @param user
  407. * the new user.
  408. */
  409. public void setUser(Object user) {
  410. final Object prevUser = this.user;
  411. if (user == prevUser || (user != null && user.equals(prevUser))) {
  412. return;
  413. }
  414. this.user = user;
  415. if (userChangeListeners != null) {
  416. final Object[] listeners = userChangeListeners.toArray();
  417. final UserChangeEvent event = new UserChangeEvent(this, user,
  418. prevUser);
  419. for (int i = 0; i < listeners.length; i++) {
  420. ((UserChangeListener) listeners[i])
  421. .applicationUserChanged(event);
  422. }
  423. }
  424. }
  425. /**
  426. * Gets the URL of the application.
  427. *
  428. * <p>
  429. * This is the URL what can be entered to a browser window to start the
  430. * application. Navigating to the application URL shows the main window (
  431. * {@link #getMainWindow()}) of the application. Note that the main window
  432. * can also be shown by navigating to the window url (
  433. * {@link com.vaadin.ui.Window#getURL()}).
  434. * </p>
  435. *
  436. * @return the application's URL.
  437. */
  438. public URL getURL() {
  439. return applicationUrl;
  440. }
  441. /**
  442. * Ends the Application.
  443. *
  444. * <p>
  445. * In effect this will cause the application stop returning any windows when
  446. * asked. When the application is closed, its state is removed from the
  447. * session and the browser window is redirected to the application logout
  448. * url set with {@link #setLogoutURL(String)}. If the logout url has not
  449. * been set, the browser window is reloaded and the application is
  450. * restarted.
  451. * </p>
  452. * .
  453. */
  454. public void close() {
  455. applicationIsRunning = false;
  456. }
  457. /**
  458. * Starts the application on the given URL.
  459. *
  460. * <p>
  461. * This method is called by Vaadin framework when a user navigates to the
  462. * application. After this call the application corresponds to the given URL
  463. * and it will return windows when asked for them. There is no need to call
  464. * this method directly.
  465. * </p>
  466. *
  467. * <p>
  468. * Application properties are defined by servlet configuration object
  469. * {@link javax.servlet.ServletConfig} and they are overridden by
  470. * context-wide initialization parameters
  471. * {@link javax.servlet.ServletContext}.
  472. * </p>
  473. *
  474. * @param applicationUrl
  475. * the URL the application should respond to.
  476. * @param applicationProperties
  477. * the Application properties as specified by the servlet
  478. * configuration.
  479. * @param context
  480. * the context application will be running in.
  481. *
  482. */
  483. public void start(URL applicationUrl, Properties applicationProperties,
  484. ApplicationContext context) {
  485. this.applicationUrl = applicationUrl;
  486. properties = applicationProperties;
  487. this.context = context;
  488. init();
  489. applicationIsRunning = true;
  490. }
  491. /**
  492. * Tests if the application is running or if it has been finished.
  493. *
  494. * <p>
  495. * Application starts running when its
  496. * {@link #start(URL, Properties, ApplicationContext)} method has been
  497. * called and stops when the {@link #close()} is called.
  498. * </p>
  499. *
  500. * @return <code>true</code> if the application is running,
  501. * <code>false</code> if not.
  502. */
  503. public boolean isRunning() {
  504. return applicationIsRunning;
  505. }
  506. /**
  507. * Gets the set of windows contained by the application.
  508. *
  509. * <p>
  510. * Note that the returned set of windows can not be modified.
  511. * </p>
  512. *
  513. * @return the Unmodifiable collection of windows.
  514. */
  515. public Collection<Window> getWindows() {
  516. return Collections.unmodifiableCollection(windows.values());
  517. }
  518. /**
  519. * <p>
  520. * Main initializer of the application. The <code>init</code> method is
  521. * called by the framework when the application is started, and it should
  522. * perform whatever initialization operations the application needs, such as
  523. * creating windows and adding components to them.
  524. * </p>
  525. */
  526. public abstract void init();
  527. /**
  528. * Gets the application's theme. The application's theme is the default
  529. * theme used by all the windows in it that do not explicitly specify a
  530. * theme. If the application theme is not explicitly set, the
  531. * <code>null</code> is returned.
  532. *
  533. * @return the name of the application's theme.
  534. */
  535. public String getTheme() {
  536. return theme;
  537. }
  538. /**
  539. * Sets the application's theme.
  540. * <p>
  541. * Note that this theme can be overridden in the the application level
  542. * windows with {@link com.vaadin.ui.Window#setTheme(String)}. Setting theme
  543. * to be <code>null</code> selects the default theme. For the available
  544. * theme names, see the contents of the VAADIN/themes directory.
  545. * </p>
  546. *
  547. * @param theme
  548. * the new theme for this application.
  549. */
  550. public void setTheme(String theme) {
  551. // Collect list of windows not having the current or future theme
  552. final LinkedList<Window> toBeUpdated = new LinkedList<Window>();
  553. final String oldAppTheme = getTheme();
  554. for (final Iterator<Window> i = getWindows().iterator(); i.hasNext();) {
  555. final Window w = i.next();
  556. final String windowTheme = w.getTheme();
  557. if ((windowTheme == null)
  558. || (!windowTheme.equals(theme) && windowTheme
  559. .equals(oldAppTheme))) {
  560. toBeUpdated.add(w);
  561. }
  562. }
  563. // Updates the theme
  564. this.theme = theme;
  565. // Ask windows to update themselves
  566. for (final Iterator<Window> i = toBeUpdated.iterator(); i.hasNext();) {
  567. i.next().requestRepaint();
  568. }
  569. }
  570. /**
  571. * Gets the mainWindow of the application.
  572. *
  573. * <p>
  574. * The main window is the window attached to the application URL (
  575. * {@link #getURL()}) and thus which is show by default to the user.
  576. * </p>
  577. * <p>
  578. * Note that each application must have at least one main window.
  579. * </p>
  580. *
  581. * @return the main window.
  582. */
  583. public Window getMainWindow() {
  584. return mainWindow;
  585. }
  586. /**
  587. * <p>
  588. * Sets the mainWindow. If the main window is not explicitly set, the main
  589. * window defaults to first created window. Setting window as a main window
  590. * of this application also adds the window to this application.
  591. * </p>
  592. *
  593. * @param mainWindow
  594. * the mainWindow to set.
  595. */
  596. public void setMainWindow(Window mainWindow) {
  597. addWindow(mainWindow);
  598. this.mainWindow = mainWindow;
  599. }
  600. /**
  601. * Returns an enumeration of all the names in this application.
  602. *
  603. * <p>
  604. * See {@link #start(URL, Properties, ApplicationContext)} how properties
  605. * are defined.
  606. * </p>
  607. *
  608. * @return an enumeration of all the keys in this property list, including
  609. * the keys in the default property list.
  610. *
  611. */
  612. public Enumeration<?> getPropertyNames() {
  613. return properties.propertyNames();
  614. }
  615. /**
  616. * Searches for the property with the specified name in this application.
  617. * This method returns <code>null</code> if the property is not found.
  618. *
  619. * See {@link #start(URL, Properties, ApplicationContext)} how properties
  620. * are defined.
  621. *
  622. * @param name
  623. * the name of the property.
  624. * @return the value in this property list with the specified key value.
  625. */
  626. public String getProperty(String name) {
  627. return properties.getProperty(name);
  628. }
  629. /**
  630. * Adds new resource to the application. The resource can be accessed by the
  631. * user of the application.
  632. *
  633. * @param resource
  634. * the resource to add.
  635. */
  636. public void addResource(ApplicationResource resource) {
  637. // Check if the resource is already mapped
  638. if (resourceKeyMap.containsKey(resource)) {
  639. return;
  640. }
  641. // Generate key
  642. final String key = String.valueOf(++lastResourceKeyNumber);
  643. // Add the resource to mappings
  644. resourceKeyMap.put(resource, key);
  645. keyResourceMap.put(key, resource);
  646. }
  647. /**
  648. * Removes the resource from the application.
  649. *
  650. * @param resource
  651. * the resource to remove.
  652. */
  653. public void removeResource(ApplicationResource resource) {
  654. final Object key = resourceKeyMap.get(resource);
  655. if (key != null) {
  656. resourceKeyMap.remove(resource);
  657. keyResourceMap.remove(key);
  658. }
  659. }
  660. /**
  661. * Gets the relative uri of the resource. This method is intended to be
  662. * called only be the terminal implementation.
  663. *
  664. * This method can only be called from within the processing of a UIDL
  665. * request, not from a background thread.
  666. *
  667. * @param resource
  668. * the resource to get relative location.
  669. * @return the relative uri of the resource or null if called in a
  670. * background thread
  671. *
  672. * @deprecated this method is intended to be used by the terminal only. It
  673. * may be removed or moved in the future.
  674. */
  675. @Deprecated
  676. public String getRelativeLocation(ApplicationResource resource) {
  677. // Gets the key
  678. final String key = resourceKeyMap.get(resource);
  679. // If the resource is not registered, return null
  680. if (key == null) {
  681. return null;
  682. }
  683. return context.generateApplicationResourceURL(resource, key);
  684. }
  685. /**
  686. * Application URI handling hub.
  687. *
  688. * <p>
  689. * This method gets called by terminal. It has lots of duties like to pass
  690. * uri handler to proper uri handlers registered to windows etc.
  691. * </p>
  692. *
  693. * <p>
  694. * In most situations developers should NOT OVERRIDE this method. Instead
  695. * developers should implement and register uri handlers to windows.
  696. * </p>
  697. *
  698. * @deprecated this method is called be the terminal implementation only and
  699. * might be removed or moved in the future. Instead of
  700. * overriding this method, add your {@link URIHandler} to a top
  701. * level {@link Window} (eg.
  702. * getMainWindow().addUriHanler(handler) instead.
  703. */
  704. @Deprecated
  705. public DownloadStream handleURI(URL context, String relativeUri) {
  706. if (this.context.isApplicationResourceURL(context, relativeUri)) {
  707. // Handles the resource request
  708. final String key = this.context.getURLKey(context, relativeUri);
  709. final ApplicationResource resource = keyResourceMap.get(key);
  710. if (resource != null) {
  711. DownloadStream stream = resource.getStream();
  712. if (stream != null) {
  713. stream.setCacheTime(resource.getCacheTime());
  714. return stream;
  715. } else {
  716. return null;
  717. }
  718. } else {
  719. // Resource requests override uri handling
  720. return null;
  721. }
  722. } else {
  723. return null;
  724. }
  725. }
  726. /**
  727. * Gets the default locale for this application.
  728. *
  729. * By default this is the preferred locale of the user using the
  730. * application. In most cases it is read from the browser defaults.
  731. *
  732. * @return the locale of this application.
  733. */
  734. public Locale getLocale() {
  735. if (locale != null) {
  736. return locale;
  737. }
  738. return Locale.getDefault();
  739. }
  740. /**
  741. * Sets the default locale for this application.
  742. *
  743. * By default this is the preferred locale of the user using the
  744. * application. In most cases it is read from the browser defaults.
  745. *
  746. * @param locale
  747. * the Locale object.
  748. *
  749. */
  750. public void setLocale(Locale locale) {
  751. this.locale = locale;
  752. }
  753. /**
  754. * <p>
  755. * An event that characterizes a change in the current selection.
  756. * </p>
  757. * Application user change event sent when the setUser is called to change
  758. * the current user of the application.
  759. *
  760. * @version
  761. * @VERSION@
  762. * @since 3.0
  763. */
  764. public class UserChangeEvent extends java.util.EventObject {
  765. /**
  766. * New user of the application.
  767. */
  768. private final Object newUser;
  769. /**
  770. * Previous user of the application.
  771. */
  772. private final Object prevUser;
  773. /**
  774. * Constructor for user change event.
  775. *
  776. * @param source
  777. * the application source.
  778. * @param newUser
  779. * the new User.
  780. * @param prevUser
  781. * the previous User.
  782. */
  783. public UserChangeEvent(Application source, Object newUser,
  784. Object prevUser) {
  785. super(source);
  786. this.newUser = newUser;
  787. this.prevUser = prevUser;
  788. }
  789. /**
  790. * Gets the new user of the application.
  791. *
  792. * @return the new User.
  793. */
  794. public Object getNewUser() {
  795. return newUser;
  796. }
  797. /**
  798. * Gets the previous user of the application.
  799. *
  800. * @return the previous Vaadin user, if user has not changed ever on
  801. * application it returns <code>null</code>
  802. */
  803. public Object getPreviousUser() {
  804. return prevUser;
  805. }
  806. /**
  807. * Gets the application where the user change occurred.
  808. *
  809. * @return the Application.
  810. */
  811. public Application getApplication() {
  812. return (Application) getSource();
  813. }
  814. }
  815. /**
  816. * The <code>UserChangeListener</code> interface for listening application
  817. * user changes.
  818. *
  819. * @version
  820. * @VERSION@
  821. * @since 3.0
  822. */
  823. public interface UserChangeListener extends EventListener, Serializable {
  824. /**
  825. * The <code>applicationUserChanged</code> method Invoked when the
  826. * application user has changed.
  827. *
  828. * @param event
  829. * the change event.
  830. */
  831. public void applicationUserChanged(Application.UserChangeEvent event);
  832. }
  833. /**
  834. * Adds the user change listener.
  835. *
  836. * This allows one to get notification each time {@link #setUser(Object)} is
  837. * called.
  838. *
  839. * @param listener
  840. * the user change listener to add.
  841. */
  842. public void addListener(UserChangeListener listener) {
  843. if (userChangeListeners == null) {
  844. userChangeListeners = new LinkedList<UserChangeListener>();
  845. }
  846. userChangeListeners.add(listener);
  847. }
  848. /**
  849. * Removes the user change listener.
  850. *
  851. * @param listener
  852. * the user change listener to remove.
  853. */
  854. public void removeListener(UserChangeListener listener) {
  855. if (userChangeListeners == null) {
  856. return;
  857. }
  858. userChangeListeners.remove(listener);
  859. if (userChangeListeners.isEmpty()) {
  860. userChangeListeners = null;
  861. }
  862. }
  863. /**
  864. * Window detach event.
  865. *
  866. * This event is sent each time a window is removed from the application
  867. * with {@link com.vaadin.Application#removeWindow(Window)}.
  868. */
  869. public class WindowDetachEvent extends EventObject {
  870. private final Window window;
  871. /**
  872. * Creates a event.
  873. *
  874. * @param window
  875. * the Detached window.
  876. */
  877. public WindowDetachEvent(Window window) {
  878. super(Application.this);
  879. this.window = window;
  880. }
  881. /**
  882. * Gets the detached window.
  883. *
  884. * @return the detached window.
  885. */
  886. public Window getWindow() {
  887. return window;
  888. }
  889. /**
  890. * Gets the application from which the window was detached.
  891. *
  892. * @return the Application.
  893. */
  894. public Application getApplication() {
  895. return (Application) getSource();
  896. }
  897. }
  898. /**
  899. * Window attach event.
  900. *
  901. * This event is sent each time a window is attached tothe application with
  902. * {@link com.vaadin.Application#addWindow(Window)}.
  903. */
  904. public class WindowAttachEvent extends EventObject {
  905. private final Window window;
  906. /**
  907. * Creates a event.
  908. *
  909. * @param window
  910. * the Attached window.
  911. */
  912. public WindowAttachEvent(Window window) {
  913. super(Application.this);
  914. this.window = window;
  915. }
  916. /**
  917. * Gets the attached window.
  918. *
  919. * @return the attached window.
  920. */
  921. public Window getWindow() {
  922. return window;
  923. }
  924. /**
  925. * Gets the application to which the window was attached.
  926. *
  927. * @return the Application.
  928. */
  929. public Application getApplication() {
  930. return (Application) getSource();
  931. }
  932. }
  933. /**
  934. * Window attach listener interface.
  935. */
  936. public interface WindowAttachListener extends Serializable {
  937. /**
  938. * Window attached
  939. *
  940. * @param event
  941. * the window attach event.
  942. */
  943. public void windowAttached(WindowAttachEvent event);
  944. }
  945. /**
  946. * Window detach listener interface.
  947. */
  948. public interface WindowDetachListener extends Serializable {
  949. /**
  950. * Window detached.
  951. *
  952. * @param event
  953. * the window detach event.
  954. */
  955. public void windowDetached(WindowDetachEvent event);
  956. }
  957. /**
  958. * Adds the window attach listener.
  959. *
  960. * Use this to get notifications each time a window is attached to the
  961. * application with {@link #addWindow(Window)}.
  962. *
  963. * @param listener
  964. * the window attach listener to add.
  965. */
  966. public void addListener(WindowAttachListener listener) {
  967. if (windowAttachListeners == null) {
  968. windowAttachListeners = new LinkedList<WindowAttachListener>();
  969. }
  970. windowAttachListeners.add(listener);
  971. }
  972. /**
  973. * Adds the window detach listener.
  974. *
  975. * Use this to get notifications each time a window is remove from the
  976. * application with {@link #removeWindow(Window)}.
  977. *
  978. * @param listener
  979. * the window detach listener to add.
  980. */
  981. public void addListener(WindowDetachListener listener) {
  982. if (windowDetachListeners == null) {
  983. windowDetachListeners = new LinkedList<WindowDetachListener>();
  984. }
  985. windowDetachListeners.add(listener);
  986. }
  987. /**
  988. * Removes the window attach listener.
  989. *
  990. * @param listener
  991. * the window attach listener to remove.
  992. */
  993. public void removeListener(WindowAttachListener listener) {
  994. if (windowAttachListeners != null) {
  995. windowAttachListeners.remove(listener);
  996. if (windowAttachListeners.isEmpty()) {
  997. windowAttachListeners = null;
  998. }
  999. }
  1000. }
  1001. /**
  1002. * Removes the window detach listener.
  1003. *
  1004. * @param listener
  1005. * the window detach listener to remove.
  1006. */
  1007. public void removeListener(WindowDetachListener listener) {
  1008. if (windowDetachListeners != null) {
  1009. windowDetachListeners.remove(listener);
  1010. if (windowDetachListeners.isEmpty()) {
  1011. windowDetachListeners = null;
  1012. }
  1013. }
  1014. }
  1015. /**
  1016. * Returns the URL user is redirected to on application close. If the URL is
  1017. * <code>null</code>, the application is closed normally as defined by the
  1018. * application running environment.
  1019. * <p>
  1020. * Desktop application just closes the application window and
  1021. * web-application redirects the browser to application main URL.
  1022. * </p>
  1023. *
  1024. * @return the URL.
  1025. */
  1026. public String getLogoutURL() {
  1027. return logoutURL;
  1028. }
  1029. /**
  1030. * Sets the URL user is redirected to on application close. If the URL is
  1031. * <code>null</code>, the application is closed normally as defined by the
  1032. * application running environment: Desktop application just closes the
  1033. * application window and web-application redirects the browser to
  1034. * application main URL.
  1035. *
  1036. * @param logoutURL
  1037. * the logoutURL to set.
  1038. */
  1039. public void setLogoutURL(String logoutURL) {
  1040. this.logoutURL = logoutURL;
  1041. }
  1042. /**
  1043. * Gets the SystemMessages for this application. SystemMessages are used to
  1044. * notify the user of various critical situations that can occur, such as
  1045. * session expiration, client/server out of sync, and internal server error.
  1046. *
  1047. * You can customize the messages by "overriding" this method and returning
  1048. * {@link CustomizedSystemMessages}. To "override" this method, re-implement
  1049. * this method in your application (the class that extends
  1050. * {@link Application}). Even though overriding static methods is not
  1051. * possible in Java, Vaadin selects to call the static method from the
  1052. * subclass instead of the original {@link #getSystemMessages()} if such a
  1053. * method exists.
  1054. *
  1055. * @return the SystemMessages for this application
  1056. */
  1057. public static SystemMessages getSystemMessages() {
  1058. return DEFAULT_SYSTEM_MESSAGES;
  1059. }
  1060. /**
  1061. * <p>
  1062. * Invoked by the terminal on any exception that occurs in application and
  1063. * is thrown by the <code>setVariable</code> to the terminal. The default
  1064. * implementation sets the exceptions as <code>ComponentErrors</code> to the
  1065. * component that initiated the exception and prints stack trace to standard
  1066. * error stream.
  1067. * </p>
  1068. * <p>
  1069. * You can safely override this method in your application in order to
  1070. * direct the errors to some other destination (for example log).
  1071. * </p>
  1072. *
  1073. * @param event
  1074. * the change event.
  1075. * @see com.vaadin.terminal.Terminal.ErrorListener#terminalError(com.vaadin.terminal.Terminal.ErrorEvent)
  1076. */
  1077. public void terminalError(Terminal.ErrorEvent event) {
  1078. final Throwable t = event.getThrowable();
  1079. if (t instanceof SocketException) {
  1080. // Most likely client browser closed socket
  1081. logger.info("SocketException in CommunicationManager."
  1082. + " Most likely client (browser) closed socket.");
  1083. return;
  1084. }
  1085. // Finds the original source of the error/exception
  1086. Object owner = null;
  1087. if (event instanceof VariableOwner.ErrorEvent) {
  1088. owner = ((VariableOwner.ErrorEvent) event).getVariableOwner();
  1089. } else if (event instanceof URIHandler.ErrorEvent) {
  1090. owner = ((URIHandler.ErrorEvent) event).getURIHandler();
  1091. } else if (event instanceof ParameterHandler.ErrorEvent) {
  1092. owner = ((ParameterHandler.ErrorEvent) event).getParameterHandler();
  1093. } else if (event instanceof ChangeVariablesErrorEvent) {
  1094. owner = ((ChangeVariablesErrorEvent) event).getComponent();
  1095. }
  1096. // Shows the error in AbstractComponent
  1097. if (owner instanceof AbstractComponent) {
  1098. if (t instanceof ErrorMessage) {
  1099. ((AbstractComponent) owner).setComponentError((ErrorMessage) t);
  1100. } else {
  1101. ((AbstractComponent) owner)
  1102. .setComponentError(new SystemError(t));
  1103. }
  1104. }
  1105. // also print the error on console
  1106. logger.log(Level.SEVERE, "Terminal error:", t);
  1107. }
  1108. /**
  1109. * Gets the application context.
  1110. * <p>
  1111. * The application context is the environment where the application is
  1112. * running in. The actual implementation class of may contains quite a lot
  1113. * more functionality than defined in the {@link ApplicationContext}
  1114. * interface.
  1115. * </p>
  1116. * <p>
  1117. * By default, when you are deploying your application to a servlet
  1118. * container, the implementation class is {@link WebApplicationContext} -
  1119. * you can safely cast to this class and use the methods from there. When
  1120. * you are deploying your application as a portlet, context implementation
  1121. * is {@link PortletApplicationContext}.
  1122. * </p>
  1123. *
  1124. * @return the application context.
  1125. */
  1126. public ApplicationContext getContext() {
  1127. return context;
  1128. }
  1129. /**
  1130. * Override this method to return correct version number of your
  1131. * Application. Version information is delivered for example to Testing
  1132. * Tools test results. By default this returns a string "NONVERSIONED".
  1133. *
  1134. * @return version string
  1135. */
  1136. public String getVersion() {
  1137. return "NONVERSIONED";
  1138. }
  1139. /**
  1140. * Gets the application error handler.
  1141. *
  1142. * The default error handler is the application itself.
  1143. *
  1144. * @return Application error handler
  1145. */
  1146. public Terminal.ErrorListener getErrorHandler() {
  1147. return errorHandler;
  1148. }
  1149. /**
  1150. * Sets the application error handler.
  1151. *
  1152. * The default error handler is the application itself. By overriding this,
  1153. * you can redirect the error messages to your selected target (log for
  1154. * example).
  1155. *
  1156. * @param errorHandler
  1157. */
  1158. public void setErrorHandler(Terminal.ErrorListener errorHandler) {
  1159. this.errorHandler = errorHandler;
  1160. }
  1161. /**
  1162. * Contains the system messages used to notify the user about various
  1163. * critical situations that can occur.
  1164. * <p>
  1165. * Customize by overriding the static
  1166. * {@link Application#getSystemMessages()} and returning
  1167. * {@link CustomizedSystemMessages}.
  1168. * </p>
  1169. * <p>
  1170. * The defaults defined in this class are:
  1171. * <ul>
  1172. * <li><b>sessionExpiredURL</b> = null</li>
  1173. * <li><b>sessionExpiredNotificationEnabled</b> = true</li>
  1174. * <li><b>sessionExpiredCaption</b> = ""</li>
  1175. * <li><b>sessionExpiredMessage</b> =
  1176. * "Take note of any unsaved data, and <u>click here</u> to continue."</li>
  1177. * <li><b>communicationErrorURL</b> = null</li>
  1178. * <li><b>communicationErrorNotificationEnabled</b> = true</li>
  1179. * <li><b>communicationErrorCaption</b> = "Communication problem"</li>
  1180. * <li><b>communicationErrorMessage</b> =
  1181. * "Take note of any unsaved data, and <u>click here</u> to continue."</li>
  1182. * <li><b>internalErrorURL</b> = null</li>
  1183. * <li><b>internalErrorNotificationEnabled</b> = true</li>
  1184. * <li><b>internalErrorCaption</b> = "Internal error"</li>
  1185. * <li><b>internalErrorMessage</b> = "Please notify the administrator.<br/>
  1186. * Take note of any unsaved data, and <u>click here</u> to continue."</li>
  1187. * <li><b>outOfSyncURL</b> = null</li>
  1188. * <li><b>outOfSyncNotificationEnabled</b> = true</li>
  1189. * <li><b>outOfSyncCaption</b> = "Out of sync"</li>
  1190. * <li><b>outOfSyncMessage</b> = "Something has caused us to be out of sync
  1191. * with the server.<br/>
  1192. * Take note of any unsaved data, and <u>click here</u> to re-sync."</li>
  1193. * <li><b>cookiesDisabledURL</b> = null</li>
  1194. * <li><b>cookiesDisabledNotificationEnabled</b> = true</li>
  1195. * <li><b>cookiesDisabledCaption</b> = "Cookies disabled"</li>
  1196. * <li><b>cookiesDisabledMessage</b> = "This application requires cookies to
  1197. * function.<br/>
  1198. * Please enable cookies in your browser and <u>click here</u> to try again.
  1199. * </li>
  1200. * </ul>
  1201. * </p>
  1202. *
  1203. */
  1204. public static class SystemMessages implements Serializable {
  1205. protected String sessionExpiredURL = null;
  1206. protected boolean sessionExpiredNotificationEnabled = true;
  1207. protected String sessionExpiredCaption = "Session Expired";
  1208. protected String sessionExpiredMessage = "Take note of any unsaved data, and <u>click here</u> to continue.";
  1209. protected String communicationErrorURL = null;
  1210. protected boolean communicationErrorNotificationEnabled = true;
  1211. protected String communicationErrorCaption = "Communication problem";
  1212. protected String communicationErrorMessage = "Take note of any unsaved data, and <u>click here</u> to continue.";
  1213. protected String authenticationErrorURL = null;
  1214. protected boolean authenticationErrorNotificationEnabled = true;
  1215. protected String authenticationErrorCaption = "Authentication problem";
  1216. protected String authenticationErrorMessage = "Take note of any unsaved data, and <u>click here</u> to continue.";
  1217. protected String internalErrorURL = null;
  1218. protected boolean internalErrorNotificationEnabled = true;
  1219. protected String internalErrorCaption = "Internal error";
  1220. protected String internalErrorMessage = "Please notify the administrator.<br/>Take note of any unsaved data, and <u>click here</u> to continue.";
  1221. protected String outOfSyncURL = null;
  1222. protected boolean outOfSyncNotificationEnabled = true;
  1223. protected String outOfSyncCaption = "Out of sync";
  1224. protected String outOfSyncMessage = "Something has caused us to be out of sync with the server.<br/>Take note of any unsaved data, and <u>click here</u> to re-sync.";
  1225. protected String cookiesDisabledURL = null;
  1226. protected boolean cookiesDisabledNotificationEnabled = true;
  1227. protected String cookiesDisabledCaption = "Cookies disabled";
  1228. protected String cookiesDisabledMessage = "This application requires cookies to function.<br/>Please enable cookies in your browser and <u>click here</u> to try again.";
  1229. /**
  1230. * Use {@link CustomizedSystemMessages} to customize
  1231. */
  1232. private SystemMessages() {
  1233. }
  1234. /**
  1235. * @return null to indicate that the application will be restarted after
  1236. * session expired message has been shown.
  1237. */
  1238. public String getSessionExpiredURL() {
  1239. return sessionExpiredURL;
  1240. }
  1241. /**
  1242. * @return true to show session expiration message.
  1243. */
  1244. public boolean isSessionExpiredNotificationEnabled() {
  1245. return sessionExpiredNotificationEnabled;
  1246. }
  1247. /**
  1248. * @return "" to show no caption.
  1249. */
  1250. public String getSessionExpiredCaption() {
  1251. return (sessionExpiredNotificationEnabled ? sessionExpiredCaption
  1252. : null);
  1253. }
  1254. /**
  1255. * @return
  1256. * "Take note of any unsaved data, and <u>click here</u> to continue."
  1257. */
  1258. public String getSessionExpiredMessage() {
  1259. return (sessionExpiredNotificationEnabled ? sessionExpiredMessage
  1260. : null);
  1261. }
  1262. /**
  1263. * @return null to reload the application after communication error
  1264. * message.
  1265. */
  1266. public String getCommunicationErrorURL() {
  1267. return communicationErrorURL;
  1268. }
  1269. /**
  1270. * @return true to show the communication error message.
  1271. */
  1272. public boolean isCommunicationErrorNotificationEnabled() {
  1273. return communicationErrorNotificationEnabled;
  1274. }
  1275. /**
  1276. * @return "Communication problem"
  1277. */
  1278. public String getCommunicationErrorCaption() {
  1279. return (communicationErrorNotificationEnabled ? communicationErrorCaption
  1280. : null);
  1281. }
  1282. /**
  1283. * @return
  1284. * "Take note of any unsaved data, and <u>click here</u> to continue."
  1285. */
  1286. public String getCommunicationErrorMessage() {
  1287. return (communicationErrorNotificationEnabled ? communicationErrorMessage
  1288. : null);
  1289. }
  1290. /**
  1291. * @return null to reload the application after authentication error
  1292. * message.
  1293. */
  1294. public String getAuthenticationErrorURL() {
  1295. return authenticationErrorURL;
  1296. }
  1297. /**
  1298. * @return true to show the authentication error message.
  1299. */
  1300. public boolean isAuthenticationErrorNotificationEnabled() {
  1301. return authenticationErrorNotificationEnabled;
  1302. }
  1303. /**
  1304. * @return "Authentication problem"
  1305. */
  1306. public String getAuthenticationErrorCaption() {
  1307. return (authenticationErrorNotificationEnabled ? authenticationErrorCaption
  1308. : null);
  1309. }
  1310. /**
  1311. * @return
  1312. * "Take note of any unsaved data, and <u>click here</u> to continue."
  1313. */
  1314. public String getAuthenticationErrorMessage() {
  1315. return (authenticationErrorNotificationEnabled ? authenticationErrorMessage
  1316. : null);
  1317. }
  1318. /**
  1319. * @return null to reload the current URL after internal error message
  1320. * has been shown.
  1321. */
  1322. public String getInternalErrorURL() {
  1323. return internalErrorURL;
  1324. }
  1325. /**
  1326. * @return true to enable showing of internal error message.
  1327. */
  1328. public boolean isInternalErrorNotificationEnabled() {
  1329. return internalErrorNotificationEnabled;
  1330. }
  1331. /**
  1332. * @return "Internal error"
  1333. */
  1334. public String getInternalErrorCaption() {
  1335. return (internalErrorNotificationEnabled ? internalErrorCaption
  1336. : null);
  1337. }
  1338. /**
  1339. * @return "Please notify the administrator.<br/>
  1340. * Take note of any unsaved data, and <u>click here</u> to
  1341. * continue."
  1342. */
  1343. public String getInternalErrorMessage() {
  1344. return (internalErrorNotificationEnabled ? internalErrorMessage
  1345. : null);
  1346. }
  1347. /**
  1348. * @return null to reload the application after out of sync message.
  1349. */
  1350. public String getOutOfSyncURL() {
  1351. return outOfSyncURL;
  1352. }
  1353. /**
  1354. * @return true to enable showing out of sync message
  1355. */
  1356. public boolean isOutOfSyncNotificationEnabled() {
  1357. return outOfSyncNotificationEnabled;
  1358. }
  1359. /**
  1360. * @return "Out of sync"
  1361. */
  1362. public String getOutOfSyncCaption() {
  1363. return (outOfSyncNotificationEnabled ? outOfSyncCaption : null);
  1364. }
  1365. /**
  1366. * @return "Something has caused us to be out of sync with the server.<br/>
  1367. * Take note of any unsaved data, and <u>click here</u> to
  1368. * re-sync."
  1369. */
  1370. public String getOutOfSyncMessage() {
  1371. return (outOfSyncNotificationEnabled ? outOfSyncMessage : null);
  1372. }
  1373. /**
  1374. * Returns the URL the user should be redirected to after dismissing the
  1375. * "you have to enable your cookies" message. Typically null.
  1376. *
  1377. * @return A URL the user should be redirected to after dismissing the
  1378. * message or null to reload the current URL.
  1379. */
  1380. public String getCookiesDisabledURL() {
  1381. return cookiesDisabledURL;
  1382. }
  1383. /**
  1384. * Determines if "cookies disabled" messages should be shown to the end
  1385. * user or not. If the notification is disabled the user will be
  1386. * immediately redirected to the URL returned by
  1387. * {@link #getCookiesDisabledURL()}.
  1388. *
  1389. * @return true to show "cookies disabled" messages to the end user,
  1390. * false to redirect to the given URL directly
  1391. */
  1392. public boolean isCookiesDisabledNotificationEnabled() {
  1393. return cookiesDisabledNotificationEnabled;
  1394. }
  1395. /**
  1396. * Returns the caption of the message shown to the user when cookies are
  1397. * disabled in the browser.
  1398. *
  1399. * @return The caption of the "cookies disabled" message
  1400. */
  1401. public String getCookiesDisabledCaption() {
  1402. return (cookiesDisabledNotificationEnabled ? cookiesDisabledCaption
  1403. : null);
  1404. }
  1405. /**
  1406. * Returns the message shown to the user when cookies are disabled in
  1407. * the browser.
  1408. *
  1409. * @return The "cookies disabled" message
  1410. */
  1411. public String getCookiesDisabledMessage() {
  1412. return (cookiesDisabledNotificationEnabled ? cookiesDisabledMessage
  1413. : null);
  1414. }
  1415. }
  1416. /**
  1417. * Contains the system messages used to notify the user about various
  1418. * critical situations that can occur.
  1419. * <p>
  1420. * Vaadin gets the SystemMessages from your application by calling a static
  1421. * getSystemMessages() method. By default the
  1422. * Application.getSystemMessages() is used. You can customize this by
  1423. * defining a static MyApplication.getSystemMessages() and returning
  1424. * CustomizedSystemMessages. Note that getSystemMessages() is static -
  1425. * changing the system messages will by default change the message for all
  1426. * users of the application.
  1427. * </p>
  1428. * <p>
  1429. * The default behavior is to show a notification, and restart the
  1430. * application the the user clicks the message. <br/>
  1431. * Instead of restarting the application, you can set a specific URL that
  1432. * the user is taken to.<br/>
  1433. * Setting both caption and message to null will restart the application (or
  1434. * go to the specified URL) without displaying a notification.
  1435. * set*NotificationEnabled(false) will achieve the same thing.
  1436. * </p>
  1437. * <p>
  1438. * The situations are:
  1439. * <li>Session expired: the user session has expired, usually due to
  1440. * inactivity.</li>
  1441. * <li>Communication error: the client failed to contact the server, or the
  1442. * server returned and invalid response.</li>
  1443. * <li>Internal error: unhandled critical server error (e.g out of memory,
  1444. * database crash)
  1445. * <li>Out of sync: the client is not in sync with the server. E.g the user
  1446. * opens two windows showing the same application, but the application does
  1447. * not support this and uses the same Window instance. When the user makes
  1448. * changes in one of the windows - the other window is no longer in sync,
  1449. * and (for instance) pressing a button that is no longer present in the UI
  1450. * will cause a out-of-sync -situation.
  1451. * </p>
  1452. */
  1453. public static class CustomizedSystemMessages extends SystemMessages
  1454. implements Serializable {
  1455. /**
  1456. * Sets the URL to go to when the session has expired.
  1457. *
  1458. * @param sessionExpiredURL
  1459. * the URL to go to, or null to reload current
  1460. */
  1461. public void setSessionExpiredURL(String sessionExpiredURL) {
  1462. this.sessionExpiredURL = sessionExpiredURL;
  1463. }
  1464. /**
  1465. * Enables or disables the notification. If disabled, the set URL (or
  1466. * current) is loaded directly when next transaction between server and
  1467. * client happens.
  1468. *
  1469. * @param sessionExpiredNotificationEnabled
  1470. * true = enabled, false = disabled
  1471. */
  1472. public void setSessionExpiredNotificationEnabled(
  1473. boolean sessionExpiredNotificationEnabled) {
  1474. this.sessionExpiredNotificationEnabled = sessionExpiredNotificationEnabled;
  1475. }
  1476. /**
  1477. * Sets the caption of the notification. Set to null for no caption. If
  1478. * both caption and message are null, client automatically forwards to
  1479. * sessionExpiredUrl after timeout timer expires. Timer uses value read
  1480. * from HTTPSession.getMaxInactiveInterval()
  1481. *
  1482. * @param sessionExpiredCaption
  1483. * the caption
  1484. */
  1485. public void setSessionExpiredCaption(String sessionExpiredCaption) {
  1486. this.sessionExpiredCaption = sessionExpiredCaption;
  1487. }
  1488. /**
  1489. * Sets the message of the notification. Set to null for no message. If
  1490. * both caption and message are null, client automatically forwards to
  1491. * sessionExpiredUrl after timeout timer expires. Timer uses value read
  1492. * from HTTPSession.getMaxInactiveInterval()
  1493. *
  1494. * @param sessionExpiredMessage
  1495. * the message
  1496. */
  1497. public void setSessionExpiredMessage(String sessionExpiredMessage) {
  1498. this.sessionExpiredMessage = sessionExpiredMessage;
  1499. }
  1500. /**
  1501. * Sets the URL to go to when there is a authentication error.
  1502. *
  1503. * @param authenticationErrorURL
  1504. * the URL to go to, or null to reload current
  1505. */
  1506. public void setAuthenticationErrorURL(String authenticationErrorURL) {
  1507. this.authenticationErrorURL = authenticationErrorURL;
  1508. }
  1509. /**
  1510. * Enables or disables the notification. If disabled, the set URL (or
  1511. * current) is loaded directly.
  1512. *
  1513. * @param authenticationErrorNotificationEnabled
  1514. * true = enabled, false = disabled
  1515. */
  1516. public void setAuthenticationErrorNotificationEnabled(
  1517. boolean authenticationErrorNotificationEnabled) {
  1518. this.authenticationErrorNotificationEnabled = authenticationErrorNotificationEnabled;
  1519. }
  1520. /**
  1521. * Sets the caption of the notification. Set to null for no caption. If
  1522. * both caption and message is null, the notification is disabled;
  1523. *
  1524. * @param authenticationErrorCaption
  1525. * the caption
  1526. */
  1527. public void setAuthenticationErrorCaption(
  1528. String authenticationErrorCaption) {
  1529. this.authenticationErrorCaption = authenticationErrorCaption;
  1530. }
  1531. /**
  1532. * Sets the message of the notification. Set to null for no message. If
  1533. * both caption and message is null, the notification is disabled;
  1534. *
  1535. * @param authenticationErrorMessage
  1536. * the message
  1537. */
  1538. public void setAuthenticationErrorMessage(
  1539. String authenticationErrorMessage) {
  1540. this.authenticationErrorMessage = authenticationErrorMessage;
  1541. }
  1542. /**
  1543. * Sets the URL to go to when there is a communication error.
  1544. *
  1545. * @param communicationErrorURL
  1546. * the URL to go to, or null to reload current
  1547. */
  1548. public void setCommunicationErrorURL(String communicationErrorURL) {
  1549. this.communicationErrorURL = communicationErrorURL;
  1550. }
  1551. /**
  1552. * Enables or disables the notification. If disabled, the set URL (or
  1553. * current) is loaded directly.
  1554. *
  1555. * @param communicationErrorNotificationEnabled
  1556. * true = enabled, false = disabled
  1557. */
  1558. public void setCommunicationErrorNotificationEnabled(
  1559. boolean communicationErrorNotificationEnabled) {
  1560. this.communicationErrorNotificationEnabled = communicationErrorNotificationEnabled;
  1561. }
  1562. /**
  1563. * Sets the caption of the notification. Set to null for no caption. If
  1564. * both caption and message is null, the notification is disabled;
  1565. *
  1566. * @param communicationErrorCaption
  1567. * the caption
  1568. */
  1569. public void setCommunicationErrorCaption(
  1570. String communicationErrorCaption) {
  1571. this.communicationErrorCaption = communicationErrorCaption;
  1572. }
  1573. /**
  1574. * Sets the message of the notification. Set to null for no message. If
  1575. * both caption and message is null, the notification is disabled;
  1576. *
  1577. * @param communicationErrorMessage
  1578. * the message
  1579. */
  1580. public void setCommunicationErrorMessage(
  1581. String communicationErrorMessage) {
  1582. this.communicationErrorMessage = communicationErrorMessage;
  1583. }
  1584. /**
  1585. * Sets the URL to go to when an internal error occurs.
  1586. *
  1587. * @param internalErrorURL
  1588. * the URL to go to, or null to reload current
  1589. */
  1590. public void setInternalErrorURL(String internalErrorURL) {
  1591. this.internalErrorURL = internalErrorURL;
  1592. }
  1593. /**
  1594. * Enables or disables the notification. If disabled, the set URL (or
  1595. * current) is loaded directly.
  1596. *
  1597. * @param internalErrorNotificationEnabled
  1598. * true = enabled, false = disabled
  1599. */
  1600. public void setInternalErrorNotificationEnabled(
  1601. boolean internalErrorNotificationEnabled) {
  1602. this.internalErrorNotificationEnabled = internalErrorNotificationEnabled;
  1603. }
  1604. /**
  1605. * Sets the caption of the notification. Set to null for no caption. If
  1606. * both caption and message is null, the notification is disabled;
  1607. *
  1608. * @param internalErrorCaption
  1609. * the caption
  1610. */
  1611. public void setInternalErrorCaption(String internalErrorCaption) {
  1612. this.internalErrorCaption = internalErrorCaption;
  1613. }
  1614. /**
  1615. * Sets the message of the notification. Set to null for no message. If
  1616. * both caption and message is null, the notification is disabled;
  1617. *
  1618. * @param internalErrorMessage
  1619. * the message
  1620. */
  1621. public void setInternalErrorMessage(String internalErrorMessage) {
  1622. this.internalErrorMessage = internalErrorMessage;
  1623. }
  1624. /**
  1625. * Sets the URL to go to when the client is out-of-sync.
  1626. *
  1627. * @param outOfSyncURL
  1628. * the URL to go to, or null to reload current
  1629. */
  1630. public void setOutOfSyncURL(String outOfSyncURL) {
  1631. this.outOfSyncURL = outOfSyncURL;
  1632. }
  1633. /**
  1634. * Enables or disables the notification. If disabled, the set URL (or
  1635. * current) is loaded directly.
  1636. *
  1637. * @param outOfSyncNotificationEnabled
  1638. * true = enabled, false = disabled
  1639. */
  1640. public void setOutOfSyncNotificationEnabled(
  1641. boolean outOfSyncNotificationEnabled) {
  1642. this.outOfSyncNotificationEnabled = outOfSyncNotificationEnabled;
  1643. }
  1644. /**
  1645. * Sets the caption of the notification. Set to null for no caption. If
  1646. * both caption and message is null, the notification is disabled;
  1647. *
  1648. * @param outOfSyncCaption
  1649. * the caption
  1650. */
  1651. public void setOutOfSyncCaption(String outOfSyncCaption) {
  1652. this.outOfSyncCaption = outOfSyncCaption;
  1653. }
  1654. /**
  1655. * Sets the message of the notification. Set to null for no message. If
  1656. * both caption and message is null, the notification is disabled;
  1657. *
  1658. * @param outOfSyncMessage
  1659. * the message
  1660. */
  1661. public void setOutOfSyncMessage(String outOfSyncMessage) {
  1662. this.outOfSyncMessage = outOfSyncMessage;
  1663. }
  1664. /**
  1665. * Sets the URL to redirect to when the browser has cookies disabled.
  1666. *
  1667. * @param cookiesDisabledURL
  1668. * the URL to redirect to, or null to reload the current URL
  1669. */
  1670. public void setCookiesDisabledURL(String cookiesDisabledURL) {
  1671. this.cookiesDisabledURL = cookiesDisabledURL;
  1672. }
  1673. /**
  1674. * Enables or disables the notification for "cookies disabled" messages.
  1675. * If disabled, the URL returned by {@link #getCookiesDisabledURL()} is
  1676. * loaded directly.
  1677. *
  1678. * @param cookiesDisabledNotificationEnabled
  1679. * true to enable "cookies disabled" messages, false
  1680. * otherwise
  1681. */
  1682. public void setCookiesDisabledNotificationEnabled(
  1683. boolean cookiesDisabledNotificationEnabled) {
  1684. this.cookiesDisabledNotificationEnabled = cookiesDisabledNotificationEnabled;
  1685. }
  1686. /**
  1687. * Sets the caption of the "cookies disabled" notification. Set to null
  1688. * for no caption. If both caption and message is null, the notification
  1689. * is disabled.
  1690. *
  1691. * @param cookiesDisabledCaption
  1692. * the caption for the "cookies disabled" notification
  1693. */
  1694. public void setCookiesDisabledCaption(String cookiesDisabledCaption) {
  1695. this.cookiesDisabledCaption = cookiesDisabledCaption;
  1696. }
  1697. /**
  1698. * Sets the message of the "cookies disabled" notification. Set to null
  1699. * for no message. If both caption and message is null, the notification
  1700. * is disabled.
  1701. *
  1702. * @param cookiesDisabledMessage
  1703. * the message for the "cookies disabled" notification
  1704. */
  1705. public void setCookiesDisabledMessage(String cookiesDisabledMessage) {
  1706. this.cookiesDisabledMessage = cookiesDisabledMessage;
  1707. }
  1708. }
  1709. /**
  1710. * Application error is an error message defined on the application level.
  1711. *
  1712. * When an error occurs on the application level, this error message type
  1713. * should be used. This indicates that the problem is caused by the
  1714. * application - not by the user.
  1715. */
  1716. public class ApplicationError implements Terminal.ErrorEvent {
  1717. private final Throwable throwable;
  1718. public ApplicationError(Throwable throwable) {
  1719. this.throwable = throwable;
  1720. }
  1721. public Throwable getThrowable() {
  1722. return throwable;
  1723. }
  1724. }
  1725. }