001: /* UiEngine.java
002:
003: {{IS_NOTE
004: Purpose:
005:
006: Description:
007:
008: History:
009: Thu Jun 9 12:58:20 2005, Created by tomyeh
010: }}IS_NOTE
011:
012: Copyright (C) 2005 Potix Corporation. All Rights Reserved.
013:
014: {{IS_RIGHT
015: This program is distributed under GPL Version 2.0 in the hope that
016: it will be useful, but WITHOUT ANY WARRANTY.
017: }}IS_RIGHT
018: */
019: package org.zkoss.zk.ui.sys;
020:
021: import java.util.List;
022: import java.util.Map;
023: import java.util.Collection;
024: import java.io.IOException;
025: import java.io.Writer;
026:
027: import org.zkoss.zk.ui.WebApp;
028: import org.zkoss.zk.ui.Desktop;
029: import org.zkoss.zk.ui.Page;
030: import org.zkoss.zk.ui.Component;
031: import org.zkoss.zk.ui.Execution;
032: import org.zkoss.zk.ui.Richlet;
033: import org.zkoss.zk.ui.UiException;
034: import org.zkoss.zk.ui.SuspendNotAllowedException;
035: import org.zkoss.zk.ui.util.DeferredValue;
036: import org.zkoss.zk.ui.metainfo.PageDefinition;
037: import org.zkoss.zk.au.AuResponse;
038: import org.zkoss.zk.au.AuWriter;
039:
040: /**
041: * UI engine is reponsible to process requests from the client,
042: * sends the response back to the client with the assistent of
043: * {@link ExecutionCtrl}.
044: *
045: * <p>{@link ExecutionCtrl} encapsulates protocol-dependent codes,
046: * such that UiEngine works independent of any protocol (such as HTTP).
047: *
048: * <p>Note: each application (a ServletContext in HTTP) has its own
049: * UI Engine (Singleton per app).
050: *
051: * @author tomyeh
052: */
053: public interface UiEngine {
054: /** Starts the engine.
055: */
056: public void start(WebApp wapp);
057:
058: /** Stops the engine.
059: * Called only if the server is about to stop.
060: */
061: public void stop(WebApp wapp);
062:
063: /** Called when a desktop is being removed.
064: * <p>Application developers don't need to remove pages and desktops.
065: * They are removed and cleaned up automatically.
066: */
067: public void desktopDestroyed(Desktop desktop);
068:
069: //-- update (draw) --//
070: /** Called before a component redraws itself if the component might
071: * include another page.
072: *
073: * <p>If a new page is created, the specified component will become
074: * the owner of the new page.
075: */
076: public void pushOwner(Component comp);
077:
078: /** Called after a component redraws itself if it ever calls
079: * {@link #pushOwner}.
080: */
081: public void popOwner();
082:
083: /** Invalidates the page to cause all of its components to redraw.
084: */
085: public void addInvalidate(Page page);
086:
087: /** Invalidates a component to cause redrawing.
088: * Called when {@link Component#invalidate} is called.
089: */
090: public void addInvalidate(Component comp);
091:
092: /** Smart updates an attribute of a component.
093: * Called when {@link Component#smartUpdate(String,String)} is called.
094: *
095: * <p>The second invocation of this method
096: * in the same execution with the same attr will override the previous one.
097: */
098: public void addSmartUpdate(Component comp, String attr, String value);
099:
100: /** Smart updates an attribute of a component with a deferred value.
101: * A deferred value is used to encapsulate a value that shall be retrieved
102: * only in the rendering phase.
103: *
104: * @since 3.0.1
105: * @see Component#smartUpdateDeferred(String, DeferredValue)
106: */
107: public void addSmartUpdate(Component comp, String attr,
108: DeferredValue value);
109:
110: /** Adds a response which will be sent to client at the end
111: * of the execution.
112: * Called when {@link Component#response} is called.
113: *
114: * <p>Note: {@link Execution#addAuResponse} is a shortcut to this method,
115: * and it is used by application developers.
116: *
117: * <p>If {@link AuResponse#getDepends} is not null, the response
118: * depends on the returned componet. In other words, the response
119: * is removed if the component is removed.
120: * If it is null, the response is component-independent.
121: *
122: * @param key could be anything. The second invocation of this method
123: * in the same execution with the same key will override the previous one.
124: */
125: public void addResponse(String key, AuResponse response);
126:
127: /** Called to update (redraw) a component, when a component is moved.
128: * If a component's page or parent is changed, this method need to be
129: * called only once for the top one.
130: *
131: * @param oldparent the parent before moved
132: * @param oldpg the page before moved
133: * @param newpg the page after moved
134: */
135: public void addMoved(Component comp, Component oldparent,
136: Page oldpg, Page newpg);
137:
138: /** Called before changing the component's UUID.
139: *
140: * @param addOnlyMoved if true, it is added only if it was moved
141: * before (see {@link #addMoved}).
142: */
143: public void addUuidChanged(Component comp, boolean addOnlyMoved);
144:
145: //-- execution --//
146: /** Creates components specified in the given page definition.
147: * Called when a new page is creates.
148: */
149: public void execNewPage(Execution exec, PageDefinition pagedef,
150: Page page, Writer out) throws IOException;
151:
152: /** Invoke {@link Richlet#service}, when a new page is creates upon
153: * visiting a richlet.
154: */
155: public void execNewPage(Execution exec, Richlet richlet, Page page,
156: Writer out) throws IOException;
157:
158: /** Executs an asynchronous update to a component (or page).
159: * It is the same as execUpdate(exec, requests, null, out).
160: *
161: * <p>Note: the output must be XML and UTF-8.
162: *
163: * @param requests a list of {@link org.zkoss.zk.au.AuRequest}.
164: * @since 3.0.1
165: */
166: public void execUpdate(Execution exec, List requests, AuWriter out)
167: throws IOException;
168:
169: /** Executs an asynchronous update to a component (or page).
170: * <p>Note: the output must be XML and UTF-8.
171: *
172: * @param requests a list of {@link org.zkoss.zk.au.AuRequest}.
173: * @param reqId the request ID which is used to invoke
174: * {@link org.zkoss.zk.ui.util.PerformanceMeter#requestCompleteAtClient}.
175: * Ignored if null or {@link org.zkoss.zk.ui.util.Configuration#getPerformanceMeter}
176: * is not defined.
177: * @return a list of request IDs that have been processed
178: * completely.
179: * @since 3.0.1
180: */
181: public Collection execUpdate(Execution exec, List requests,
182: String reqId, AuWriter out) throws IOException;
183:
184: /** Executes the recovering.
185: */
186: public void execRecover(Execution exec, FailoverManager failover);
187:
188: /** Creates components from the specified page and definition.
189: * It can be called when {@link #execNewPage} or {@link #execUpdate}
190: * was called.
191: * It assumes the execution is already locked to this desktop.
192: *
193: * <p>Note: if both page and parent are null, the created components
194: * don't belong to any page/parent.
195: *
196: * @param exec the execution (never null).
197: * @param pagedef the page definition (never null).
198: * @param page the page. Ignored if parent is specified (and
199: * parent's page is used).
200: * @param parent the parent component, or null if no parent compoent.
201: * If parent is specified, page is ignored.
202: * @param arg a map of parameters that is accessible by the arg variable
203: * in EL, or by {@link Execution#getArg}.
204: * Ignored if null.
205: * @return the components being created.
206: */
207: public Component[] createComponents(Execution exec,
208: PageDefinition pagedef, Page page, Component parent, Map arg);
209:
210: /** Sends a temporary redirect response to the client using the specified
211: * redirect location URL.
212: *
213: * <p>After calling this method, the caller shall end the processing
214: * immediately (by returning). All pending requests and events will
215: * be dropped.
216: *
217: * @param uri the URI to redirect to, or null to reload the same page
218: * @param target the new target, or null to denote the same browser window
219: */
220: public void sendRedirect(String uri, String target);
221:
222: /** Aborts the current execution.
223: * if not null, it means the current execution is aborting
224: *
225: * <p>Note: if setAbortingReason is ever set with non-null, you
226: * CANNOT set it back to null.
227: *
228: * <p>After call this method, you shall not keep processing the page
229: * because the rendering is dropped and the client is out-of-sync
230: * with the server.
231: *
232: * @param aborting the aborting reason.
233: */
234: public void setAbortingReason(AbortingReason aborting);
235:
236: //-- wait/notify --//
237: /** Suspends the current processing of an event and wait until the
238: * other thread invokes {@link #notify(Object)}, {@link #notifyAll(Object)},
239: * {@link #notify(Desktop, Object)} or {@link #notifyAll(Desktop, Object)}
240: * for the specified object.
241: *
242: * <p>It can only be called when the current thread is processing an event.
243: * And, when called, the current processing is suspended and ZK continues
244: * to process the next event and finally render the result.
245: *
246: * <p>It is typical use to implement a modal dialog where it won't return
247: * until the modal dialog ends.
248: *
249: * @param obj any non-null object to identify what to wait, such that
250: * {@link #notify(Object)} and {@link #notify(Desktop, Object)} knows
251: * which object to notify.
252: * @exception UiException if it is called not during event processing.
253: * @exception SuspendNotAllowedException if there are too many suspended
254: * exceptions.
255: * Deployers can control the maximal allowed number of suspended exceptions
256: * by specifying <code>max-suspended-thread</code> in <code>zk.xml</code>,
257: * or invoking {@link org.zkoss.zk.ui.util.Configuration#setMaxSuspendedThreads}.
258: */
259: public void wait(Object obj) throws InterruptedException,
260: SuspendNotAllowedException;
261:
262: /** Wakes up a single event processing thread that is waiting on the
263: * specified object.
264: *
265: * <p>Unlike {@link #notify(Desktop, Object)}, this method can be invoked only
266: * if the same desktop is locked for processing requests.
267: *
268: * @param obj any non-null object to identify what to notify. It must be
269: * same object passed to {@link #wait}.
270: * @see #notify(Desktop, Object)
271: * @see #notifyAll(Object)
272: * @exception UiException if it is called not during event processing.
273: */
274: public void notify(Object obj);
275:
276: /** Wakes up all event processing thread that are waiting on the
277: * specified object.
278: *
279: * <p>Unlike {@link #notify(Desktop, Object)}, this method can be invoked only
280: * if the same desktop is locked for processing requests.
281: *
282: * @param obj any non-null object to identify what to notify. It must be
283: * same object passed to {@link #wait}.
284: * @see #notify(Desktop, Object)
285: * @see #notifyAll(Object)
286: * @exception UiException if it is called not during event processing.
287: */
288: public void notifyAll(Object obj);
289:
290: /** Wakes up a single event processing thread for the specified desktop
291: * that is waiting on the specified object.
292: *
293: * <p>Unlike {@link #notify(Object)}, this method can be called any time.
294: * It is designed to let working threads resume an event processing
295: * thread.
296: *
297: * <p>Notice: if this method is NOT called in an event processing thread,
298: * the resumed thread won't execute until the next request is received.
299: * To enforce it happen, you might use the timer component (found in ZUL).
300: *
301: * @param desktop the desktop which the suspended thread is processing.
302: * It must be the same desktop of the suspended thread.
303: * @param obj any non-null object to identify what to notify. It must be
304: * same object passed to {@link #wait}.
305: * @see #notify(Object)
306: * @see #notifyAll(Desktop, Object)
307: */
308: public void notify(Desktop desktop, Object obj);
309:
310: /** Wakes up all event processing theads for the specified desktop
311: * that are waiting on the specified object.
312: *
313: * <p>Unlike {@link #notifyAll(Object)}, this method can be called any time.
314: * It is designed to let working threads resume an event processing
315: * thread.
316: *
317: * <p>If this method is NOT called in an event processing thread,
318: * the resumed thread won't execute until the next request is received.
319: * To enforce it happen, you might use the timer component (found in ZUL).
320: *
321: * @param desktop the desktop which the suspended thread is processing.
322: * It must be the same desktop of the suspended thread.
323: * @param obj any non-null object to identify what to notify. It must be
324: * same object passed to {@link #wait}.
325: * @see #notify(Object)
326: * @see #notifyAll(Desktop, Object)
327: */
328: public void notifyAll(Desktop desktop, Object obj);
329:
330: /** Activates an execution such that you can access a component.
331: * You must call {@link #deactivate} in the finally clause.
332: *
333: * <p>Note: you RARELY need to invoke this method because {@link #execNewPage}
334: * and {@link #execUpdate} will activate and deactivate automatically.
335: *
336: * <p>Note: this method can be called only when processing a client request
337: * (e.g., HTTP) other than creating a new page and processing async-update.
338: *
339: * <p>Also, even if you use this method to grant the right to access
340: * components of the specified page, don't post events, create, remove,
341: * invalidate and do any smart updates. In other words, READ ONLY.
342: */
343: public void activate(Execution exec);
344:
345: /** Deactivates an execution, such that other threads could activate
346: * and access components.
347: */
348: public void deactivate(Execution exec);
349:
350: /** Returns if any suspended event processing thread in the
351: * whole system.
352: */
353: public boolean hasSuspendedThread();
354:
355: /** Returns a collection of suspended event processing threads
356: * belonging to the specified desktop,
357: * or empty if no suspended thread at all.
358: *
359: * <p>An event processing thread is an instance of
360: * {@link EventProcessingThread}
361: *
362: * @param desktop the desktop that the suspended event processing
363: * threads belong to (never null).
364: */
365: public Collection getSuspendedThreads(Desktop desktop);
366:
367: /** Ceases the specified event thread.
368: *
369: * @param desktop which desktop the event thread belongs to
370: * @param cause an arbitrary text to describe the cause.
371: * It will be the message of the thrown InterruptedException.
372: * @return true if the event processing thread is ceased successfully;
373: * false if no such thread or it is not suspended.
374: */
375: public boolean ceaseSuspendedThread(Desktop desktop,
376: EventProcessingThread evtthd, String cause);
377: }
|