📄 configuration.java
字号:
/* Configuration.java{{IS_NOTE Purpose: Description: History: Sun Mar 26 16:06:56 2006, Created by tomyeh}}IS_NOTECopyright (C) 2006 Potix Corporation. All Rights Reserved.{{IS_RIGHT This program is distributed under GPL Version 2.0 in the hope that it will be useful, but WITHOUT ANY WARRANTY.}}IS_RIGHT*/package org.zkoss.zk.ui.util;import java.util.Iterator;import java.util.List;import java.util.LinkedList;import java.util.Collections;import java.util.Map;import java.util.HashMap;import java.util.Set;import java.util.HashSet;import org.zkoss.lang.Classes;import org.zkoss.lang.PotentialDeadLockException;import org.zkoss.lang.Exceptions;import org.zkoss.util.WaitLock;import org.zkoss.util.logging.Log;import org.zkoss.xel.ExpressionFactory;import org.zkoss.xel.Expressions;import org.zkoss.zk.ui.Component;import org.zkoss.zk.ui.WebApp;import org.zkoss.zk.ui.Session;import org.zkoss.zk.ui.Desktop;import org.zkoss.zk.ui.Execution;import org.zkoss.zk.ui.Executions;import org.zkoss.zk.ui.Richlet;import org.zkoss.zk.ui.UiException;import org.zkoss.zk.ui.event.Event;import org.zkoss.zk.ui.event.EventThreadInit;import org.zkoss.zk.ui.event.EventThreadCleanup;import org.zkoss.zk.ui.event.EventThreadSuspend;import org.zkoss.zk.ui.event.EventThreadResume;import org.zkoss.zk.ui.sys.WebAppCtrl;import org.zkoss.zk.ui.sys.UiEngine;import org.zkoss.zk.ui.sys.DesktopCacheProvider;import org.zkoss.zk.ui.sys.UiFactory;import org.zkoss.zk.ui.sys.FailoverManager;import org.zkoss.zk.ui.sys.IdGenerator;import org.zkoss.zk.ui.impl.RichletConfigImpl;import org.zkoss.zk.ui.impl.EventInterceptors;import org.zkoss.zk.device.Devices;/** * The ZK configuration. * * <p>To retrieve the current configuration, use * {@link org.zkoss.zk.ui.WebApp#getConfiguration}. * * <p>Note: A {@link Configuration} instance can be assigned to at most one * {@link WebApp} instance. * * @author tomyeh */public class Configuration { private static final Log log = Log.lookup(Configuration.class); private static final String PROP_EXPRESS_FACTORY = "org.zkoss.xel.ExpressionFactory.class"; private WebApp _wapp; /** List of classes. */ private final List _evtInits = new LinkedList(), _evtCleans = new LinkedList(), _evtSusps = new LinkedList(), _evtResus = new LinkedList(), _appInits = new LinkedList(), _appCleans = new LinkedList(), _sessInits = new LinkedList(), _sessCleans = new LinkedList(), _dtInits = new LinkedList(), _dtCleans = new LinkedList(), _execInits = new LinkedList(), _execCleans = new LinkedList(); /** List of objects. */ private final List _uriIntcps = new LinkedList(), _reqIntcps = new LinkedList(); private final Map _prefs = Collections.synchronizedMap(new HashMap()), _errURIs = Collections.synchronizedMap(new HashMap()); /** Map(String name, [Class richlet, Map params] or Richilet richlet). */ private final Map _richlets = new HashMap(); /** Map(String path, [String name, boolean wildcard]). */ private final Map _richletmaps = new HashMap(); /** Map(String deviceType, List(ErrorPage)). */ private final Map _errpgs = new HashMap(3); private Monitor _monitor; private PerformanceMeter _pfmeter; private final List _themeURIs = new LinkedList(); private transient String[] _roThemeURIs = new String[0]; private ThemeProvider _themeProvider; /** A set of disabled theme URIs. */ private Set _disThemeURIs; private Class _wappcls, _uiengcls, _dcpcls, _uiftycls, _failmancls, _idgencls; private int _dtTimeout = 3600, _dtMax = 10, _sessTimeout = 0, _sparThdMax = 100, _suspThdMax = -1, _maxUploadSize = 5120, _maxProcTime = 3000, _promptDelay = 900, _tooltipDelay = 800; private String _charsetResp = "UTF-8", _charsetUpload = "UTF-8"; private CharsetFinder _charsetFinderUpload; /** The event interceptors. */ private final EventInterceptors _eis = new EventInterceptors(); /** whether to use the event processing thread. */ private boolean _useEvtThd = true; /** keep-across-visits. */ private boolean _keepDesktop; /** Whether to disable components that don't belong to the modal window. */ private boolean _disableBehindModal = true; /** Whether to keep the session alive when receiving onTimer. */ private boolean _timerKeepAlive; /** Contructor. */ public Configuration() { _errURIs.put(new Integer(302), ""); _errURIs.put(new Integer(401), ""); _errURIs.put(new Integer(403), ""); } /** Returns the Web application that this configuration belongs to, * or null if it is not associated yet. */ public WebApp getWebApp() { return _wapp; } /** Associates it with a web application. */ public void setWebApp(WebApp wapp) { _wapp = wapp; } /** Adds a listener class. * * @param klass the listener class must implement at least one of * {@link Monitor}, {@link PerformanceMeter}, {@link EventThreadInit}, * {@link EventThreadCleanup}, {@link EventThreadSuspend}, * {@link EventThreadResume}, {@link WebAppInit}, {@link WebAppCleanup}, * {@link SessionInit}, {@link SessionCleanup}, {@link DesktopInit}, * {@link DesktopCleanup}, {@link ExecutionInit}, {@link ExecutionCleanup}, * {@link URIInterceptor}, {@link RequestInterceptor}, {@link EventInterceptor} * interfaces. */ public void addListener(Class klass) throws Exception { boolean added = false; if (Monitor.class.isAssignableFrom(klass)) { if (_monitor != null) throw new UiException("Monitor listener can be assigned only once"); _monitor = (Monitor)klass.newInstance(); added = true; } if (PerformanceMeter.class.isAssignableFrom(klass)) { if (_pfmeter != null) throw new UiException("PerformanceMeter listener can be assigned only once"); _pfmeter = (PerformanceMeter)klass.newInstance(); added = true; } if (EventThreadInit.class.isAssignableFrom(klass)) { synchronized (_evtInits) { _evtInits.add(klass); } added = true; } if (EventThreadCleanup.class.isAssignableFrom(klass)) { synchronized (_evtCleans) { _evtCleans.add(klass); } added = true; } if (EventThreadSuspend.class.isAssignableFrom(klass)) { synchronized (_evtSusps) { _evtSusps.add(klass); } added = true; } if (EventThreadResume.class.isAssignableFrom(klass)) { synchronized (_evtResus) { _evtResus.add(klass); } added = true; } if (WebAppInit.class.isAssignableFrom(klass)) { synchronized (_appInits) { _appInits.add(klass); } added = true; } if (WebAppCleanup.class.isAssignableFrom(klass)) { synchronized (_appCleans) { _appCleans.add(klass); } added = true; } if (SessionInit.class.isAssignableFrom(klass)) { synchronized (_sessInits) { _sessInits.add(klass); } added = true; } if (SessionCleanup.class.isAssignableFrom(klass)) { synchronized (_sessCleans) { _sessCleans.add(klass); } added = true; } if (DesktopInit.class.isAssignableFrom(klass)) { synchronized (_dtInits) { _dtInits.add(klass); } added = true; } if (DesktopCleanup.class.isAssignableFrom(klass)) { synchronized (_dtCleans) { _dtCleans.add(klass); } added = true; } if (ExecutionInit.class.isAssignableFrom(klass)) { synchronized (_execInits) { _execInits.add(klass); } added = true; } if (ExecutionCleanup.class.isAssignableFrom(klass)) { synchronized (_execCleans) { _execCleans.add(klass); } added = true; } if (URIInterceptor.class.isAssignableFrom(klass)) { try { final Object obj = klass.newInstance(); synchronized (_uriIntcps) { _uriIntcps.add(obj); } } catch (Throwable ex) { log.error("Failed to instantiate "+klass, ex); } added = true; } if (RequestInterceptor.class.isAssignableFrom(klass)) { try { final Object obj = klass.newInstance(); synchronized (_reqIntcps) { _reqIntcps.add(obj); } } catch (Throwable ex) { log.error("Failed to instantiate "+klass, ex); } added = true; } if (EventInterceptor.class.isAssignableFrom(klass)) { try { _eis.addEventInterceptor((EventInterceptor)klass.newInstance()); } catch (Throwable ex) { log.error("Failed to instantiate "+klass, ex); } added = true; } if (!added) throw new UiException("Unknown listener: "+klass); } /** Removes a listener class. */ public void removeListener(Class klass) { synchronized (_evtInits) { _evtInits.remove(klass); } synchronized (_evtCleans) { _evtCleans.remove(klass); } synchronized (_evtSusps) { _evtSusps.remove(klass); } synchronized (_evtResus) { _evtResus.remove(klass); } synchronized (_appInits) { _appInits.remove(klass); } synchronized (_appCleans) { _appCleans.remove(klass); } synchronized (_sessInits) { _sessInits.remove(klass); } synchronized (_sessCleans) { _sessCleans.remove(klass); } synchronized (_dtInits) { _dtInits.remove(klass); } synchronized (_dtCleans) { _dtCleans.remove(klass); } synchronized (_execInits) { _execInits.remove(klass); } synchronized (_execCleans) { _execCleans.remove(klass); } synchronized (_uriIntcps) { for (Iterator it = _uriIntcps.iterator(); it.hasNext();) { final Object obj = it.next(); if (obj.getClass().equals(klass)) it.remove(); } } synchronized (_reqIntcps) { for (Iterator it = _reqIntcps.iterator(); it.hasNext();) { final Object obj = it.next(); if (obj.getClass().equals(klass)) it.remove(); } } _eis.removeEventInterceptor(klass); } /** Contructs a list of {@link EventThreadInit} instances and invokes * {@link EventThreadInit#prepare} for * each relevant listener registered by {@link #addListener}. * * <p>Used only internally (by {@link UiEngine} before starting an event * processing thread). * * @exception UiException to prevent a thread from being processed * if {@link EventThreadInit#prepare} throws an exception * @return a list of {@link EventThreadInit} instances that are * constructed in this method (and their {@link EventThreadInit#prepare} * are called successfully), or null. */ public List newEventThreadInits(Component comp, Event evt) throws UiException { if (_evtInits.isEmpty()) return null; //it is OK to test LinkedList.isEmpty without synchronized final List inits = new LinkedList(); synchronized (_evtInits) { for (Iterator it = _evtInits.iterator(); it.hasNext();) { final Class klass = (Class)it.next(); try { final EventThreadInit init = (EventThreadInit)klass.newInstance(); init.prepare(comp, evt); inits.add(init); } catch (Throwable ex) { throw UiException.Aide.wrap(ex); //Don't intercept; to prevent the event being processed } } } return inits; } /** Invokes {@link EventThreadInit#init} for each instance returned * by {@link #newEventThreadInits}. * * <p>Used only internally. * * @param inits a list of {@link EventThreadInit} instances returned from * {@link #newEventThreadInits}, or null if no instance at all. * @param comp the component which the event is targeting * @param evt the event to process * @exception UiException to prevent a thread from being processed * if {@link EventThreadInit#prepare} throws an exception * @return false if you want to ignore the event, i.e., not to proceed * any event processing for the specified event (evt). */ public boolean invokeEventThreadInits(List inits, Component comp, Event evt) throws UiException { if (inits == null || inits.isEmpty()) return true; //not to ignore for (Iterator it = inits.iterator(); it.hasNext();) { final EventThreadInit fn = (EventThreadInit)it.next(); try { try { if (!fn.init(comp, evt)) return false; //ignore the event } catch (AbstractMethodError ex) { //backward compatible prior to 3.0 fn.getClass().getMethod( "init", new Class[] {Component.class, Event.class}) .invoke(fn, new Object[] {comp, evt}); } } catch (Throwable ex) { throw UiException.Aide.wrap(ex); //Don't intercept; to prevent the event being processed } } return true; } /** Invokes {@link EventThreadCleanup#cleanup} for each relevant * listener registered by {@link #addListener}. * * <p>Used only internally. * * <p>An instance of {@link EventThreadCleanup} is constructed first, * and then invoke {@link EventThreadCleanup#cleanup}. * * <p>It never throws an exception but logs and adds it to the errs argument, * if not null. * * @param comp the component which the event is targeting * @param evt the event to process * @param errs a list of exceptions (java.lang.Throwable) if any exception * occured before this method is called, or null if no exeption at all. * Note: you can manipulate the list directly to add or clean up exceptions. * For example, if exceptions are fixed correctly, you can call errs.clear() * such that no error message will be displayed at the client. * @return a list of {@link EventThreadCleanup}, or null */ public List newEventThreadCleanups(Component comp, Event evt, List errs) { if (_evtCleans.isEmpty()) return null; //it is OK to test LinkedList.isEmpty without synchronized final List cleanups = new LinkedList(); synchronized (_evtCleans) { for (Iterator it = _evtCleans.iterator(); it.hasNext();) { final Class klass = (Class)it.next(); try { final EventThreadCleanup cleanup = (EventThreadCleanup)klass.newInstance(); cleanup.cleanup(comp, evt, errs); cleanups.add(cleanup); } catch (Throwable t) { if (errs != null) errs.add(t); log.error("Failed to invoke "+klass, t); } } } return cleanups; } /** Invoke {@link EventThreadCleanup#complete} for each instance returned by * {@link #newEventThreadCleanups}. * * <p>Used only internally. * * <p>It never throws an exception but logs and adds it to the errs argument, * if not null. * * @param cleanups a list of {@link EventThreadCleanup} instances returned from * {@link #newEventThreadCleanups}, or null if no instance at all. * @param errs used to hold the exceptions that are thrown by * {@link EventThreadCleanup#complete}. * If null, all exceptions are ignored (but logged). */ public void invokeEventThreadCompletes(List cleanups, Component comp, Event evt, List errs) { if (cleanups == null || cleanups.isEmpty()) return; for (Iterator it = cleanups.iterator(); it.hasNext();) { final EventThreadCleanup fn = (EventThreadCleanup)it.next(); try { fn.complete(comp, evt); } catch (Throwable ex) { if (errs != null) errs.add(ex); log.error("Failed to invoke "+fn, ex); } }
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -