hammant 2002/12/15 17:00:01 Modified: altrmi build.xml altrmi/src/java/org/apache/excalibur/altrmi/client/impl/callback/socket CallbackEnabledSocketCustomStreamInvocationHandler.java altrmi/src/java/org/apache/excalibur/altrmi/client/impl/http ClientHttpReadWriter.java CustomHttpInvocationHandler.java altrmi/src/java/org/apache/excalibur/altrmi/client/impl/socket SocketCustomStreamInvocationHandler.java altrmi/src/java/org/apache/excalibur/altrmi/client/impl/stream ClientCustomStreamReadWriter.java StreamInvocationHandler.java altrmi/src/java/org/apache/excalibur/altrmi/server/impl/http CustomHttpServlet.java altrmi/src/test/org/apache/excalibur/altrmi/test/http CustomHttpServletTestCase.java KludgeServlet.java Added: altrmi/src/java/org/apache/excalibur/altrmi/server/impl/http CustomHttpServer.java HttpCustomServerConnection.java Log: HTTP transport complete... with some blockers concerning Jetty :-( Pairing by with Charles Lowell again Revision Changes Path 1.51 +4 -5 jakarta-avalon-excalibur/altrmi/build.xml Index: build.xml =================================================================== RCS file: /home/cvs/jakarta-avalon-excalibur/altrmi/build.xml,v retrieving revision 1.50 retrieving revision 1.51 diff -u -r1.50 -r1.51 --- build.xml 14 Dec 2002 09:09:07 -0000 1.50 +++ build.xml 16 Dec 2002 01:00:00 -0000 1.51 @@ -249,8 +249,6 @@ <!-- Plain tests --> - <echo message="w" file="poo.txt"/> - <junit fork="true" haltonfailure="${junit.failonerror}" printsummary="yes" @@ -261,9 +259,10 @@ <formatter type="plain" usefile="false"/> <!-- text reports for humans --> <batchtest todir="${build.tests}"> <fileset dir="${build.testclasses}"> -<!-- <include name="**/test/**/SimpleAsy*TestCase.class"/> --> - <include name="**/test/**/*TestCase.class"/> - <exclude name="**/Abstract*"/> + <include name="**/test/**/CustomHttpServletTestCase.class"/> + +<!-- <include name="**/test/**/*TestCase.class"/> + <exclude name="**/Abstract*"/> --> <exclude name="**/JSXObjectStreamTestCase.class"/> </fileset> </batchtest> 1.9 +2 -2 jakarta-avalon-excalibur/altrmi/src/java/org/apache/excalibur/altrmi/client/impl/callback/socket/CallbackEnabledSocketCustomStreamInvocationHandler.java Index: CallbackEnabledSocketCustomStreamInvocationHandler.java =================================================================== RCS file: /home/cvs/jakarta-avalon-excalibur/altrmi/src/java/org/apache/excalibur/altrmi/client/impl/callback/socket/CallbackEnabledSocketCustomStreamInvocationHandler.java,v retrieving revision 1.8 retrieving revision 1.9 diff -u -r1.8 -r1.9 --- CallbackEnabledSocketCustomStreamInvocationHandler.java 13 Dec 2002 00:09:13 -0000 1.8 +++ CallbackEnabledSocketCustomStreamInvocationHandler.java 16 Dec 2002 01:00:01 -0000 1.9 @@ -48,7 +48,7 @@ { if( mCallbackEnabledClientCustomStreamReadWriter == null ) { - mCallbackEnabledClientCustomStreamReadWriter = new CallbackEnabledClientCustomStreamReadWriter( in, out, mInterfacesClassLoader ); + mCallbackEnabledClientCustomStreamReadWriter = new CallbackEnabledClientCustomStreamReadWriter( in, out, m_interfacesClassLoader ); } return mCallbackEnabledClientCustomStreamReadWriter; } 1.2 +27 -1 jakarta-avalon-excalibur/altrmi/src/java/org/apache/excalibur/altrmi/client/impl/http/ClientHttpReadWriter.java Index: ClientHttpReadWriter.java =================================================================== RCS file: /home/cvs/jakarta-avalon-excalibur/altrmi/src/java/org/apache/excalibur/altrmi/client/impl/http/ClientHttpReadWriter.java,v retrieving revision 1.1 retrieving revision 1.2 diff -u -r1.1 -r1.2 --- ClientHttpReadWriter.java 13 Dec 2002 00:09:14 -0000 1.1 +++ ClientHttpReadWriter.java 16 Dec 2002 01:00:01 -0000 1.2 @@ -8,10 +8,14 @@ package org.apache.excalibur.altrmi.client.impl.http; import org.apache.excalibur.altrmi.client.impl.ClientStreamReadWriter; +import org.apache.excalibur.altrmi.client.impl.stream.ClientCustomStreamReadWriter; import org.apache.excalibur.altrmi.common.AltrmiReply; import org.apache.excalibur.altrmi.common.AltrmiRequest; +import org.apache.excalibur.altrmi.common.AltrmiConnectionException; import java.io.IOException; +import java.io.InputStream; +import java.io.OutputStream; import java.net.URL; import java.net.URLConnection; @@ -19,11 +23,13 @@ { private String m_host; private int m_port; + private ClassLoader m_interfacesClassLoader; - public ClientHttpReadWriter(String host, int port) + public ClientHttpReadWriter(String host, int port, ClassLoader interfacesClassLoader) { m_host = host; m_port = port; + m_interfacesClassLoader = interfacesClassLoader; } public AltrmiReply postRequest(AltrmiRequest altrmiRequest) @@ -31,6 +37,26 @@ { URL url = new URL("http",m_host, m_port,"/mystuff/Dump/"); URLConnection connection = url.openConnection(); + connection.setDoOutput(true); + connection.setDoInput(true); + + ClientCustomStreamReadWriter clientCustomStreamReadWriter; + try + { + OutputStream outputStream = connection.getOutputStream(); + InputStream inputStream = connection.getInputStream(); + clientCustomStreamReadWriter = new ClientCustomStreamReadWriter( + inputStream, outputStream, m_interfacesClassLoader); + return clientCustomStreamReadWriter.postRequest(altrmiRequest); + } + catch (AltrmiConnectionException e) + { + throw new IOException("Connection exception during read/writing:" + e.getMessage()); + } + catch (IOException e) + { + e.printStackTrace(); //To change body of catch statement use Options | File Templates. + } // OutputStream out = connection // ObjectOutputStream out 1.2 +2 -2 jakarta-avalon-excalibur/altrmi/src/java/org/apache/excalibur/altrmi/client/impl/http/CustomHttpInvocationHandler.java Index: CustomHttpInvocationHandler.java =================================================================== RCS file: /home/cvs/jakarta-avalon-excalibur/altrmi/src/java/org/apache/excalibur/altrmi/client/impl/http/CustomHttpInvocationHandler.java,v retrieving revision 1.1 retrieving revision 1.2 diff -u -r1.1 -r1.2 --- CustomHttpInvocationHandler.java 13 Dec 2002 00:09:14 -0000 1.1 +++ CustomHttpInvocationHandler.java 16 Dec 2002 01:00:01 -0000 1.2 @@ -42,7 +42,7 @@ m_port = port; - setObjectReadWriter(new ClientHttpReadWriter(host,port)); + setObjectReadWriter(new ClientHttpReadWriter(host,port, classLoader)); } 1.6 +2 -2 jakarta-avalon-excalibur/altrmi/src/java/org/apache/excalibur/altrmi/client/impl/socket/SocketCustomStreamInvocationHandler.java Index: SocketCustomStreamInvocationHandler.java =================================================================== RCS file: /home/cvs/jakarta-avalon-excalibur/altrmi/src/java/org/apache/excalibur/altrmi/client/impl/socket/SocketCustomStreamInvocationHandler.java,v retrieving revision 1.5 retrieving revision 1.6 diff -u -r1.5 -r1.6 --- SocketCustomStreamInvocationHandler.java 13 Dec 2002 00:09:14 -0000 1.5 +++ SocketCustomStreamInvocationHandler.java 16 Dec 2002 01:00:01 -0000 1.6 @@ -55,6 +55,6 @@ protected ClientStreamReadWriter createClientStreamReadWriter( InputStream in, OutputStream out ) throws AltrmiConnectionException { - return new ClientCustomStreamReadWriter( in, out, mInterfacesClassLoader ); + return new ClientCustomStreamReadWriter( in, out, m_interfacesClassLoader ); } } 1.6 +3 -1 jakarta-avalon-excalibur/altrmi/src/java/org/apache/excalibur/altrmi/client/impl/stream/ClientCustomStreamReadWriter.java Index: ClientCustomStreamReadWriter.java =================================================================== RCS file: /home/cvs/jakarta-avalon-excalibur/altrmi/src/java/org/apache/excalibur/altrmi/client/impl/stream/ClientCustomStreamReadWriter.java,v retrieving revision 1.5 retrieving revision 1.6 diff -u -r1.5 -r1.6 --- ClientCustomStreamReadWriter.java 13 Dec 2002 00:09:14 -0000 1.5 +++ ClientCustomStreamReadWriter.java 16 Dec 2002 01:00:01 -0000 1.6 @@ -33,6 +33,8 @@ private DataOutputStream mDataOutputStream; private ClassLoader mInterfacesClassLoader; + + /** * Constructor ClientCustomStreamReadWriter * 1.9 +14 -14 jakarta-avalon-excalibur/altrmi/src/java/org/apache/excalibur/altrmi/client/impl/stream/StreamInvocationHandler.java Index: StreamInvocationHandler.java =================================================================== RCS file: /home/cvs/jakarta-avalon-excalibur/altrmi/src/java/org/apache/excalibur/altrmi/client/impl/stream/StreamInvocationHandler.java,v retrieving revision 1.8 retrieving revision 1.9 diff -u -r1.8 -r1.9 --- StreamInvocationHandler.java 13 Dec 2002 00:09:14 -0000 1.8 +++ StreamInvocationHandler.java 16 Dec 2002 01:00:01 -0000 1.9 @@ -36,10 +36,10 @@ public abstract class StreamInvocationHandler extends AbstractClientInvocationHandler { - private ClientStreamReadWriter mObjectReadWriter; - private boolean mMethodLogging = false; - private long mLastRealRequest = System.currentTimeMillis(); - protected final ClassLoader mInterfacesClassLoader; + private ClientStreamReadWriter m_objectReadWriter; + private boolean m_methodLogging = false; + private long m_lastRealRequest = System.currentTimeMillis(); + protected final ClassLoader m_interfacesClassLoader; /** * Constructor StreamInvocationHandler @@ -50,7 +50,7 @@ */ public StreamInvocationHandler( ClassLoader interfacesClassLoader ) { - mInterfacesClassLoader = interfacesClassLoader; + m_interfacesClassLoader = interfacesClassLoader; } /** @@ -62,7 +62,7 @@ */ public ClassLoader getInterfacesClassLoader() { - return mInterfacesClassLoader; + return m_interfacesClassLoader; } /** @@ -77,12 +77,12 @@ super.setAltrmiConnectionListener( altrmiConnectionListener ); - mMethodLogging = altrmiConnectionListener.methodLogging(); + m_methodLogging = altrmiConnectionListener.methodLogging(); } protected void setObjectReadWriter( ClientStreamReadWriter objectReadWriter ) { - mObjectReadWriter = objectReadWriter; + m_objectReadWriter = objectReadWriter; } protected void requestWritten() @@ -103,7 +103,7 @@ if( request.getRequestCode() != AltrmiRequestConstants.PINGREQUEST ) { - mLastRealRequest = System.currentTimeMillis(); + m_lastRealRequest = System.currentTimeMillis(); } try @@ -115,7 +115,7 @@ int tries = 0; long start = 0; - if( mMethodLogging ) + if( m_methodLogging ) { start = System.currentTimeMillis(); } @@ -130,7 +130,7 @@ { long t1 = System.currentTimeMillis(); - reply = (AltrmiReply)mObjectReadWriter.postRequest( request ); + reply = (AltrmiReply)m_objectReadWriter.postRequest( request ); long t2 = System.currentTimeMillis(); @@ -184,7 +184,7 @@ } } - if( mMethodLogging ) + if( m_methodLogging ) { if( request instanceof MethodRequest ) { @@ -231,6 +231,6 @@ */ public long getLastRealRequest() { - return mLastRealRequest; + return m_lastRealRequest; } } 1.2 +48 -32 jakarta-avalon-excalibur/altrmi/src/java/org/apache/excalibur/altrmi/server/impl/http/CustomHttpServlet.java Index: CustomHttpServlet.java =================================================================== RCS file: /home/cvs/jakarta-avalon-excalibur/altrmi/src/java/org/apache/excalibur/altrmi/server/impl/http/CustomHttpServlet.java,v retrieving revision 1.1 retrieving revision 1.2 diff -u -r1.1 -r1.2 --- CustomHttpServlet.java 13 Dec 2002 00:09:14 -0000 1.1 +++ CustomHttpServlet.java 16 Dec 2002 01:00:01 -0000 1.2 @@ -7,63 +7,79 @@ */ package org.apache.excalibur.altrmi.server.impl.http; -import org.apache.excalibur.altrmi.common.MethodRequest; +import org.apache.excalibur.altrmi.server.AltrmiServerException; import org.apache.excalibur.altrmi.server.AltrmiPublisher; -import org.apache.excalibur.altrmi.server.MethodInvocationHandler; -import org.apache.excalibur.altrmi.server.PublicationDescription; -import org.apache.excalibur.altrmi.server.PublicationException; -import org.apache.excalibur.altrmi.server.impl.adapters.InvocationHandlerAdapter; +import org.apache.excalibur.altrmi.server.impl.ServerCustomStreamReadWriter; import javax.servlet.ServletException; import javax.servlet.http.HttpServlet; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; +import java.io.BufferedReader; import java.io.IOException; - -public class CustomHttpServlet extends HttpServlet implements AltrmiPublisher +import java.io.InputStream; +import java.io.OutputStream; +import java.io.PrintWriter; + +/** + * Class CustomHttpServlet + * + * + * @author Paul Hammant + * @author Charles Lowell + * @version $Revision$ + */ +public class CustomHttpServlet extends HttpServlet { - InvocationHandlerAdapter inInvocationHandlerAdapter = new InvocationHandlerAdapter(); + CustomHttpServer customHttpServer; + public CustomHttpServlet() { + try + { + customHttpServer = new CustomHttpServer(); + } + catch (AltrmiServerException e) + { + throw new RuntimeException("TODO" + e.getMessage()); + } } public void doGet(HttpServletRequest httpServletRequest, HttpServletResponse httpServletResponse) throws ServletException, IOException { - super.doGet(httpServletRequest, httpServletResponse); - } + httpServletResponse.setContentType("x-altrmi"); + final BufferedReader inputReader = httpServletRequest.getReader(); + InputStream in = new InputStream() + { + public int read() throws IOException + { + return inputReader.read(); + } + }; - public void publish( Object impl, String asName, Class interfaceToExpose ) throws PublicationException - { - inInvocationHandlerAdapter.publish(impl, asName, interfaceToExpose); + final PrintWriter outputWriter = httpServletResponse.getWriter(); + OutputStream out = new OutputStream() + { + public void write(int b) throws IOException + { + outputWriter.write(b); + } + }; + customHttpServer.processRequest(in,out); } - public void publish( Object impl, String asName, PublicationDescription publicationDescription ) - throws PublicationException + public void doPost(HttpServletRequest httpServletRequest, HttpServletResponse httpServletResponse) throws ServletException, IOException { - inInvocationHandlerAdapter.publish(impl, asName, publicationDescription); + doGet(httpServletRequest, httpServletResponse); } - public void unPublish( Object impl, String publishedName ) throws PublicationException - { - inInvocationHandlerAdapter.unPublish(impl, publishedName); - } - public void replacePublished( Object oldImpl, String publishedName, Object withImpl ) - throws PublicationException + public AltrmiPublisher getPublisher() { - inInvocationHandlerAdapter.replacePublished(oldImpl, publishedName, withImpl); - } + return customHttpServer; - public MethodInvocationHandler getMethodInvocationHandler( MethodRequest methodRequest, - String objectName ) - { - return inInvocationHandlerAdapter.getMethodInvocationHandler(methodRequest, objectName); } - public MethodInvocationHandler getMethodInvocationHandler( String publishedName ) - { - return inInvocationHandlerAdapter.getMethodInvocationHandler(publishedName); - } } 1.1 jakarta-avalon-excalibur/altrmi/src/java/org/apache/excalibur/altrmi/server/impl/http/CustomHttpServer.java Index: CustomHttpServer.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.excalibur.altrmi.server.impl.http; import org.apache.avalon.framework.logger.ConsoleLogger; import org.apache.excalibur.altrmi.server.AltrmiServerException; import org.apache.excalibur.altrmi.server.impl.AbstractServer; import org.apache.excalibur.altrmi.server.impl.ServerCustomStreamReadWriter; import org.apache.excalibur.altrmi.server.impl.ServerStreamReadWriter; import org.apache.excalibur.altrmi.server.impl.adapters.InvocationHandlerAdapter; import java.io.InputStream; import java.io.OutputStream; /** * Class CustomHttpServer * * * @author Paul Hammant * @author Charles Lowell * @version $Revision: 1.1 $ */ public class CustomHttpServer extends AbstractServer { /** * Construct a Custom Http Server * * * * @throws AltrmiServerException If a problem instantiating. * */ public CustomHttpServer() throws AltrmiServerException { super(); // new RegistryHelper().put("/.altrmi/optimizations/port=" + port, // new CompleteSocketCustomStreamPipedBinder(super.getInovcationHandlerAdapter())); } /** * Construct a Custom Http Server * * @param invocationHandlerAdapter The invocation handler to use. * * @throws AltrmiServerException If a problem instantiating. * */ public CustomHttpServer( InvocationHandlerAdapter invocationHandlerAdapter) throws AltrmiServerException { super(invocationHandlerAdapter); // new RegistryHelper().put("/.altrmi/optimizations/port=" + port, // new CompleteSocketCustomStreamPipedBinder(invocationHandlerAdapter)); } /** * Method start * */ public void start() { setState(STARTING); //todo setState(STARTED); } /** * Method stop * */ public void stop() { setState(SHUTTINGDOWN); //TODO killAllConnections(); setState(STOPPED); } protected void processRequest(InputStream in, OutputStream out) { ServerStreamReadWriter ssrw = new ServerCustomStreamReadWriter(); ssrw.setStreams(in, out); HttpCustomServerConnection hcsc = new HttpCustomServerConnection(this, ssrw); hcsc.enableLogging(new ConsoleLogger()); Thread thread = new Thread(hcsc, "SocketStreamServerConnection Thread"); thread.start(); } } 1.1 jakarta-avalon-excalibur/altrmi/src/java/org/apache/excalibur/altrmi/server/impl/http/HttpCustomServerConnection.java Index: HttpCustomServerConnection.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.excalibur.altrmi.server.impl.http; import org.apache.excalibur.altrmi.server.impl.AbstractServer; import org.apache.excalibur.altrmi.server.impl.ServerStreamReadWriter; import org.apache.excalibur.altrmi.server.impl.StreamServerConnection; /** * Class HttpCustomServerConnection * * * @author Paul Hammant * @author Charles Lowell * @version $Revision: 1.1 $ */ public class HttpCustomServerConnection extends StreamServerConnection { /** * Construct a HTTP Custom Stream Server Connection * @param abstractServer The Abstract Server that will process invocations and requests * @param readWriter The readWriter for the transport type */ public HttpCustomServerConnection( final AbstractServer abstractServer, ServerStreamReadWriter readWriter) { super(abstractServer, readWriter); } /** * Kill connections */ protected void killConnection() { //TODO } } 1.2 +23 -11 jakarta-avalon-excalibur/altrmi/src/test/org/apache/excalibur/altrmi/test/http/CustomHttpServletTestCase.java Index: CustomHttpServletTestCase.java =================================================================== RCS file: /home/cvs/jakarta-avalon-excalibur/altrmi/src/test/org/apache/excalibur/altrmi/test/http/CustomHttpServletTestCase.java,v retrieving revision 1.1 retrieving revision 1.2 diff -u -r1.1 -r1.2 --- CustomHttpServletTestCase.java 13 Dec 2002 00:09:15 -0000 1.1 +++ CustomHttpServletTestCase.java 16 Dec 2002 01:00:01 -0000 1.2 @@ -29,6 +29,9 @@ public class CustomHttpServletTestCase extends AbstractHelloTestCase { private static final int HTTP_PORT = 8181; + HttpServer m_httpServer; + SocketListener m_listener; + HttpContext m_context; public CustomHttpServletTestCase(String name) { @@ -43,24 +46,27 @@ KludgeServlet.setRealServlet(customHttpServlet); // Create the server - HttpServer server = new HttpServer(); + + m_httpServer = new HttpServer(); // Create a port listener - SocketListener listener = new SocketListener(); - listener.setPort(HTTP_PORT); - server.addListener(listener); + + m_listener = new SocketListener(); + m_listener.setPort(HTTP_PORT); + m_httpServer.addListener(m_listener); // Create a context - HttpContext context = new HttpContext(); - context.setContextPath("/mystuff/*"); - server.addContext(context); + + m_context = new HttpContext(); + m_context.setContextPath("/mystuff/*"); + m_httpServer.addContext(m_context); // Create a servlet container ServletHandler servlets = new ServletHandler(); - context.addHandler(servlets); + m_context.addHandler(servlets); // Map a servlet onto the container - servlets.addServlet("Dump", "/Dump/*", "org.apache.excalibur.altrmi.server.impl.http.CustomHttpServlet"); + servlets.addServlet("Dump", "/Dump/*", "org.apache.excalibur.altrmi.test.http.KludgeServlet"); // Serve static content from the context // String home = System.getProperty("jetty.home", "."); @@ -68,7 +74,7 @@ // context.addHandler(new ResourceHandler()); // Start the http server - server.start(); + m_httpServer.start(); @@ -76,7 +82,7 @@ testServer = new TestInterfaceImpl(); PublicationDescription pd = new PublicationDescription(TestInterface.class, new Class[]{TestInterface3.class, TestInterface2.class}); - customHttpServlet.publish(testServer, "Hello", pd); + customHttpServlet.getPublisher().publish(testServer, "Hello", pd); // Client side setup altrmiFactory = new ClientClassAltrmiFactory(false); @@ -96,9 +102,15 @@ Thread.yield(); altrmiFactory.close(); Thread.yield(); + m_httpServer.removeContext(m_context); + m_listener.stop(); + m_httpServer.removeListener(m_listener); + m_httpServer.stop(); server.stop(); Thread.yield(); server = null; + m_listener = null; + m_httpServer = null; testServer = null; super.tearDown(); } 1.2 +11 -2 jakarta-avalon-excalibur/altrmi/src/test/org/apache/excalibur/altrmi/test/http/KludgeServlet.java Index: KludgeServlet.java =================================================================== RCS file: /home/cvs/jakarta-avalon-excalibur/altrmi/src/test/org/apache/excalibur/altrmi/test/http/KludgeServlet.java,v retrieving revision 1.1 retrieving revision 1.2 diff -u -r1.1 -r1.2 --- KludgeServlet.java 13 Dec 2002 00:09:15 -0000 1.1 +++ KludgeServlet.java 16 Dec 2002 01:00:01 -0000 1.2 @@ -12,20 +12,29 @@ import javax.servlet.ServletException; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; +import javax.servlet.http.HttpServlet; import java.io.IOException; -public class KludgeServlet extends CustomHttpServlet +public class KludgeServlet extends HttpServlet { private static CustomHttpServlet realServlet; public static void setRealServlet(CustomHttpServlet realServlet) { KludgeServlet.realServlet = realServlet; + System.out.println("---> kludge"); } - public void doGet(HttpServletRequest httpServletRequest, HttpServletResponse httpServletResponse) throws ServletException, IOException + protected void doGet(HttpServletRequest httpServletRequest, HttpServletResponse httpServletResponse) throws ServletException, IOException { + System.out.println("--> doGet Called"); realServlet.doGet(httpServletRequest, httpServletResponse); + } + + protected void doPost(HttpServletRequest httpServletRequest, HttpServletResponse httpServletResponse) throws ServletException, IOException + { + System.out.println("--> doPost Called"); + realServlet.doPost(httpServletRequest, httpServletResponse); }
-- To unsubscribe, e-mail: <mailto:[EMAIL PROTECTED]> For additional commands, e-mail: <mailto:[EMAIL PROTECTED]>