[jboss-svn-commits] JBossWS SVN: r1086 - in branches/jbossws-1.0.3.SP1/src: main/java/org/jboss/ws/tools test/java/org/jboss/test/ws/tools/fixture test/java/org/jboss/test/ws/tools/jbws_206/tests/UserException test/resources/tools/jbws-206/wscompileArtifacts/UserException/sei test/resources/tools/jbws-206/wscompileArtifacts/UserException/usertypes test/resources/tools/jbws-206/wsdlFixture/UserException

jboss-svn-commits at lists.jboss.org jboss-svn-commits at lists.jboss.org
Thu Sep 28 04:21:36 EDT 2006


Author: thomas.diesler at jboss.com
Date: 2006-09-28 04:21:26 -0400 (Thu, 28 Sep 2006)
New Revision: 1086

Added:
   branches/jbossws-1.0.3.SP1/src/test/resources/tools/jbws-206/wscompileArtifacts/UserException/usertypes/AnonymousException.java
   branches/jbossws-1.0.3.SP1/src/test/resources/tools/jbws-206/wscompileArtifacts/UserException/usertypes/MyFaultType.java
Modified:
   branches/jbossws-1.0.3.SP1/src/main/java/org/jboss/ws/tools/WSDLToJava.java
   branches/jbossws-1.0.3.SP1/src/test/java/org/jboss/test/ws/tools/fixture/JBossSourceComparator.java
   branches/jbossws-1.0.3.SP1/src/test/java/org/jboss/test/ws/tools/jbws_206/tests/UserException/UserExceptionWSDL2JavaTestCase.java
   branches/jbossws-1.0.3.SP1/src/test/resources/tools/jbws-206/wscompileArtifacts/UserException/sei/UserExceptionSEI.java
   branches/jbossws-1.0.3.SP1/src/test/resources/tools/jbws-206/wsdlFixture/UserException/UserExceptionService_RPC_11.wsdl
Log:
[JBWS-1193] [JBWS-1153] Fixes for class names of exceptions representing faults

Modified: branches/jbossws-1.0.3.SP1/src/main/java/org/jboss/ws/tools/WSDLToJava.java
===================================================================
--- branches/jbossws-1.0.3.SP1/src/main/java/org/jboss/ws/tools/WSDLToJava.java	2006-09-28 08:16:31 UTC (rev 1085)
+++ branches/jbossws-1.0.3.SP1/src/main/java/org/jboss/ws/tools/WSDLToJava.java	2006-09-28 08:21:26 UTC (rev 1086)
@@ -36,7 +36,6 @@
 import org.apache.xerces.xs.XSComplexTypeDefinition;
 import org.apache.xerces.xs.XSElementDeclaration;
 import org.apache.xerces.xs.XSModelGroup;
-import org.apache.xerces.xs.XSObject;
 import org.apache.xerces.xs.XSObjectList;
 import org.apache.xerces.xs.XSParticle;
 import org.apache.xerces.xs.XSSimpleTypeDefinition;
@@ -196,7 +195,7 @@
    public void setPackageNamespaceMap(Map<String, String> map)
    {
      //Lets convert the package->namespace map to namespace->package map
-     Set keys = map.keySet();
+     Set<String> keys = map.keySet();
      Iterator<String> iter = keys.iterator();
      while(iter != null && iter.hasNext())
      {
@@ -409,14 +408,12 @@
                XSTypeDefinition xt = xsmodel.getTypeDefinition(xmlType.getLocalPart(), xmlType.getNamespaceURI());
 
                boolean primitive = true;
-               WrappedArray wrappedArray = new WrappedArray(xt);
-               String arraySuffix = "";
+               WrappedArray wrappedArray = new WrappedArray(xt);               
                if (wrappedArray.unwrap())
                {
                   xt = wrappedArray.xt;
                   xmlType = wrappedArray.xmlType;
-                  primitive = !wrappedArray.nillable;
-                  arraySuffix = wrappedArray.suffix;
+                  primitive = !wrappedArray.nillable;                  
                }
 
                if (xt instanceof XSSimpleTypeDefinition)
@@ -450,7 +447,14 @@
 
             Class cl = getJavaType(faultXMLType, false);
             if (cl == null)
-               buf.append(seiPkgName + "." + cleanUpFaultName(faultXMLType.getLocalPart()));
+            {
+               String exceptionName = xt.getName();
+               if (exceptionName==null)
+               {
+                  exceptionName = faultXMLName.getLocalPart();
+               }
+               buf.append(seiPkgName + "." + utils.firstLetterUpperCase(exceptionName));
+            }
             else
                buf.append( cl.getName());
             buf.append( "," );
@@ -593,33 +597,6 @@
    }
 
    /**
-    * WSDL may have appended the Faults with 'Fault' or 'Error'
-    * @param faultname
-    * @return
-    */
-   private String cleanUpFaultName(String faultname)
-   {
-      //Clean up the faultname from Error and Fault
-      boolean endsfault = faultname.endsWith("Fault");
-
-      if (endsfault)
-      {
-         int index = faultname.lastIndexOf("Fault");
-         faultname = faultname.substring(0, index);
-      }
-      else
-      {
-         boolean endsError = faultname.endsWith("Error");
-         if (endsError)
-         {
-            int index = faultname.lastIndexOf("Error");
-            faultname = faultname.substring(0, index);
-         }
-      }
-      return faultname;
-   }
-
-   /**
     * Check if an holder is required for the input type
     * @param wout
     * @param cls

Modified: branches/jbossws-1.0.3.SP1/src/test/java/org/jboss/test/ws/tools/fixture/JBossSourceComparator.java
===================================================================
--- branches/jbossws-1.0.3.SP1/src/test/java/org/jboss/test/ws/tools/fixture/JBossSourceComparator.java	2006-09-28 08:16:31 UTC (rev 1085)
+++ branches/jbossws-1.0.3.SP1/src/test/java/org/jboss/test/ws/tools/fixture/JBossSourceComparator.java	2006-09-28 08:21:26 UTC (rev 1086)
@@ -1,33 +1,26 @@
 /*
-  * 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.
-  */
+ * 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.test.ws.tools.fixture;
 
-import com.thoughtworks.qdox.JavaDocBuilder;
-import com.thoughtworks.qdox.model.AbstractJavaEntity;
-import com.thoughtworks.qdox.model.JavaClass;
-import com.thoughtworks.qdox.model.JavaField;
-import com.thoughtworks.qdox.model.JavaSource;
-import org.jboss.logging.Logger;
-
 import java.io.File;
 import java.io.FileNotFoundException;
 import java.io.FileReader;
@@ -37,6 +30,16 @@
 import java.util.Comparator;
 import java.util.List;
 
+import org.jboss.logging.Logger;
+
+import com.thoughtworks.qdox.JavaDocBuilder;
+import com.thoughtworks.qdox.model.AbstractJavaEntity;
+import com.thoughtworks.qdox.model.JavaClass;
+import com.thoughtworks.qdox.model.JavaField;
+import com.thoughtworks.qdox.model.JavaMethod;
+import com.thoughtworks.qdox.model.JavaSource;
+import com.thoughtworks.qdox.model.Type;
+
 /**
  *  Compares whether two Java source files are identical
  *  Uses QDox.  [Based on APITestCase of QDox Testsuite]
@@ -56,8 +59,7 @@
     * don't implement Comparable
     */
 
-   private static Comparator ENTITY_COMPARATOR = new Comparator()
-   {
+   private static Comparator ENTITY_COMPARATOR = new Comparator() {
       public int compare(Object obj1, Object obj2)
       {
          AbstractJavaEntity entity1 = (AbstractJavaEntity)obj1;
@@ -68,7 +70,8 @@
 
    public JBossSourceComparator()
    {
-      if (builder == null) builder = new JavaDocBuilder();
+      if (builder == null)
+         builder = new JavaDocBuilder();
    }
 
    public JBossSourceComparator(File dir)
@@ -78,8 +81,7 @@
 
    }
 
-   public JBossSourceComparator(String file1, String file2)
-           throws Exception
+   public JBossSourceComparator(String file1, String file2) throws Exception
    {
       this();
       try
@@ -94,8 +96,7 @@
       }
    }
 
-   public JBossSourceComparator(File file1, File file2)
-           throws Exception
+   public JBossSourceComparator(File file1, File file2) throws Exception
    {
       this();
       try
@@ -122,13 +123,13 @@
     * java.util.* and java.util.Vector are not exact types.
     * @throws Exception
     */
-   public void validateImports()
-           throws Exception
+   public void validateImports() throws Exception
    {
       String[] imp1 = source1.getImports();
       String[] imp2 = source2.getImports();
 
-      if (imp1 == null && imp2 == null) return;
+      if (imp1 == null && imp2 == null)
+         return;
       if (imp1 == null && imp2 != null)
          throw new Exception("Imports are not equal");
       if (imp1 != null && imp2 == null)
@@ -148,8 +149,7 @@
     * @return
     * @throws Exception
     */
-   public boolean validate()
-           throws Exception
+   public boolean validate() throws Exception
    {
       boolean result = true;
       if (source1 == null)
@@ -163,16 +163,15 @@
          validateAPI(source1, source2);
       }
       catch (Exception e)
-      { 
-         log.error("Validation Failed:", e); 
+      {
+         log.error("Validation Failed:", e);
          result = false;
          throw e;
       }
       return result;
    }
 
-   public boolean validateAPI(JavaSource expected, JavaSource actual)
-           throws Exception
+   public boolean validateAPI(JavaSource expected, JavaSource actual) throws Exception
    {
       boolean result = false;
       List expectedClasses = Arrays.asList(expected.getClasses());
@@ -186,31 +185,25 @@
 
       for (int i = 0; i < expectedClasses.size(); i++)
       {
-         checkClassesEqual((JavaClass)expectedClasses.get(i),
-                 (JavaClass)actualClasses.get(i));
+         checkClassesEqual((JavaClass)expectedClasses.get(i), (JavaClass)actualClasses.get(i));
       }
 
       return result;
    }
 
-   private void checkClassesEqual(JavaClass expected,
-                                  JavaClass actual)
-           throws Exception
+   private void checkClassesEqual(JavaClass expected, JavaClass actual) throws Exception
    {
       if (!expected.getPackage().equals(actual.getPackage()))
          throw new Exception("Package names should be equal");
-      checkModifiersEquals("Class modifiers should be equal", expected,
-              actual);
+      checkModifiersEquals("Class modifiers should be equal", expected, actual);
       if (!expected.getName().equals(actual.getName()))
          throw new Exception("Class names should be equal");
-      if ((expected.getSuperJavaClass() != null)
-              && (actual.getSuperJavaClass() != null))
+      if ((expected.getSuperJavaClass() != null) && (actual.getSuperJavaClass() != null))
       {
          if (!expected.getSuperJavaClass().getName().equals(actual.getSuperJavaClass().getName()))
             throw new Exception("Super class should be equal");
       }
-      if ((expected.getSuperJavaClass() == null)
-              ^ (actual.getSuperJavaClass() == null))
+      if ((expected.getSuperJavaClass() == null) ^ (actual.getSuperJavaClass() == null))
       {
          throw new Exception("Super class should be equal");
       }
@@ -221,10 +214,7 @@
 
    }
 
-
-   private void checkFieldEquals(JavaField expected,
-                                 JavaField actual)
-           throws Exception
+   private void checkFieldEquals(JavaField expected, JavaField actual) throws Exception
    {
       StringBuffer message = new StringBuffer("-> checkFieldEquals");
       message.append(" Expected : ");
@@ -241,8 +231,7 @@
       checkModifiersEquals(message.toString() + "Field modifiers should be equal", expected, actual);
    }
 
-   private void checkFieldsEqual(JavaClass expected, JavaClass actual)
-           throws Exception
+   private void checkFieldsEqual(JavaClass expected, JavaClass actual) throws Exception
    {
       List expectedFields = Arrays.asList(expected.getFields());
       Collections.sort(expectedFields, ENTITY_COMPARATOR);
@@ -260,15 +249,11 @@
 
       for (int i = 0; i < expectedFields.size(); i++)
       {
-         checkFieldEquals((JavaField)expectedFields.get(i),
-                 (JavaField)actualFields.get(i));
+         checkFieldEquals((JavaField)expectedFields.get(i), (JavaField)actualFields.get(i));
       }
    }
 
-
-   private void checkInnerClassesEquals(JavaClass expected,
-                                        JavaClass actual)
-           throws Exception
+   private void checkInnerClassesEquals(JavaClass expected, JavaClass actual) throws Exception
    {
       List expectedInnerClasses = Arrays.asList(expected.getInnerClasses());
       Collections.sort(expectedInnerClasses, ENTITY_COMPARATOR);
@@ -285,15 +270,12 @@
          throw new Exception(message.toString() + "Number of inner classes should be equal");
       for (int i = 0; i < expectedInnerClasses.size(); i++)
       {
-         checkClassesEqual((JavaClass)expectedInnerClasses.get(i),
-                 (JavaClass)actualInnerClasses.get(i));
+         checkClassesEqual((JavaClass)expectedInnerClasses.get(i), (JavaClass)actualInnerClasses.get(i));
       }
 
    }
 
-   private void checkInterfacesEqual(JavaClass expected,
-                                     JavaClass actual)
-           throws Exception
+   private void checkInterfacesEqual(JavaClass expected, JavaClass actual) throws Exception
    {
       List expectedImplements = Arrays.asList(expected.getImplements());
       Collections.sort(expectedImplements);
@@ -315,8 +297,7 @@
       }
    }
 
-   private void checkMethodsEqual(JavaClass expected, JavaClass actual)
-           throws Exception
+   private void checkMethodsEqual(JavaClass expected, JavaClass actual) throws Exception
    {
       List expectedMethods = Arrays.asList(expected.getMethods());
       Collections.sort(expectedMethods, ENTITY_COMPARATOR);
@@ -333,17 +314,49 @@
          throw new Exception(message.toString() + "Number of methods should be equal");
       for (int i = 0; i < expectedMethods.size(); i++)
       {
-         if (!expectedMethods.get(i).equals(actualMethods.get(i)))
-            throw new Exception("Method "  + expectedMethods.get(i) +  
-                  "and " + actualMethods.get(i) + " should be equal");
+         JavaMethod expectedMethod = (JavaMethod)expectedMethods.get(i);
+         JavaMethod actualMethod = (JavaMethod)actualMethods.get(i);
+
+         if (expectedMethod.equals(actualMethod) == false)
+         {
+            throw new Exception("Method " + expectedMethod + "and " + actualMethod + " should be equal");
+         }
+
+         checkExceptionsEqual(expectedMethod, actualMethod);
       }
+   }
 
+   private void checkExceptionsEqual(JavaMethod expected, JavaMethod actual) throws Exception
+   {
+      List expectedExceptions = Arrays.asList(expected.getExceptions());
+      Collections.sort(expectedExceptions);
+      List actualExceptions = Arrays.asList(actual.getExceptions());
+      Collections.sort(actualExceptions);
+
+      StringBuffer message = new StringBuffer("-> checkExceptionsEqual");
+      message.append(" Expected : ");
+      message.append(expectedExceptions);
+      message.append(" Actual : ");
+      message.append(actualExceptions);
+
+      if (expectedExceptions.size() != actualExceptions.size())
+      {
+         throw new Exception(message + " Number of exceptions should be equal");
+      }
+
+      for (int j = 0; j < expectedExceptions.size(); j++)
+      {
+         Type expectedException = (Type)expectedExceptions.get(j);
+         Type actualException = (Type)actualExceptions.get(j);
+
+         if (expectedException.equals(actualException) == false)
+         {
+            throw new Exception("Exception " + expectedException + " and " + actualException + " should be equal for method " + expected);
+         }
+      }
    }
 
-   private void checkModifiersEquals(String msg,
-                                     AbstractJavaEntity expected,
-                                     AbstractJavaEntity actual)
-           throws Exception
+   private void checkModifiersEquals(String msg, AbstractJavaEntity expected, AbstractJavaEntity actual) throws Exception
    {
 
       List expectedModifiers = Arrays.asList(expected.getModifiers());

Modified: branches/jbossws-1.0.3.SP1/src/test/java/org/jboss/test/ws/tools/jbws_206/tests/UserException/UserExceptionWSDL2JavaTestCase.java
===================================================================
--- branches/jbossws-1.0.3.SP1/src/test/java/org/jboss/test/ws/tools/jbws_206/tests/UserException/UserExceptionWSDL2JavaTestCase.java	2006-09-28 08:16:31 UTC (rev 1085)
+++ branches/jbossws-1.0.3.SP1/src/test/java/org/jboss/test/ws/tools/jbws_206/tests/UserException/UserExceptionWSDL2JavaTestCase.java	2006-09-28 08:21:26 UTC (rev 1086)
@@ -54,5 +54,7 @@
    {  
       checkUserType( "CustomException.java");
       checkUserType( "MyException.java"); 
+      checkUserType( "AnonymousException.java");
+      checkUserType( "MyFaultType.java");
    } 
 }

Modified: branches/jbossws-1.0.3.SP1/src/test/resources/tools/jbws-206/wscompileArtifacts/UserException/sei/UserExceptionSEI.java
===================================================================
--- branches/jbossws-1.0.3.SP1/src/test/resources/tools/jbws-206/wscompileArtifacts/UserException/sei/UserExceptionSEI.java	2006-09-28 08:16:31 UTC (rev 1085)
+++ branches/jbossws-1.0.3.SP1/src/test/resources/tools/jbws-206/wscompileArtifacts/UserException/sei/UserExceptionSEI.java	2006-09-28 08:21:26 UTC (rev 1086)
@@ -10,4 +10,8 @@
         org.jboss.test.webservice.userexception.CustomException,  java.rmi.RemoteException;
     public void testUserException(java.lang.String string_1) throws 
         org.jboss.test.webservice.userexception.MyException,  java.rmi.RemoteException;
+    public void testAnonymousException(java.lang.String string_1) throws 
+        org.jboss.test.webservice.userexception.AnonymousException,  java.rmi.RemoteException;
+    public void testMyFaultType() throws 
+        org.jboss.test.webservice.userexception.MyFaultType,  java.rmi.RemoteException;
 }

Copied: branches/jbossws-1.0.3.SP1/src/test/resources/tools/jbws-206/wscompileArtifacts/UserException/usertypes/AnonymousException.java (from rev 1085, branches/jbossws-1.0.3.GA_JBWS-1193/src/test/resources/tools/jbws-206/wscompileArtifacts/UserException/usertypes/AnonymousException.java)

Copied: branches/jbossws-1.0.3.SP1/src/test/resources/tools/jbws-206/wscompileArtifacts/UserException/usertypes/MyFaultType.java (from rev 1085, branches/jbossws-1.0.3.GA_JBWS-1193/src/test/resources/tools/jbws-206/wscompileArtifacts/UserException/usertypes/MyFaultType.java)

Modified: branches/jbossws-1.0.3.SP1/src/test/resources/tools/jbws-206/wsdlFixture/UserException/UserExceptionService_RPC_11.wsdl
===================================================================
--- branches/jbossws-1.0.3.SP1/src/test/resources/tools/jbws-206/wsdlFixture/UserException/UserExceptionService_RPC_11.wsdl	2006-09-28 08:16:31 UTC (rev 1085)
+++ branches/jbossws-1.0.3.SP1/src/test/resources/tools/jbws-206/wsdlFixture/UserException/UserExceptionService_RPC_11.wsdl	2006-09-28 08:21:26 UTC (rev 1086)
@@ -22,8 +22,21 @@
 			<complexType name="MyException">
 				<sequence />
 			</complexType>
+            <xsd:complexType name="MyFaultType">
+                <xsd:sequence>
+                    <xsd:element name="message" type="string"/>
+                </xsd:sequence>
+            </xsd:complexType>			
 			<element name="CustomException" type="tns:CustomException" />
 			<element name="MyException" type="tns:MyException" />
+            <element name="MyFault" type="tns:MyFaultType"/>						
+			<element name="anonymousException">
+				<complexType>
+					<sequence>
+						<element type="string" name="message"/>
+					</sequence>
+				</complexType>
+			</element>
 		</schema>
 	</types>
 	<message name="UserExceptionSEI_testCustomException" />
@@ -38,6 +51,18 @@
 	<message name="MyException">
 		<part name="MyException" element="ns2:MyException" />
 	</message>
+	<message name="UserExceptionSEI_testAnonymousException">
+		<part name="String_1" type="xsd:string" />
+	</message>
+    <message name="UserExceptionSEI_testAnonymousExceptionResponse" />
+    <message name="AnonymousException">
+        <part name="AnonymousException" element="ns2:anonymousException"/>
+    </message>
+    <message name="UserExceptionSEI_testMyFaultType"/>
+    <message name="UserExceptionSEI_testMyFaultTypeResponse"/>
+    <message name="MyFault">
+        <part name="MyFault" element="ns2:MyFault"/>
+    </message>
 	<portType name="UserExceptionSEI">
 		<operation name="testCustomException">
 			<input message="tns:UserExceptionSEI_testCustomException" />
@@ -51,6 +76,18 @@
 				message="tns:UserExceptionSEI_testUserExceptionResponse" />
 			<fault name="MyException" message="tns:MyException" />
 		</operation>
+		<operation name="testAnonymousException" parameterOrder="String_1">
+			<input message="tns:UserExceptionSEI_testAnonymousException" />
+			<output
+				message="tns:UserExceptionSEI_testAnonymousExceptionResponse" />
+			<fault name="AnonymousException" message="tns:AnonymousException" />
+		</operation>
+		<operation name="testMyFaultType">
+		    <input message="tns:UserExceptionSEI_testMyFaultType" />
+		    <output
+		        message="tns:UserExceptionSEI_testMyFaultTypeResponse" />
+		    <fault name="MyFault" message="tns:MyFault" />
+		</operation>
 	</portType>
 	<binding name="UserExceptionSEIBinding"
 		type="tns:UserExceptionSEI">
@@ -84,6 +121,34 @@
 				<soap:fault name="MyException" use="literal" />
 			</fault>
 		</operation>
+		<operation name="testAnonymousException">
+			<soap:operation soapAction="" />
+			<input>
+				<soap:body use="literal"
+					namespace="http://org.jboss.ws" />
+			</input>
+			<output>
+				<soap:body use="literal"
+					namespace="http://org.jboss.ws" />
+			</output>
+			<fault name="AnonymousException">
+				<soap:fault name="AnonymousException" use="literal" />
+			</fault>
+		</operation>
+		<operation name="testMyFaultType">
+			<soap:operation soapAction="" />
+			<input>
+				<soap:body use="literal"
+					namespace="http://org.jboss.ws" />
+			</input>
+			<output>
+				<soap:body use="literal"
+					namespace="http://org.jboss.ws" />
+			</output>
+			<fault name="MyFault">
+				<soap:fault name="MyFault" use="literal" />
+			</fault>
+		</operation>		
 	</binding>
 	<service name="UserExceptionService">
 		<port name="UserExceptionSEIPort"




More information about the jboss-svn-commits mailing list