/* Executions.java

	Purpose:
		
	Description:
		
	History:
		Fri Jun  3 17:55:08     2005, Created by tomyeh

Copyright (C) 2005 Potix Corporation. All Rights Reserved.

{{IS_RIGHT
	This program is distributed under LGPL Version 2.1 in the hope that
	it will be useful, but WITHOUT ANY WARRANTY.
}}IS_RIGHT
*/
package org.zkoss.zk.ui;

import java.io.IOException;
import java.io.Reader;
import java.net.MalformedURLException;
import java.net.URL;
import java.util.Map;

import javax.servlet.ServletRequest;

import org.zkoss.idom.Document;
import org.zkoss.xel.ExpressionFactory;
import org.zkoss.xel.VariableResolver;
import org.zkoss.zk.ui.event.Event;
import org.zkoss.zk.ui.event.EventListener;
import org.zkoss.zk.ui.metainfo.LanguageDefinition;
import org.zkoss.zk.ui.metainfo.PageDefinition;
import org.zkoss.zk.ui.sys.DesktopCtrl;
import org.zkoss.zk.ui.sys.UiEngine;
import org.zkoss.zk.ui.sys.WebAppCtrl;
import org.zkoss.zk.xel.Evaluator;

/**
 * Utilities to access {@link Execution}.
 *
 * @author tomyeh
 */
public class Executions {
	/** Stores the current {@link Execution}. */
	protected static final ThreadLocal<Execution> _exec = new ThreadLocal<Execution>();

	/** Returns the current execution.
	 */
	public static final Execution getCurrent() {
		return _exec.get();
	}

	/** Returns the evaluator of the current execution.
	 * It is usually used to parse the expression into {@link org.zkoss.xel.Expression}
	 * or used with {@link org.zkoss.zk.xel.ExValue}.
	 * for performance improvement.
	 *
	 * @param page the page that this evaluator is associated.
	 * If null, the current page and then the first page is assumed.
	 * @param expfcls the implementation of {@link ExpressionFactory},
	 * or null to use the default ({@link org.zkoss.zk.ui.util.Configuration#getExpressionFactoryClass}.
	 * @since 3.0.0
	 */
	public static final Evaluator getEvaluator(Page page, Class<? extends ExpressionFactory> expfcls) {
		return getCurrent().getEvaluator(page, expfcls);
	}

	/** Returns the evaluator of the current execution.
	 * It is a shortcut of getEvaluator(comp != null ? comp.getPage(): null)
	 *
	 * @param comp the component to retrieve the page for the evaluator
	 * @param expfcls the implementation of {@link ExpressionFactory},
	 * or null to use the default ({@link org.zkoss.zk.ui.util.Configuration#getExpressionFactoryClass}.
	 * @since 3.0.0
	 */
	public static final Evaluator getEvaluator(Component comp, Class<? extends ExpressionFactory> expfcls) {
		return getCurrent().getEvaluator(comp, expfcls);
	}

	/** Evaluates the specified expression by use of the current context
	 * ({@link #getCurrent}).
	 *
	 * <p>The function mapper is retrieved from component's page's function
	 * mapper ({@link Page#getFunctionMapper}).
	 * If null, the current page, if any, is used to retrieve
	 * the mapper.
	 *
	 * <p>For better performance, you can use the instance returned by
	 *{@link #getEvaluator} to parse and cached the parsed expression.
	 * {@link org.zkoss.zk.xel.ExValue} is a utility class to simply
	 * the task.
	 *
	 * @param comp as the self variable (ignored if null)
	 */
	public static final Object evaluate(Component comp, String expr, Class expectedType) {
		return getCurrent().evaluate(comp, expr, expectedType);
	}

	/** Evaluates the specified expression with the resolver of the current
	 * execution ({@link #getCurrent}).
	 *
	 * <p>The function mapper is retrieved from page's function
	 * mapper ({@link Page#getFunctionMapper}).
	 * If null, the current page, if any, is used to retrieve
	 * the mapper.
	 *
	 * <p>For better performance, you can use the instance returned by
	 *{@link #getEvaluator} to parse and cached the parsed expression.
	 * {@link org.zkoss.zk.xel.ExValue} is a utility class to simply
	 * the task.
	 *
	 * @param page used as the self variable and to retrieve the function
	 * mapper if funmap is not defined. Ignored if null.
	 */
	public static final Object evaluate(Page page, String expr, Class expectedType) {
		return getCurrent().evaluate(page, expr, expectedType);
	}

	/** Encodes the specified URL.
	 *
	 * <p>It resolves "*" contained in URI, if any, to the proper Locale,
	 * and the browser code.
	 * Refer to {@link org.zkoss.web.servlet.Servlets#locate(javax.servlet.ServletContext, ServletRequest, String, Locator)}
	 * for details. 
	 *
	 * @exception NullPointerException if the current execution is not
	 * available.
	 * @see #encodeURL
	 */
	public static final String encodeURL(String uri) {
		return getCurrent().encodeURL(uri);
	}

	/**  Encodes the specified URL into an instance of {@link URL}.
	 * It is similar to {@link #encodeURL}, except it returns an instance
	 * of {@link URL}.
	 *
	 * @exception NullPointerException if the current execution is not
	 * available.
	 * @exception MalformedURLException if failed to convert it to
	 * a legal {@link URL}
	 * @since 3.5.0
	 */
	public static final URL encodeToURL(String uri) throws MalformedURLException {
		final Execution exec = getCurrent();
		uri = exec.encodeURL(uri);
		if (uri.indexOf("://") < 0) {
			final StringBuffer sb = new StringBuffer(256).append(exec.getScheme()).append("://")
					.append(exec.getServerName());
			int port = exec.getServerPort();
			if (port != 80)
				sb.append(':').append(port);
			if (uri.length() > 0 && uri.charAt(0) != '/')
				sb.append('/');
			uri = sb.append(uri).toString();
		}
		return new URL(uri);
	}

	/** Creates components from a page file specified by an URI.
	 * Shortcut to {@link Execution#createComponents(String, Component, Map)}.
	 *
	 * @param parent the parent component, or null if you want it to be
	 * a root component. If parent is null, the page is assumed to be
	 * the current page, which is determined by the execution context.
	 * In other words, the new component will be the root component
	 * of the current page if parent is null.
	 * @param arg a map of parameters that is accessible by the arg variable
	 * in EL, or by {@link Execution#getArg}.
	 * Ignored if null.
	 * @return the first component being created.
	 * @see #createComponents(PageDefinition, Component, Map)
	 */
	public static final Component createComponents(String uri, Component parent, Map<?, ?> arg) {
		return getCurrent().createComponents(uri, parent, arg);
	}

	/** Creates components based on the specified page definition.
	 * Shortcut to {@link Execution#createComponents(PageDefinition, Component, Map)}.
	 *
	 * @param pagedef the page definition to use. It cannot be null.
	 * @param parent the parent component, or null if you want it to be
	 * a root component. If parent is null, the page is assumed to be
	 * the current page, which is determined by the execution context.
	 * In other words, the new component will be the root component
	 * of the current page if parent is null.
	 * @param arg a map of parameters that is accessible by the arg variable
	 * in EL, or by {@link Execution#getArg}.
	 * Ignored if null.
	 * @return the first component being created.
	 * @see #createComponents(String, Component, Map)
	 */
	public static final Component createComponents(PageDefinition pagedef, Component parent, Map<?, ?> arg) {
		return getCurrent().createComponents(pagedef, parent, arg);
	}

	/** Creates components that don't belong to any page
	 * from the specified page definition.
	 *
	 * <p>Unlike {@link #createComponents(PageDefinition,Component,Map)},
	 * this method can be invoked without the current execution, such as
	 * a working thread. In this case, the wapp argument must be specified.
	 *
	 * @param wapp the Web application. It is optional and used only if
	 * no current execution (e.g., in a working thread).
	 * The instance of {@link WebApp} can be retrieved by use of {@link org.zkoss.zk.ui.http.WebManager#getWebApp},
	 * while the instance of {@link org.zkoss.zk.ui.http.WebManager} can be retrieved
	 * by {@link org.zkoss.zk.ui.http.WebManager#getWebManager}
	 * @param pagedef the page definition to use. It cannot be null.
	 * @param arg a map of parameters that is accessible by the arg variable
	 * in EL, or by {@link Execution#getArg}.
	 * Ignored if null.
	 * @return all top-level components being created.
	 * @see #createComponents(WebApp, String, Map)
	 * @since 3.6.2
	 */
	public static Component[] createComponents(WebApp wapp, PageDefinition pagedef, Map<?, ?> arg) {
		final CCInfo cci = beforeCC(wapp);
		try {
			return cci.exec.createComponents(pagedef, arg);
		} finally {
			afterCC(cci);
		}
	}

	/** Creates components that don't belong to any page
	 * from a page file specified by an URI.
	 *
	 * <p>It loads the page definition from the specified URI (by
	 * use {@link #getPageDefinition} ), and then
	 * invokes {@link #createComponents(WebApp,PageDefinition,Map)}
	 * to create components.
	 *
	 * <p>Unlike {@link #createComponents(String,Component,Map)},
	 * this method can be invoked without the current execution, such as
	 * a working thread. In this case, the wapp argument must be specified.
	 *
	 * @param wapp the Web application. It is optional and used only if
	 * no current execution (e.g., in a working thread).
	 * The instance of {@link WebApp} can be retrieved by use of {@link org.zkoss.zk.ui.http.WebManager#getWebApp},
	 * while the instance of {@link org.zkoss.zk.ui.http.WebManager} can be retrieved
	 * by {@link org.zkoss.zk.ui.http.WebManager#getWebManager}
	 * @param arg a map of parameters that is accessible by the arg variable
	 * in EL, or by {@link Execution#getArg}.
	 * Ignored if null.
	 * @return all top-level components being created.
	 * @see #createComponents(WebApp, PageDefinition, Map)
	 * @see #createComponentsDirectly(WebApp, String, String, Map)
	 * @see #createComponentsDirectly(WebApp, Document, String, Map)
	 * @see #createComponentsDirectly(WebApp, Reader, String, Map)
	 * @since 3.6.2
	 */
	public static Component[] createComponents(WebApp wapp, String uri, Map<?, ?> arg) {
		final CCInfo cci = beforeCC(wapp);
		try {
			return cci.exec.createComponents(uri, arg);
		} finally {
			afterCC(cci);
		}
	}

	/** Creates components that belong to the given page
	 * from a page file specified by an URI.
	 *
	 * @param page the page, or null if you want it to attach the created components.
	 * @param resolver the variable resolver used to resolve variables.
	 * Ignored if null.
	 * @param arg a map of parameters that is accessible by the arg variable
	 * in EL, or by {@link Execution#getArg}.
	 * Ignored if null.
	 * @return all top-level components being created.
	 * @see #createComponents(WebApp, PageDefinition, Map)
	 * @see #createComponentsDirectly(WebApp, String, String, Map)
	 * @see #createComponentsDirectly(WebApp, Document, String, Map)
	 * @see #createComponentsDirectly(WebApp, Reader, String, Map)
	 * @since 8.0.1
	 */
	public static Component[] createComponents(String uri, Page page, VariableResolver resolver, Map<?, ?> arg) {
		return getCurrent().createComponents(uri, page, resolver, arg);
	}

	/** Creates components from the raw content specified by a string.
	 * Shortcut to {@link Execution#createComponentsDirectly(String, String, Component, Map)}.
	 *
	 * @param content the raw content of the page. It must be a XML and
	 * compliant to the page format (such as ZUL).
	 * @param extension the default extension if the content doesn't specify
	 * an language. In other words, if
	 * the content doesn't specify an language, {@link LanguageDefinition#getByExtension}
	 * is called.
	 * If extension is null and the content doesn't specify a language,
	 * the language called "xul/html" is assumed.
	 * @param parent the parent component, or null if you want it to be
	 * a root component. If parent is null, the page is assumed to be
	 * the current page, which is determined by the execution context.
	 * In other words, the new component will be the root component
	 * of the current page if parent is null.
	 * @param arg a map of parameters that is accessible by the arg variable
	 * in EL, or by {@link Execution#getArg}.
	 * Ignored if null.
	 * @return the first component being created.
	 * @see #createComponents(PageDefinition, Component, Map)
	 * @see #createComponents(String, Component, Map)
	 * @see #createComponentsDirectly(Document, String, Component, Map)
	 * @see #createComponentsDirectly(Reader, String, Component, Map)
	 */
	public static final Component createComponentsDirectly(String content, String extension, Component parent,
			Map<?, ?> arg) {
		return getCurrent().createComponentsDirectly(content, extension, parent, arg);
	}

	/** Creates components from the raw content specified by a DOM tree.
	 * Shortcut to {@link Execution#createComponentsDirectly(Document, String, Component, Map)}.
	 *
	 * @param content the raw content in DOM.
	 * @param extension the default extension if the content doesn't specify
	 * an language. In other words, if
	 * the content doesn't specify an language, {@link LanguageDefinition#getByExtension}
	 * is called.
	 * If extension is null and the content doesn't specify a language,
	 * the language called "xul/html" is assumed.
	 * @param parent the parent component, or null if you want it to be
	 * a root component. If parent is null, the page is assumed to be
	 * the current page, which is determined by the execution context.
	 * In other words, the new component will be the root component
	 * of the current page if parent is null.
	 * @param arg a map of parameters that is accessible by the arg variable
	 * in EL, or by {@link Execution#getArg}.
	 * Ignored if null.
	 * @return the first component being created.
	 * @see #createComponents(PageDefinition, Component, Map)
	 * @see #createComponents(String, Component, Map)
	 * @see #createComponentsDirectly(String, String, Component, Map)
	 * @see #createComponentsDirectly(Reader, String, Component, Map)
	 */
	public static final Component createComponentsDirectly(Document content, String extension, Component parent,
			Map<?, ?> arg) {
		return getCurrent().createComponentsDirectly(content, extension, parent, arg);
	}

	/** Creates components from the raw content read from the specified reader.
	 * Shortcut to {@link Execution#createComponentsDirectly(Reader, String, Component, Map)}.
	 *
	 * <p>The raw content is loader and parsed to a page defintion by use of
	 * {@link Execution#getPageDefinitionDirectly(Reader, String)}, and then
	 * invokes {@link #createComponents(PageDefinition,Component,Map)}
	 * to create components.
	 *
	 * @param reader the reader to retrieve the raw content.
	 * @param extension the default extension if the content doesn't specify
	 * an language. In other words, if
	 * the content doesn't specify an language, {@link LanguageDefinition#getByExtension}
	 * is called.
	 * If extension is null and the content doesn't specify a language,
	 * the language called "xul/html" is assumed.
	 * @param parent the parent component, or null if you want it to be
	 * a root component. If parent is null, the page is assumed to be
	 * the current page, which is determined by the execution context.
	 * In other words, the new component will be the root component
	 * of the current page if parent is null.
	 * @param arg a map of parameters that is accessible by the arg variable
	 * in EL, or by {@link Execution#getArg}.
	 * Ignored if null.
	 * @return the first component being created.
	 * @see #createComponents(PageDefinition, Component, Map)
	 * @see #createComponents(String, Component, Map)
	 * @see #createComponentsDirectly(Document, String, Component, Map)
	 * @see #createComponentsDirectly(String, String, Component, Map)
	 */
	public static Component createComponentsDirectly(Reader reader, String extension, Component parent, Map<?, ?> arg)
			throws IOException {
		return getCurrent().createComponentsDirectly(reader, extension, parent, arg);
	}

	/** Creates components that don't belong to any page
	 * from the raw content specified by a string.
	 *
	 * <p>The raw content is parsed to a page definition by use of
	 * {@link #getPageDefinitionDirectly(WebApp,String,String)}, and then
	 * invokes {@link #createComponents(WebApp,PageDefinition,Map)}
	 * to create components.
	 *
	 * <p>Unlike {@link #createComponentsDirectly(String,String,Component,Map)},
	 * this method can be invoked without the current execution, such as
	 * a working thread. In this case, the wapp argument must be specified.
	 *
	 * @param wapp the Web application. It is optional and used only if
	 * no current execution (e.g., in a working thread).
	 * The instance of {@link WebApp} can be retrieved by use of {@link org.zkoss.zk.ui.http.WebManager#getWebApp},
	 * while the instance of {@link org.zkoss.zk.ui.http.WebManager} can be retrieved
	 * by {@link org.zkoss.zk.ui.http.WebManager#getWebManager}
	 * @param content the raw content of the page. It must be in ZUML.
	 * @param extension the default extension if the content doesn't specify
	 * an language. In other words, if
	 * the content doesn't specify an language, {@link LanguageDefinition#getByExtension}
	 * is called.
	 * If extension is null and the content doesn't specify a language,
	 * the language called "xul/html" is assumed.
	 * @param arg a map of parameters that is accessible by the arg variable
	 * in EL, or by {@link Execution#getArg}.
	 * Ignored if null.
	 * @return all top-level components being created.
	 * @see #createComponents(WebApp, PageDefinition, Map)
	 * @see #createComponents(WebApp, String, Map)
	 * @see #createComponentsDirectly(WebApp, Document, String, Map)
	 * @see #createComponentsDirectly(WebApp, Reader, String, Map)
	 * @since 3.6.2
	 */
	public static Component[] createComponentsDirectly(WebApp wapp, String content, String extension, Map<?, ?> arg) {
		final CCInfo cci = beforeCC(wapp);
		try {
			return cci.exec.createComponentsDirectly(content, extension, arg);
		} finally {
			afterCC(cci);
		}
	}

	/** Creates components that don't belong to any page
	 * from the raw content specified by a DOM tree.
	 *
	 * <p>The raw content is parsed to a page definition by use of
	 * {@link #getPageDefinitionDirectly(WebApp,Document, String)}, and then
	 * invokes {@link #createComponents(WebApp,PageDefinition,Map)}
	 * to create components.
	 *
	 * <p>Unlike {@link #createComponentsDirectly(Document,String,Component,Map)},
	 * this method can be invoked without the current execution, such as
	 * a working thread. In this case, the wapp argument must be specified.
	 *
	 * @param wapp the Web application. It is optional and used only if
	 * no current execution (e.g., in a working thread).
	 * The instance of {@link WebApp} can be retrieved by use of {@link org.zkoss.zk.ui.http.WebManager#getWebApp},
	 * while the instance of {@link org.zkoss.zk.ui.http.WebManager} can be retrieved
	 * by {@link org.zkoss.zk.ui.http.WebManager#getWebManager}
	 * @param content the raw content in DOM.
	 * @param extension the default extension if the content doesn't specify
	 * an language. In other words, if
	 * the content doesn't specify an language, {@link LanguageDefinition#getByExtension}
	 * is called.
	 * If extension is null and the content doesn't specify a language,
	 * the language called "xul/html" is assumed.
	 * @param arg a map of parameters that is accessible by the arg variable
	 * in EL, or by {@link Execution#getArg}.
	 * Ignored if null.
	 * @return all top-level components being created.
	 * @see #createComponents(WebApp, PageDefinition, Map)
	 * @see #createComponents(WebApp, String, Map)
	 * @see #createComponentsDirectly(WebApp, Document, String, Map)
	 * @see #createComponentsDirectly(WebApp, Reader, String, Map)
	 * @since 3.6.2
	 */
	public static Component[] createComponentsDirectly(WebApp wapp, Document content, String extension, Map<?, ?> arg) {
		final CCInfo cci = beforeCC(wapp);
		try {
			return cci.exec.createComponentsDirectly(content, extension, arg);
		} finally {
			afterCC(cci);
		}
	}

	/** Creates components that don't belong to any page
	 * from the raw content read from the specified reader.
	 *
	 * <p>Unl
	 *
	 * <p>The raw content is loaded and parsed to a page definition by use of
	 * {@link #getPageDefinitionDirectly(WebApp,Reader,String)}, and then
	 * invokes {@link #createComponents(WebApp,PageDefinition,Map)}
	 * to create components.
	 *
	 * <p>Unlike {@link #createComponentsDirectly(Reader,String,Component,Map)},
	 * this method can be invoked without the current execution, such as
	 * a working thread. In this case, the wapp argument must be specified.
	 *
	 * @param wapp the Web application. It is optional and used only if
	 * no current execution (e.g., in a working thread).
	 * The instance of {@link WebApp} can be retrieved by use of {@link org.zkoss.zk.ui.http.WebManager#getWebApp},
	 * while the instance of {@link org.zkoss.zk.ui.http.WebManager} can be retrieved
	 * by {@link org.zkoss.zk.ui.http.WebManager#getWebManager}
	 * @param reader the reader to retrieve the raw content in ZUML.
	 * @param extension the default extension if the content doesn't specify
	 * an language. In other words, if
	 * the content doesn't specify an language, {@link LanguageDefinition#getByExtension}
	 * is called.
	 * If extension is null and the content doesn't specify a language,
	 * the language called "xul/html" is assumed.
	 * @param arg a map of parameters that is accessible by the arg variable
	 * in EL, or by {@link Execution#getArg}.
	 * Ignored if null.
	 * @return all top-level components being created.
	 * @see #createComponents(WebApp, PageDefinition, Map)
	 * @see #createComponents(WebApp, String, Map)
	 * @see #createComponentsDirectly(WebApp, Document, String, Map)
	 * @see #createComponentsDirectly(WebApp, String, String, Map)
	 * @since 3.6.2
	 */
	public static Component[] createComponentsDirectly(WebApp wapp, Reader reader, String extension, Map<?, ?> arg)
			throws IOException {
		final CCInfo cci = beforeCC(wapp);
		try {
			return cci.exec.createComponentsDirectly(reader, extension, arg);
		} finally {
			afterCC(cci);
		}
	}

	/** Returns the page definition from the page file specified by an URI.
	 *
	 * <p>Like {@link #createComponents(WebApp,PageDefinition,Map)},
	 * this method can be invoked without the current execution, such as
	 * a working thread. In this case, the wapp argument must be specified.
	 *
	 * @param wapp the Web application. It is optional and used only if
	 * no current execution (e.g., in a working thread).
	 * The instance of {@link WebApp} can be retrieved by use of {@link org.zkoss.zk.ui.http.WebManager#getWebApp},
	 * while the instance of {@link org.zkoss.zk.ui.http.WebManager} can be retrieved
	 * by {@link org.zkoss.zk.ui.http.WebManager#getWebManager}
	 * @param uri the URI of the page file.
	 *
	 * @see #getPageDefinitionDirectly(WebApp, String, String)
	 * @see #getPageDefinitionDirectly(WebApp, Document, String)
	 * @see #getPageDefinitionDirectly(WebApp, Reader, String)
	 * @since 3.6.2
	 */
	public static PageDefinition getPageDefinition(WebApp wapp, String uri) {
		final CCInfo cci = beforeCC(wapp);
		try {
			return cci.exec.getPageDefinition(uri);
		} finally {
			afterCC(cci);
		}
	}

	/** Converts the specified page content to a page definition.
	 *
	 * <p>Like {@link #createComponents(WebApp,PageDefinition,Map)},
	 * this method can be invoked without the current execution, such as
	 * a working thread. In this case, the wapp argument must be specified.
	 *
	 * @param wapp the Web application. It is optional and used only if
	 * no current execution (e.g., in a working thread).
	 * The instance of {@link WebApp} can be retrieved by use of {@link org.zkoss.zk.ui.http.WebManager#getWebApp},
	 * while the instance of {@link org.zkoss.zk.ui.http.WebManager} can be retrieved
	 * by {@link org.zkoss.zk.ui.http.WebManager#getWebManager}
	 * @param content the raw content of the page. It must be in ZUML.
	 * @param extension the default extension if the content doesn't specify
	 * an language. In other words, if
	 * the content doesn't specify an language, {@link LanguageDefinition#getByExtension}
	 * is called.
	 * If extension is null and the content doesn't specify a language,
	 * the language called "xul/html" is assumed.
	 * @see #getPageDefinitionDirectly(WebApp, Document, String)
	 * @see #getPageDefinitionDirectly(WebApp, Reader, String)
	 * @see #getPageDefinition
	 * @since 3.6.2
	 */
	public PageDefinition getPageDefinitionDirectly(WebApp wapp, String content, String extension) {
		final CCInfo cci = beforeCC(wapp);
		try {
			return cci.exec.getPageDefinitionDirectly(content, extension);
		} finally {
			afterCC(cci);
		}
	}

	/** Converts the specified page content, in DOM, to a page definition.
	 *
	 * <p>Like {@link #createComponentsDirectly(WebApp,Document,String,Map)},
	 * this method can be invoked without the current execution, such as
	 * a working thread. In this case, the wapp argument must be specified.
	 *
	 * @param wapp the Web application. It is optional and used only if
	 * no current execution (e.g., in a working thread).
	 * The instance of {@link WebApp} can be retrieved by use of {@link org.zkoss.zk.ui.http.WebManager#getWebApp},
	 * while the instance of {@link org.zkoss.zk.ui.http.WebManager} can be retrieved
	 * by {@link org.zkoss.zk.ui.http.WebManager#getWebManager}
	 * @param content the raw content of the page in DOM.
	 * @param extension the default extension if the content doesn't specify
	 * an language. In other words, if
	 * the content doesn't specify an language, {@link LanguageDefinition#getByExtension}
	 * is called.
	 * If extension is null and the content doesn't specify a language,
	 * the language called "xul/html" is assumed.
	 * @see #getPageDefinitionDirectly(WebApp, String, String)
	 * @see #getPageDefinitionDirectly(WebApp, Reader, String)
	 * @see #getPageDefinition
	 * @since 3.6.2
	 */
	public PageDefinition getPageDefinitionDirectly(WebApp wapp, Document content, String extension) {
		final CCInfo cci = beforeCC(wapp);
		try {
			return cci.exec.getPageDefinitionDirectly(content, extension);
		} finally {
			afterCC(cci);
		}
	}

	/** Reads the raw content from a reader and converts it into
	 * a page definition.
	 *
	 * <p>Like {@link #createComponentsDirectly(WebApp,Reader,String,Map)},
	 * this method can be invoked without the current execution, such as
	 * a working thread. In this case, the wapp argument must be specified.
	 *
	 * @param wapp the Web application. It is optional and used only if
	 * no current execution (e.g., in a working thread).
	 * The instance of {@link WebApp} can be retrieved by use of {@link org.zkoss.zk.ui.http.WebManager#getWebApp},
	 * while the instance of {@link org.zkoss.zk.ui.http.WebManager} can be retrieved
	 * by {@link org.zkoss.zk.ui.http.WebManager#getWebManager}
	 * @param reader used to input the raw content of the page. It must be in ZUML.
	 * @param extension the default extension if the content doesn't specify
	 * an language. In other words, if
	 * the content doesn't specify an language, {@link LanguageDefinition#getByExtension}
	 * is called.
	 * If extension is null and the content doesn't specify a language,
	 * the language called "xul/html" is assumed.
	 * @see #getPageDefinitionDirectly(WebApp, String, String)
	 * @see #getPageDefinitionDirectly(WebApp, Document, String)
	 * @see #getPageDefinition
	 * @since 3.6.2
	 */
	public PageDefinition getPageDefinitionDirectly(WebApp wapp, Reader reader, String extension) throws IOException {
		final CCInfo cci = beforeCC(wapp);
		try {
			return cci.exec.getPageDefinitionDirectly(reader, extension);
		} finally {
			afterCC(cci);
		}
	}

	private static final CCInfo beforeCC(WebApp wapp) {
		Execution exec = Executions.getCurrent();
		if (exec != null)
			return new CCInfo(exec, false);

		((WebAppCtrl) wapp).getUiEngine().activate(exec = CCExecution.newInstance(wapp));
		return new CCInfo(exec, true);

	}

	private static final void afterCC(CCInfo cci) {
		if (cci.created) {
			try {
				((WebAppCtrl) cci.exec.getDesktop().getWebApp()).getUiEngine().deactivate(cci.exec);
			} catch (Throwable ex) {
			}
		}
	}

	private static class CCInfo {
		private final Execution exec;
		private final boolean created;

		private CCInfo(Execution exec, boolean created) {
			this.exec = exec;
			this.created = created;
		}
	}

	/** Sends a temporary redirect response to the client using the specified
	 * redirect location URL by use of the current execution,
	 * {@link #getCurrent}.
	 *
	 * <p>After calling this method, the caller shall end the processing
	 * immediately (by returning). All pending requests and events will
	 * be dropped.
	 *
	 * @param uri the URI to redirect to, or null to reload the same page
	 * @see Execution#sendRedirect
	 */
	public static void sendRedirect(String uri) {
		getCurrent().sendRedirect(uri);
	}

	/** A shortcut of Executions.getCurrent().include(page).
	 *
	 * @see Execution#include(java.io.Writer,String,Map,int)
	 * @see Execution#include(String)
	 */
	public static void include(String page) throws IOException {
		getCurrent().include(page);
	}

	/** A shortcut of Executions.getCurrent().forward(page).
	 *
	 * @see Execution#forward(java.io.Writer,String,Map,int)
	 * @see Execution#forward(String)
	 */
	public static void forward(String page) throws IOException {
		getCurrent().forward(page);
	}

	//-- wait/notify --//
	/** Suspends the current processing of an event and wait until the
	 * other thread invokes {@link #notify(Object)}, {@link #notifyAll(Object)},
	 * {@link #notify(Desktop, Object)} or {@link #notifyAll(Desktop, Object)}
	 * for the specified object.
	 *
	 * <p>It can only be called when the current thread is processing an event.
	 * And, when called, the current processing is suspended and ZK continues
	 * to process the next event and finally render the result.
	 *
	 * <p>It is typical use to implement a modal dialog where it won't return
	 * until the modal dialog ends.
	 *
	 * @param mutex any non-null object to identify what to notify.
	 * It must be same object passed to {@link #notify(Desktop, Object)}.
	 * If there is racing issue, you have to enclose it with
	 * <code>synchronized</code> (though it is optional).
	 * @exception UiException if it is called not during event processing.
	 * @exception SuspendNotAllowedException if there are too many suspended
	 * exceptions.
	 * Deployers can control the maximal allowed number of suspended exceptions
	 * by specifying <code>max-suspended-thread</code> in <code>zk.xml</code>,
	 * or invoking {@link org.zkoss.zk.ui.util.Configuration#setMaxSuspendedThreads}.
	 */
	public static final void wait(Object mutex) throws InterruptedException, SuspendNotAllowedException {
		getUiEngine().wait(mutex);
	}

	/** Wakes up a single event processing thread that is waiting on the
	 * specified object.
	 *
	 * <p>Unlike {@link #notify(Desktop, Object)}, this method can be invoked only
	 * in the event listener that processing the same desktop.
	 * In addition, this method can be called under the event listener.
	 *
	 * <p>Use {@link #notify(Desktop, Object)} if you want to notify in other
	 * thread, such as a working thread.
	 *
	 * @param mutex any non-null object to identify what to notify.
	 * It must be same object passed to {@link #wait}.
	 * If there is racing issue, you have to enclose it with
	 * <code>synchronized</code> (though it is optional).
	 * @see #notify(Desktop, Object)
	 * @see #notifyAll(Object)
	 * @exception UiException if it is called not during event processing.
	 */
	public static final void notify(Object mutex) {
		getUiEngine().notify(mutex);
	}

	/** Wakes up a single event processing thread for the specified desktop
	 * that is waiting on the specified object.
	 *
	 * <p>Unlike {@link #notify(Object)}, this method can be called any time.
	 * It is designed to let working threads resume an event processing
	 * thread.
	 *
	 * <p>Notice: if this method is NOT called in an event processing thread,
	 * the resumed thread won't execute until the next request is received.
	 * To enforce it happen, you might use the timer component (found in ZUL).
	 *
	 * <p>Notice: to resolve racing issue, you usually need to follow
	 * this pattern.
	 * <pre><code>
	//Event Handling Thread
	synchronized (mutex) {
	final WorkingThread worker = new WorkingThread(desktop);
	synchronized (mutex) {
		worker.start();
		Executions.wait(mutex);
	}
	....
	}
	//Working Thread
	public void run() {
	....
	synchronized (mutex) {
		Executions.notify(desktop, mutex);
	}
	}
	 </code></pre>
	 *
	 * @param desktop the desktop which the suspended thread is processing.
	 * It must be the same desktop of the suspended thread.
	 * @param mutex any non-null object to identify what to notify.
	 * It must be same object passed to {@link #wait}.
	 * If there is racing issue, you have to enclose it with
	 * <code>synchronized</code> (though it is optional).
	 * @see #notify(Object)
	 * @see #notifyAll(Desktop, Object)
	 */
	public static final void notify(Desktop desktop, Object mutex) {
		getUiEngine(desktop).notify(desktop, mutex);
	}

	/** Wakes up all event processing thread that are waiting on the
	 * specified object.
	 *
	 * <p>Unlike {@link #notify(Desktop, Object)}, this method can be invoked only
	 * in the event listener that processing the same desktop.
	 * In addition, this method can be called under the event listener.
	 *
	 * <p>Use {@link #notifyAll(Desktop, Object)} if you want to notify in other
	 * thread, such as a working thread.
	 *
	 * @param mutex any non-null object to identify what to notify.
	 * It must be same object passed to {@link #wait}.
	 * If there is racing issue, you have to enclose it with
	 * <code>synchronized</code> (though it is optional).
	 * @see #notify(Desktop, Object)
	 * @see #notifyAll(Object)
	 * @exception UiException if it is called not during event processing.
	 */
	public static final void notifyAll(Object mutex) {
		getUiEngine().notifyAll(mutex);
	}

	/** Wakes up all event processing threads for the specified desktop
	 * that are waiting on the specified object.
	 *
	 * <p>Unlike {@link #notifyAll(Object)}, this method can be called any time.
	 * It is designed to let working threads resume an event processing
	 * thread.
	 *
	 * <p>Notice: if this method is NOT called in an event processing thread,
	 * the resumed thread won't execute until the next request is received.
	 * To enforce it happen, you might use the timer component (found in ZUL).
	 *
	 * <p>Notice: to resolve racing issue, you usually need to follow
	 * this pattern.
	 * <pre><code>
	//Event Handling Thread
	synchronized (mutex) {
	final WorkingThread worker = new WorkingThread(desktop);
	synchronized (mutex) {
		worker.start();
		Executions.wait(mutex);
	}
	....
	}
	//Working Thread
	public void run() {
	....
	synchronized (mutex) {
		Executions.notifyAll(desktop, mutex);
	}
	}
	 </code></pre>
	 *
	 * @param desktop the desktop which the suspended thread is processing.
	 * It must be the same desktop of the suspended thread.
	 * @param mutex any non-null object to identify what to notify.
	 * It must be same object passed to {@link #wait}.
	 * If there is racing issue, you have to enclose it with
	 * <code>synchronized</code> (though it is optional).
	 * @see #notify(Object)
	 * @see #notifyAll(Desktop, Object)
	 */
	public static final void notifyAll(Desktop desktop, Object mutex) {
		getUiEngine(desktop).notifyAll(desktop, mutex);
	}

	/** Schedules a task to run under the server push of the given desktop asynchronously.
	 * The caller can be any thread, not
	 * limited to the event listener of the given desktop.
	 *
	 * <p>The task is executed when the server push of the given desktop
	 * is granted. The task is executed asynchronously. That is, this method
	 * return without waiting for the task to be executed.
	 *
	 * <p>The task is executed in the thread serving the server-push request,
	 * so no additional thread will be created. It is safe to use in a clustering
	 * environment.
	 *
	 * <p>The task is represented by an event listener. When the server push
	 * is ready to serve the given task, {@link EventListener#onEvent} is called
	 * with the given event.
	 *
	 * <p>Like {@link #activate}, this method can be called anywhere, not limited
	 * to the event listener of the given desktop. It can be called even
	 * if there is no current execution.
	 *
	 * <p>Alternative to {@link #schedule}, you could use {@link #activate}/{@link #deactivate}
	 * if you prefer something to be done synchronously.
	 *
	 * <p>The server-push is disabled by default. To use it, you have to enable
	 * it first with {@link Desktop#enableServerPush} for the given desktop.
	 * Once enabled, you can use as many as server-push threads you like
	 * (for the desktop with the server-push feature enabled).
	 *
	 * @param task the task to execute
	 * @param event the event to be passed to the task (i.e., the event listener).
	 * It could null or any instance as long as the task recognizes it.
	 * @exception IllegalStateException if the server push is not enabled.
	 * @exception DesktopUnavailableException if the desktop is removed
	 * (when activating).
	 * @since 5.0.6
	 */
	public static <T extends Event> void schedule(Desktop desktop, EventListener<T> task, T event) {
		((DesktopCtrl) desktop).scheduleServerPush(task, event);
	}

	/** Activates a thread to allow it access the given desktop synchronously.
	 * It causes the current thread to wait until the desktop is available
	 * to access, the desktop no longer exists,
	 * or some other thread interrupts this thread.
	 *
	 * <p>Alternative to {@link #activate}/{@link #deactivate}, you could use
	 * {@link #schedule} to execute a task under server push. {@link #schedule} is
	 * asynchronous, while {@link #activate}/{@link #deactivate} is synchronous
	 *
	 * <p>Like {@link #schedule}, this method can be called anywhere, not limited
	 * to the event listener of the given desktop. It can be called even
	 * if there is no current execution.
	 *
	 * <p>The server-push is disabled by default. To use it, you have to enable
	 * it first with {@link Desktop#enableServerPush} for the given desktop.
	 * Once enabled, you can use as many as server-push threads you like
	 * (for the desktop with the server-push feature enabled).
	 *
	 * <p>Before a thread, not running in the event listener of the given desktop,
	 * can access the desktop, you have to activate it first by {@link #activate}.
	 * Once this method returns, the thread is activated and it, like
	 * an event listener of the given desktop, can manipulate the desktop directly.
	 *
	 * <p>A typical use pattern:
	 *
	 * <pre><code>class MyWorkingThread extends Thread {
	 *  public void run() {
	 *    while (anything_to_publish) {
	 *       //prepare something to publish
	 *       //you can create new components and manipulate them before
	 *       //activation, as long as they are not attached to the desktop
	 *
	 *       Executions.activate(desktop);
	 *       try {
	 *         try {
	 *           //activated
	 *           //manipulate the components that are attached the desktop
	 *         } finally {
	 *           Executions.deactivate(desktop)
	 *         }
	 *       } catch (DesktopUnavailableException ex) {
	 *         //clean up (since desktop is dead)
	 *       }
	 *   }
	 * }
	 *}</code></pre>
	 *
	 * <p>Note: the access of components is sequentialized. That is,
	 * at most one thread is activated. All others, including
	 * the event listeners, have to wait until it is deactivated
	 * (i.e., until {@link #deactivate} is called).
	 * Thus, it is better to minimize the time remaining activated.
	 * A typical practice is to create new components and manipulate them
	 * before activated. Then, you have to only attach them after activated.
	 *
	 * <pre><code> Tree tree = new Tree();
	 * new Treechildren().setParent(tree); //initialize the tree
	 * Exections.activate(desktop);
	 * try {
	 *   tree.setPage(page); //assume page is a page of desktop
	 *</code></pre>
	 *
	 * <p>Note: you don't need to invoke this method in the event listener
	 * since it is already activated when an event listen starts execution.
	 *
	 * <p> Note: When you call this method, ZK framework would require a lock on the
	 * thread. In the rare case that the framework, at the same time, is waiting
	 * on the release of another lock from your application, then a deadlock
	 * would result.
	 *
	 * @exception InterruptedException if it is interrupted by other thread
	 * @exception IllegalStateException if the server push is not enabled.
	 * @exception DesktopUnavailableException if the desktop is removed
	 * (when activating).
	 * @since 3.0.0
	 */
	public static final void activate(Desktop desktop) throws InterruptedException, DesktopUnavailableException {
		activate(desktop, 0);
	}

	/** Activates a thread to allow it access the given desktop synchronously,
	 * or until a certain amount of time has elapsed.
	 * It causes the current thread to wait until the desktop is available
	 * to access, the desktop no longer exists,
	 * some other thread interrupts this thread,
	 * or a certain amount of real time has elapsed.
	 * <p> Note: When you call this method, ZK framework would require a lock on the
	 * thread. In the rare case that the framework, at the same time, is waiting
	 * on the release of another lock from your application, then a deadlock
	 * would result.
	 *
	 * @param timeout the maximum time to wait in milliseconds.
	 * Ignored (i.e., never timeout) if non-positive.
	 * @return whether it is activated or it is timeout.
	 * The only reason it returns false is timeout.
	 * @exception InterruptedException if it is interrupted by other thread
	 * @exception DesktopUnavailableException if the desktop is removed
	 * (when activating).
	 * @exception IllegalStateException if the server push is not
	 * enabled for this desktop yet ({@link Desktop#enableServerPush}).
	 * @since 3.0.0
	 * @see #activate(Desktop)
	 * @see #deactivate
	 */
	public static final boolean activate(Desktop desktop, long timeout)
			throws InterruptedException, DesktopUnavailableException {
		return ((DesktopCtrl) desktop).activateServerPush(timeout);
	}

	/** Deactivates a thread that has invoked {@link #activate} successfully.
	 * @since 3.0.0
	 * @see #activate(Desktop)
	 * @see #activate(Desktop, long)
	 */
	public static final void deactivate(Desktop desktop) {
		((DesktopCtrl) desktop).deactivateServerPush();
	}

	private static final UiEngine getUiEngine(Desktop desktop) {
		if (desktop == null)
			throw new IllegalArgumentException("desktop cannot be null");
		return ((WebAppCtrl) desktop.getWebApp()).getUiEngine();
	}

	private static final UiEngine getUiEngine() {
		final Execution exec = getCurrent();
		if (exec == null)
			throw new IllegalStateException("This method can be called only under an event listener");
		return ((WebAppCtrl) exec.getDesktop().getWebApp()).getUiEngine();
	}
}
