001: /* *************************************************************************
002:
003: Millstone(TM)
004: Open Sourced User Interface Library for
005: Internet Development with Java
006:
007: Millstone is a registered trademark of IT Mill Ltd
008: Copyright (C) 2000-2005 IT Mill Ltd
009:
010: *************************************************************************
011:
012: This library is free software; you can redistribute it and/or
013: modify it under the terms of the GNU Lesser General Public
014: license version 2.1 as published by the Free Software Foundation.
015:
016: This library is distributed in the hope that it will be useful,
017: but WITHOUT ANY WARRANTY; without even the implied warranty of
018: MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
019: Lesser General Public License for more details.
020:
021: You should have received a copy of the GNU Lesser General Public
022: License along with this library; if not, write to the Free Software
023: Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
024:
025: *************************************************************************
026:
027: For more information, contact:
028:
029: IT Mill Ltd phone: +358 2 4802 7180
030: Ruukinkatu 2-4 fax: +358 2 4802 7181
031: 20540, Turku email: info@itmill.com
032: Finland company www: www.itmill.com
033:
034: Primary source for MillStone information and releases: www.millstone.org
035:
036: ********************************************************************** */
037:
038: package org.millstone.webadapter;
039:
040: import org.millstone.base.Application;
041: import org.millstone.base.terminal.ThemeResource;
042: import org.millstone.base.ui.FrameWindow;
043: import org.millstone.base.ui.Window;
044:
045: import java.text.DateFormatSymbols;
046: import java.util.Calendar;
047: import java.util.GregorianCalendar;
048: import java.util.Iterator;
049: import java.util.LinkedList;
050: import java.util.Set;
051:
052: import javax.servlet.http.HttpSession;
053:
054: /** This a function library that can be used from the theme XSL-files. It provides
055: * easy access to current application, window, theme, webbrowser and session. The
056: * internal threadlocal state must be maintained by the webadapter in order go guarantee
057: * that it works.
058: *
059: * @author IT Mill Ltd.
060: * @version 3.1.1
061: * @since 3.0
062: */
063:
064: public class ThemeFunctionLibrary {
065:
066: static private final int APPLICATION = 0;
067: static private final int WINDOW = 1;
068: static private final int WEBBROWSER = 2;
069: static private final int SESSION = 3;
070: static private final int WEBADAPTERSERVLET = 4;
071: static private final int THEME = 5;
072:
073: static private ThreadLocal state = new ThreadLocal();
074:
075: static protected void setState(Application application,
076: Window window, WebBrowser webBrowser, HttpSession session,
077: WebAdapterServlet webAdapterServlet, String theme) {
078: state.set(new Object[] { application, window, webBrowser,
079: session, webAdapterServlet, theme });
080: }
081:
082: static protected void cleanState() {
083: state.set(null);
084: }
085:
086: /** Returns a reference to the application object associated
087: * with the session that the call came from.
088: */
089: static public Application application() {
090: try {
091: return (Application) ((Object[]) state.get())[APPLICATION];
092: } catch (NullPointerException e) {
093: throw new IllegalStateException();
094: }
095: }
096:
097: /** Returns a reference to the current window object associated
098: * with the session that the call came from.
099: */
100: static public Window window() {
101: try {
102: return (Window) ((Object[]) state.get())[WINDOW];
103: } catch (NullPointerException e) {
104: throw new IllegalStateException();
105: }
106: }
107:
108: /** Returns a reference to the browser object associated
109: * with the session that the call came from.
110: */
111: static public WebBrowser browser() {
112: try {
113: return (WebBrowser) ((Object[]) state.get())[WEBBROWSER];
114: } catch (NullPointerException e) {
115: throw new IllegalStateException();
116: }
117: }
118:
119: /** Returns a reference to the current servlet http session object
120: * that is associated with the session that the call came from.
121: */
122: static public HttpSession session() {
123: try {
124: return (HttpSession) ((Object[]) state.get())[SESSION];
125: } catch (NullPointerException e) {
126: throw new IllegalStateException();
127: }
128: }
129:
130: /** Return a reference to the current theme object that is
131: * associated with the session that the call came from.
132: */
133: static public String theme() {
134: try {
135: return (String) ((Object[]) state.get())[THEME];
136: } catch (NullPointerException e) {
137: throw new IllegalStateException();
138: }
139: }
140:
141: /** Return an URI to the named resource from the named theme.
142: */
143: static public String resource(String resource, String theme) {
144: try {
145: return ((WebAdapterServlet) ((Object[]) state.get())[WEBADAPTERSERVLET])
146: .getResourceLocation(theme, new ThemeResource(
147: resource));
148: } catch (NullPointerException e) {
149: throw new IllegalStateException();
150: }
151: }
152:
153: /** Return an URI to the named resource.
154: */
155: static public String resource(String resource) {
156: try {
157: return ((WebAdapterServlet) ((Object[]) state.get())[WEBADAPTERSERVLET])
158: .getResourceLocation(theme(), new ThemeResource(
159: resource));
160: } catch (NullPointerException e) {
161: throw new IllegalStateException();
162: }
163: }
164:
165: /** Generate JavaScript for page that performs
166: * client-side combility checks.
167: * The script includes HTML/JavaScript commands to be included
168: * in the body of the millstone-form.
169: */
170: static public boolean probeClient() {
171: return (browser().performClientCheck() && !browser()
172: .isClientSideChecked());
173: }
174:
175: /** Generate JavaScript for page header that handles
176: * window refreshing, opening and closing.
177: *
178: * Generates script that:
179: * <ul>
180: * <li>Requests that all windows that need repaint be reloaded</li>
181: * <li>Sets the window name</li>
182: * <li>Closes window if it is set to be closed </li>
183: * <ul>
184: *
185: */
186: static public String windowScript() {
187: return generateWindowScript(
188: window(),
189: application(),
190: (WebAdapterServlet) ((Object[]) state.get())[WEBADAPTERSERVLET],
191: browser());
192: }
193:
194: static protected String generateWindowScript(Window window,
195: Application app, WebAdapterServlet wa, WebBrowser browser) {
196:
197: StringBuffer script = new StringBuffer();
198: LinkedList update = new LinkedList();
199:
200: // Add all the windows needto update list
201: Set dirtyWindows = wa != null ? wa.getDirtyWindows(app) : null;
202: if (dirtyWindows != null)
203: for (Iterator i = dirtyWindows.iterator(); i.hasNext();) {
204: Window w = (Window) i.next();
205: if (w != window) {
206: if (w instanceof FrameWindow)
207: update.addFirst(w);
208: else
209: update.addLast(w);
210: }
211: }
212:
213: // Remove all windows that are in frames, of such frame windows that
214: // will be updated anyway
215: Object[] u = update.toArray();
216: if (u.length > 0
217: && (window != null && window instanceof FrameWindow))
218: u[u.length - 1] = window;
219: for (int i = 0; i < u.length; i++) {
220: try {
221: FrameWindow w = (FrameWindow) u[i];
222: LinkedList framesets = new LinkedList();
223: framesets.add(w.getFrameset());
224: while (!framesets.isEmpty()) {
225: FrameWindow.Frameset fs = (FrameWindow.Frameset) framesets
226: .removeFirst();
227: for (Iterator j = fs.getFrames().iterator(); j
228: .hasNext();) {
229: FrameWindow.Frame f = (FrameWindow.Frame) j
230: .next();
231: if (f instanceof FrameWindow.Frameset)
232: framesets.add(f);
233: else if (f.getWindow() != null) {
234: update.remove(f.getWindow());
235: wa.removeDirtyWindow(app, f.getWindow());
236: }
237: }
238: }
239: } catch (ClassCastException ignored) {
240: }
241: }
242:
243: // Set window name
244: if (window != null) {
245: script.append("window.name = \""
246: + getWindowTargetName(app, window) + "\";\n");
247: }
248:
249: // Generate window updatescript
250: for (Iterator i = update.iterator(); i.hasNext();) {
251: Window w = (Window) i.next();
252: script.append(getWindowRefreshScript(app, w, browser));
253:
254: wa.removeDirtyWindow(app, w);
255:
256: // Windows that are closed immediately are "painted" now
257: if (w.getApplication() == null || !w.isVisible())
258: w.requestRepaintRequests();
259: }
260:
261: // Close current window if it is not visible
262: if (window == null || !window.isVisible())
263: script.append("window.close();\n");
264:
265: return script.toString();
266: }
267:
268: /** Returns an unique target name for a given window name.
269: * @param windowName Name of the window.
270: * @return An unique ID for window target
271: * @throws IllegalStateException If application for window is null.
272: */
273: static public String getWindowTargetName(Application application,
274: Window window) {
275: try {
276: return "" + application.hashCode() + "_" + window.getName();
277: } catch (NullPointerException e) {
278: throw new IllegalStateException();
279: }
280: }
281:
282: /** Returns an unique target name for current window.
283: * @return An unique ID for window target
284: */
285: static public String getWindowTargetName() {
286: return getWindowTargetName(application(), window());
287: }
288:
289: /** Returns an unique target name for current window.
290: * @return An unique ID for window target
291: * @throws IllegalStateException If application for window is null.
292: */
293: static public String getWindowTargetName(String name) {
294: Window w = application().getWindow(name);
295: if (w != null)
296: return getWindowTargetName(application(), w);
297: else
298: return name;
299: }
300:
301: /* Static mapping for 0 to be sunday. */
302: private static int[] weekdays = new int[] { Calendar.SUNDAY,
303: Calendar.MONDAY, Calendar.TUESDAY, Calendar.WEDNESDAY,
304: Calendar.THURSDAY, Calendar.FRIDAY, Calendar.SATURDAY };
305:
306: /** Returns the country and region code for current application locale.
307: * @see Locale#getCountry()
308: * @return language Country code of the current application locale.
309: */
310: static public String getLocaleCountryId() {
311: try {
312: Application app = (Application) ((Object[]) state.get())[APPLICATION];
313: return app.getLocale().getCountry();
314: } catch (NullPointerException e) {
315: throw new IllegalStateException();
316: }
317: }
318:
319: /** Returns the language code for current application locale.
320: * @see Locale#getLanguage()
321: * @return language Language code for current application locale.
322: */
323: static public String getLocaleLanguageId() {
324: try {
325: Application app = (Application) ((Object[]) state.get())[APPLICATION];
326: return app.getLocale().getLanguage();
327: } catch (NullPointerException e) {
328: throw new IllegalStateException();
329: }
330: }
331:
332: /** Get name for week day.
333: * @param Number of week day. 0 first day of week.
334: * @return Name of week day in applications current locale.
335: */
336: static public int getFirstDayOfWeek() {
337: try {
338: Application app = (Application) ((Object[]) state.get())[APPLICATION];
339: Calendar cal = new GregorianCalendar(app.getLocale());
340: int first = cal.getFirstDayOfWeek();
341: for (int i = 0; i < 7; i++) {
342: if (first == weekdays[i])
343: return i;
344: }
345: return 0; // default to sunday
346: } catch (NullPointerException e) {
347: throw new IllegalStateException();
348: }
349: }
350:
351: /** Get name for week day.
352: * @param Number of week day. 0 sunday, 1 monday, ...
353: * @return Name of week day in applications current locale.
354: */
355: static public String getShortWeekday(int dayOfWeek) {
356: try {
357: Application app = (Application) ((Object[]) state.get())[APPLICATION];
358: DateFormatSymbols df = new DateFormatSymbols(app
359: .getLocale());
360: return df.getShortWeekdays()[weekdays[dayOfWeek]];
361: } catch (NullPointerException e) {
362: throw new IllegalStateException();
363: }
364: }
365:
366: /** Get short name for month.
367: * @param Number of month. 0 is January, 1 is February, and so on.
368: * @return Name of month in applications current locale.
369: */
370: static public String getShortMonth(int month) {
371: try {
372: Application app = (Application) ((Object[]) state.get())[APPLICATION];
373: DateFormatSymbols df = new DateFormatSymbols(app
374: .getLocale());
375: String monthName = df.getShortMonths()[month];
376: return monthName;
377: } catch (NullPointerException e) {
378: throw new IllegalStateException();
379: }
380: }
381:
382: /** Get name for month.
383: * @param Number of month. 0 is January, 1 is February, and so on.
384: * @return Name of month in applications current locale.
385: */
386: static public String getMonth(int month) {
387: try {
388: Application app = (Application) ((Object[]) state.get())[APPLICATION];
389: DateFormatSymbols df = new DateFormatSymbols(app
390: .getLocale());
391: String monthName = df.getMonths()[month];
392: return monthName;
393: } catch (NullPointerException e) {
394: throw new IllegalStateException();
395: }
396: }
397:
398: /** Get Form Action URL for the requested window.
399: *
400: * <p>This returns the action for the window main form. This action
401: * can be set through WebApplicationContect setWindowFormAction method..</p>
402: *
403: * @return Form action for the current window.
404: */
405: static public String getFormAction() {
406:
407: Window win = window();
408: Application app = application();
409:
410: return ((WebApplicationContext) app.getContext())
411: .getWindowFormAction(win);
412: }
413:
414: /** Generate JavaScript for updating given window */
415: static protected String getWindowRefreshScript(
416: Application application, Window window, WebBrowser browser) {
417:
418: if (application == null)
419: return "";
420:
421: if (window == null)
422: return "";
423:
424: if (window == null)
425: return "";
426:
427: // If window is closed or hidden
428: if (window.getApplication() == null || !window.isVisible())
429: return "win = window.open(\"\",\""
430: + getWindowTargetName(application, window)
431: + "\");\n "
432: + "if (win != null) { win.close(); }\n";
433:
434: String url = window.getURL().toString();
435:
436: String features = "dependent=yes,";
437: int width = window.getWidth();
438: int height = window.getHeight();
439: if (width >= 0)
440: features += "width=" + width;
441: if (height >= 0)
442: features += ((features.length() > 0) ? "," : "")
443: + "height=" + height;
444: switch (window.getBorder()) {
445: case Window.BORDER_NONE:
446: features += ((features.length() > 0) ? "," : "")
447: + "toolbar=0,location=0,menubar=0,status=0,resizable=1,scrollbars="
448: + (window.isScrollable() ? "1" : "0");
449: break;
450: case Window.BORDER_MINIMAL:
451: features += ((features.length() > 0) ? "," : "")
452: + "toolbar=1,location=0,menubar=0,status=1,resizable=1,scrollbars="
453: + (window.isScrollable() ? "1" : "0");
454: break;
455: case Window.BORDER_DEFAULT:
456: features += ((features.length() > 0) ? "," : "")
457: + "toolbar=1,location=1,menubar=1,status=1,resizable=1,scrollbars="
458: + (window.isScrollable() ? "1" : "0");
459: break;
460: }
461:
462: String script = "win = window.open(\"\",\""
463: + getWindowTargetName(application, window) + "\",\""
464: + features + "\");\n" + "if (win != null) {"
465: + "var form = null;";
466:
467: if (browser != null
468: && (browser.getJavaScriptVersion().supports(
469: WebBrowser.JAVASCRIPT_1_5) || browser
470: .getJavaScriptVersion().supports(
471: WebBrowser.JSCRIPT_1_0))) {
472: script += "try { form = win.document.forms[\"millstone\"];"
473: + "} catch (e) { form = null;}";
474: } else {
475: script += "form = win.document.forms[\"millstone\"];";
476: }
477:
478: script += "if (form != null) {" + "form.submit();"
479: + "} else {win.location.href = \"" + url + "\";}}";
480:
481: return script;
482: }
483: }
|