commits@javamail.java.net

[javamail~mercurial:169] Updates from Jason.

From: <shannon_at_kenai.com>
Date: Wed, 16 Sep 2009 20:51:49 +0000

Project: javamail
Repository: mercurial
Revision: 169
Author: shannon
Date: 2009-09-16 20:34:49 UTC
Link:

Log Message:
------------
Add MailSSLSocketFactory to javadocs.
Remove no longer needed HK2 kludge.
Add package javadocs for com.sun.mail.util package.
Move FindBugs configuration to mail/pom.xml.
Need to export com.sun.mail.handlers package too so JAF can find the handlers.
mailapi.jar needs to export com.sun.mail.util and com.sun.mail.handlers.
Remove unneeded imports.
Added new MailHandler, contributed by Jason Mehrens.
Updates from Jason.


Revisions:
----------
161
162
163
164
165
166
167
168
169


Modified Paths:
---------------
javadoc/pom.xml
pom.xml
mail/pom.xml
mailapi/pom.xml
demo/src/main/java/msgsend.java
demo/src/main/java/msgshow.java
assembly.xml
build.properties
build.xml
doc/release/CHANGES.txt
doc/release/README.txt
mail/src/main/java/com/sun/mail/util/logging/MailHandler.java
mail/src/test/java/com/sun/mail/util/logging/MailHandlerTest.java


Added Paths:
------------
mail/src/main/java/com/sun/mail/util/package.html
logging/pom.xml
logging/src/main/java/FileErrorManager.java
logging/src/main/java/MailHandlerDemo.java
logging/src/main/java/README.txt
logging/src/main/java/SummaryFormatter.java
logging/src/main/java/SummaryNameFormatter.java
logging/src/main/java/maildemo.properties
mail/src/main/java/com/sun/mail/util/logging/LogManagerProperties.java
mail/src/main/java/com/sun/mail/util/logging/MailHandler.java
mail/src/main/java/com/sun/mail/util/logging/package.html
mail/src/test/java/com/sun/mail/util/logging/MailHandlerTest.java


Diffs:
------
diff -r fb5e9b99db4e -r 9122564f6ddb javadoc/pom.xml
--- a/javadoc/pom.xml Mon Aug 24 21:27:24 2009 -0700
+++ b/javadoc/pom.xml Tue Sep 01 14:01:20 2009 -0700
@@ -92,7 +92,7 @@
                         com/sun/mail/smtp/SMTPAddressSucceededException.java,
                         com/sun/mail/smtp/SMTPSendFailedException.java,
                         com/sun/mail/smtp/SMTPTransport.java,
- com/sun/mail/smtp/SMTPSSLTransport.java
+ com/sun/mail/smtp/SMTPSSLTransport.java,
                         com/sun/mail/util/MailSSLSocketFactory.java
                                         "/>
                                     <fileset dir="../dsn/src/main/java"
@@ -153,7 +153,7 @@
                                 </group>
                             </groups>
                             <subpackages>
-javax:com.sun.mail.imap:com.sun.mail.pop3:com.sun.mail.smtp:com.sun.mail.dsn
+javax:com.sun.mail.imap:com.sun.mail.pop3:com.sun.mail.smtp:com.sun.mail.dsn:com.sun.mail.util
                             </subpackages>
                             <!-- XXX - following should work, but doesn't -->
                             <excludePackageNames>


diff -r 9122564f6ddb -r 7b9dffc129b5 pom.xml
--- a/pom.xml Tue Sep 01 14:01:20 2009 -0700
+++ b/pom.xml Tue Sep 01 21:12:17 2009 -0700
@@ -172,16 +172,6 @@
                         <Private-Package>
                             ${mail.packages.private}
                         </Private-Package>
- <!--
- The following entry makes this jar an HK2 jar as
- well. This is needed because GlassFish currently
- picks up only OSGi bundles that have this entry.
- Remove this when GlassFish does not have this
- limitation.
- -->
- <HK2-Bundle-Name>
- ${project.groupId}:${project.artifactId}
- </HK2-Bundle-Name>
                     </instructions>
                 </configuration>
                 <!--


diff -r 7b9dffc129b5 -r 1348c55e330c mail/src/main/java/com/sun/mail/util/package.html
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/mail/src/main/java/com/sun/mail/util/package.html Wed Sep 02 14:45:53 2009 -0700
@@ -0,0 +1,58 @@
+<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 3.2 Final//EN">
+<HTML>
+<HEAD>
+<!--
+
+ DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER.
+
+ Copyright 1997-2008 Sun Microsystems, Inc. All rights reserved.
+
+ The contents of this file are subject to the terms of either the GNU
+ General Public License Version 2 only ("GPL") or the Common Development
+ and Distribution License("CDDL") (collectively, the "License"). You
+ may not use this file except in compliance with the License. You can obtain
+ a copy of the License at https://glassfish.dev.java.net/public/CDDL+GPL.html
+ or glassfish/bootstrap/legal/LICENSE.txt. See the License for the specific
+ language governing permissions and limitations under the License.
+
+ When distributing the software, include this License Header Notice in each
+ file and include the License file at glassfish/bootstrap/legal/LICENSE.txt.
+ Sun designates this particular file as subject to the "Classpath" exception
+ as provided by Sun in the GPL Version 2 section of the License file that
+ accompanied this code. If applicable, add the following below the License
+ Header, with the fields enclosed by brackets [] replaced by your own
+ identifying information: "Portions Copyrighted [year]
+ [name of copyright owner]"
+
+ Contributor(s):
+
+ If you wish your version of this file to be governed by only the CDDL or
+ only the GPL Version 2, indicate your decision by adding "[Contributor]
+ elects to include this software in this distribution under the [CDDL or GPL
+ Version 2] license." If you don't indicate a single choice of license, a
+ recipient has the option to distribute your version of this file under
+ either the CDDL, the GPL Version 2 or to extend the choice of license to
+ its licensees as provided above. However, if you add GPL Version 2 code
+ and therefore, elected the GPL Version 2 license, then the option applies
+ only if the new code is made subject to such option by the copyright
+ holder.
+
+
+-->
+
+</HEAD>
+<BODY BGCOLOR="white">
+
+Utility classes for use with the JavaMail API.
+These utility classes are not part of the JavaMail specification.
+While this package contains many classes used by the JavaMail implementation
+and not intended for direct use by applications, the classes documented
+here may be of use to applications.
+<P>
+<strong>WARNING:</strong> The APIs in this package should be
+considered <strong>EXPERIMENTAL</strong>. They may be changed in the
+future in ways that are incompatible with applications using the
+current APIs.
+
+</BODY>
+</HTML>


diff -r 1348c55e330c -r 741fce7507de mail/pom.xml
--- a/mail/pom.xml Wed Sep 02 14:45:53 2009 -0700
+++ b/mail/pom.xml Wed Sep 02 15:48:42 2009 -0700
@@ -76,18 +76,42 @@
                 <filtering>true</filtering>
             </resource>
         </resources>
+ <plugins>
+ <!--
+ Configure FindBugs to run with "mvn findbugs:findbugs"
+ and generate XML output that can be used by the Hudson
+ FindBugs plugin.
+ -->
+ <plugin>
+ <groupId>org.codehaus.mojo</groupId>
+ <artifactId>findbugs-maven-plugin</artifactId>
+ <configuration>
+ <skip>false</skip>
+ <threshold>Normal</threshold>
+ <excludeFilterFile>exclude.xml</excludeFilterFile>
+ <findbugsXmlOutput>true</findbugsXmlOutput>
+ <findbugsXmlWithMessages>true</findbugsXmlWithMessages>
+ </configuration>
+ </plugin>
+ </plugins>
     </build>
 
     <reporting>
         <plugins>
+ <!--
+ Configure FindBugs to run with "mvn site" and
+ generate html output that can be viewed directly.
+ -->
             <plugin>
                 <groupId>org.codehaus.mojo</groupId>
                 <artifactId>findbugs-maven-plugin</artifactId>
                 <configuration>
+ <skip>false</skip>
                     <threshold>Normal</threshold>
                     <excludeFilterFile>exclude.xml</excludeFilterFile>
                 </configuration>
             </plugin>
         </plugins>
     </reporting>
+
 </project>

diff -r 1348c55e330c -r 741fce7507de pom.xml
--- a/pom.xml Wed Sep 02 14:45:53 2009 -0700
+++ b/pom.xml Wed Sep 02 15:48:42 2009 -0700
@@ -285,6 +285,23 @@
 -->
         </plugins>
 
+ <pluginManagement>
+ <plugins>
+ <plugin>
+ <!--
+ By default, disable the FindBugs plugin for all modules.
+ It's enabled in the "mail" module, which is the only
+ module where we actually want to run it.
+ -->
+ <groupId>org.codehaus.mojo</groupId>
+ <artifactId>findbugs-maven-plugin</artifactId>
+ <configuration>
+ <skip>true</skip>
+ </configuration>
+ </plugin>
+ </plugins>
+ </pluginManagement>
+
         <extensions>
             <extension>
                 <groupId>org.jvnet.wagon-svn</groupId>


diff -r 741fce7507de -r 8e59536209d3 mail/pom.xml
--- a/mail/pom.xml Wed Sep 02 15:48:42 2009 -0700
+++ b/mail/pom.xml Wed Sep 02 15:50:08 2009 -0700
@@ -65,7 +65,8 @@
             com.sun.mail.imap; version=${mail.version},
             com.sun.mail.pop3; version=${mail.version},
             com.sun.mail.smtp; version=${mail.version},
- com.sun.mail.util; version=${mail.version}
+ com.sun.mail.util; version=${mail.version},
+ com.sun.mail.handlers; version=${mail.version}
         </mail.packages.export>
     </properties>
 


diff -r 8e59536209d3 -r 7d2aae547106 mailapi/pom.xml
--- a/mailapi/pom.xml Wed Sep 02 15:50:08 2009 -0700
+++ b/mailapi/pom.xml Wed Sep 02 15:52:08 2009 -0700
@@ -50,6 +50,14 @@
     <packaging>jar</packaging>
     <name>JavaMail API jar</name>
 
+ <properties>
+ <mail.packages.export>
+ javax.mail.*; version=${mail.spec.version},
+ com.sun.mail.util; version=${mail.version},
+ com.sun.mail.handlers; version=${mail.version}
+ </mail.packages.export>
+ </properties>
+
     <build>
         <plugins>
             <plugin>


diff -r 7d2aae547106 -r cfaa49a57246 demo/src/main/java/msgsend.java
--- a/demo/src/main/java/msgsend.java Wed Sep 02 15:52:08 2009 -0700
+++ b/demo/src/main/java/msgsend.java Wed Sep 09 18:14:03 2009 -0700
@@ -30,7 +30,6 @@
  */
 
 import java.io.*;
-import java.net.InetAddress;
 import java.util.Properties;
 import java.util.Date;
 

diff -r 7d2aae547106 -r cfaa49a57246 demo/src/main/java/msgshow.java
--- a/demo/src/main/java/msgshow.java Wed Sep 02 15:52:08 2009 -0700
+++ b/demo/src/main/java/msgshow.java Wed Sep 09 18:14:03 2009 -0700
@@ -34,7 +34,6 @@
 import javax.mail.*;
 import javax.mail.event.*;
 import javax.mail.internet.*;
-import javax.activation.*;
 
 /*
  * Demo app that exercises the Message interfaces.


diff -r cfaa49a57246 -r d4fa948c94c5 assembly.xml
--- a/assembly.xml Wed Sep 09 18:14:03 2009 -0700
+++ b/assembly.xml Thu Sep 10 14:57:45 2009 -0700
@@ -177,6 +177,22 @@
                 </fileSets>
             </sources>
         </moduleSet>
+
+ <moduleSet>
+ <includes>
+ <include>com.sun.mail:logging</include>
+ </includes>
+ <sources>
+ <includeModuleDirectory>false</includeModuleDirectory>
+ <fileSets>
+ <fileSet>
+ <directory>src/main/java</directory>
+ <outputDirectory>demo/logging</outputDirectory>
+ </fileSet>
+ </fileSets>
+ </sources>
+ </moduleSet>
+
     </moduleSets>
 
     <!-- include docs, specs, and javadocs -->

diff -r cfaa49a57246 -r d4fa948c94c5 build.properties
--- a/build.properties Wed Sep 09 18:14:03 2009 -0700
+++ b/build.properties Thu Sep 10 14:57:45 2009 -0700
@@ -1,22 +1,37 @@
 #
-# The contents of this file are subject to the terms
-# of the Common Development and Distribution License
-# (the "License"). You may not use this file except
-# in compliance with the License.
-#
-# You can obtain a copy of the license at
-# glassfish/bootstrap/legal/CDDLv1.0.txt or
-# https://glassfish.dev.java.net/public/CDDLv1.0.html.
-# See the License for the specific language governing
-# permissions and limitations under the License.
-#
-# When distributing Covered Code, include this CDDL
-# HEADER in each file and include the License file at
-# glassfish/bootstrap/legal/CDDLv1.0.txt. If applicable,
-# add the following below this CDDL HEADER, with the
-# fields enclosed by brackets "[]" replaced with your
-# own identifying information: Portions Copyright [yyyy]
-# [name of copyright owner]
+# DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER.
+#
+# Copyright 1997-2009 Sun Microsystems, Inc. All rights reserved.
+#
+# The contents of this file are subject to the terms of either the GNU
+# General Public License Version 2 only ("GPL") or the Common Development
+# and Distribution License("CDDL") (collectively, the "License"). You
+# may not use this file except in compliance with the License. You can obtain
+# a copy of the License at https://glassfish.dev.java.net/public/CDDL+GPL.html
+# or glassfish/bootstrap/legal/LICENSE.txt. See the License for the specific
+# language governing permissions and limitations under the License.
+#
+# When distributing the software, include this License Header Notice in each
+# file and include the License file at glassfish/bootstrap/legal/LICENSE.txt.
+# Sun designates this particular file as subject to the "Classpath" exception
+# as provided by Sun in the GPL Version 2 section of the License file that
+# accompanied this code. If applicable, add the following below the License
+# Header, with the fields enclosed by brackets [] replaced by your own
+# identifying information: "Portions Copyrighted [year]
+# [name of copyright owner]"
+#
+# Contributor(s):
+#
+# If you wish your version of this file to be governed by only the CDDL or
+# only the GPL Version 2, indicate your decision by adding "[Contributor]
+# elects to include this software in this distribution under the [CDDL or GPL
+# Version 2] license." If you don't indicate a single choice of license, a
+# recipient has the option to distribute your version of this file under
+# either the CDDL, the GPL Version 2 or to extend the choice of license to
+# its licensees as provided above. However, if you add GPL Version 2 code
+# and therefore, elected the GPL Version 2 license, then the option applies
+# only if the new code is made subject to such option by the copyright
+# holder.
 #
 
 ### Component Properties ###
@@ -56,6 +71,9 @@
 # taglib
 src.taglib.dir=taglib/src/main/java
 resources.taglib.dir=taglib/src/main/resources
+# logging
+src.logging.dir=logging/src/main/java
+component.classes.logging.dir=logging/target/classes
 # legal
 resources.legal.dir=legal/src/main/resources
 #

diff -r cfaa49a57246 -r d4fa948c94c5 build.xml
--- a/build.xml Wed Sep 09 18:14:03 2009 -0700
+++ b/build.xml Thu Sep 10 14:57:45 2009 -0700
@@ -2,7 +2,7 @@
 <!--
     DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER.
 
- Copyright 1997-2008 Sun Microsystems, Inc. All rights reserved.
+ Copyright 1997-2009 Sun Microsystems, Inc. All rights reserved.
 
     The contents of this file are subject to the terms of either the GNU
     General Public License Version 2 only ("GPL") or the Common Development
@@ -248,6 +248,23 @@
             <include name="*"/>
         </javac>
 
+ <mkdir dir="${component.classes.logging.dir}"/>
+ <javac srcdir="${src.logging.dir}"
+ destdir="${component.classes.logging.dir}"
+ debug="${javac.debug}"
+ optimize="${javac.optimize}"
+ source="${javac.source}"
+ deprecation="${javac.deprecation}"
+ failonerror="true"
+ target="${javac.target}">
+ <classpath>
+ <pathelement location="${component.classes.dir}"/>
+ <pathelement location="${component.classes.demo.dir}"/>
+ <pathelement location="${activation.jar}"/>
+ </classpath>
+ <include name="*"/>
+ </javac>
+
         <!-- XXX - still need to add rules to build webapp -->
 
     </target>
@@ -262,6 +279,7 @@
             <fileset dir="${component.classes.demo.dir}"/>
             <fileset dir="${component.classes.client.dir}"/>
             <fileset dir="${component.classes.servlet.dir}"/>
+ <fileset dir="${component.classes.logging.dir}"/>
         </delete>
     </target>
 
@@ -296,6 +314,8 @@
                 prefix="${rel}/demo/webapp/src/taglib"/>
             <zipfileset dir="${resources.taglib.dir}"
                 prefix="${rel}/demo/webapp/src/taglib"/>
+ <zipfileset dir="${src.logging.dir}"
+ prefix="${rel}/demo/logging"/>
         </zip>
     </target>
 

diff -r cfaa49a57246 -r d4fa948c94c5 doc/release/CHANGES.txt
--- a/doc/release/CHANGES.txt Wed Sep 09 18:14:03 2009 -0700
+++ b/doc/release/CHANGES.txt Thu Sep 10 14:57:45 2009 -0700
@@ -25,6 +25,7 @@
 <no id> better handle modifying messages created from input streams
 <no id> include server error message in exception when SMTP authentication fails
 <no id> InternetAddress verifies domain per RFC1034 instead of RFC822 in strict
+<no id> com.sun.mail.util.logging.MailLogHandler contributed by Jason Mehrens
 
 
                   CHANGES IN THE 1.4.2 RELEASE

diff -r cfaa49a57246 -r d4fa948c94c5 doc/release/README.txt
--- a/doc/release/README.txt Wed Sep 09 18:14:03 2009 -0700
+++ b/doc/release/README.txt Thu Sep 10 14:57:45 2009 -0700
@@ -128,6 +128,8 @@
                         web browser to read and send mail
     demo/servlet/README.txt
                         README file that describes the JavaMailServlet
+ demo/logging/ source files for demo program showing use of the
+ com.sun.mail.util.logging.MailHandler class
 
 
 Requirements

diff -r cfaa49a57246 -r d4fa948c94c5 javadoc/pom.xml
--- a/javadoc/pom.xml Wed Sep 09 18:14:03 2009 -0700
+++ b/javadoc/pom.xml Thu Sep 10 14:57:45 2009 -0700
@@ -93,7 +93,8 @@
                         com/sun/mail/smtp/SMTPSendFailedException.java,
                         com/sun/mail/smtp/SMTPTransport.java,
                         com/sun/mail/smtp/SMTPSSLTransport.java,
- com/sun/mail/util/MailSSLSocketFactory.java
+ com/sun/mail/util/MailSSLSocketFactory.java,
+ com/sun/mail/util/logging/MailHandler.java
                                         "/>
                                     <fileset dir="../dsn/src/main/java"
                                         includes="
@@ -153,7 +154,7 @@
                                 </group>
                             </groups>
                             <subpackages>
-javax:com.sun.mail.imap:com.sun.mail.pop3:com.sun.mail.smtp:com.sun.mail.dsn:com.sun.mail.util
+javax:com.sun.mail.imap:com.sun.mail.pop3:com.sun.mail.smtp:com.sun.mail.dsn:com.sun.mail.util:com.sun.mail.util.logging
                             </subpackages>
                             <!-- XXX - following should work, but doesn't -->
                             <excludePackageNames>
@@ -165,12 +166,8 @@
                             </additionalparam>
                             <sourcepath>${basedir}/target/javadoc</sourcepath>
                             <links>
- <link>
-http://java.sun.com/j2se/1.4.2/docs/api
- </link>
- <link>
-http://java.sun.com/javase/technologies/desktop/javabeans/glasgow/javadocs
- </link>
+ <link>http://java.sun.com/j2se/1.4.2/docs/api</link>
+ <link>http://java.sun.com/javase/technologies/desktop/javabeans/glasgow/javadocs</link>
                             </links>
                         </configuration>
                     </execution>

diff -r cfaa49a57246 -r d4fa948c94c5 logging/pom.xml
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/logging/pom.xml Thu Sep 10 14:57:45 2009 -0700
@@ -0,0 +1,64 @@
+<?xml version="1.0" encoding="iso-8859-1"?>
+<!--
+ DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER.
+
+ Copyright 1997-2009 Sun Microsystems, Inc. All rights reserved.
+
+ The contents of this file are subject to the terms of either the GNU
+ General Public License Version 2 only ("GPL") or the Common Development
+ and Distribution License("CDDL") (collectively, the "License"). You
+ may not use this file except in compliance with the License. You can obtain
+ a copy of the License at https://glassfish.dev.java.net/public/CDDL+GPL.html
+ or glassfish/bootstrap/legal/LICENSE.txt. See the License for the specific
+ language governing permissions and limitations under the License.
+
+ When distributing the software, include this License Header Notice in each
+ file and include the License file at glassfish/bootstrap/legal/LICENSE.txt.
+ Sun designates this particular file as subject to the "Classpath" exception
+ as provided by Sun in the GPL Version 2 section of the License file that
+ accompanied this code. If applicable, add the following below the License
+ Header, with the fields enclosed by brackets [] replaced by your own
+ identifying information: "Portions Copyrighted [year]
+ [name of copyright owner]"
+
+ Contributor(s):
+
+ If you wish your version of this file to be governed by only the CDDL or
+ only the GPL Version 2, indicate your decision by adding "[Contributor]
+ elects to include this software in this distribution under the [CDDL or GPL
+ Version 2] license." If you don't indicate a single choice of license, a
+ recipient has the option to distribute your version of this file under
+ either the CDDL, the GPL Version 2 or to extend the choice of license to
+ its licensees as provided above. However, if you add GPL Version 2 code
+ and therefore, elected the GPL Version 2 license, then the option applies
+ only if the new code is made subject to such option by the copyright
+ holder.
+-->
+
+<project xmlns="http://maven.apache.org/POM/4.0.0"
+ xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+ xsi:schemaLocation="http://maven.apache.org/POM/4.0.0
+ http://maven.apache.org/maven-v4_0_0.xsd">
+ <parent>
+ <groupId>com.sun.mail</groupId>
+ <artifactId>all</artifactId>
+ <version>1.4.3-SNAPSHOT</version>
+ </parent>
+ <modelVersion>4.0.0</modelVersion>
+ <groupId>com.sun.mail</groupId>
+ <artifactId>logging</artifactId>
+ <packaging>jar</packaging>
+ <name>JavaMail API logging demo</name>
+
+ <dependencies>
+ <dependency>
+ <groupId>javax.mail</groupId>
+ <artifactId>mail</artifactId>
+ </dependency>
+ <dependency>
+ <groupId>com.sun.mail</groupId>
+ <artifactId>demo</artifactId>
+ <version>1.4.3-SNAPSHOT</version>
+ </dependency>
+ </dependencies>
+</project>

diff -r cfaa49a57246 -r d4fa948c94c5 logging/src/main/java/FileErrorManager.java
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/logging/src/main/java/FileErrorManager.java Thu Sep 10 14:57:45 2009 -0700
@@ -0,0 +1,249 @@
+/*
+ * Copyright 2009 Sun Microsystems, Inc. All Rights Reserved.
+ * Copyright 2009 Jason Mehrens. All Rights Reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * - Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ *
+ * - Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * - Neither the name of Sun Microsystems nor the names of its
+ * contributors may be used to endorse or promote products derived
+ * from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS
+ * IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
+ * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
+ * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+ * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+ * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
+ * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
+ * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
+ * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+ * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+
+import java.io.*;
+import java.security.*;
+import java.util.logging.*;
+
+/**
+ * An error manager used to store mime messages from the <tt>MailHandler</tt>
+ * to the file system when the email server is unavailable or unreachable.
+ * The code to manually setup this error manager can be as simple as the
+ * following:
+ * <tt><pre>
+ * File dir = new File("path to dir");
+ * FileErrorManager em = new FileErrorManager(dir);
+ * </pre></tt>
+ *
+ * <p>
+ * <b>Configuration:</b>
+ * The code to setup this error manager via the logging properties
+ * can be as simple as the following:
+ * <tt><pre>
+ * #Default FileErrorManager settings.
+ * com.sun.mail.util.logging.FileErrorManager.pattern = path to directory
+ * </pre></tt>
+ *
+ * If properties are not defined, or contain invalid values, then the specified
+ * default values are used.
+ * <ul>
+ * <li>com.sun.mail.util.logging.FileErrorManager.pattern the absolute file path
+ * to the directory which will store any failed email messages. (defaults
+ * to the value of the system property <tt>java.io.tmpdir</tt>)
+ * </ul>
+ *
+ * @author Jason Mehrens
+ */
+public class FileErrorManager extends ErrorManager {
+
+ /**
+ * Stores the LogManager.
+ */
+ private static final LogManager manager = LogManager.getLogManager();
+ /**
+ * Used to report internal errors.
+ */
+ private final ErrorManager internal = new ErrorManager();
+ /**
+ * Directory of the email store.
+ */
+ private final File emailStore;
+
+ /**
+ * Creates a new error manager. Files are stored in the users temp
+ * directory.
+ * @exception SecurityException if unable to access system properties or
+ * if a security manager is present and unable to read or write to users
+ * temp directory.
+ */
+ public FileErrorManager() {
+ this.emailStore = getEmailStore();
+ init();
+ }
+
+ /**
+ * Creates a new error manager.
+ * @param dir a directory to store the email files.
+ * @throws NullPointerException if <tt>dir</tt> is <tt>null</tt>
+ * @throws IllegalArgumentException if <tt>dir</tt> is a
+ * <tt>java.io.File</tt> subclass, not a directory, or is not an absolute
+ * path.
+ * @throws SecurityException if a security manager is present and unable
+ * to read or write to a given directory.
+ */
+ public FileErrorManager(File dir) {
+ this.emailStore = dir;
+ init();
+ }
+
+ /**
+ * If the message parameter is a raw email, and passes the store term, then
+ * this method will store the email to the file system. If the message
+ * parameter is not a raw email then the message is forwarded to the super
+ * class. If an email is written to the filesystem without error, then the
+ * orignal reported error is ignored.
+ * @param msg String raw email or plain error message.
+ * @param ex Exception that occured in the mail handler.
+ * @param code int error manager code.
+ */
+ public void error(String msg, Exception ex, int code) {
+ if (isRawEmail(msg, ex, code)) {
+ try {
+ storeEmail(msg);
+ } catch (final IOException IOE) {
+ super.error(msg, ex, code);
+ internal.error(emailStore.toString(), IOE, ErrorManager.WRITE_FAILURE);
+ } catch (final RuntimeException RE) {
+ super.error(msg, ex, code);
+ internal.error(emailStore.toString(), RE, ErrorManager.WRITE_FAILURE);
+ }
+ } else {
+ super.error(msg, ex, code);
+ }
+ }
+
+ private void init() {
+ File dir = this.emailStore;
+ if (dir.getClass() != File.class) { //for security.
+ throw new IllegalArgumentException(dir.getClass().getName());
+ }
+
+ if (!dir.isDirectory()) {
+ throw new IllegalArgumentException("File must be a directory.");
+ }
+
+ //For now, only absolute paths are allowed.
+ if (!dir.isAbsolute()) {
+ throw new IllegalArgumentException("Only absolute paths are allowed.");
+ }
+
+ if (!dir.canRead()) { //Can throw under a security manager.
+ internal.error(dir.getAbsolutePath(),
+ new SecurityException("read"), ErrorManager.OPEN_FAILURE);
+ }
+
+ if (!dir.canWrite()) { //Can throw under a security manager.
+ internal.error(dir.getAbsolutePath(),
+ new SecurityException("write"), ErrorManager.OPEN_FAILURE);
+ }
+ }
+
+ private String prefixName() {
+ return "FileErrorManager";
+ }
+
+ private String suffixName() {
+ return ".eml";
+ }
+
+ private boolean isRawEmail(String msg, Exception ex, int code) {
+ if (msg != null && msg.length() > 0) {
+ return !msg.startsWith(Level.SEVERE.getName());
+ }
+ return false;
+ }
+
+ private void storeEmail(String email) throws IOException {
+ File tmp = null;
+ FileOutputStream out = null;
+ for (;;) {
+ tmp = File.createTempFile(prefixName(), suffixName(), emailStore);
+ try {
+ out = new FileOutputStream(tmp);
+ break;
+ } catch (FileNotFoundException FNFE) {
+ if (!tmp.exists()) { //retry if file is locked
+ throw FNFE;
+ }
+ }
+ }
+
+ try {
+ PrintStream ps = new PrintStream(new NewlineOutputStream(out));
+ ps.print(email);
+ ps.flush();
+ tmp = null; //Don't delete 'tmp' if all bytes were written.
+ ps.close();
+
+ } finally {
+ close(out);
+ delete(tmp); //Only deletes if not null.
+ }
+ }
+
+ private void close(OutputStream out) {
+ if (out != null) {
+ try {
+ out.close();
+ } catch (IOException IOE) {
+ internal.error(out.toString(), IOE, ErrorManager.CLOSE_FAILURE);
+ }
+ }
+ }
+
+ private void delete(File tmp) {
+ if (tmp != null) {
+ try {
+ if (!tmp.delete() && tmp.exists()) {
+ try {
+ tmp.deleteOnExit();
+ } catch (final RuntimeException shutdown) {
+ if (!tmp.delete()) {
+ internal.error(tmp.getAbsolutePath(), shutdown, ErrorManager.CLOSE_FAILURE);
+ }
+ }
+ }
+ } catch (SecurityException SE) {
+ internal.error(tmp.toString(), SE, ErrorManager.CLOSE_FAILURE);
+ }
+ }
+ }
+
+ /**
+ * Gets the location of the email store.
+ * @return the File location.
+ */
+ private File getEmailStore() {
+ String dir = manager.getProperty(
+ getClass().getName().concat(".pattern"));
+ if (dir == null) {
+ dir = (String) AccessController.doPrivileged(new PrivilegedAction() {
+
+ public Object run() {
+ return System.getProperty("java.io.tmpdir", "");
+ }
+ });
+ }
+ return new File(dir);
+ }
+}

diff -r cfaa49a57246 -r d4fa948c94c5 logging/src/main/java/MailHandlerDemo.java
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/logging/src/main/java/MailHandlerDemo.java Thu Sep 10 14:57:45 2009 -0700
@@ -0,0 +1,330 @@
+/*
+ * Copyright 2009 Sun Microsystems, Inc. All Rights Reserved.
+ * Copyright 2009 Jason Mehrens. All Rights Reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * - Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ *
+ * - Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * - Neither the name of Sun Microsystems nor the names of its
+ * contributors may be used to endorse or promote products derived
+ * from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS
+ * IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
+ * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
+ * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+ * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+ * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
+ * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
+ * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
+ * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+ * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+
+import com.sun.mail.util.logging.MailHandler;
+import java.util.logging.*;
+import javax.mail.*;
+import java.util.Comparator;
+import java.io.*;
+
+/**
+ * Demo for the different configurations for the MailHandler.
+ * If the logging properties file or class is not specified then this
+ * demo will apply some default settings to store emails in the users temp dir.
+ * @author Jason Mehrens
+ */
+public class MailHandlerDemo {
+
+ private static final String CLASS_NAME = MailHandlerDemo.class.getName();
+ private static final Logger LOGGER = Logger.getLogger(CLASS_NAME);
+
+ /**
+ * @param args the command line arguments
+ */
+ public static void main(String[] args) {
+ init(); //may create log messages.
+ try {
+ LOGGER.log(Level.FINEST, "This is the finest part of the demo.",
+ new MessagingException("Fake"));
+ LOGGER.log(Level.FINER, "This is the finer part of the demo.",
+ new NullPointerException("Fake"));
+ LOGGER.log(Level.FINE, "This is the fine part of the demo.");
+ LOGGER.log(Level.CONFIG, "Logging config file is {0}.", getConfigLocation());
+ LOGGER.log(Level.INFO, "Your temp directory is {0}, please wait...", getTempDir());
+
+ try { //waste some time for the custom formatter.
+ Thread.sleep(3L * 1000L);
+ } catch (InterruptedException ex) {
+ Thread.currentThread().interrupt();
+ }
+
+ LOGGER.log(Level.WARNING, "This is a warning.", new FileNotFoundException("Fake"));
+ LOGGER.log(Level.SEVERE, "The end of the demo.", new IOException("Fake"));
+ } finally {
+ closeHandlers();
+ }
+ }
+
+ /**
+ * Example for body only messages.
+ * On close the remaining messages are sent.
+ */
+ private static void initBodyOnly() {
+ MailHandler h = new MailHandler();
+ h.setSubject("Body only demo");
+ LOGGER.addHandler(h);
+ }
+
+ /**
+ * Example showing that when the mail handler reaches capacity it
+ * will format and send the current records. Capacity is used to roughly
+ * limit the size of an outgoing message.
+ * On close any remaining messages are sent.
+ */
+ private static void initLowCapacity() {
+ MailHandler h = new MailHandler(5);
+ h.setSubject("Low capacity demo");
+ LOGGER.addHandler(h);
+ }
+
+ /**
+ * Example for body only messages.
+ * On close any remaining messages are sent.
+ */
+ private static void initSimpleAttachment() {
+ MailHandler h = new MailHandler();
+ h.setSubject("Body and attachment demo");
+ h.setAttachmentFormatters(new Formatter[]{new XMLFormatter()});
+ h.setAttachmentNames(new String[]{"data.xml"});
+ LOGGER.addHandler(h);
+ }
+
+ /**
+ * Example setup for priority messages by level.
+ * If the push level is triggered the message is high priority.
+ * Otherwise, on close any remaining messages are sent.
+ */
+ private static void initWithPushLevel() {
+ MailHandler h = new MailHandler();
+ h.setSubject("Push level demo");
+ h.setPushLevel(Level.WARNING);
+ LOGGER.addHandler(h);
+ }
+
+ /**
+ * Example for priority messages by custom trigger.
+ * If the push filter is triggered the message is high priority.
+ * Otherwise, on close any remaining messages are sent.
+ */
+ private static void initWithPushFilter() {
+ MailHandler h = new MailHandler();
+ h.setSubject("Push on MessagingException demo");
+ h.setPushLevel(Level.ALL);
+ h.setPushFilter(new MessageErrorsFilter(true));
+ LOGGER.addHandler(h);
+ }
+
+ /**
+ * Example for circular buffer behavior. The level, push level, and
+ * capacity are set the same so that the memory handler push results
+ * in a mail handler push. All messages are high priority.
+ * On close any remaining records are discarded because they never reach
+ * the mail handler.
+ */
+ private static void initPushOnly() {
+ final int capacity = 3;
+ final Level pushLevel = Level.WARNING;
+ final MailHandler h = new MailHandler(capacity);
+ h.setPushLevel(pushLevel);
+ h.setSubject("Push only demo");
+ MemoryHandler m = new MemoryHandler(h, capacity, pushLevel);
+ h.setLevel(m.getLevel());
+ LOGGER.addHandler(m);
+ pushOnlyHandler = h;
+ }
+ private static Handler pushOnlyHandler;
+
+ /**
+ * Example for circular buffer behavior as normal priority. The push level,
+ * and capacity are set the same so that the memory handler push results
+ * in a mail handler push. All messages are normal priority.
+ * On close any remaining records are discarded because they never reach
+ * the mail handler.
+ */
+ private static void initPushNormal() {
+ final int capacity = 3;
+ final MailHandler h = new MailHandler(capacity);
+ h.setSubject("Push normal demo");
+ MemoryHandler m = new MemoryHandler(h, capacity, Level.WARNING) {
+
+ public void push() {
+ super.push(); //push to target.
+ super.flush(); //make the target send the email.
+ }
+ };
+ LOGGER.addHandler(m);
+ pushNormalHandler = h;
+ }
+ private static Handler pushNormalHandler;
+
+ /**
+ * Example for various kinds of custom sorting, formatting, and filtering
+ * for multiple attachment messages.
+ * On close any remaining messages are sent.
+ */
+ private static void initCustomAttachments() {
+ MailHandler h = new MailHandler();
+
+ //Sort records by level keeping the severe messages at the top.
+ h.setComparator(new LevelAndSeqComparator(true));
+
+ //Use subject to provide a hint as to what is in the email.
+ h.setSubject(new SummaryNameFormatter("Log containing {0} records with {1} errors."));
+
+ //Make the body give a simple summary of what happened.
+ h.setFormatter(new SummaryFormatter());
+
+ //Create 3 attachments.
+ h.setAttachmentFormatters(new Formatter[]{new XMLFormatter(), new XMLFormatter(), new SimpleFormatter()});
+
+ //filter each attachment differently.
+ h.setAttachmentFilters(new Filter[]{null, new MessageErrorsFilter(false),
+ new MessageErrorsFilter(true)});
+
+
+ //create simple names.
+ h.setAttachmentNames(new String[]{"all.xml", "errors.xml", "errors.txt"});
+
+ //extract simple name, replace the rest with formatters.
+ h.setAttachmentNames(new Formatter[]{h.getAttachmentNames()[0],
+ new SummaryNameFormatter("{0} records and {1} mail errors"),
+ new SummaryNameFormatter("{0,choice,0#no records|1#1 record|" +
+ "1<{0,number,integer} records} and " +
+ "{1,choice,0#no errors|1#1 error|1<" +
+ "{1,number,integer} errors}")});
+
+ LOGGER.addHandler(h);
+ }
+
+ /**
+ * Sets up the demos that will run.
+ */
+ private static void init() {
+ initBodyOnly();
+ initLowCapacity();
+ initSimpleAttachment();
+ initWithPushLevel();
+ initWithPushFilter();
+ initCustomAttachments();
+ initPushOnly();
+ initPushNormal();
+ applyFallbackSettings();
+ }
+
+ private static void closeHandlers() {
+ Handler[] handlers = LOGGER.getHandlers();
+ for (int i = 0; i < handlers.length; i++) {
+ Handler h = handlers[i];
+ h.close();
+ LOGGER.removeHandler(h);
+ }
+ }
+
+ private static void applyFallbackSettings() {
+ if (getConfigLocation() == null) {
+ LOGGER.setLevel(Level.ALL);
+ LOGGER.info("Check your user temp dir for output.");
+ Handler[] handlers = LOGGER.getHandlers();
+ for (int i = 0; i < handlers.length; i++) {
+ Handler h = handlers[i];
+ fallbackSettings(h);
+ }
+ fallbackSettings(pushOnlyHandler);
+ fallbackSettings(pushNormalHandler);
+ }
+ }
+
+ private static void fallbackSettings(Handler h) {
+ h.setErrorManager(new FileErrorManager());
+ h.setLevel(Level.ALL);
+ }
+
+ private static String getTempDir() {
+ return System.getProperty("java.io.tmpdir");
+ }
+
+ private static String getConfigLocation() {
+ String file = System.getProperty("java.util.logging.config.file");
+ if (file == null) {
+ return System.getProperty("java.util.logging.config.class");
+ }
+ return file;
+ }
+
+ private static final class MessageErrorsFilter implements Filter {
+
+ private final boolean complement;
+
+ MessageErrorsFilter(boolean complement) {
+ this.complement = complement;
+ }
+
+ public boolean isLoggable(LogRecord r) {
+ return r.getThrown() instanceof MessagingException == complement;
+ }
+ }
+
+ /**
+ * Orders log records by level then sequence number.
+ */
+ private static final class LevelAndSeqComparator
+ implements Comparator, java.io.Serializable {
+
+ private static final long serialVersionUID = 6269562326337300267L;
+ private final boolean reverse;
+
+ LevelAndSeqComparator() {
+ this(false);
+ }
+
+ LevelAndSeqComparator(final boolean reverse) {
+ this.reverse = reverse;
+ }
+
+ public int compare(Object o1, Object o2) {
+ LogRecord r1 = (LogRecord) o1;
+ LogRecord r2 = (LogRecord) o2;
+ final int first = r1.getLevel().intValue();
+ final int second = r2.getLevel().intValue();
+ if (first < second) {
+ return reverse ? 1 : -1;
+ } else if (first > second) {
+ return reverse ? -1 : 1;
+ } else {
+ return compareSeq(r1, r2);
+ }
+ }
+
+ private int compareSeq(LogRecord r1, LogRecord r2) {
+ final long first = r1.getSequenceNumber();
+ final long second = r2.getSequenceNumber();
+ if (first < second) {
+ return reverse ? 1 : -1;
+ } else if (first > second) {
+ return reverse ? -1 : 1;
+ } else {
+ return 0;
+ }
+ }
+ }
+}

diff -r cfaa49a57246 -r d4fa948c94c5 logging/src/main/java/README.txt
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/logging/src/main/java/README.txt Thu Sep 10 14:57:45 2009 -0700
@@ -0,0 +1,70 @@
+Logging Demo
+------------
+
+Notes:
+======
+
+This should not be taken as a demo of how to use the logging API, but
+rather how to use the features of the MailHandler.
+
+To run the demo:
+================
+
+ 1. The demo requires Java version 1.4 or newer.
+ We *strongly* encourage you to use the latest version of J2SE,
+ which you can download from http://java.sun.com/j2se/.
+
+ 2. Set your CLASSPATH to include the "mail.jar" and "activation.jar".
+
+ For JDK 1.1 on UNIX:
+
+ export CLASSPATH=/u/me/download/mail.jar:/u/me/download/activation.jar.
+
+ For JDK 1.2 and newer on UNIX:
+
+ export CLASSPATH=/u/me/download/mail.jar:/u/me/download/activation.jar:.
+
+ 3. Go to the demo/logging directory
+
+ 4. Compile all the files using your Java compiler. For example:
+
+ javac *.java
+
+ 5. Not required but, you should edit the maildemo.properties and change the
+ mail.to address and mail.host to your mail server ip or host name.
+
+ 6. Run the demo. For example:
+
+ java -Djava.util.logging.config.file=/u/me/download/javamail/demo/maildemo.properties MailHandlerDemo
+
+
+
+Overview of the Classes
+=======================
+
+Main Classes:
+
+ MailHandlerDemo = The main method creates log messages
+ for the MailHander to capture. The
+ initXXX methods describe some of the
+ common setup code for different types
+ of email messages.
+
+ FileErrorManager = Used to store email messages to the
+ local file system when mail transport
+ fails. This is installed as a
+ fallback in case the logging config is
+ not specified.
+
+ SummaryFormatter = An example compact formatter for the
+ body of an email message.
+
+ SummaryNameFormatter = An example formatter used to generate
+ subject lines and attachment file
+ names based on the contents of the
+ email message.
+
+Support files:
+
+ maildemo.properties = A sample LogManager properties file for
+ the MailHandlerDemo.

diff -r cfaa49a57246 -r d4fa948c94c5 logging/src/main/java/SummaryFormatter.java
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/logging/src/main/java/SummaryFormatter.java Thu Sep 10 14:57:45 2009 -0700
@@ -0,0 +1,102 @@
+/*
+ * Copyright 2009 Sun Microsystems, Inc. All Rights Reserved.
+ * Copyright 2009 Jason Mehrens. All Rights Reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * - Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ *
+ * - Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * - Neither the name of Sun Microsystems nor the names of its
+ * contributors may be used to endorse or promote products derived
+ * from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS
+ * IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
+ * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
+ * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+ * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+ * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
+ * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
+ * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
+ * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+ * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+
+import java.util.logging.*;
+import java.text.DateFormat;
+import java.util.Date;
+
+/**
+ * A compact formatter used to summarize an error report.
+ * @author Jason Mehrens
+ */
+public class SummaryFormatter extends Formatter {
+
+ private long oldest;
+ private long newest;
+ private long count;
+
+ public SummaryFormatter() {
+ reset();
+ }
+
+ public String format(LogRecord record) {
+ final String data;
+ if (record.getThrown() != null) {
+ data = record.getLevel() + " with detail." + newLine();
+ } else {
+ data = record.getLevel() + " with no detail." + newLine();
+ }
+ track(record.getMillis());
+ return data;
+ }
+
+ public synchronized String getTail(Handler h) {
+ try {
+ if (count > 0L) {
+ return formatNow();
+ }
+ return "";
+ } finally {
+ reset();
+ }
+ }
+
+ public synchronized String toString() {
+ return formatNow();
+ }
+
+ private String formatNow() {
+ assert Thread.holdsLock(this);
+ DateFormat f = DateFormat.getDateTimeInstance();
+ return newLine() + "These " + count + " messages occured between " +
+ f.format(new Date(oldest)) + " and " +
+ f.format(new Date(newest));
+
+ }
+
+ private synchronized void track(long time) {
+ count++;
+ this.oldest = Math.min(this.oldest, time);
+ this.newest = Math.max(this.newest, time);
+ }
+
+ private synchronized void reset() {
+ this.count = 0L;
+ this.oldest = Long.MAX_VALUE;
+ this.newest = Long.MIN_VALUE;
+ }
+
+ private static String newLine() {
+ return "\n";
+ }
+}

diff -r cfaa49a57246 -r d4fa948c94c5 logging/src/main/java/SummaryNameFormatter.java
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/logging/src/main/java/SummaryNameFormatter.java Thu Sep 10 14:57:45 2009 -0700
@@ -0,0 +1,110 @@
+/*
+ * Copyright 2009 Sun Microsystems, Inc. All Rights Reserved.
+ * Copyright 2009 Jason Mehrens. All Rights Reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * - Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ *
+ * - Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * - Neither the name of Sun Microsystems nor the names of its
+ * contributors may be used to endorse or promote products derived
+ * from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS
+ * IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
+ * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
+ * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+ * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+ * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
+ * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
+ * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
+ * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+ * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+
+import java.text.MessageFormat;
+import java.util.logging.*;
+import com.sun.mail.util.logging.MailHandler;
+
+/**
+ * Creates an attachment name based on the number of records and errors.
+ * The pattern is a <tt>java.text.MesageFormat</tt> with two parameters.
+ * The first parameter is the number of records formatted. The second is the
+ * number of records with errors.
+ * @author Jason Mehrens
+ */
+public class SummaryNameFormatter extends Formatter {
+
+ private final String pattern;
+ private long count;
+ private long errors;
+
+ /**
+ * Creates a simple pattern.
+ */
+ public SummaryNameFormatter() {
+ this("{0} records and {1} errors");
+ }
+
+ /**
+ * Creates formatter using a message format style pattern.
+ * @param pattern the pattern.
+ * @throws NullPointerException if pattern is null.
+ */
+ public SummaryNameFormatter(final String pattern) {
+ if (pattern == null) {
+ throw new NullPointerException();
+ }
+ this.pattern = pattern;
+ }
+
+ public synchronized String format(LogRecord r) {
+ count++;
+ if (r.getThrown() != null) {
+ errors++;
+ }
+ return "";
+ }
+
+ public synchronized String getTail(Handler h) {
+ final long records = this.count; //read
+ final long thrown = this.errors;
+ this.count = 0; //reset
+ this.errors = 0;
+ return toString(records, thrown) + extFrom(h);
+ }
+
+ public synchronized String toString() {
+ return toString(count, errors);
+ }
+
+ private String toString(final long count, final long errors) {
+ return MessageFormat.format(pattern, new Object[]{new Long(count), new Long(errors)});
+ }
+
+ private String extFrom(Handler h) {
+ if(h instanceof MailHandler) {
+ MailHandler mh = (MailHandler)h;
+ Formatter[] content = mh.getAttachmentFormatters();

[truncated due to length]