/* * The contents of this file are subject to the Mozilla Public License Version 1.1 * (the "License"); you may not use this file except in compliance with the License. * You may obtain a copy of the License at . * * Software distributed under the License is distributed on an "AS IS" basis, WITHOUT * WARRANTY OF ANY KIND, either express or implied. See the License for the specific * language governing rights and limitations under the License. * * The Original Code is the Venice Web Communities System. * * The Initial Developer of the Original Code is Eric J. Bowersox , * for Silverwrist Design Studios. Portions created by Eric J. Bowersox are * Copyright (C) 2002-03 Eric J. Bowersox/Silverwrist Design Studios. All Rights Reserved. * * Contributor(s): */ package com.silverwrist.dynamo.app; import java.io.*; import java.util.*; import javax.servlet.*; import javax.servlet.http.*; import org.apache.commons.collections.*; import org.apache.log4j.Logger; import org.w3c.dom.*; import com.silverwrist.util.*; import com.silverwrist.util.xml.*; import com.silverwrist.dynamo.DynamoVersion; import com.silverwrist.dynamo.Namespaces; import com.silverwrist.dynamo.event.*; import com.silverwrist.dynamo.except.*; import com.silverwrist.dynamo.iface.*; import com.silverwrist.dynamo.script.ScriptController; import com.silverwrist.dynamo.util.*; /** * The main "engine" class of the Dynamo framework, which holds most of the service providers and other * classes registered (usually by the defined {@link com.silverwrist.dynamo.iface.Application Application} class). * Exactly one of these is created per Dynamo instance; for Dynamo Web applications, a reference to it is saved * in the servlet context attributes. It is also responsible for reading and parsing the Dynamo XML configuration * file and instantiating components defined therein. * * @author Eric J. Bowersox <erbo@silcom.com> * @version X */ public class ApplicationContainer implements ResourceProvider, ResourceProviderManager, RendererRegistration, ObjectProvider, EventListenerRegistration, OutputObjectFilterRegistration, QueryRenderer, PostDynamicUpdate, RenderImmediate, RequestPreprocessorRegistration, ExceptionTranslatorRegistration { /*-------------------------------------------------------------------------------- * Internal class recording renderer registrations and providing a * "shutdown hook" *-------------------------------------------------------------------------------- */ private class RegisteredRenderer implements ComponentShutdown { /*==================================================================== * Attributes *==================================================================== */ private Renderer m_renderer; private HashSet m_known_classes; /*==================================================================== * Constructors *==================================================================== */ RegisteredRenderer(Class klass, Renderer renderer) { m_renderer = renderer; m_known_classes = new HashSet(); m_known_classes.add(klass); } // end constructor RegisteredRenderer(DynamicClass dclass, Renderer renderer) { m_renderer = renderer; m_known_classes = new HashSet(); m_known_classes.add(dclass); } // end constructor /*==================================================================== * Implementations from interface ComponentShutdown *==================================================================== */ public synchronized void shutdown() { Iterator it = m_known_classes.iterator(); while (it.hasNext()) { // remove all class rendering entries registered with this "event" Object obj = it.next(); if (obj instanceof Class) m_class_renderers.remove(obj); else if (obj instanceof DynamicClass) m_class_renderers.remove(obj); } // end while m_known_classes.clear(); } // end shutdown /*==================================================================== * External operations *==================================================================== */ public Renderer getRenderer() { return m_renderer; } // end getRenderer public synchronized void add(Class klass) { m_known_classes.add(klass); } // end add public synchronized void add(DynamicClass dclass) { m_known_classes.add(dclass); } // end add } // end class RegisteredRenderer /*-------------------------------------------------------------------------------- * Static data members *-------------------------------------------------------------------------------- */ private static Logger logger = Logger.getLogger(ApplicationContainer.class); private static final String[] SUBSTRATE_MAP_KEYS = { ApplicationSubstrate.OBJ_BASE_PATH, ApplicationSubstrate.OBJ_CODE_PATH, ApplicationSubstrate.OBJ_CLASSES_PATH, ApplicationSubstrate.OBJ_LIBS_PATH }; private static final ApplicationListener[] APP_LISTENER_TEMPLATE = new ApplicationListener[0]; private static final SessionInfoListener[] SESSION_LISTENER_TEMPLATE = new SessionInfoListener[0]; private static final String TEMPLATE_CLASSNAME = "$$$BLORT$$$"; /*-------------------------------------------------------------------------------- * Attributes *-------------------------------------------------------------------------------- */ private int m_refs; // reference count private ApplicationSubstrate m_substrate; // application substrate object private File m_resource_base; // base directory for resources private Vector m_resource_providers = new Vector(); // resource providers private LinkedList m_shutdown_list = new LinkedList(); // list of objects to shut down private HashMap m_connections = new HashMap(); // list of connection pools private HashMap m_objects = new HashMap(); // list of base objects private Application m_application = null; // the application object private Hashtable m_class_renderers = new Hashtable(); // renderers for static classes private Hashtable m_dclass_renderers = new Hashtable(); // renderers for dynamic classes private Vector m_application_listeners = new Vector(); // application event listeners private Vector m_session_listeners = new Vector(); // session event listeners private BackgroundProcessor m_background; // background processor private ScriptController m_script_ctrl; // script controller private ApplicationServiceManager m_app_sm; // application service manager private PropertySerializationSupport m_pss; // property serialization support private Set m_known_sessions; // known sessions private String m_identity; // server identity private Map m_rewrite_rules; // URL rewriting rules private Vector m_output_filters = new Vector(); // output filters private HashMap m_update_listeners = new HashMap(); // update listeners private Vector m_request_preprocessors = new Vector(); // request preprocessors private Vector m_exception_xlators = new Vector(); // exception translators /*-------------------------------------------------------------------------------- * Constructor *-------------------------------------------------------------------------------- */ /** * Creates the application container. * * @param config_file A reference to the Dynamo XML configuration file. * @param substrate A reference to the {@link com.silverwrist.dynamo.iface.ApplicationSubstrate ApplicationSubstrate} * object, which provides certain services and object references to the * ApplicationContainer. (Usually, this will be specific to the Dynamo application * type, for example, Web application.) * @exception com.silverwrist.dynamo.except.ConfigException If there is an error in the configuration which will * not allow Dynamo to be initialized. */ public ApplicationContainer(File config_file, ApplicationSubstrate substrate) throws ConfigException { if (logger.isDebugEnabled()) logger.debug("new ApplicationContainer - config file is " + config_file.getAbsolutePath()); substrate.initialize(); m_substrate = substrate; m_refs = 1; m_app_sm = new ApplicationServiceManager(); m_pss = new PropertySerializationSupport(); m_known_sessions = Collections.synchronizedSet(new HashSet()); XMLLoader loader = XMLLoader.get(); // Initialize the init services and runtime services with defaults. m_app_sm.addInitService(ResourceProvider.class,(ResourceProvider)this); m_app_sm.addInitService(ResourceProviderManager.class,(ResourceProviderManager)this); m_app_sm.addInitService(RendererRegistration.class,(RendererRegistration)this); m_app_sm.addInitService(ObjectProvider.class,(ObjectProvider)this); m_app_sm.addInitService(EventListenerRegistration.class,(EventListenerRegistration)this); m_app_sm.addInitService(OutputObjectFilterRegistration.class,(OutputObjectFilterRegistration)this); m_app_sm.addInitService(PropertySerializer.class,(PropertySerializer)m_pss); m_app_sm.addInitService(PropertySerializerRegistration.class,(PropertySerializerRegistration)m_pss); m_app_sm.addInitService(PostDynamicUpdate.class,(PostDynamicUpdate)this); m_app_sm.addInitService(RequestPreprocessorRegistration.class,(RequestPreprocessorRegistration)this); m_app_sm.addInitService(ExceptionTranslatorRegistration.class,(ExceptionTranslatorRegistration)this); m_app_sm.addRuntimeService(ResourceProvider.class,(ResourceProvider)this); m_app_sm.addRuntimeService(ObjectProvider.class,(ObjectProvider)this); m_app_sm.addRuntimeService(EventListenerRegistration.class,(EventListenerRegistration)this); m_app_sm.addRuntimeService(PropertySerializer.class,(PropertySerializer)m_pss); m_app_sm.addRuntimeService(PostDynamicUpdate.class,(PostDynamicUpdate)this); m_app_sm.addRuntimeService(RenderImmediate.class,(RenderImmediate)this); m_app_sm.addOutputService(ResourceProvider.class,(ResourceProvider)this); m_app_sm.addOutputService(ObjectProvider.class,(ObjectProvider)this); m_app_sm.addOutputService(QueryRenderer.class,(QueryRenderer)this); // Create initialization services interface object. ServiceProvider init_svcs = m_app_sm.createInitServices(); try { // load the configuration file Document config_doc = loader.load(config_file,false); Element root = loader.getRootElement(config_doc,"configuration"); // get the element and process it Element control = loader.getSubElement(root,"control"); processControlSection(control); m_shutdown_list.addFirst(m_background); m_app_sm.addInitService(BackgroundScheduler.class,m_background); m_app_sm.addRuntimeService(BackgroundScheduler.class,m_background); // initialize some default renderers m_shutdown_list.addFirst(registerRenderer(DataItem.class,new DataItemRenderer())); m_shutdown_list.addFirst(registerRenderer(java.util.List.class,new ListRenderer())); // initialize the scripting engine m_script_ctrl = new ScriptController(); m_script_ctrl.initialize(control,init_svcs); m_shutdown_list.addFirst(m_script_ctrl); // add the scripting engine's services so they can be used by external components m_app_sm.addInitService(ScriptEngineConfig.class,m_script_ctrl); m_app_sm.addRuntimeService(ScriptExecute.class,m_script_ctrl); // get all database connection configurations List l = loader.getMatchingSubElements(root,"dbconnection"); Iterator it = l.iterator(); Element elt; while (it.hasNext()) { // get each element in turn elt = (Element)(it.next()); DBConnectionPool pool = (DBConnectionPool)createNamedObject(elt,init_svcs,DBConnectionPool.class, "no.notDBPool"); m_connections.put(pool.getName(),pool); } // end while m_app_sm.addInitService(HookServiceProviders.class,m_app_sm); // Sort the "object" definitions by priority order to determine in what order to instantiate them. l = loader.getMatchingSubElements(root,"object"); if (!(l.isEmpty())) { // copy elements into binary heap it = l.iterator(); BinaryHeap prioheap = new BinaryHeap(l.size()); while (it.hasNext()) { // sort elements by priority elt = (Element)(it.next()); prioheap.insert(new HeapContents(elt)); } // end while while (prioheap.size()>0) { // now remove and instantiate the elements HeapContents hc = (HeapContents)(prioheap.remove()); NamedObject nobj = createNamedObject(hc.getElement(),init_svcs,null,null); m_objects.put(nobj.getName(),nobj); } // end while } // end if // Find the application definition and initialize the application. elt = loader.getSubElement(root,"application"); m_application = (Application)createNamedObject(elt,init_svcs,Application.class,"no.notApp"); } // end try catch (IOException e) { // unable to read config file - send back a ConfigException logger.fatal("ApplicationContainer config read failed",e); ConfigException ce = new ConfigException(ApplicationContainer.class,"ApplicationContainerMessages", "creation.ioError",e); ce.setParameter(0,config_file.getAbsolutePath()); throw ce; } // end catch catch (XMLLoadException e) { // XML loader failed - send back a ConfigException logger.fatal("ApplicationContainer config load failed",e); throw new ConfigException(e); } // end catch // Create the "server identity" string. StringBuffer buf = new StringBuffer(); String app_id = m_application.getIdentity(); if (app_id!=null) buf.append(app_id).append(' '); buf.append("Dynamo/").append(DynamoVersion.VERSION); m_identity = buf.toString(); logger.info("Server: " + m_identity); // Fire the "application initialized" events. ApplicationListener[] listeners = (ApplicationListener[])(m_application_listeners.toArray(APP_LISTENER_TEMPLATE)); if (listeners.length>0) { // call the event handlers... if (logger.isDebugEnabled()) logger.debug("ApplicationContainer: " + listeners.length + " init handler(s) to call"); ApplicationEventRequest req = new ApplicationEventRequest(m_app_sm.createRuntimeServices(),true); ApplicationEvent evt = new ApplicationEvent(req,m_application); for (int i=0; iComponentInitialize associated with the object, or null * if there is no such instance. */ private static final ComponentInitialize getComponentInitialize(Object obj) { if (obj instanceof ComponentInitialize) return (ComponentInitialize)obj; if (obj instanceof ServiceProvider) { // it may be a service provider interface try { // look for ComponentInitialize as a service ServiceProvider sp = (ServiceProvider)obj; ComponentInitialize rc = (ComponentInitialize)(sp.queryService(ComponentInitialize.class)); return rc; } // end try catch (NoSuchServiceException e) { // do nothing here } // end catch } // end if return null; // no dice! } // end getComponentInitialize /** * Finds an instance of the {@link com.silverwrist.dynamo.iface.ComponentShutdown ComponentShutdown} interface * associated with the given object, either through implementation of the interface, or by querying its * {@link com.silverwrist.dynamo.iface.ServiceProvider ServiceProvider} implementation. * * @param obj The object to be queried. * @return The instance of ComponentShutdown associated with the object, or null * if there is no such instance. */ private static final ComponentShutdown getComponentShutdown(Object obj) { if (obj instanceof ComponentShutdown) return (ComponentShutdown)obj; if (obj instanceof ServiceProvider) { // it may be a service provider interface try { // look for ComponentShutdown as a service ServiceProvider sp = (ServiceProvider)obj; ComponentShutdown rc = (ComponentShutdown)(sp.queryService(ComponentShutdown.class)); return rc; } // end try catch (NoSuchServiceException e) { // do nothing here } // end catch } // end if return null; // no dice! } // end getComponentShutdown /** * Destroys all data associated with this ApplicationContainer. */ private final synchronized void destroy() { if (logger.isDebugEnabled()) logger.debug("ApplicationContainer.destroy(): " + m_known_sessions.size() + " sessions to shutdown"); Iterator it = m_known_sessions.iterator(); while (it.hasNext()) { // shut down each session ComponentShutdown cs = (ComponentShutdown)(it.next()); cs.shutdown(); } // end while m_known_sessions.clear(); // Fire the "application exiting" events. ApplicationListener[] listeners = (ApplicationListener[])(m_application_listeners.toArray(APP_LISTENER_TEMPLATE)); if (logger.isDebugEnabled()) logger.debug("ApplicationContainer.destroy(): " + listeners.length + " exit handlers to call"); if (listeners.length>0) { // call the event handlers... ApplicationEventRequest req = new ApplicationEventRequest(m_app_sm.createRuntimeServices(),false); ApplicationEvent evt = new ApplicationEvent(req,m_application); for (int i=0; i0) { // shut down all components in reverse order of creation ComponentShutdown sd = (ComponentShutdown)(m_shutdown_list.removeFirst()); sd.shutdown(); } // end while if (logger.isDebugEnabled()) logger.debug("ApplicationContainer.destroy(): clearing internal data structures"); m_connections.clear(); m_objects.clear(); m_class_renderers.clear(); m_dclass_renderers.clear(); m_application = null; m_resource_providers.clear(); m_application_listeners.clear(); m_session_listeners.clear(); if (logger.isDebugEnabled()) logger.debug("ApplicationContainer.destroy(): terminating substrate"); m_substrate.terminate(); m_substrate = null; } // end destroy private final Map getSubstrateReplaceMap() { HashMap rc = new HashMap(); for (int i=0; imax_munch) { // found one that munches more...save it wrp = tmp; max_munch = test; } // end if } // end while } // end synchronized block return wrp; } // end locateResourceProvider private final InputStream getResourceInternal(ComponentResName crn) throws IOException { File res_file = new File(m_resource_base,crn.getStringValue(0,false)); if (!(res_file.exists()) || res_file.isDirectory() || !(res_file.canRead())) throw new NoSuchResourceException(crn.getStringValue(0,true)); return new FileInputStream(res_file); } // end getResourceInternal private final long getResourceModTimeInternal(ComponentResName crn) { File res_file = new File(m_resource_base,crn.getStringValue(0,false)); if (!(res_file.exists()) || res_file.isDirectory() || !(res_file.canRead())) return 0; return res_file.lastModified(); } // end getResourceModTimeInternal private final RegisteredRenderer searchDClassRenderers(DynamicClass dclass) { return (RegisteredRenderer)(m_dclass_renderers.get(dclass)); } // end searchDClassRenderer private final RegisteredRenderer searchArrayRenderers(Class klass, String template) { if (klass.isPrimitive() || (klass==Object.class)) return null; // should have been picked up already // look at this level for the class member RegisteredRenderer rc = null; try { // load the array class corresponding to the right depth, then check the renderer map Class tmp = Class.forName(StringUtils.replace(template,TEMPLATE_CLASSNAME,klass.getName())); rc = (RegisteredRenderer)(m_class_renderers.get(tmp)); if (rc!=null) return rc; } // end try catch (ClassNotFoundException e) { // this class was not found, so it can't be present rc = null; } // end catch // Try all interfaces implemented by the object. Class[] ifaces = klass.getInterfaces(); for (int i=0; iObjectProvider. * * @param namespace The namespace to interpret the name relative to. * @param name The name of the object to be retrieved. * @return The object reference specified. */ public Object getObject(String namespace, String name) { if (namespace.equals(Namespaces.SUBSTRATE_NAMESPACE)) return m_substrate.getObject(namespace,name); if (namespace.equals(Namespaces.DATABASE_CONNECTIONS_NAMESPACE)) { // get a database connection Object rc = m_connections.get(name); if (rc!=null) return rc; } // end if if (namespace.equals(Namespaces.DYNAMO_OBJECT_NAMESPACE)) { // get an object Object rc = m_objects.get(name); if (rc!=null) return rc; } // end if if (namespace.equals(Namespaces.DYNAMO_APPLICATION_NAMESPACE)) { // return one of the application data elements if (name.equals("application")) return m_application; else if (name.equals("identity")) return m_identity; else if (name.equals("__container__")) return this; } // end if throw new NoSuchObjectException("ApplicationContainer",namespace,name); } // end getObject /*-------------------------------------------------------------------------------- * Implementations from interface EventListenerRegistration *-------------------------------------------------------------------------------- */ public ComponentShutdown registerApplicationListener(ApplicationListener listener) { m_application_listeners.add(listener); return new ShutdownVectorRemove(m_application_listeners,listener); } // end registerApplicationListener public ComponentShutdown registerSessionInfoListener(SessionInfoListener listener) { m_session_listeners.add(listener); return new ShutdownVectorRemove(m_session_listeners,listener); } // end registerSessionInfoListener public synchronized ComponentShutdown registerDynamicUpdateListener(Class event_type, DynamicUpdateListener listener) { if (!(DynamicUpdateEvent.class.isAssignableFrom(event_type))) throw new IllegalArgumentException("event type is not valid"); Vector vec = (Vector)(m_update_listeners.get(event_type)); if (vec==null) { // creatr vector for this event type vec = new Vector(); m_update_listeners.put(event_type,vec); } // end if vec.add(listener); return new ShutdownVectorRemove(vec,listener); } // end registerDynamicUpdateListener /*-------------------------------------------------------------------------------- * Implementations from interface OutputObjectFilterRegistration *-------------------------------------------------------------------------------- */ public ComponentShutdown registerOutputObjectFilter(OutputObjectFilter filter) { if (logger.isDebugEnabled()) logger.debug("Registering new OutputObjectFilter: " + filter); m_output_filters.add(filter); return new ShutdownVectorRemove(m_output_filters,filter); } // end registerOutputObjectFilter /*-------------------------------------------------------------------------------- * Implementations from interface QueryRenderer *-------------------------------------------------------------------------------- */ public Renderer getRendererForObject(Object obj) { RegisteredRenderer rc = null; if (obj instanceof DynamicObject) { // this is a dynamic object - search by its dynamic class first DynamicClass dclass = ((DynamicObject)obj).getDClass(); rc = (RegisteredRenderer)(m_dclass_renderers.get(dclass)); if (rc==null) { // search for ancestor class, "snap" reference if possible rc = searchDClassRenderers(dclass); if (rc!=null) { // add this class to the mapping m_dclass_renderers.put(dclass,rc); rc.add(dclass); } // end if } // end if if (rc!=null) return rc.getRenderer(); } // end if Class klass = obj.getClass(); rc = (RegisteredRenderer)(m_class_renderers.get(klass)); if (rc==null) { // search for ancestor class, "snap" reference if possible rc = searchClassRenderers(klass); if (rc!=null) { // found it - add this class to the mapping m_class_renderers.put(klass,rc); rc.add(klass); } // end if } // end if return ((rc==null) ? null : rc.getRenderer()); } // end getRendererForObject /*-------------------------------------------------------------------------------- * Implementations from interface PostDynamicUpdate *-------------------------------------------------------------------------------- */ public void postUpdate(DynamicUpdateEvent event) { if (logger.isDebugEnabled()) logger.debug("PostDynamicUpdate: posting an event of type " + event.getClass().getName()); Class klass = event.getClass(); for (;;) { // get the event listeners Vector vec = (Vector)(m_update_listeners.get(klass)); if (vec!=null) { // call the event handlers Iterator it = vec.iterator(); while (it.hasNext()) ((DynamicUpdateListener)(it.next())).updateReceived(event); } // end if if (klass==DynamicUpdateEvent.class) break; klass = klass.getSuperclass(); } // end for (ever) } // end postUpdate /*-------------------------------------------------------------------------------- * Implementations from interface RenderImmediate *-------------------------------------------------------------------------------- */ public String renderTextObject(Object obj) throws IOException, RenderingException { if (logger.isDebugEnabled()) logger.debug("RenderImmediate rendering an object of type " + obj.getClass().getName()); BufferTextRenderControl control = new BufferTextRenderControl(wrapOutputServices(null)); control.renderSubObject(obj); return control.getData(); } // end renderTextObject /*-------------------------------------------------------------------------------- * Implementations from interface RequestPreprocessorRegistration *-------------------------------------------------------------------------------- */ public ComponentShutdown registerRequestPreprocessor(RequestPreprocessor rp) { if (logger.isDebugEnabled()) logger.debug("Registering new RequestPreprocessor: " + rp); m_request_preprocessors.add(rp); return new ShutdownVectorRemove(m_request_preprocessors,rp); } // end registerRequestPreprocessor /*-------------------------------------------------------------------------------- * Implementations from interface ExceptionTranslatorRegistration *-------------------------------------------------------------------------------- */ public ComponentShutdown registerExceptionTranslator(ExceptionTranslator xlat) { if (logger.isDebugEnabled()) logger.debug("Registering new ExceptionTranslator: " + xlat); m_exception_xlators.add(xlat); return new ShutdownVectorRemove(m_exception_xlators,xlat); } // end registerExceptionTranslator /*-------------------------------------------------------------------------------- * External operations *-------------------------------------------------------------------------------- */ /** * Adds a reference to the reference count of the ApplicationContainer. Each servlet * or other initializing component that attempts to initialize the ApplicationContainer * increases its reference count by 1. */ public synchronized void addRef() { ++m_refs; if (logger.isDebugEnabled()) logger.debug("ApplicationContainer.addRef(): refcount now " + m_refs); } // end addRef /** * Removes a reference from the reference count of the ApplicationContainer. Each servlet that * references the ApplicationContainer and is destroyed decreases the reference count by 1. * When the reference count reaches 0, the ApplicationContainer is destroyed. * * @return true if the ApplicationContainer was destroyed, false if not. */ public synchronized boolean release() { if (--m_refs==0) { // clean up this stuff if (logger.isDebugEnabled()) logger.debug("ApplicationContainer.release(): refcount now 0 - destroying!"); destroy(); return true; } // end if if (logger.isDebugEnabled()) logger.debug("ApplicationContainer.release(): refcount now " + m_refs); return false; } // end release /** * Returns the instance of the {@link com.silverwrist.dynamo.iface.Application Application} object defined in * the Dynamo XML configuration file and instantiated when the ApplicationContainer was created. * * @return The Application object. */ public Application getApplication() { return m_application; } // end getApplication public ServiceProvider getInitServices() { return m_app_sm.createInitServices(); } // end getInitServices public ServiceProvider wrapServices(ServiceProvider sp) { return m_app_sm.createRuntimeServices(sp); } // end wrapServices public ServiceProvider wrapOutputServices(ServiceProvider sp) { return m_app_sm.createOutputServices(sp); } // end wrapOutputServices /** * Returns a list of all registered {@link com.silverwrist.dynamo.event.SessionInfoListener SessionInfoListener} * objects. * * @return A list of all registered SessionInfoListener objects. */ public SessionInfoListener[] getSessionListeners() { return (SessionInfoListener[])(m_session_listeners.toArray(SESSION_LISTENER_TEMPLATE)); } // end getSessionListeners /** * Adds a session to our list of known sessions, which will be shut down when the application container * is itself destroyed. * * @param link The link to the session. */ public void addSessionLink(ComponentShutdown link) { m_known_sessions.add(link); } // end addSessionLink /** * Removes a session from our list of known sessions, so it will no longer be automatically shut down * when the application container is itself destroyed. * * @param link The link to the session. */ public void removeSessionLink(ComponentShutdown link) { m_known_sessions.remove(link); } // end removeSessionLink public void setServerHeader(HttpServletResponse resp) { resp.setHeader("Server",m_identity); } // end setServerHeader public Map getRewriteRuleMap() { return m_rewrite_rules; } // end getRewriteRuleMap public Object filterOutput(Object out, Request r) throws RenderingException { Object rc = out; for (int i=(m_output_filters.size()-1); i>=0; i--) { // look for new objects that filter this one OutputObjectFilter filt = (OutputObjectFilter)(m_output_filters.get(i)); Object tmp_rc = filt.filterObject(rc,r); if (tmp_rc!=null) rc = tmp_rc; } // end for return rc; } // end filterOutput public void preprocessRequest(Request r) { for (int i=(m_request_preprocessors.size()-1); i>=0; i--) { // preprocess the request, if we have any preprocessors installed RequestPreprocessor rp = (RequestPreprocessor)(m_request_preprocessors.get(i)); rp.preprocessRequest(r); } // end for } // end preprocessRequest public Object translateException(Request r, Exception e) { for (int i=(m_exception_xlators.size()-1); i>=0; i--) { // try to translate exceptions ExceptionTranslator xlat = (ExceptionTranslator)(m_exception_xlators.get(i)); Object o = xlat.translateException(r,e); if (o!=null) return o; // found a translation } // end for return e; // return the exception itself as a last resort } // end translateException public String translateSubstratePathName(String input) { return StringUtils.replaceAllVariables(input,getSubstrateReplaceMap()); } // end translateSubstratePathName } // end class ApplicationContainer