1293 lines
46 KiB
Java
1293 lines
46 KiB
Java
/*
|
|
* 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 <http://www.mozilla.org/MPL/>.
|
|
*
|
|
* 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 <erbo@silcom.com>,
|
|
* 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
|
|
* <CODE>ApplicationContainer</CODE>. (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 <control/> 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; i<listeners.length; i++)
|
|
listeners[i].applicationInitialized(evt);
|
|
|
|
} // end if
|
|
|
|
if (logger.isDebugEnabled())
|
|
logger.debug("ApplicationContainer initialization done");
|
|
|
|
} // end constructor
|
|
|
|
/*--------------------------------------------------------------------------------
|
|
* Internal operations
|
|
*--------------------------------------------------------------------------------
|
|
*/
|
|
|
|
private static final Class getUltimateComponent(Class klass)
|
|
{
|
|
while (klass.isArray())
|
|
klass = klass.getComponentType();
|
|
return klass;
|
|
|
|
} // end getUltimateComponent
|
|
|
|
/**
|
|
* Finds an instance of the {@link com.silverwrist.dynamo.iface.ComponentInitialize ComponentInitialize} 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 <CODE>ComponentInitialize</CODE> associated with the object, or <CODE>null</CODE>
|
|
* 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 <CODE>ComponentShutdown</CODE> associated with the object, or <CODE>null</CODE>
|
|
* 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 <CODE>ApplicationContainer</CODE>.
|
|
*/
|
|
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; i<listeners.length; i++)
|
|
listeners[i].applicationExiting(evt);
|
|
|
|
} // end if
|
|
|
|
if (logger.isDebugEnabled())
|
|
logger.debug("ApplicationContainer.destroy(): " + m_shutdown_list.size() + " objects to blow away");
|
|
|
|
while (m_shutdown_list.size()>0)
|
|
{ // 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; i<SUBSTRATE_MAP_KEYS.length; i++)
|
|
{ // load the map with return values
|
|
try
|
|
{ // get each object in turn from the substrate and add it to the map
|
|
Object tmp = m_substrate.getObject(ApplicationSubstrate.NAMESPACE,SUBSTRATE_MAP_KEYS[i]);
|
|
rc.put(SUBSTRATE_MAP_KEYS[i],tmp.toString());
|
|
|
|
} // end try
|
|
catch (NoSuchObjectException e)
|
|
{ // skip this object and try the next one
|
|
} // end catch
|
|
|
|
} // end for
|
|
|
|
return rc;
|
|
|
|
} // end getSubstrateReplaceMap
|
|
|
|
private final void processControlSection(Element control) throws ConfigException, XMLLoadException
|
|
{
|
|
Map replace_map = getSubstrateReplaceMap();
|
|
XMLLoader loader = XMLLoader.get();
|
|
DOMElementHelper control_h = new DOMElementHelper(control);
|
|
|
|
// Get the thread counts and create the background processor.
|
|
int num_norm = 2;
|
|
int num_low = 2;
|
|
Element elt = control_h.getSubElement("background-threads");
|
|
if (elt!=null)
|
|
{ // read in the values
|
|
num_norm = loader.getAttributeInt(elt,"normal",2);
|
|
num_low = loader.getAttributeInt(elt,"low",2);
|
|
|
|
} // end if
|
|
|
|
// Create the background services and the background processor.
|
|
SimpleServiceProvider bg_svcs = new SimpleServiceProvider("Background Services");
|
|
bg_svcs.addService(ResourceProvider.class,this);
|
|
bg_svcs.addService(ObjectProvider.class,this);
|
|
m_background = new BackgroundProcessor(num_norm,num_low,bg_svcs);
|
|
|
|
// Get the resource root directory.
|
|
String res_root = loader.getSubElementText(control_h,"resource-root");
|
|
m_resource_base = new File(StringUtils.replaceAllVariables(res_root,replace_map));
|
|
if (!(m_resource_base.isDirectory()))
|
|
{ // the resource base MUST be a directory!
|
|
ConfigException ce = new ConfigException(ApplicationContainer.class,"ApplicationContainerMessages",
|
|
"resource.rootErr");
|
|
ce.setParameter(0,m_resource_base.getAbsolutePath());
|
|
throw ce;
|
|
|
|
} // end if
|
|
|
|
// Get the list of rewrite rules.
|
|
Element rewrite_sect = loader.getSubElement(control_h,"url-rewrite-rules");
|
|
List rewrite_list = loader.getMatchingSubElements(rewrite_sect,"rule");
|
|
HashMap tmp_map = new HashMap();
|
|
Iterator it = rewrite_list.iterator();
|
|
while (it.hasNext())
|
|
{ // get each rule and create corresponding object
|
|
elt = (Element)(it.next());
|
|
RewriteRule rule = new RewriteRule(elt);
|
|
tmp_map.put(rule.getName(),rule);
|
|
|
|
} // end while
|
|
|
|
m_rewrite_rules = Collections.unmodifiableMap(tmp_map);
|
|
|
|
} // end processControlSection
|
|
|
|
private final NamedObject createNamedObject(Element config_root, ServiceProvider services,
|
|
Class extratest, String extratest_msg)
|
|
throws ConfigException
|
|
{
|
|
XMLLoader loader = XMLLoader.get();
|
|
String klassname = null;
|
|
try
|
|
{ // get the classname and load it, and create an object
|
|
klassname = loader.getAttribute(config_root,"classname");
|
|
if (logger.isDebugEnabled())
|
|
{ // output a proper debug message
|
|
Class desired = (extratest==null) ? NamedObject.class : extratest;
|
|
logger.debug("createNamedObject: Creating new NamedObject of class " + klassname
|
|
+ ", which should implement " + desired.getName());
|
|
|
|
} // end if
|
|
|
|
Class klass = Class.forName(klassname);
|
|
if (!(NamedObject.class.isAssignableFrom(klass)))
|
|
{ // this object is not a valid NamedObject
|
|
logger.error("object " + klassname + " does not implement NamedObject");
|
|
ConfigException ce = new ConfigException(ApplicationContainer.class,"ApplicationContainerMessages",
|
|
"no.notDynamo");
|
|
ce.setParameter(0,klassname);
|
|
throw ce;
|
|
|
|
} // end if
|
|
|
|
if ((extratest!=null) && !(extratest.isAssignableFrom(klass)))
|
|
{ // this object is not a valid (whatever)
|
|
logger.error("object " + klassname + " does not implement " + extratest.getName());
|
|
ConfigException ce = new ConfigException(ApplicationContainer.class,"ApplicationContainerMessages",
|
|
extratest_msg);
|
|
ce.setParameter(0,klassname);
|
|
throw ce;
|
|
|
|
} // end if
|
|
|
|
// instantiate the object, and initialize it as needed
|
|
Object rc = klass.newInstance();
|
|
ComponentInitialize init = getComponentInitialize(rc);
|
|
if (init!=null)
|
|
init.initialize(config_root,services);
|
|
|
|
synchronized (this)
|
|
{ // save its shutdown hook for later
|
|
ComponentShutdown sd = getComponentShutdown(rc);
|
|
if (sd!=null)
|
|
m_shutdown_list.addFirst(sd);
|
|
|
|
} // end synchronized block
|
|
|
|
if (logger.isDebugEnabled())
|
|
logger.debug("Object \"" + ((NamedObject)rc).getName() + "\" (of class " + klassname + ") created");
|
|
|
|
return (NamedObject)rc;
|
|
|
|
} // end try
|
|
catch (XMLLoadException e)
|
|
{ // error getting class name - throw the ConfigException
|
|
logger.error("XML loader failure",e);
|
|
throw new ConfigException(e);
|
|
|
|
} // end catch
|
|
catch (ClassNotFoundException e)
|
|
{ // the class was not found
|
|
ConfigException ce = new ConfigException(ApplicationContainer.class,"ApplicationContainerMessages",
|
|
"no.classNotFound");
|
|
ce.setParameter(0,klassname);
|
|
throw ce;
|
|
|
|
} // end catch
|
|
catch (IllegalAccessException e)
|
|
{ // unable to create this object
|
|
ConfigException ce = new ConfigException(ApplicationContainer.class,"ApplicationContainerMessages",
|
|
"no.createError");
|
|
ce.setParameter(0,klassname);
|
|
throw ce;
|
|
|
|
} // end catch
|
|
catch (InstantiationException e)
|
|
{ // unable to create this object
|
|
ConfigException ce = new ConfigException(ApplicationContainer.class,"ApplicationContainerMessages",
|
|
"no.createError");
|
|
ce.setParameter(0,klassname);
|
|
throw ce;
|
|
|
|
} // end catch
|
|
|
|
} // end createNamedObject
|
|
|
|
private final WrappedResourceProvider locateResourceProvider(ComponentResName crn)
|
|
{
|
|
WrappedResourceProvider wrp = null;
|
|
synchronized (m_resource_providers)
|
|
{ // perform the "maximum munch" algorithm to try and find a provider
|
|
int max_munch = 0;
|
|
Iterator it = m_resource_providers.iterator();
|
|
while (it.hasNext())
|
|
{ // look at each mounted provider and try to find a better possibility
|
|
WrappedResourceProvider tmp = (WrappedResourceProvider)(it.next());
|
|
int test = tmp.getMatchCount(crn);
|
|
if (test>max_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; i<ifaces.length; i++)
|
|
{ // look for interfaces implemented by the object
|
|
rc = searchArrayRenderers(ifaces[i],template);
|
|
if (rc!=null)
|
|
return rc;
|
|
|
|
} // end for
|
|
|
|
Class superclass = klass.getSuperclass();
|
|
if (superclass!=null)
|
|
{ // try the superclass now
|
|
rc = searchArrayRenderers(superclass,template);
|
|
if (rc!=null)
|
|
return rc;
|
|
|
|
} // end if
|
|
|
|
return null; // give up
|
|
|
|
} // end searchArrayRenderers
|
|
|
|
private final RegisteredRenderer searchClassRenderers(Class klass)
|
|
{
|
|
if (klass.isPrimitive() || (klass==Object.class))
|
|
return null; // should have been picked up already
|
|
|
|
// look at this level for the class member
|
|
RegisteredRenderer rc = (RegisteredRenderer)(m_class_renderers.get(klass));
|
|
if (rc!=null)
|
|
return rc;
|
|
|
|
if (klass.isArray())
|
|
{ // for arrays, use the parallel function to search back over the component
|
|
// class's hierarchy
|
|
Class component = getUltimateComponent(klass);
|
|
if (component.isPrimitive() || (component==Object.class))
|
|
return null; // no chance this should have been picked up
|
|
String template = StringUtils.replace(klass.getName(),component.getName(),TEMPLATE_CLASSNAME);
|
|
return searchArrayRenderers(component,template);
|
|
|
|
} // end if
|
|
|
|
// Try all interfaces implemented by the object.
|
|
Class[] ifaces = klass.getInterfaces();
|
|
for (int i=0; i<ifaces.length; i++)
|
|
{ // look for interfaces implemented by the object
|
|
rc = searchClassRenderers(ifaces[i]);
|
|
if (rc!=null)
|
|
return rc;
|
|
|
|
} // end for
|
|
|
|
Class superclass = klass.getSuperclass();
|
|
if (superclass!=null)
|
|
{ // try the superclass now
|
|
rc = searchClassRenderers(superclass);
|
|
if (rc!=null)
|
|
return rc;
|
|
|
|
} // end if
|
|
|
|
return null; // give up
|
|
|
|
} // end searchClassRenderers
|
|
|
|
/*--------------------------------------------------------------------------------
|
|
* Implementations from interface ResourceProvider
|
|
*--------------------------------------------------------------------------------
|
|
*/
|
|
|
|
public InputStream getResource(String resource_path) throws IOException
|
|
{
|
|
ComponentResName crn = new ComponentResName(resource_path);
|
|
WrappedResourceProvider wrp = locateResourceProvider(crn);
|
|
if (wrp==null)
|
|
return getResourceInternal(crn);
|
|
else
|
|
return wrp.getResource(crn);
|
|
|
|
} // end getResource
|
|
|
|
public long getResourceModTime(String resource_path)
|
|
{
|
|
try
|
|
{ // build the resource name and return it
|
|
ComponentResName crn = new ComponentResName(resource_path);
|
|
WrappedResourceProvider wrp = locateResourceProvider(crn);
|
|
if (wrp==null)
|
|
return getResourceModTimeInternal(crn);
|
|
else
|
|
return wrp.getResourceModTime(crn);
|
|
|
|
} // end try
|
|
catch (NoSuchResourceException e)
|
|
{ // just deal with exceptions in here
|
|
return 0;
|
|
|
|
} // end catch
|
|
|
|
} // end getResourceModTime
|
|
|
|
/*--------------------------------------------------------------------------------
|
|
* Implementations from interface ResourceProviderManager
|
|
*--------------------------------------------------------------------------------
|
|
*/
|
|
|
|
public ComponentShutdown mountResourceProvider(String mount_path, ResourceProvider provider)
|
|
throws ConfigException
|
|
{
|
|
ComponentResName crn = null;
|
|
try
|
|
{ // create component name for mount path
|
|
crn = new ComponentResName(mount_path);
|
|
|
|
} // end try
|
|
catch (NoSuchResourceException e)
|
|
{ // this is not a valid name - throw ConfigException
|
|
ConfigException ce = new ConfigException(ApplicationContainer.class,"ApplicationContainerMessages",
|
|
"mountRP.badName");
|
|
ce.setParameter(0,mount_path);
|
|
throw ce;
|
|
|
|
} // end catch
|
|
|
|
WrappedResourceProvider wrp = new WrappedResourceProvider(crn,provider);
|
|
if (m_resource_providers.contains(wrp))
|
|
{ // resource provider already mounted on this path - bogus!
|
|
ConfigException ce = new ConfigException(ApplicationContainer.class,"ApplicationContainerMessages",
|
|
"mountRP.already");
|
|
ce.setParameter(0,mount_path);
|
|
throw ce;
|
|
|
|
} // end if
|
|
|
|
m_resource_providers.add(wrp);
|
|
return new ShutdownVectorRemove(m_resource_providers,wrp);
|
|
|
|
} // end mountResourceProvider
|
|
|
|
/*--------------------------------------------------------------------------------
|
|
* Implementations from interface RendererRegistration
|
|
*--------------------------------------------------------------------------------
|
|
*/
|
|
|
|
public ComponentShutdown registerRenderer(Class klass, Renderer renderer) throws ConfigException
|
|
{
|
|
if (m_class_renderers.containsKey(klass))
|
|
{ // renderer already registered - bogus!
|
|
ConfigException ce = new ConfigException(ApplicationContainer.class,"ApplicationContainerMessages",
|
|
"registerRenderer.already");
|
|
ce.setParameter(0,klass.getName());
|
|
throw ce;
|
|
|
|
} // end if
|
|
|
|
if (logger.isDebugEnabled())
|
|
logger.debug("Registering a new renderer for class " + klass.getName());
|
|
RegisteredRenderer rr = new RegisteredRenderer(klass,renderer);
|
|
m_class_renderers.put(klass,rr);
|
|
return rr;
|
|
|
|
} // end registerRenderer
|
|
|
|
public ComponentShutdown registerRenderer(DynamicClass dclass, Renderer renderer) throws ConfigException
|
|
{
|
|
if (m_dclass_renderers.containsKey(dclass))
|
|
{ // renderer already registered - bogus!
|
|
ConfigException ce = new ConfigException(ApplicationContainer.class,"ApplicationContainerMessages",
|
|
"registerRenderer.already");
|
|
ce.setParameter(0,dclass.getName());
|
|
throw ce;
|
|
|
|
} // end if
|
|
|
|
if (logger.isDebugEnabled())
|
|
logger.debug("Registering a new renderer for dynamic class " + dclass.getName());
|
|
RegisteredRenderer rr = new RegisteredRenderer(dclass,renderer);
|
|
m_class_renderers.put(dclass,rr);
|
|
return rr;
|
|
|
|
} // end if
|
|
|
|
/*--------------------------------------------------------------------------------
|
|
* Implementations from interface ObjectProvider
|
|
*--------------------------------------------------------------------------------
|
|
*/
|
|
|
|
/**
|
|
* Retrieves an object from this <CODE>ObjectProvider</CODE>.
|
|
*
|
|
* @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 <CODE>ApplicationContainer</CODE>. Each servlet
|
|
* or other initializing component that attempts to initialize the <CODE>ApplicationContainer</CODE>
|
|
* 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 <CODE>ApplicationContainer</CODE>. Each servlet that
|
|
* references the <CODE>ApplicationContainer</CODE> and is destroyed decreases the reference count by 1.
|
|
* When the reference count reaches 0, the <CODE>ApplicationContainer</CODE> is destroyed.
|
|
*
|
|
* @return <CODE>true</CODE> if the <CODE>ApplicationContainer</CODE> was destroyed, <CODE>false</CODE> 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 <CODE>ApplicationContainer</CODE> was created.
|
|
*
|
|
* @return The <CODE>Application</CODE> 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 <CODE>SessionInfoListener</CODE> 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
|