donaldp 2003/02/28 14:51:54 Modified: . build.xml Added: src/api/org/apache/avalon/phoenix ApplicationEvent.java ApplicationListener.java BlockContext.java BlockEvent.java package.html src/api/org/apache/avalon/phoenix/metadata BlockListenerMetaData.java BlockMetaData.java DependencyMetaData.java SarMetaData.java package.html src/api/org/apache/avalon/phoenix/metainfo BlockDescriptor.java BlockInfo.java DependencyDescriptor.java ServiceDescriptor.java package.html Removed: src/java/org/apache/avalon/phoenix ApplicationEvent.java ApplicationListener.java BlockContext.java BlockEvent.java package.html src/java/org/apache/avalon/phoenix/metadata BlockListenerMetaData.java BlockMetaData.java DependencyMetaData.java SarMetaData.java package.html src/java/org/apache/avalon/phoenix/metainfo BlockDescriptor.java BlockInfo.java DependencyDescriptor.java ServiceDescriptor.java package.html Log: Migrate API layer into new source tree. Revision Changes Path 1.200 +7 -5 avalon-phoenix/build.xml Index: build.xml =================================================================== RCS file: /home/cvs/avalon-phoenix/build.xml,v retrieving revision 1.199 retrieving revision 1.200 diff -u -r1.199 -r1.200 --- build.xml 8 Feb 2003 17:24:31 -0000 1.199 +++ build.xml 28 Feb 2003 22:51:52 -0000 1.200 @@ -22,7 +22,7 @@ <project name="Avalon Phoenix" default="main" basedir="."> - <!-- + <!--Abstr Give user a chance to override without editing this file (and without typing -D each time he compiles it) --> @@ -54,6 +54,7 @@ <property name="documentation.dir" value="${src.dir}/documentation"/> <property name="test.dir" value="${src.dir}/test"/> <property name="compat.dir" value="${src.dir}/compat"/> + <property name="api.dir" value="${src.dir}/api"/> <property name="conf.dir" value="${src.dir}/conf"/> <property name="script.dir" value="${src.dir}/script"/> <property name="lib.dir" value="lib"/> @@ -234,6 +235,7 @@ <classpath refid="project.class.path" /> <src path="${build.src}" /> <src path="${compat.dir}" /> + <src path="${api.dir}"/> <exclude name="${constants.file}" /> <exclude name="${container.constants.file}"/> <exclude name="org/apache/avalon/phoenix/frontends/PhoenixServlet.java" unless="servlet.present"/> @@ -482,7 +484,7 @@ <copy todir="${bin.dist.lib}"> <fileset dir="${lib.dir}"> <include name="excalibur*.jar"/> - <include name="sandbox-info-*.jar"/> + <include name="sandbox-info-*.jar"/> </fileset> <fileset dir="${build.lib}"> <include name="phoenix-containerkit.jar"/> @@ -827,7 +829,7 @@ <mkdir dir="${build.javadocs}"/> <javadoc packagenames="org.apache.*" - sourcepath="${java.dir}:${compat.dir}" + sourcepath="${java.dir}:${compat.dir}:${api.dir}" destdir="${build.javadocs}"> <classpath refid="project.class.path" /> <doclet name="com.sun.tools.doclets.standard.Standard"> @@ -890,10 +892,10 @@ <copy todir="${build.docs}/api" filtering="off"> <fileset dir="${build.javadocs}"/> </copy> - + <copy todir="../avalon-site/docs/phoenix" filtering="off"> <fileset dir="${build.docs}"/> - </copy> + </copy> </target> 1.1 avalon-phoenix/src/api/org/apache/avalon/phoenix/ApplicationEvent.java Index: ApplicationEvent.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.phoenix; import java.util.EventObject; import org.apache.avalon.phoenix.metadata.SarMetaData; /** * This is the class that is used to deliver notifications * about Application state changes to the * <code>ApplicationListener</code>s of a Server Application. * * @author <a href="mailto:peter at apache.org">Peter Donald</a> */ public final class ApplicationEvent extends EventObject { private final String m_name; private final SarMetaData m_sarMetaData; /** * Construct the <code>ApplicationEvent</code>. * * @param name the name of app * @param sarMetaData the SarMetaData object for app */ public ApplicationEvent( final String name, final SarMetaData sarMetaData ) { super( name ); if( null == name ) { throw new NullPointerException( "name" ); } if( null == sarMetaData ) { throw new NullPointerException( "sarMetaData" ); } m_name = name; m_sarMetaData = sarMetaData; } /** * Retrieve name of app. * * @return the name of app */ public String getName() { return m_name; } /** * Retrieve the SarMetaData for app. * * @return the SarMetaData for app */ public SarMetaData getSarMetaData() { return m_sarMetaData; } } 1.1 avalon-phoenix/src/api/org/apache/avalon/phoenix/ApplicationListener.java Index: ApplicationListener.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.phoenix; import java.util.EventListener; /** * Implementations of this interface receive notifications about * changes to the state of Application. * The implementation <em>must</em> have a zero argument * constructor and is instantiated before any other component of the Server * Application. To receive notification events, the implementation class * should be specified in the <tt>assembly.xml</tt> descriptor. * * @author <a href="mailto:peter at apache.org">Peter Donald</a> */ public interface ApplicationListener extends EventListener, BlockListener { /** * Notification that a block has just been added * to Server Application. * * @param event the BlockEvent */ void blockAdded( BlockEvent event ); /** * Notification that a block is just about to be * removed from Server Application. * * @param event the BlockEvent */ void blockRemoved( BlockEvent event ); /** * Notification that an application is being started. * * @param applicationEvent the ApplicationEvent * */ void applicationStarting( ApplicationEvent applicationEvent ) throws Exception; /** * Notification that an application has now started. */ void applicationStarted(); /** * Notification that an application is being stopped. */ void applicationStopping(); /** * Notification that an application has stopped. */ void applicationStopped(); /** * Notification that an application has failed at some moment. * This is for information only as Phoenix will do the right * thing for correct shutdown both before and after this method * is called. The user of this method should NOT call System.exit() * * @param causeOfFailure */ void applicationFailure( Exception causeOfFailure ); } 1.1 avalon-phoenix/src/api/org/apache/avalon/phoenix/BlockContext.java Index: BlockContext.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.phoenix; import java.io.File; import java.io.InputStream; import org.apache.avalon.framework.context.Context; import org.apache.avalon.framework.logger.Logger; /** * Context via which Blocks communicate with container. * * @author <a href="mailto:peter at apache.org">Peter Donald</a> */ public interface BlockContext extends Context { String APP_NAME = "app.name"; String APP_HOME_DIR = "app.home"; String NAME = "block.name"; /** * Base directory of .sar application. * * TODO: Should this be getHomeDirectory() or getWorkingDirectory() or other? * TODO: Should a Block be able to declare it doesn't use the Filesystem? If * it declares this then it would be an error to call this method. * * @return the base directory */ File getBaseDirectory(); /** * Retrieve name of block. * * @return the name of block */ String getName(); /** * A block can request that the application it resides in be * shut down. This method will schedule the blocks application * for shutdown. Note that this is just a request and the kernel * may or may not honour the request (by default the request will * be honored). */ void requestShutdown(); /** * Retrieve a resource from the SAR file. The specified * name is relative the root of the archive. So you could * use it to retrieve a html page from within sar by loading * the resource named "data/main.html" or similar. * Names may be prefixed with '/' character. * * @param name the name of resource * @return the InputStream for resource or null if no such resource */ InputStream getResourceAsStream( String name ); /** * Retrieve logger coresponding to named category. * * @return the logger * @deprecated This allows block writers to "break-out" of their logging * hierarchy which is considered bad form. Replace by * Logger.getChildLogger(String) where original logger is aquired * via AbstractLogEnabled. */ Logger getLogger( String name ); /** * This method gives the block access to a named [EMAIL PROTECTED] ClassLoader}. * The [EMAIL PROTECTED] ClassLoader}s for an application are declared in the * <tt>environment.xml</tt> descriptor. See the Specification for details. * * @param name the name of the classloader * @return the classloader * @throws Exception if no such [EMAIL PROTECTED] ClassLoader} */ ClassLoader getClassLoader( String name ) throws Exception; /** * Retrieve the proxy for this object. * Each Block is referenced by other Blocks via their Proxy. When Phoenix * shuts down the Block, it can automatically invalidate the proxy. Thus * any attempt to call a method on a "dead"/shutdown object will result in * an [EMAIL PROTECTED] IllegalStateException}. This is desirable as it will * stop objects from using the Block when it is in an invalid state. * * <p>The proxy also allows Phoenix to associate "Context" information with * the object. For instance, a Block may expect to run with a * specific ContextClassLoader set. However if this Block were to be passed * to another component that processed the Block in a thread that did not * have the correct context information setup, then the Block could fail * to perform as expected. By passing the proxy instead, the correct context * information is maintained by Phoenix.</p> * * <p>Note that only interfaces that the Block declares as offered services * will actually be implemented by the proxy.</p> */ //Object getProxy(); /** * This method is similar to [EMAIL PROTECTED] #getProxy()} except that it operates * on arbitrary objects. It will in effect proxy all interfaces that the * component supports. * * <p>Proxying arbitrary objects is useful for the same reason it is useful * to proxy the Block. Thus it is recomended that when needed you pass * Proxys of objects to minimize the chance of incorrect behaviour.</p> */ //Object getProxy( Object other ); /** * This method generates a Proxy of the specified object using the * specified interfaces. In other respects it is identical to * getProxy( Object other ) */ //Object getProxy( Object other, Class[] interfaces ); /** * Retrieve the MBeanServer for this application. * * NOTE: Unsure if this will ever be implemented * may be retrievable via CM instead, or perhaps in * a directory or whatever. */ //MBeanServer getMBeanServer(); } 1.1 avalon-phoenix/src/api/org/apache/avalon/phoenix/BlockEvent.java Index: BlockEvent.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.phoenix; import java.util.EventObject; import org.apache.avalon.phoenix.metainfo.BlockInfo; /** * This is the class that is used to deliver notifications * about Blocks state changes to the [EMAIL PROTECTED] org.apache.avalon.phoenix.BlockListener}s * of a Server Application. * * @author <a href="mailto:peter at apache.org">Peter Donald</a> */ public final class BlockEvent extends EventObject { private final String m_name; private final Object m_block; private final BlockInfo m_blockInfo; /** * Construct the <tt>BlockEvent</tt>. * * @param name the name of block * @param block the block object * @param blockInfo the BlockInfo object for block */ public BlockEvent( final String name, final Object block, final BlockInfo blockInfo ) { super( name ); if( null == name ) { throw new NullPointerException( "name" ); } if( null == block ) { throw new NullPointerException( "block" ); } if( null == blockInfo ) { throw new NullPointerException( "blockInfo" ); } m_name = name; m_block = block; m_blockInfo = blockInfo; } /** * Retrieve name of block. * * @return the name of block */ public String getName() { return m_name; } /** * Retrieve the block instance. * * @return the block instance */ public Object getObject() { return m_block; } /** * Retrieve the block instance. * * @return the block instance * @deprecated Use getObject() instead as this may * cause a ClassCastException */ public Block getBlock() { return (Block)getObject(); } /** * Retrieve the BlockInfo for block. * * @return the BlockInfo for block */ public BlockInfo getBlockInfo() { return m_blockInfo; } } 1.1 avalon-phoenix/src/api/org/apache/avalon/phoenix/package.html Index: package.html =================================================================== <html><body> Avalon Phoenix is a powerful scalable program that uses all the other main Avalon packages. It acts as a Container for applications built on top of the Avalon Framework, allowing dynamic loading and unloading of those applications. </body></html> 1.1 avalon-phoenix/src/api/org/apache/avalon/phoenix/metadata/BlockListenerMetaData.java Index: BlockListenerMetaData.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.phoenix.metadata; /** * This describs a BlockListener. * * @author <a href="mailto:peter at apache.org">Peter Donald</a> */ public final class BlockListenerMetaData { private final String m_name; private final String m_implementationKey; public BlockListenerMetaData( final String name, final String implementationKey ) { m_name = name; m_implementationKey = implementationKey; } public String getImplementationKey() { return m_implementationKey; } /** * @deprecated Use getImplementationKey() instead. */ public String getClassname() { return getImplementationKey(); } public String getName() { return m_name; } } 1.1 avalon-phoenix/src/api/org/apache/avalon/phoenix/metadata/BlockMetaData.java Index: BlockMetaData.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.phoenix.metadata; import org.apache.avalon.phoenix.metainfo.BlockInfo; /** * This is the structure describing each block. * * @author <a href="mailto:peter at apache.org">Peter Donald</a> */ public class BlockMetaData { private final String m_name; private final DependencyMetaData[] m_dependencies; private final boolean m_disableProxy; private final BlockInfo m_blockInfo; public BlockMetaData( final String name, final DependencyMetaData[] dependencies, final boolean disableProxy, final BlockInfo blockInfo ) { m_name = name; m_dependencies = dependencies; m_disableProxy = disableProxy; m_blockInfo = blockInfo; } public String getName() { return m_name; } /** * @deprecated Please use [EMAIL PROTECTED] #getImplementationKey} instead. */ public String getClassname() { return getImplementationKey(); } public String getImplementationKey() { return getBlockInfo().getBlockDescriptor().getImplementationKey(); } public BlockInfo getBlockInfo() { return m_blockInfo; } public DependencyMetaData getDependency( final String name ) { for( int i = 0; i < m_dependencies.length; i++ ) { if( m_dependencies[ i ].getRole().equals( name ) ) { return m_dependencies[ i ]; } } return null; } public DependencyMetaData[] getDependencies() { return m_dependencies; } public boolean isDisableProxy() { return m_disableProxy; } } 1.1 avalon-phoenix/src/api/org/apache/avalon/phoenix/metadata/DependencyMetaData.java Index: DependencyMetaData.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.phoenix.metadata; /** * This is the structure describing the instances of roles provided to each block. * * @author <a href="mailto:peter at apache.org">Peter Donald</a> */ public final class DependencyMetaData { private final String m_name; private final String m_role; private final String m_alias; public DependencyMetaData( final String name, final String role, final String alias ) { m_name = name; m_alias = alias; m_role = role; } public String getRole() { return m_role; } public String getName() { return m_name; } public String getAlias() { return m_alias; } } 1.1 avalon-phoenix/src/api/org/apache/avalon/phoenix/metadata/SarMetaData.java Index: SarMetaData.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.phoenix.metadata; import java.io.File; /** * MetaData for the application. * * @author <a href="mailto:peter at apache.org">Peter Donald</a> */ public class SarMetaData { private final String m_name; private final File m_homeDirectory; private final BlockMetaData[] m_blocks; private final BlockListenerMetaData[] m_listeners; public SarMetaData( final String name, final File homeDirectory, final BlockMetaData[] blocks, final BlockListenerMetaData[] listeners ) { m_name = name; m_homeDirectory = homeDirectory; m_blocks = blocks; m_listeners = listeners; } public String getName() { return m_name; } public File getHomeDirectory() { return m_homeDirectory; } public BlockMetaData[] getBlocks() { return m_blocks; } public BlockListenerMetaData[] getListeners() { return m_listeners; } } 1.1 avalon-phoenix/src/api/org/apache/avalon/phoenix/metadata/package.html Index: package.html =================================================================== <html><body> Block listeners and service dependency meta data. </body></html> 1.1 avalon-phoenix/src/api/org/apache/avalon/phoenix/metainfo/BlockDescriptor.java Index: BlockDescriptor.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.phoenix.metainfo; import org.apache.avalon.framework.Version; /** * * @author <a href="mailto:peter at apache.org">Peter Donald</a> */ public class BlockDescriptor { /** * The short name of the Block. Useful for displaying * human readable strings describing the type in * assembly tools or generators. */ private final String m_name; private final String m_implementationKey; private final Version m_version; private final String m_schemaType; public BlockDescriptor( final String name, final String implementationKey, final String schemaType, final Version version ) { m_name = name; m_implementationKey = implementationKey; m_version = version; m_schemaType = schemaType; } /** * Retrieve the name of Block type. * * @return the name of Block type. */ public String getName() { return m_name; } /** * Retrieve the Class Name of Block. * * @return the Class Name of block * @see #getImplementationKey * @deprecated Deprecated and replaced by [EMAIL PROTECTED] #getImplementationKey} */ public String getClassname() { return getImplementationKey(); } /** * Retrieve the implementation key for the Block. * Usually the keys is a classname. * * @return the implementation key for the Block */ public String getImplementationKey() { return m_implementationKey; } /** * Retrieve Version of current Block. * * @return the version of block */ public Version getVersion() { return m_version; } /** * Retrieve the Schema Type of Block * * @return the Schema Type of block */ public String getSchemaType() { return m_schemaType; } } 1.1 avalon-phoenix/src/api/org/apache/avalon/phoenix/metainfo/BlockInfo.java Index: BlockInfo.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.phoenix.metainfo; /** * This class contains meta-information of use to administative * tools and the kernel. It describes the services offered by a type * of block, the dependencies of the block, the management interface of * block (if any) and also contains information useful to presenting * information in administative screens (like human readable names etc). * * @author <a href="mailto:peter at apache.org">Peter Donald</a> */ public class BlockInfo { private final BlockDescriptor m_descriptor; private final ServiceDescriptor[] m_services; private final ServiceDescriptor[] m_managementAccessPoints; private final DependencyDescriptor[] m_dependencies; /** * Basic constructor that takes as parameters all parts. */ public BlockInfo( final BlockDescriptor descriptor, final ServiceDescriptor[] services, final ServiceDescriptor[] managementAccessPoints, final DependencyDescriptor[] dependencies ) { m_descriptor = descriptor; m_services = services; m_managementAccessPoints = managementAccessPoints; m_dependencies = dependencies; } /** * Return meta information that is generallly only required by administration tools. * * It should be loaded on demand and not always present in memory. * * @return the BlockDescriptor */ public BlockDescriptor getBlockDescriptor() { return m_descriptor; } /** * This returns a list of Services that this block exports. * * @return an array of Services */ public ServiceDescriptor[] getServices() { return m_services; } /** * This returns a list of Services that this block can be Managed by. * * @return an array of Management Access Points (management services) */ public ServiceDescriptor[] getManagementAccessPoints() { return m_managementAccessPoints; } /** * Return an array of Service dependencies that this Block depends upon. * * @return an array of Service dependencies */ public DependencyDescriptor[] getDependencies() { return m_dependencies; } /** * Retrieve a dependency with a particular role. * * @param role the role * @return the dependency or null if it does not exist */ public DependencyDescriptor getDependency( final String role ) { for( int i = 0; i < m_dependencies.length; i++ ) { if( m_dependencies[ i ].getRole().equals( role ) ) { return m_dependencies[ i ]; } } return null; } } 1.1 avalon-phoenix/src/api/org/apache/avalon/phoenix/metainfo/DependencyDescriptor.java Index: DependencyDescriptor.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.phoenix.metainfo; /** * A descriptor that describes dependency information for Block. * * @author <a href="mailto:peter at apache.org">Peter Donald</a> */ public final class DependencyDescriptor { private final String m_role; private final ServiceDescriptor m_service; /** * Constructor that has all parts as parameters. */ public DependencyDescriptor( final String role, final ServiceDescriptor service ) { m_role = role; m_service = service; } /** * Return role of dependency. * * The role is what is used by block implementor to * aquire dependency in ComponentManager. * * @return the name of the dependency */ public String getRole() { return m_role; } /** * Return Service dependency provides. * * @return the service dependency provides */ public ServiceDescriptor getService() { return m_service; } public String toString() { return "Dependency[" + getRole() + "::" + getService() + "]"; } } 1.1 avalon-phoenix/src/api/org/apache/avalon/phoenix/metainfo/ServiceDescriptor.java Index: ServiceDescriptor.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.phoenix.metainfo; import org.apache.avalon.framework.Version; /** * This class describes the meta info of a service offered by a Block. * Each service is defined by an interface name and the version of that * interface. * * @author <a href="mailto:peter at apache.org">Peter Donald</a> */ public final class ServiceDescriptor { public static final String ARRAY_POSTFIX = org.apache.avalon.framework.info.DependencyDescriptor.ARRAY_POSTFIX; public static final String MAP_POSTFIX = org.apache.avalon.framework.info.DependencyDescriptor.MAP_POSTFIX; private final Version m_version; private final String m_name; /** * Construct a service with specified name and version. * * @param name the name of the service * @param version the version of service */ public ServiceDescriptor( final String name, final Version version ) { m_name = name; m_version = version; } /** * Return the version of interface * * @return the version of interface */ public Version getVersion() { return m_version; } /** * Return name of Service (which coresponds to the interface * name eg org.apache.block.WebServer) * * @return the name of the Service */ public String getName() { return m_name; } /** * Return the type of component type if the service * is an array or Map Service. Otherwise just return the * name of service. * * @return the Service component type */ public String getComponentType() { final String fullname = getName(); if( isArray() ) { final int end = fullname.length() - ARRAY_POSTFIX.length(); return fullname.substring( 0, end ); } else if( isMap() ) { final int end = fullname.length() - MAP_POSTFIX.length(); return fullname.substring( 0, end ); } else { return fullname; } } /** * Return true if Service name designates an array of services. * * @return true if Service name designates an array of services. */ public boolean isArray() { return m_name.endsWith( ARRAY_POSTFIX ); } /** * Return true if Service name designates an map of services. * * @return true if Service name designates an map of services. */ public boolean isMap() { return m_name.endsWith( MAP_POSTFIX ); } /** * Determine if specified service will match this service. * To match a service has to have same name and must comply with version. * * @param other the other ServiceInfo * @return true if matches, false otherwise */ public boolean matches( final ServiceDescriptor other ) { final String name = getComponentType(); return other.getName().equals( name ) && other.getVersion().complies( m_version ); } /** * Convert to a string of format name/version * * @return string describing service */ public String toString() { return m_name + "/" + m_version; } } 1.1 avalon-phoenix/src/api/org/apache/avalon/phoenix/metainfo/package.html Index: package.html =================================================================== <html><body> Block, service and dependency descriptors. </body></html>
--------------------------------------------------------------------- To unsubscribe, e-mail: [EMAIL PROTECTED] For additional commands, e-mail: [EMAIL PROTECTED]