[jboss-osgi-commits] JBoss-OSGI SVN: r89545 - in projects/jboss-osgi/trunk: bundles/common/src/main/java/org/jboss/osgi/common/service and 5 other directories.
jboss-osgi-commits at lists.jboss.org
jboss-osgi-commits at lists.jboss.org
Sat May 30 06:24:43 EDT 2009
Author: thomas.diesler at jboss.com
Date: 2009-05-30 06:24:42 -0400 (Sat, 30 May 2009)
New Revision: 89545
Removed:
projects/jboss-osgi/trunk/bundles/common/src/main/java/org/jboss/osgi/common/internal/DeployerServiceTracker.java
Modified:
projects/jboss-osgi/trunk/bundles/common/src/main/java/org/jboss/osgi/common/internal/CommonServicesActivator.java
projects/jboss-osgi/trunk/bundles/common/src/main/java/org/jboss/osgi/common/internal/SimpleDeployerService.java
projects/jboss-osgi/trunk/bundles/common/src/main/java/org/jboss/osgi/common/service/DeployerService.java
projects/jboss-osgi/trunk/bundles/common/src/main/java/org/jboss/osgi/common/service/DeployerServiceDelegate.java
projects/jboss-osgi/trunk/bundles/microcontainer/src/main/java/org/jboss/osgi/microcontainer/internal/MicrocontainerServiceImpl.java
projects/jboss-osgi/trunk/runtime/equinox/src/main/resources/osgi-deployers-jboss-beans.xml
projects/jboss-osgi/trunk/runtime/felix/src/main/resources/osgi-deployers-jboss-beans.xml
projects/jboss-osgi/trunk/runtime/knopflerfish/src/main/resources/osgi-deployers-jboss-beans.xml
projects/jboss-osgi/trunk/spi/src/main/java/org/jboss/osgi/spi/testing/capability/HuskyCapability.java
Log:
DeployerServiceDelegate uses provider=microcontainer and falls back provider=system
Modified: projects/jboss-osgi/trunk/bundles/common/src/main/java/org/jboss/osgi/common/internal/CommonServicesActivator.java
===================================================================
--- projects/jboss-osgi/trunk/bundles/common/src/main/java/org/jboss/osgi/common/internal/CommonServicesActivator.java 2009-05-30 00:02:39 UTC (rev 89544)
+++ projects/jboss-osgi/trunk/bundles/common/src/main/java/org/jboss/osgi/common/internal/CommonServicesActivator.java 2009-05-30 10:24:42 UTC (rev 89545)
@@ -23,6 +23,8 @@
//$Id$
+import java.util.Properties;
+
import javax.management.JMException;
import javax.management.MBeanServer;
import javax.management.StandardMBean;
@@ -54,6 +56,12 @@
// Track LogReaderService and add/remove LogListener
trackLogReaderService(context);
+ // Register the system DeployerService
+ Properties props = new Properties();
+ props.setProperty("provider", "system");
+ SimpleDeployerService service = new SimpleDeployerService(context);
+ context.registerService(DeployerService.class.getName(), service, props);
+
// Register the DeployerServiceDelegate
DeployerServiceDelegate delegate = new DeployerServiceDelegate(context);
context.registerService(DeployerServiceDelegate.class.getName(), delegate, null);
Deleted: projects/jboss-osgi/trunk/bundles/common/src/main/java/org/jboss/osgi/common/internal/DeployerServiceTracker.java
===================================================================
--- projects/jboss-osgi/trunk/bundles/common/src/main/java/org/jboss/osgi/common/internal/DeployerServiceTracker.java 2009-05-30 00:02:39 UTC (rev 89544)
+++ projects/jboss-osgi/trunk/bundles/common/src/main/java/org/jboss/osgi/common/internal/DeployerServiceTracker.java 2009-05-30 10:24:42 UTC (rev 89545)
@@ -1,77 +0,0 @@
-/*
- * JBoss, Home of Professional Open Source
- * Copyright 2005, JBoss Inc., and individual contributors as indicated
- * by the @authors tag. See the copyright.txt in the distribution for a
- * full listing of individual contributors.
- *
- * This is free software; you can redistribute it and/or modify it
- * under the terms of the GNU Lesser General Public License as
- * published by the Free Software Foundation; either version 2.1 of
- * the License, or (at your option) any later version.
- *
- * This software is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public
- * License along with this software; if not, write to the Free
- * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
- * 02110-1301 USA, or see the FSF site: http://www.fsf.org.
- */
-package org.jboss.osgi.common.internal;
-
-//$Id$
-
-import org.jboss.osgi.common.log.LogServiceTracker;
-import org.jboss.osgi.common.service.DeployerService;
-import org.osgi.framework.BundleContext;
-import org.osgi.framework.ServiceReference;
-import org.osgi.service.log.LogService;
-import org.osgi.util.tracker.ServiceTracker;
-
-/**
- * A {@link ServiceTracker} that tracks the {@link DeployerService}.
- * In case there is not such service registered, it returns an instance
- * of {@link SimpleDeployerService}
- *
- * @author thomas.diesler at jboss.com
- * @since 27-May-2009
- */
-public class DeployerServiceTracker extends ServiceTracker
-{
- private LogServiceTracker log;
- private BundleContext context;
-
- public DeployerServiceTracker(BundleContext context)
- {
- super(context, DeployerService.class.getName(), null);
- this.log = new LogServiceTracker(context);
- this.context = context;
- }
-
- @Override
- public Object addingService(ServiceReference reference)
- {
- DeployerService service = (DeployerService)super.addingService(reference);
- log.log(LogService.LOG_INFO, "Adding DeployerService: " + service.getClass().getName());
- return service;
- }
-
- @Override
- public void removedService(ServiceReference reference, Object service)
- {
- log.log(LogService.LOG_INFO, "Removing DeployerService: " + service.getClass().getName());
- super.removedService(reference, service);
- }
-
- @Override
- public DeployerService getService()
- {
- DeployerService service = (DeployerService)super.getService();
- if (service == null)
- service = new SimpleDeployerService(context);
-
- return service;
- }
-}
\ No newline at end of file
Modified: projects/jboss-osgi/trunk/bundles/common/src/main/java/org/jboss/osgi/common/internal/SimpleDeployerService.java
===================================================================
--- projects/jboss-osgi/trunk/bundles/common/src/main/java/org/jboss/osgi/common/internal/SimpleDeployerService.java 2009-05-30 00:02:39 UTC (rev 89544)
+++ projects/jboss-osgi/trunk/bundles/common/src/main/java/org/jboss/osgi/common/internal/SimpleDeployerService.java 2009-05-30 10:24:42 UTC (rev 89545)
@@ -95,7 +95,7 @@
}
}
- public void undeploy(BundleInfo[] bundleInfos) throws Exception
+ public void undeploy(BundleInfo[] bundleInfos) throws BundleException
{
for (BundleInfo info : bundleInfos)
undeploy(info.getLocation());
@@ -104,7 +104,7 @@
// Note, in contrary to deploy(BundleInfo[]) this
// method does not start the bundle. The client
// is expected to do that
- public void deploy(URL url) throws Exception
+ public void deploy(URL url) throws BundleException
{
Bundle bundle = context.installBundle(url.toExternalForm());
log.log(LogService.LOG_INFO, "Installed: " + bundle);
@@ -112,7 +112,7 @@
registerManagedBundle(bundle);
}
- public void undeploy(URL url) throws Exception
+ public boolean undeploy(URL url) throws BundleException
{
Bundle bundle = deployments.remove(url.toExternalForm());
if (bundle != null)
@@ -120,10 +120,12 @@
unregisterManagedBundle(bundle);
bundle.uninstall();
log.log(LogService.LOG_INFO, "Uninstalled: " + bundle);
+ return true;
}
else
{
log.log(LogService.LOG_WARNING, "Cannot find bundle for: " + url);
+ return false;
}
}
Modified: projects/jboss-osgi/trunk/bundles/common/src/main/java/org/jboss/osgi/common/service/DeployerService.java
===================================================================
--- projects/jboss-osgi/trunk/bundles/common/src/main/java/org/jboss/osgi/common/service/DeployerService.java 2009-05-30 00:02:39 UTC (rev 89544)
+++ projects/jboss-osgi/trunk/bundles/common/src/main/java/org/jboss/osgi/common/service/DeployerService.java 2009-05-30 10:24:42 UTC (rev 89545)
@@ -26,41 +26,49 @@
import javax.management.ObjectName;
import org.jboss.osgi.spi.management.ObjectNameFactory;
+import org.osgi.framework.BundleException;
//$Id$
-
/**
- * A Service that can be used to deploy bundles or archives
- * to the runtime.
+ * A Service that can be used to deploy/undeploy bundles or archives to/from the runtime.
*
* @author thomas.diesler at jboss.com
* @since 23-Jan-2009
*/
public interface DeployerService
{
- /**
- * The object name under which this is registered: 'jboss.osgi:service=DeployerService'
+ /**
+ * The object name under which this is registered: 'jboss.osgi:service=DeployerService'
*/
ObjectName MBEAN_DEPLOYER_SERVICE = ObjectNameFactory.create("jboss.osgi:service=DeployerService");
-
+
/**
* Deploy an array of bundles
*/
- void deploy(BundleInfo[] bundles) throws Exception;
+ void deploy(BundleInfo[] bundles) throws BundleException;
/**
* Undeploy an array of bundles
*/
- void undeploy(BundleInfo[] bundles) throws Exception;
+ void undeploy(BundleInfo[] bundles) throws BundleException;
- /**
- * Deploy MC beans from URL
+ /**
+ * Deploy bundle from URL
*/
- void deploy(URL url) throws Exception;
+ void deploy(URL url) throws BundleException;
/**
- * Undeploy MC beans from URL
+ * Undeploy bundle from URL.
+ *
+ * Note, due to the dynamic nature of OSGi services it is
+ * possible that a {@link DeployerService} is asked to undeploy
+ * a bundle URL which it did not deploy itself.
+ *
+ * In this case this method should return false, so that the
+ * {@link DeployerServiceDelegate} can use another {@link DeployerService}
+ *
+ * @return true if thhis service could undeploy the bundle
*/
- void undeploy(URL url) throws Exception;
+ boolean undeploy(URL url) throws BundleException;
}
\ No newline at end of file
Modified: projects/jboss-osgi/trunk/bundles/common/src/main/java/org/jboss/osgi/common/service/DeployerServiceDelegate.java
===================================================================
--- projects/jboss-osgi/trunk/bundles/common/src/main/java/org/jboss/osgi/common/service/DeployerServiceDelegate.java 2009-05-30 00:02:39 UTC (rev 89544)
+++ projects/jboss-osgi/trunk/bundles/common/src/main/java/org/jboss/osgi/common/service/DeployerServiceDelegate.java 2009-05-30 10:24:42 UTC (rev 89545)
@@ -24,17 +24,15 @@
//$Id$
import java.net.URL;
-import java.util.HashMap;
-import java.util.Map;
-import org.jboss.osgi.common.internal.DeployerServiceTracker;
import org.jboss.osgi.common.log.LogServiceTracker;
import org.osgi.framework.BundleContext;
-import org.osgi.service.log.LogService;
+import org.osgi.framework.BundleException;
+import org.osgi.framework.InvalidSyntaxException;
+import org.osgi.framework.ServiceReference;
/**
- * A {@link DeployerService} that delegates to the service that is tracked
- * by the given {@link DeployerServiceTracker}
+ * A {@link DeployerService} that delegates to the service that is tracked by the given {@link DeployerServiceTracker}
*
* This delegate is registered as an MBean
*
@@ -44,50 +42,86 @@
public class DeployerServiceDelegate implements DeployerService
{
private LogServiceTracker log;
+ private BundleContext context;
- private DeployerServiceTracker tracker;
- private Map<String, DeployerService> serviceMap = new HashMap<String, DeployerService>();
-
public DeployerServiceDelegate(BundleContext context)
{
- log = new LogServiceTracker(context);
-
- tracker = new DeployerServiceTracker(context);
- tracker.open();
+ this.log = new LogServiceTracker(context);
+ this.context = context;
}
- public void deploy(BundleInfo[] bundles) throws Exception
+ public void deploy(BundleInfo[] bundles) throws BundleException
{
- DeployerService service = tracker.getService();
- for (BundleInfo info : bundles)
- serviceMap.put(info.getLocation().toString(), service);
-
+ DeployerService service = getDefaultDeployerService();
service.deploy(bundles);
}
- public void deploy(URL url) throws Exception
+ public void deploy(URL url) throws BundleException
{
- DeployerService service = tracker.getService();
- serviceMap.put(url.toString(), service);
+ DeployerService service = getDefaultDeployerService();
service.deploy(url);
}
- public void undeploy(BundleInfo[] bundles) throws Exception
+ public void undeploy(BundleInfo[] bundles) throws BundleException
{
for (BundleInfo info : bundles)
undeploy(info.getLocation());
}
- public void undeploy(URL url) throws Exception
+ public boolean undeploy(URL url) throws BundleException
{
- DeployerService service = serviceMap.remove(url.toString());
+ boolean undeployed = false;
+
+ DeployerService service = getMicrocontainerDeployerService();
if (service != null)
+ undeployed = service.undeploy(url);
+
+ if (undeployed == false)
{
- service.undeploy(url);
+ service = getSystemDeployerService();
+ undeployed = service.undeploy(url);
}
- else
+
+ return undeployed;
+ }
+
+ private DeployerService getDefaultDeployerService()
+ {
+ // First try the MC provider
+ DeployerService service = getMicrocontainerDeployerService();
+
+ // Fall back to the system provider
+ if (service == null)
+ service = getSystemDeployerService();
+
+ return service;
+ }
+
+ private DeployerService getMicrocontainerDeployerService()
+ {
+ DeployerService service = null;
+
+ try
{
- log.log(LogService.LOG_WARNING, "Cannot find DeployerService for: " + url);
+ String filter = "(provider=microcontainer)";
+ String serviceName = DeployerService.class.getName();
+ ServiceReference[] srefs = context.getServiceReferences(serviceName, filter);
+ if (srefs != null)
+ service = (DeployerService)context.getService(srefs[0]);
}
+ catch (InvalidSyntaxException ex)
+ {
+ throw new IllegalArgumentException(ex);
+ }
+
+ return service;
}
+
+ private DeployerService getSystemDeployerService()
+ {
+ String serviceName = DeployerService.class.getName();
+ ServiceReference sref = context.getServiceReference(serviceName);
+ return (DeployerService)context.getService(sref);
+ }
+
}
\ No newline at end of file
Modified: projects/jboss-osgi/trunk/bundles/microcontainer/src/main/java/org/jboss/osgi/microcontainer/internal/MicrocontainerServiceImpl.java
===================================================================
--- projects/jboss-osgi/trunk/bundles/microcontainer/src/main/java/org/jboss/osgi/microcontainer/internal/MicrocontainerServiceImpl.java 2009-05-30 00:02:39 UTC (rev 89544)
+++ projects/jboss-osgi/trunk/bundles/microcontainer/src/main/java/org/jboss/osgi/microcontainer/internal/MicrocontainerServiceImpl.java 2009-05-30 10:24:42 UTC (rev 89545)
@@ -23,13 +23,13 @@
//$Id$
-import java.io.IOException;
import java.net.URL;
import java.util.ArrayList;
import java.util.Collections;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
+import java.util.Properties;
import javax.management.MBeanServer;
import javax.management.StandardMBean;
@@ -43,7 +43,6 @@
import org.jboss.dependency.spi.ControllerState;
import org.jboss.deployers.client.spi.Deployment;
import org.jboss.deployers.client.spi.main.MainDeployer;
-import org.jboss.deployers.spi.DeploymentException;
import org.jboss.deployers.vfs.spi.client.VFSDeployment;
import org.jboss.deployers.vfs.spi.client.VFSDeploymentFactory;
import org.jboss.kernel.Kernel;
@@ -58,6 +57,7 @@
import org.jboss.virtual.VFS;
import org.jboss.virtual.VirtualFile;
import org.osgi.framework.BundleContext;
+import org.osgi.framework.BundleException;
import org.osgi.framework.ServiceReference;
import org.osgi.service.log.LogService;
import org.osgi.util.tracker.ServiceTracker;
@@ -112,7 +112,7 @@
return context != null ? context.getTarget() : null;
}
- public void deploy(BundleInfo[] bundles) throws Exception
+ public void deploy(BundleInfo[] bundles) throws BundleException
{
ClassLoader ctxLoader = Thread.currentThread().getContextClassLoader();
try
@@ -137,44 +137,80 @@
Deployment[] depArr = deployments.toArray(new Deployment[deployments.size()]);
mainDeployer.checkComplete(depArr);
}
- catch (IOException ex)
+ catch (RuntimeException rte)
{
- DeploymentException.rethrowAsDeploymentException("Cannot deploy bundles: ", ex);
+ throw rte;
}
+ catch (Exception ex)
+ {
+ throw new BundleException("Cannot deploy bundles", ex);
+ }
finally
{
Thread.currentThread().setContextClassLoader(ctxLoader);
}
}
- public void undeploy(BundleInfo[] bundles) throws Exception
+ public void undeploy(BundleInfo[] bundles) throws BundleException
{
- MainDeployer mainDeployer = (MainDeployer)getRegisteredBean("MainDeployer");
- for (BundleInfo bundle : bundles)
+ try
{
- String deploymentName = contextMap.remove(bundle.getLocation());
- if (deploymentName != null)
+ MainDeployer mainDeployer = (MainDeployer)getRegisteredBean("MainDeployer");
+ for (BundleInfo bundle : bundles)
{
- mainDeployer.removeDeployment(deploymentName);
+ String deploymentName = contextMap.remove(bundle.getLocation());
+ if (deploymentName != null)
+ {
+ mainDeployer.removeDeployment(deploymentName);
+ }
+ else
+ {
+ log.log(LogService.LOG_WARNING, "Package not deployed: " + bundle.getLocation());
+ }
}
- else
- {
- log.log(LogService.LOG_WARNING, "Package not deployed: " + bundle.getLocation());
- }
+ mainDeployer.process();
}
- mainDeployer.process();
+ catch (RuntimeException rte)
+ {
+ throw rte;
+ }
+ catch (Exception ex)
+ {
+ log.log(LogService.LOG_WARNING, "Cannot undeploy bundles", ex);
+ }
}
- public void deploy(URL url) throws Exception
+ public void deploy(URL url) throws BundleException
{
BundleInfo info = new LocationOnlyBundleInfo(url);
deploy(new BundleInfo[] { info });
}
- public void undeploy(URL url) throws Exception
+ public boolean undeploy(URL url) throws BundleException
{
- BundleInfo info = new LocationOnlyBundleInfo(url);
- undeploy(new BundleInfo[] { info });
+ String deploymentName = contextMap.remove(url);
+ if (deploymentName == null)
+ {
+ log.log(LogService.LOG_WARNING, "Package not deployed: " + url);
+ return false;
+ }
+
+ try
+ {
+ MainDeployer mainDeployer = (MainDeployer)getRegisteredBean("MainDeployer");
+ mainDeployer.removeDeployment(deploymentName);
+ mainDeployer.process();
+ return true;
+ }
+ catch (RuntimeException rte)
+ {
+ throw rte;
+ }
+ catch (Exception ex)
+ {
+ log.log(LogService.LOG_WARNING, "Cannot undeploy bundle", ex);
+ return false;
+ }
}
void start()
@@ -208,8 +244,10 @@
context.registerService(MicrocontainerService.class.getName(), mcServiceImpl, null);
// Register the DeployerService
+ Properties props = new Properties();
+ props.setProperty("provider", "microcontainer");
log.log(LogService.LOG_DEBUG, "Register DeployerService");
- context.registerService(DeployerService.class.getName(), mcServiceImpl, null);
+ context.registerService(DeployerService.class.getName(), mcServiceImpl, props);
// Register the MicrocontainerServiceMBean
registerMicrocontainerServiceMBean(mbeanServer);
Modified: projects/jboss-osgi/trunk/runtime/equinox/src/main/resources/osgi-deployers-jboss-beans.xml
===================================================================
--- projects/jboss-osgi/trunk/runtime/equinox/src/main/resources/osgi-deployers-jboss-beans.xml 2009-05-30 00:02:39 UTC (rev 89544)
+++ projects/jboss-osgi/trunk/runtime/equinox/src/main/resources/osgi-deployers-jboss-beans.xml 2009-05-30 10:24:42 UTC (rev 89545)
@@ -29,10 +29,11 @@
javax.management,
javax.xml.parsers,
org.jboss.logging,
- org.jboss.osgi.spi.service,
- org.jboss.osgi.spi.management,
- org.jboss.osgi.spi.testing,
- org.jboss.osgi.spi.testing.capability,
+ org.jboss.osgi.spi;version=1.0,
+ org.jboss.osgi.spi.logging;version=1.0,
+ org.jboss.osgi.spi.management;version=1.0,
+ org.jboss.osgi.spi.testing;version=1.0,
+ org.jboss.osgi.spi.testing.capability;version=1.0,
org.osgi.framework; version=1.4,
org.osgi.service.packageadmin; version=1.2,
org.osgi.service.startlevel; version=1.1,
Modified: projects/jboss-osgi/trunk/runtime/felix/src/main/resources/osgi-deployers-jboss-beans.xml
===================================================================
--- projects/jboss-osgi/trunk/runtime/felix/src/main/resources/osgi-deployers-jboss-beans.xml 2009-05-30 00:02:39 UTC (rev 89544)
+++ projects/jboss-osgi/trunk/runtime/felix/src/main/resources/osgi-deployers-jboss-beans.xml 2009-05-30 10:24:42 UTC (rev 89545)
@@ -30,11 +30,11 @@
org.jboss.osgi.jndi,
org.jboss.osgi.jmx,
org.jboss.osgi.microcontainer,
- org.jboss.osgi.spi,
- org.jboss.osgi.spi.logging,
- org.jboss.osgi.spi.management,
- org.jboss.osgi.spi.testing,
- org.jboss.osgi.spi.testing.capability,
+ org.jboss.osgi.spi;version=1.0,
+ org.jboss.osgi.spi.logging;version=1.0,
+ org.jboss.osgi.spi.management;version=1.0,
+ org.jboss.osgi.spi.testing;version=1.0,
+ org.jboss.osgi.spi.testing.capability;version=1.0,
org.jboss.xb.binding;version=2.0,
org.jboss.xb.binding.sunday.unmarshalling;version=2.0,
Modified: projects/jboss-osgi/trunk/runtime/knopflerfish/src/main/resources/osgi-deployers-jboss-beans.xml
===================================================================
--- projects/jboss-osgi/trunk/runtime/knopflerfish/src/main/resources/osgi-deployers-jboss-beans.xml 2009-05-30 00:02:39 UTC (rev 89544)
+++ projects/jboss-osgi/trunk/runtime/knopflerfish/src/main/resources/osgi-deployers-jboss-beans.xml 2009-05-30 10:24:42 UTC (rev 89545)
@@ -28,10 +28,11 @@
javax.management,
javax.xml.parsers,
org.jboss.logging,
- org.jboss.osgi.spi.service,
- org.jboss.osgi.spi.management,
- org.jboss.osgi.spi.testing,
- org.jboss.osgi.spi.testing.capability,
+ org.jboss.osgi.spi;version=1.0,
+ org.jboss.osgi.spi.logging;version=1.0,
+ org.jboss.osgi.spi.management;version=1.0,
+ org.jboss.osgi.spi.testing;version=1.0,
+ org.jboss.osgi.spi.testing.capability;version=1.0,
org.osgi.framework; version=1.4,
org.osgi.service.packageadmin; version=1.2,
org.osgi.service.startlevel; version=1.1,
Modified: projects/jboss-osgi/trunk/spi/src/main/java/org/jboss/osgi/spi/testing/capability/HuskyCapability.java
===================================================================
--- projects/jboss-osgi/trunk/spi/src/main/java/org/jboss/osgi/spi/testing/capability/HuskyCapability.java 2009-05-30 00:02:39 UTC (rev 89544)
+++ projects/jboss-osgi/trunk/spi/src/main/java/org/jboss/osgi/spi/testing/capability/HuskyCapability.java 2009-05-30 10:24:42 UTC (rev 89545)
@@ -38,6 +38,7 @@
// [TODO] make this a reference
super("org.jboss.osgi.husky.runtime.Connector");
+ addBundles(new JMXCapability().getBundles());
addBundle("bundles/jboss-osgi-husky.jar");
}
}
\ No newline at end of file
More information about the jboss-osgi-commits
mailing list