leif 2002/11/07 01:50:41
Modified: component/src/java/org/apache/avalon/excalibur/component
ExcaliburComponentManagerCreator.java
component/src/java/org/apache/avalon/excalibur/component/servlet
AbstractComponentManagerServlet.java
AbstractReferenceProxyLatch.java
ComponentManagerReferenceProxy.java
ExcaliburComponentManagerServlet.java
Added: component/src/java/org/apache/avalon/excalibur/component/servlet
AbstractServiceManagerServlet.java
ServiceManagerReferenceProxy.java
Log:
Add access methods for the ServiceManager so that users can easily start
moving their code away from using the ComponentManager.
Revision Changes Path
1.7 +27 -3
jakarta-avalon-excalibur/component/src/java/org/apache/avalon/excalibur/component/ExcaliburComponentManagerCreator.java
Index: ExcaliburComponentManagerCreator.java
===================================================================
RCS file:
/home/cvs/jakarta-avalon-excalibur/component/src/java/org/apache/avalon/excalibur/component/ExcaliburComponentManagerCreator.java,v
retrieving revision 1.6
retrieving revision 1.7
diff -u -r1.6 -r1.7
--- ExcaliburComponentManagerCreator.java 7 Nov 2002 06:37:53 -0000 1.6
+++ ExcaliburComponentManagerCreator.java 7 Nov 2002 09:50:41 -0000 1.7
@@ -22,6 +22,8 @@
import org.apache.avalon.framework.logger.ConsoleLogger;
import org.apache.avalon.framework.logger.LogKitLogger;
import org.apache.avalon.framework.logger.Logger;
+import org.apache.avalon.framework.service.ServiceManager;
+import org.apache.excalibur.container.legacy.ComponentManager2ServiceManager;
import org.apache.excalibur.instrument.InstrumentManager;
import org.apache.excalibur.instrument.manager.DefaultInstrumentManager;
import org.apache.log.Hierarchy;
@@ -50,8 +52,10 @@
* m_componentManagerCreator = null;
* </pre>
*
- * The ComponentManager or any of the other managers can be accessed using their
- * getter methods. getComponentManager() for example.
+ * The ServiceManager (ComponentManager) or any of the other managers can be
accessed
+ * using their getter methods. getServiceManager() for example. Note that
+ * while the ComponentManager is still available, it has been deprecated in favor
+ * of the ServiceManager interface.
*
* @author <a href="mailto:leif@;apache.org">Leif Mortenson</a>
* @version CVS $Revision$ $Date$
@@ -80,6 +84,9 @@
/** Internal component manager. */
private ComponentManager m_componentManager;
+ /** Internal service manager. */
+ private ServiceManager m_serviceManager;
+
/** Internal instrument manager. */
private InstrumentManager m_instrumentManager;
/*---------------------------------------------------------------
@@ -347,6 +354,9 @@
* Returns the configured ComponentManager.
*
* @return The configured ComponentManager.
+ *
+ * @deprecated The ComponentManager interface has been deprecated.
+ * Please use the getServiceManager method.
*/
public ComponentManager getComponentManager()
{
@@ -354,6 +364,16 @@
}
/**
+ * Returns the configured ServiceManager.
+ *
+ * @return The configured ServiceManager.
+ */
+ public ServiceManager getServiceManager()
+ {
+ return m_serviceManager;
+ }
+
+ /**
* Returns the logger for internal use.
*/
private Logger getLogger()
@@ -468,6 +488,10 @@
componentManager.configure( componentManagerConfig );
componentManager.initialize();
m_componentManager = componentManager;
+
+ // Now wrap the ComponentManager so that we can provide access to it as
+ // a ServiceManager.
+ m_serviceManager = new ComponentManager2ServiceManager( m_componentManager
);
}
}
1.6 +5 -2
jakarta-avalon-excalibur/component/src/java/org/apache/avalon/excalibur/component/servlet/AbstractComponentManagerServlet.java
Index: AbstractComponentManagerServlet.java
===================================================================
RCS file:
/home/cvs/jakarta-avalon-excalibur/component/src/java/org/apache/avalon/excalibur/component/servlet/AbstractComponentManagerServlet.java,v
retrieving revision 1.5
retrieving revision 1.6
diff -u -r1.5 -r1.6
--- AbstractComponentManagerServlet.java 7 Nov 2002 06:37:53 -0000 1.5
+++ AbstractComponentManagerServlet.java 7 Nov 2002 09:50:41 -0000 1.6
@@ -29,6 +29,10 @@
* to enable servlets to have access to a ComponentManager as well as logging
* and instrumentation features.
*
+ * @deprecated Use of this class has been deprecated along with the
+ * ComponentManager interface. Please use the
+ * AbstractServiceManagerServlet.
+ *
* @author <a href="mailto:leif@;apache.org">Leif Mortenson</a>
* @version CVS $Revision$ $Date$
* @since 4.2
@@ -159,7 +163,6 @@
getLogger().debug( "servlet.destroy()" );
}
- //System.out.println( "AbstractComponentManagerServlet.destroy()" );
// Release the ComponentManager by removing its reference.
m_componentManager = null;
1.5 +6 -1
jakarta-avalon-excalibur/component/src/java/org/apache/avalon/excalibur/component/servlet/AbstractReferenceProxyLatch.java
Index: AbstractReferenceProxyLatch.java
===================================================================
RCS file:
/home/cvs/jakarta-avalon-excalibur/component/src/java/org/apache/avalon/excalibur/component/servlet/AbstractReferenceProxyLatch.java,v
retrieving revision 1.4
retrieving revision 1.5
diff -u -r1.4 -r1.5
--- AbstractReferenceProxyLatch.java 7 Nov 2002 06:37:53 -0000 1.4
+++ AbstractReferenceProxyLatch.java 7 Nov 2002 09:50:41 -0000 1.5
@@ -10,6 +10,7 @@
import org.apache.avalon.excalibur.logger.LoggerManager;
import org.apache.avalon.framework.component.ComponentManager;
import org.apache.avalon.framework.logger.AbstractLogEnabled;
+import org.apache.avalon.framework.service.ServiceManager;
import org.apache.excalibur.instrument.InstrumentManager;
/**
@@ -73,6 +74,10 @@
if( object instanceof LoggerManager )
{
proxy = new LoggerManagerReferenceProxy( (LoggerManager)object, this,
name );
+ }
+ else if( object instanceof ServiceManager )
+ {
+ proxy = new ServiceManagerReferenceProxy( (ServiceManager)object, this,
name );
}
else if( object instanceof ComponentManager )
{
1.3 +4 -1
jakarta-avalon-excalibur/component/src/java/org/apache/avalon/excalibur/component/servlet/ComponentManagerReferenceProxy.java
Index: ComponentManagerReferenceProxy.java
===================================================================
RCS file:
/home/cvs/jakarta-avalon-excalibur/component/src/java/org/apache/avalon/excalibur/component/servlet/ComponentManagerReferenceProxy.java,v
retrieving revision 1.2
retrieving revision 1.3
diff -u -r1.2 -r1.3
--- ComponentManagerReferenceProxy.java 21 Aug 2002 12:45:11 -0000 1.2
+++ ComponentManagerReferenceProxy.java 7 Nov 2002 09:50:41 -0000 1.3
@@ -14,6 +14,9 @@
/**
* Reference Proxy to a ComponentManager
*
+ * @deprecated The ComponentManager interface has been deprecated in favor
+ * of the ServiceManager.
+ *
* @author <a href="mailto:leif@;apache.org">Leif Mortenson</a>
* @version CVS $Revision$ $Date$
* @since 4.2
1.6 +17 -8
jakarta-avalon-excalibur/component/src/java/org/apache/avalon/excalibur/component/servlet/ExcaliburComponentManagerServlet.java
Index: ExcaliburComponentManagerServlet.java
===================================================================
RCS file:
/home/cvs/jakarta-avalon-excalibur/component/src/java/org/apache/avalon/excalibur/component/servlet/ExcaliburComponentManagerServlet.java,v
retrieving revision 1.5
retrieving revision 1.6
diff -u -r1.5 -r1.6
--- ExcaliburComponentManagerServlet.java 7 Nov 2002 06:37:53 -0000 1.5
+++ ExcaliburComponentManagerServlet.java 7 Nov 2002 09:50:41 -0000 1.6
@@ -20,12 +20,13 @@
import org.apache.avalon.excalibur.logger.LoggerManager;
import org.apache.avalon.framework.component.ComponentManager;
import org.apache.avalon.framework.container.ContainerUtil;
+import org.apache.avalon.framework.service.ServiceManager;
import org.apache.excalibur.instrument.InstrumentManager;
/**
* Makes it possible for servlets to work with Avalon components
* without having to do any coding to setup and manage the
- * lifecycle of the ComponentManager.
+ * lifecycle of the ServiceManager (ComponentManager).
* <p>
* To make use of the ExcaliburComponentManagerServet. You will
* need to define the servlet in your web.xml file as follows:
@@ -73,7 +74,7 @@
* Please pay particular attention to the load-on-startup element. It is used
* to control the order in which servlets are started by the servlet engine.
* It must have a value which is less than any other servlets making use of
- * the ComponentManager. This is to ensure that the ComponentManager is
+ * the ServiceManager. This is to ensure that the ServiceManager is
* initialized before any other servlets attempt to start using it.
* <p>
* All of the configuration files are located in the WEB-INF directory by
@@ -84,8 +85,8 @@
* by this servlet, so there is no need to access the class directly.
* <p>
* Once the servlet has been configured, other servlets may gain access to
- * the ComponentManager, InstrumentManager and LoggerManager via the
- * ServletContext using the following code within a servlet:
+ * the ServiceManager (ComponentManager), InstrumentManager and LoggerManager
+ * via the ServletContext using the following code within a servlet:
* <pre>
* // Get a reference to the ServletContext
* ServletContext servletContext = getServletContext();
@@ -98,7 +99,11 @@
* InstrumentManager instrumentManager =
* (InstrumentManager)m_servletContext.getAttribute(
InstrumentManager.class.getName() );
*
- * // Acquire the ComponentManager
+ * // Acquire the ServiceManager
+ * ServiceManager serviceManager =
+ * (ServiceManager)m_servletContext.getAttribute(
ServiceManager.class.getName() );
+ *
+ * // Acquire the ComponentManager ( Deprecated )
* ComponentManager componentManager =
* (ComponentManager)m_servletContext.getAttribute(
ComponentManager.class.getName() );
* </pre>
@@ -232,6 +237,8 @@
// Create the actual ReferenceProxies.
ReferenceProxy loggerManagerProxy = m_latch.createProxy(
loggerManager, "LoggerManager" );
+ ReferenceProxy serviceManagerProxy = m_latch.createProxy(
+ m_componentManagerCreator.getServiceManager(), "ServiceManager" );
ReferenceProxy componentManagerProxy = m_latch.createProxy(
m_componentManagerCreator.getComponentManager(), "ComponentManager" );
ReferenceProxy instrumentManagerProxy = m_latch.createProxy(
@@ -239,8 +246,9 @@
// Store references to the proxies in the ServletContext so that other
servlets can gain
// access to them
- servletContext.setAttribute( LoggerManager.class.getName(),
loggerManagerProxy );
- servletContext.setAttribute( ComponentManager.class.getName(),
componentManagerProxy );
+ servletContext.setAttribute( LoggerManager.class.getName(),
loggerManagerProxy );
+ servletContext.setAttribute( ServiceManager.class.getName(),
serviceManagerProxy );
+ servletContext.setAttribute( ComponentManager.class.getName(),
componentManagerProxy );
servletContext.setAttribute( InstrumentManager.class.getName(),
instrumentManagerProxy );
//System.out.println( "ExcaliburComponentManagerServlet.init() END" );
@@ -257,6 +265,7 @@
// Remove the references to the managers from the servlet context.
servletContext.removeAttribute( LoggerManager.class.getName() );
+ servletContext.removeAttribute( ServiceManager.class.getName() );
servletContext.removeAttribute( ComponentManager.class.getName() );
servletContext.removeAttribute( InstrumentManager.class.getName() );
1.1
jakarta-avalon-excalibur/component/src/java/org/apache/avalon/excalibur/component/servlet/AbstractServiceManagerServlet.java
Index: AbstractServiceManagerServlet.java
===================================================================
/*
* Copyright (C) The Apache Software Foundation. All rights reserved.
*
* This software is published under the terms of the Apache Software License
* version 1.1, a copy of which has been included with this distribution in
* the LICENSE.txt file.
*/
package org.apache.avalon.excalibur.component.servlet;
import java.io.IOException;
import java.util.ArrayList;
import javax.servlet.ServletConfig;
import javax.servlet.ServletContext;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import org.apache.avalon.excalibur.logger.LoggerManager;
import org.apache.avalon.framework.service.ServiceManager;
import org.apache.avalon.framework.logger.Logger;
import org.apache.excalibur.instrument.CounterInstrument;
import org.apache.excalibur.instrument.Instrument;
import org.apache.excalibur.instrument.Instrumentable;
import org.apache.excalibur.instrument.InstrumentManager;
import org.apache.excalibur.instrument.ValueInstrument;
/**
* Abstract Servlet which can be used with the ExcaliburServiceManagerServlet
* to enable servlets to have access to a ServiceManager as well as logging
* and instrumentation features.
*
* @author <a href="mailto:leif@;apache.org">Leif Mortenson</a>
* @version CVS $Revision: 1.1 $ $Date: 2002/11/07 09:50:41 $
* @since 4.2
*/
public abstract class AbstractServiceManagerServlet
extends HttpServlet
implements Instrumentable
{
private String m_referenceName;
private ServiceManager m_serviceManager;
private Logger m_logger;
/** Instrumentable Name assigned to this Instrumentable */
private String m_instrumentableName;
/** Stores the instruments during initialization. */
private ArrayList m_instrumentList;
/** Stores the child instrumentables during initialization. */
private ArrayList m_childList;
/** Flag which is to used to keep track of when the Instrumentable has been
registered. */
private boolean m_registered;
/** Counts the number of times the service is requested. */
private CounterInstrument m_instrumentRequests;
/** Records the amount of time execute takes to be processed. */
private ValueInstrument m_instrumentTime;
/*---------------------------------------------------------------
* Constructors
*-------------------------------------------------------------*/
/**
* Create a new AbstractServiceManagerServlet.
*
* @param referenceName A name which does not include any spaces or periods
* that will be used to name the logger category and
* instrumentable which represents this servlet.
*/
public AbstractServiceManagerServlet( String referenceName )
{
//System.out.println( "AbstractServiceManagerServlet( " + referenceName + "
)" );
m_referenceName = referenceName;
// Set up Instrumentable like AbstractInstrumentable
m_registered = false;
m_instrumentList = new ArrayList();
m_childList = new ArrayList();
// Create the instruments
setInstrumentableName( referenceName );
addInstrument( m_instrumentRequests = new CounterInstrument( "requests" ) );
addInstrument( m_instrumentTime = new ValueInstrument( "time" ) );
}
/*---------------------------------------------------------------
* HttpServlet Methods
*-------------------------------------------------------------*/
/**
* Called by the servlet container to initialize a servlet before it is
* put into service.
*
* @param config ServletConfig object for the servlet.
*
* @throws ServletException If there are any initialization problems.
*/
public void init( ServletConfig config )
throws ServletException
{
ServletContext context = config.getServletContext();
// Initialize logging for the servlet.
LoggerManager loggerManager =
(LoggerManager)context.getAttribute( LoggerManager.class.getName() );
if ( loggerManager == null )
{
throw new IllegalStateException(
"The ExcaliburComponentManagerServlet servlet was not correctly
initialized." );
}
Logger logger = loggerManager.getLoggerForCategory( "servlet" );
m_logger = logger.getChildLogger( m_referenceName );
if ( getLogger().isDebugEnabled() )
{
getLogger().debug( "servlet.init( config )" );
}
// Obtain a reference to the ServiceManager
m_serviceManager =
(ServiceManager)context.getAttribute( ServiceManager.class.getName() );
if ( m_serviceManager == null )
{
throw new IllegalStateException(
"The ExcaliburComponentManagerServlet servlet was not correctly
initialized." );
}
// Register this servlet with the InstrumentManager if it exists.
InstrumentManager instrumentManager =
(InstrumentManager)context.getAttribute(
InstrumentManager.class.getName() );
if ( instrumentManager != null )
{
try
{
instrumentManager.registerInstrumentable(
this, "servlets." + getInstrumentableName() );
}
catch ( Exception e )
{
throw new ServletException(
"Unable to register the servlet with the instrument manager.", e
);
}
}
// Do this last so the subclasses will be able to access these objects in
their
// init method.
super.init( config );
}
/**
* Called by the servlet container to indicate to a servlet that the servlet
* is being taken out of service.
*/
public void destroy()
{
if ( getLogger().isDebugEnabled() )
{
getLogger().debug( "servlet.destroy()" );
}
// Release the ServiceManager by removing its reference.
m_serviceManager = null;
super.destroy();
// Make sure that the component manager gets collected.
System.gc();
// Give the system time for the Gc to complete. This is necessary to make
sure that
// the ECMServlet has time to dispose all of its managers before the Tomcat
server
// invalidates the current class loader.
try
{
Thread.sleep(250);
}
catch ( InterruptedException e )
{
}
}
/**
* Receives standard HTTP requests from the public service method and dispatches
* them to the doXXX methods defined in this class.
* Overrides the default method to allow for instrumentation.
*
* @param request The HttpServletRequest object that contains the request the
* client made of the servlet.
* @param response The HttpServletResponse object that contains the response
* the servlet returns to the client.
*/
public void service( HttpServletRequest request, HttpServletResponse response )
throws ServletException, IOException
{
if ( getLogger().isDebugEnabled() )
{
StringBuffer sb = new StringBuffer( request.getRequestURI() );
String query = request.getQueryString();
if ( query != null )
{
sb.append( "?" );
sb.append( query );
}
getLogger().debug( "Request: " + sb.toString() );
}
long start = System.currentTimeMillis();
// Notify the Instrument Manager
m_instrumentRequests.increment();
super.service( request, response );
// Notify the Instrument Manager how long the service took.
if ( m_instrumentTime.isActive() )
{
m_instrumentTime.setValue( (int)( System.currentTimeMillis() - start ) );
}
}
/*---------------------------------------------------------------
* Instrumentable Methods
*-------------------------------------------------------------*/
/**
* Gets the name of the Instrumentable.
*
* @return The name used to identify a Instrumentable.
*/
public final String getInstrumentableName()
{
return m_instrumentableName;
}
/**
* Sets the name for the Instrumentable. The Instrumentable Name is used
* to uniquely identify the Instrumentable during the configuration of
* the InstrumentManager and to gain access to an InstrumentableDescriptor
* through the InstrumentManager. The value should be a string which does
* not contain spaces or periods.
* <p>
* This value may be set by a parent Instrumentable, or by the
* InstrumentManager using the value of the 'instrumentable' attribute in
* the configuration of the component.
*
* @param name The name used to identify a Instrumentable.
*/
public final void setInstrumentableName( String name )
{
m_instrumentableName = name;
}
/**
* Any Object which implements Instrumentable can also make use of other
* Instrumentable child objects. This method is used to tell the
* InstrumentManager about them.
*
* @return An array of child Instrumentables. This method should never
* return null. If there are no child Instrumentables, then
* EMPTY_INSTRUMENTABLE_ARRAY can be returned.
*/
public final Instrumentable[] getChildInstrumentables()
{
m_registered = true;
if( m_childList.size() == 0 )
{
return Instrumentable.EMPTY_INSTRUMENTABLE_ARRAY;
}
else
{
Instrumentable[] children = new Instrumentable[ m_childList.size() ];
m_childList.toArray( children );
return children;
}
}
/**
* Obtain a reference to all the Instruments that the Instrumentable object
* wishes to expose. All sampling is done directly through the
* Instruments as opposed to the Instrumentable interface.
*
* @return An array of the Instruments available for profiling. Should
* never be null. If there are no Instruments, then
* EMPTY_INSTRUMENT_ARRAY can be returned. This should never be
* the case though unless there are child Instrumentables with
* Instruments.
*/
public final Instrument[] getInstruments()
{
m_registered = true;
if( m_instrumentList.size() == 0 )
{
return Instrumentable.EMPTY_INSTRUMENT_ARRAY;
}
else
{
Instrument[] instruments = new Instrument[ m_instrumentList.size() ];
m_instrumentList.toArray( instruments );
return instruments;
}
}
/*---------------------------------------------------------------
* Methods
*-------------------------------------------------------------*/
/**
* Adds an Instrument to the list of Instruments published by the component.
* This method may not be called after the Instrumentable has been
* registered with the InstrumentManager.
*
* @param instrument Instrument to publish.
*/
protected void addInstrument( Instrument instrument )
{
if( m_registered )
{
throw new IllegalStateException( "Instruments can not be added after the
"
+ "Instrumentable is registered with the InstrumentManager." );
}
m_instrumentList.add( instrument );
}
/**
* Adds a child Instrumentable to the list of child Instrumentables
* published by the component. This method may not be called after the
* Instrumentable has been registered with the InstrumentManager.
* <p>
* Note that Child Instrumentables must be named by the caller using the
* setInstrumentableName method.
*
* @param child Child Instrumentable to publish.
*/
protected void addChildInstrumentable( Instrumentable child )
{
if( m_registered )
{
throw new IllegalStateException( "Child Instrumentables can not be added
after the "
+ "Instrumentable is registered with the InstrumentManager." );
}
m_childList.add( child );
}
/**
* Obtain a reference to the servlet's logger.
*
* @return The servlet's logger.
*/
protected Logger getLogger()
{
return m_logger;
}
/**
* Returns the current ServiceManager.
*
* @return The current ServiceManager.
*/
public ServiceManager getServiceManager()
{
return m_serviceManager;
}
}
1.1
jakarta-avalon-excalibur/component/src/java/org/apache/avalon/excalibur/component/servlet/ServiceManagerReferenceProxy.java
Index: ServiceManagerReferenceProxy.java
===================================================================
/*
* Copyright (C) The Apache Software Foundation. All rights reserved.
*
* This software is published under the terms of the Apache Software License
* version 1.1, a copy of which has been included with this distribution in
* the LICENSE.txt file.
*/
package org.apache.avalon.excalibur.component.servlet;
import org.apache.avalon.framework.service.ServiceException;
import org.apache.avalon.framework.service.ServiceManager;
/**
* Reference Proxy to a ServiceManager
*
* @author <a href="mailto:leif@;apache.org">Leif Mortenson</a>
* @version CVS $Revision: 1.1 $ $Date: 2002/11/07 09:50:41 $
* @since 4.2
*/
final class ServiceManagerReferenceProxy
extends AbstractReferenceProxy
implements ServiceManager
{
private ServiceManager m_serviceManager;
/*---------------------------------------------------------------
* Constructors
*-------------------------------------------------------------*/
/**
* Create a new proxy.
*
* @param serviceManager ServiceManager being proxied.
* @param latch Latch wich will be notified when this proxy is finalized.
* @param name Name of the proxy.
*/
ServiceManagerReferenceProxy( ServiceManager serviceManager,
AbstractReferenceProxyLatch latch,
String name )
{
super( latch, name );
m_serviceManager = serviceManager;
}
/*---------------------------------------------------------------
* ServiceManager Methods
*-------------------------------------------------------------*/
/**
* Get the <code>Object</code> associated with the given role. For
* instance, If the <code>ServiceManager</code> had a
* <code>LoggerComponent</code> stored and referenced by role, I would use
* the following call:
* <pre>
* try
* {
* MyComponent log;
* myComponent = (MyComponent) manager.lookup(MyComponent.ROLE);
* }
* catch (...)
* {
* ...
* }
* </pre>
*
* @param role The role name of the <code>Object</code> to retrieve.
* @return an <code>Object</code> value
* @throws ServiceException if an error occurs
*/
public Object lookup( String role )
throws ServiceException
{
return m_serviceManager.lookup( role );
}
/**
* Check to see if a <code>Object</code> exists for a role.
*
* @param role a string identifying the role to check.
* @return True if the object exists, False if it does not.
*/
public boolean hasService( String role )
{
return m_serviceManager.hasService( role );
}
/**
* Return the <code>Object</code> when you are finished with it. This
* allows the <code>ServiceManager</code> to handle the End-Of-Life Lifecycle
* events associated with the <code>Object</code>. Please note, that no
* Exception should be thrown at this point. This is to allow easy use of the
* ServiceManager system without having to trap Exceptions on a release.
*
* @param object The <code>Object</code> we are releasing.
*/
public void release( Object service )
{
m_serviceManager.release( service );
}
}
--
To unsubscribe, e-mail: <mailto:avalon-cvs-unsubscribe@;jakarta.apache.org>
For additional commands, e-mail: <mailto:avalon-cvs-help@;jakarta.apache.org>