psmith 2003/09/21 20:54:03 Modified: . build.properties.sample build.xml Added: src/java/org/apache/log4j/net IMAppender.java DefaultEvaluator.java Log: Addition of the IMAppender to the log4j sandbox, kindly donated to the ASF by Rafael Luque Leiva and Ruth Zamorano. This appender requires the Smack library, which is required to be setup in the build.properties (see build.properties.samples). Revision Changes Path 1.1 jakarta-log4j-sandbox/src/java/org/apache/log4j/net/IMAppender.java Index: IMAppender.java =================================================================== /* * ============================================================================ * The Apache Software License, Version 1.1 * ============================================================================ * * Copyright (C) 1999 The Apache Software Foundation. All rights reserved. * * Redistribution and use in source and binary forms, with or without modifica- * tion, are permitted provided that the following conditions are met: * * 1. Redistributions of source code must retain the above copyright notice, * this list of conditions and the following disclaimer. * * 2. 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. * * 3. The end-user documentation included with the redistribution, if any, must * include the following acknowledgment: "This product includes software * developed by the Apache Software Foundation (http://www.apache.org/)." * Alternately, this acknowledgment may appear in the software itself, if * and wherever such third-party acknowledgments normally appear. * * 4. The names "log4j" and "Apache Software Foundation" must not be used to * endorse or promote products derived from this software without prior * written permission. For written permission, please contact * [EMAIL PROTECTED] * * 5. Products derived from this software may not be called "Apache", nor may * "Apache" appear in their name, without prior written permission of the * Apache Software Foundation. * * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED 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 * APACHE SOFTWARE FOUNDATION OR ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLU- * DING, 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. * * This software consists of voluntary contributions made by many individuals * on behalf of the Apache Software Foundation. For more information on the * Apache Software Foundation, please see <http://www.apache.org/>. * */ package org.apache.log4j.net; import org.apache.log4j.AppenderSkeleton; import org.apache.log4j.Layout; import org.apache.log4j.helpers.CyclicBuffer; import org.apache.log4j.helpers.LogLog; import org.apache.log4j.helpers.OptionConverter; import org.apache.log4j.spi.ErrorCode; import org.apache.log4j.spi.LoggingEvent; import org.apache.log4j.spi.TriggeringEventEvaluator; import org.jivesoftware.smack.Chat; import org.jivesoftware.smack.GroupChat; import org.jivesoftware.smack.SSLXMPPConnection; import org.jivesoftware.smack.XMPPConnection; /** * IMAppender appends logging requests through instant * messaging network. * * <p>More info about the IMAppender in the article * "Instant logging: Harness the power of log4j with Jabber" * (developerWorks, August 2003) at * <http://www-106.ibm.com/developerworks/java/library/j-instlog/></p> * * @author Rafael Luque * @author Ruth Zamorano */ public class IMAppender extends AppenderSkeleton { // ----------------------------------------------- Variables private String host; private int port = 5222; private String username; private String password; private String recipient; private boolean chatroom = false; private String nickname; private boolean SSL = false; private int bufferSize = 16; protected TriggeringEventEvaluator evaluator; protected CyclicBuffer cb; protected XMPPConnection con; protected Chat chat; protected GroupChat groupchat; // -------------------------------------------- Constructors /** * The default constructor will instantiate the appender * with a default TriggeringEventEvaluator that will * trigger on events with level ERROR or higher. */ public IMAppender() { this(new DefaultEvaluator()); } public IMAppender(TriggeringEventEvaluator evaluator) { this.evaluator = evaluator; } // ------------------------------- Setter and getter methods public String getHost() { return this.host; } public void setHost(String host) { this.host = host; } public int getPort() { return this.port; } public void setPort(int port) { this.port = port; } public String getUsername() { return this.username; } public void setUsername(String username) { this.username = username; } public String getPassword() { return this.password; } public void setPassword(String password) { this.password = password; } public String getRecipient() { return this.recipient; } public void setRecipient(String recipient) { this.recipient = recipient; } public boolean isChatroom() { return this.chatroom; } public void setChatroom(boolean chatroom) { this.chatroom = chatroom; } public String getNickname() { return this.nickname; } public void setNickname(String nickname) { this.nickname = nickname; } public boolean isSSL() { return this.SSL; } public void setSSL(boolean SSL) { this.SSL = SSL; } public int getBufferSize() { return this.bufferSize; } public void setBufferSize(int bufferSize) { this.bufferSize = bufferSize; } /** * The <b>EvaluatorClass</b> option takes a string value * representing the name of the class implementing the * [EMAIL PROTECTED] TriggeringEventEvaluator} interface. A corresponding * object will be instantiated and assigned as the triggering * event evaluator for the SMTPAppender. */ public void setEvaluatorClass(String value) { evaluator = (TriggeringEventEvaluator) OptionConverter.instantiateByClassName( value, TriggeringEventEvaluator.class, evaluator); } public String getEvaluatorClass() { return (evaluator == null) ? null : evaluator.getClass().getName(); } // ---------------------------------- Log4j callback methods /** * Options are activated and become effective only * after calling this method. */ public void activateOptions() { try { cb = new CyclicBuffer(bufferSize); // Create a connection to the XMPP server LogLog.debug("Establishing connection with XMPP server"); if (SSL) { con = new SSLXMPPConnection(host, port); } else { con = new XMPPConnection(host, port); } // Most servers require you to login // before performing other tasks LogLog.debug("About to login as [" + username + "/" + password + "]"); con.login(username, password); // Start a conversation with IMAddress if (chatroom) { LogLog.debug("About to create ChatGroup"); groupchat = con.createGroupChat(recipient); LogLog.debug("About to join room"); groupchat.join((nickname != null) ? nickname : username); } else { chat = con.createChat(recipient); } } catch (Exception e) { errorHandler.error( "Error while activating options" + " for appender named [" + name + "]", e, ErrorCode.GENERIC_FAILURE); } } /** * Close this IMAppender. Closing all resources used * by the appender. A closed appender cannot be re-opened. */ public synchronized void close() { if (this.closed) { return; } LogLog.debug("Closing appender [" + name + "]"); this.closed = true; // Closes the connection by setting presence to unavailable // then closing the stream to the XMPP server. if (con != null) { con.close(); } // Help GC con = null; chat = null; groupchat = null; } /** * This method called by [EMAIL PROTECTED] AppenderSkeleton#doAppend} * method does most of the real appending work. Adds the event * to a buffer and checks if the event triggers a message to * be sent. */ public void append(LoggingEvent event) { // check pre-conditions if (!checkEntryConditions()) { return; } cb.add(event); if (evaluator.isTriggeringEvent(event)) { sendBuffer(); } } /** * Send the contents of the cyclic buffer as an IM message. */ protected void sendBuffer() { try { StringBuffer buf = new StringBuffer(); int len = cb.length(); for (int i = 0; i < len; i++) { LoggingEvent event = cb.get(); buf.append(layout.format(event)); // if layout doesn't handle exception, // the appender has to do it if (layout.ignoresThrowable()) { String[] s = event.getThrowableStrRep(); if (s != null) { for (int j = 0; j < s.length; j++) { buf.append(Layout.LINE_SEP); buf.append(s[j]); } } } } if (chatroom) { groupchat.sendMessage(buf.toString()); } else { chat.sendMessage(buf.toString()); } } catch (Exception e) { errorHandler.error( "Could not send message in IMAppender [" + name + "]", e, ErrorCode.GENERIC_FAILURE); } } /** * This method determines if there is a sense in attempting * to append. * * <p>It checks whether there is an output chat available * and also if there is a set layout. If these checks fail, * then the boolean value <code>false</code> is returned. */ protected boolean checkEntryConditions() { if ((this.chat == null) && (this.groupchat == null)) { errorHandler.error("Chat object not configured"); return false; } if (this.layout == null) { errorHandler.error("No layout set for appender named [" + name + "]"); return false; } return true; } /** * The IMAppender requires a layout. Hence, this method * returns <code>true</code>. */ public boolean requiresLayout() { return true; } } 1.1 jakarta-log4j-sandbox/src/java/org/apache/log4j/net/DefaultEvaluator.java Index: DefaultEvaluator.java =================================================================== /* * ============================================================================ * The Apache Software License, Version 1.1 * ============================================================================ * * Copyright (C) 1999 The Apache Software Foundation. All rights reserved. * * Redistribution and use in source and binary forms, with or without modifica- * tion, are permitted provided that the following conditions are met: * * 1. Redistributions of source code must retain the above copyright notice, * this list of conditions and the following disclaimer. * * 2. 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. * * 3. The end-user documentation included with the redistribution, if any, must * include the following acknowledgment: "This product includes software * developed by the Apache Software Foundation (http://www.apache.org/)." * Alternately, this acknowledgment may appear in the software itself, if * and wherever such third-party acknowledgments normally appear. * * 4. The names "log4j" and "Apache Software Foundation" must not be used to * endorse or promote products derived from this software without prior * written permission. For written permission, please contact * [EMAIL PROTECTED] * * 5. Products derived from this software may not be called "Apache", nor may * "Apache" appear in their name, without prior written permission of the * Apache Software Foundation. * * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED 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 * APACHE SOFTWARE FOUNDATION OR ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLU- * DING, 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. * * This software consists of voluntary contributions made by many individuals * on behalf of the Apache Software Foundation. For more information on the * Apache Software Foundation, please see <http://www.apache.org/>. * */ package org.apache.log4j.net; import org.apache.log4j.Level; import org.apache.log4j.spi.LoggingEvent; import org.apache.log4j.spi.TriggeringEventEvaluator; /** * <code>DefaultEvaluator</code> implements the single method * <code>TriggeringEventEvaluator</code> interface. This class * allows the <code>IMAppender</code> to decide when to perform the * message delivery. * * @author Rafael Luque * @author Ruth Zamorano */ public class DefaultEvaluator implements TriggeringEventEvaluator { /** * This method returns <code>true</code> if the event level * has ERROR level or higher. Otherwise it returns * <code>false</code>. */ public boolean isTriggeringEvent(LoggingEvent event) { return event.getLevel().isGreaterOrEqual(Level.ERROR); } } 1.7 +2 -0 jakarta-log4j-sandbox/build.properties.sample Index: build.properties.sample =================================================================== RCS file: /home/cvs/jakarta-log4j-sandbox/build.properties.sample,v retrieving revision 1.6 retrieving revision 1.7 diff -u -r1.6 -r1.7 --- build.properties.sample 27 Aug 2003 07:58:46 -0000 1.6 +++ build.properties.sample 22 Sep 2003 03:54:03 -0000 1.7 @@ -22,3 +22,5 @@ # Jalopy OPTIONAL; required to run the jalpoy targets jalopy.lib=d:/development/code-opensource/other/jalopy-b10/lib +# Smack jar OPTIONAL; required to build the org.apache.log4j.net.IMAppender +smack.jar=../smack-1.2.0/smack.jar 1.13 +29 -1 jakarta-log4j-sandbox/build.xml Index: build.xml =================================================================== RCS file: /home/cvs/jakarta-log4j-sandbox/build.xml,v retrieving revision 1.12 retrieving revision 1.13 diff -u -r1.12 -r1.13 --- build.xml 28 Aug 2003 01:34:10 -0000 1.12 +++ build.xml 22 Sep 2003 03:54:03 -0000 1.13 @@ -46,6 +46,7 @@ <pathelement location="${build.home}/classes"/> <pathelement location="${log4j.jar}"/> <pathelement location="${servlet.jar}"/> + <pathelement location="${smack.jar}"/> </path> @@ -84,7 +85,23 @@ <tstamp /> </target> - <target name="build" depends="init, build.core, build.servlet"/> + <target name="imCheck"> + <available classname="org.jivesoftware.smack.XMPPConnection" property="im-jar-present"> + <classpath> + <pathelement location="${smack.jar}"/> + </classpath> + </available> + </target> + + <target name="imNoJar" unless="im-jar-present"> + <echo >Smack library not found, the IMAppender will not be included in the build/jar</echo> + </target> + + <target name="im" depends="imCheck, imNoJar" if="im-jar-present"> + <echo message="Smack IM jar is present."/> + </target> + + <target name="build" depends="init, build.core, build.servlet, build.im"/> <target name="build.core" depends="init"> <mkdir dir="${javac.dest}" /> @@ -118,6 +135,17 @@ </javac> </target> + <target name="build.im" depends="init, im" if="im-jar-present"> + <javac srcdir="${java.source.dir}" + destdir="${javac.dest}" + debug="${build.debug}" + deprecation="${build.deprecation}" + optimize="${build.optimize}" + verbose="${build.verbose}"> + <include name="**/net/**/*.java"/> + <classpath refid="compile.classpath"/> + </javac> + </target> <!-- ================================================================= --> <!-- Remove all build generated files. --> <!-- ================================================================= -->
--------------------------------------------------------------------- To unsubscribe, e-mail: [EMAIL PROTECTED] For additional commands, e-mail: [EMAIL PROTECTED]