/* * 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; } } } }