Patch for the afore mentioned bug fixes and enhancements. ------------------------ Cut Here ------------------------ diff -u -N orig/CategorizedMessage.java new/CategorizedMessage.java --- orig/CategorizedMessage.java Wed Dec 31 18:00:00 1969 +++ new/CategorizedMessage.java Mon Oct 7 13:27:29 2002 @@ -0,0 +1,88 @@ +/* + * Copyright (C) The Apache Software Foundation. All rights reserved. + * + * This software is published under the terms of the Apache Software + * License version 1.1, a copy of which has been included with this + * distribution in the LICENSE.txt file. + */ + +package org.apache.log4j.nt; + +import java.beans.*; + +/** + * Class that allows you to assign a category number to a message to be + * logged to the NTEventLogAppender. This category number will show up in + * the Category column of the Windows Event Log. If you have text assigned + * to those numbers in a resource DLL, you will see the text instead of the + * number. + * + * @author <a href="mailto:[EMAIL PROTECTED]">Brian Lind</a> + */ +public class CategorizedMessage extends Object implements java.io.Serializable { + + private PropertyChangeSupport propertySupport; + + /** Holds value of property message. */ + private Object message; + + /** Holds value of property eventCategory. */ + private int eventCategory; + + /** Creates new CategorizedMessage */ + public CategorizedMessage() { + propertySupport = new PropertyChangeSupport ( this ); + } + + /** Creates new CategorizedMessage */ + public CategorizedMessage(int eventCategory, Object message) { + this(); + this.eventCategory = eventCategory; + this.message = message; + } + + + public void addPropertyChangeListener (PropertyChangeListener listener) { + propertySupport.addPropertyChangeListener (listener); + } + + public void removePropertyChangeListener (PropertyChangeListener listener) { + propertySupport.removePropertyChangeListener (listener); + } + + /** Getter for property message. + * @return Value of property message. + */ + public Object getMessage() { + return message; + } + + /** Setter for property message. + * @param message New value of property message. + */ + public void setMessage(Object message) { + this.message = message; + } + + /** Getter for property eventCategory. + * @return Value of property eventCategory. + */ + public int getEventCategory() { + return eventCategory; + } + + /** Setter for property eventCategory. + * @param eventCategory New value of property eventCategory. + */ + public void setEventCategory(int eventCategory) { + this.eventCategory = eventCategory; + } + + public java.lang.String toString() { + if( message != null ) + return message.toString(); + else + return "null"; + } + +} diff -u -N orig/EventLogCategories.mc new/EventLogCategories.mc --- orig/EventLogCategories.mc Mon Oct 7 13:14:05 2002 +++ new/EventLogCategories.mc Mon Oct 7 13:27:29 2002 @@ -1,20 +1,20 @@ -MessageId=0xC350 +MessageId=1 Language=English Fatal . -MessageId=0x9C40 +MessageId=2 Language=English Error . -MessageId=0x7530 +MessageId=3 Language=English Warn . -MessageId=0x4E20 +MessageId=4 Language=English Info . -MessageId=0x2710 +MessageId=5 Language=English Debug . diff -u -N orig/ExampleCategories.mc new/ExampleCategories.mc --- orig/ExampleCategories.mc Wed Dec 31 18:00:00 1969 +++ new/ExampleCategories.mc Mon Oct 7 13:27:29 2002 @@ -0,0 +1,44 @@ +MessageId=1 +Language=English +Fatal +. +MessageId=2 +Language=English +Error +. +MessageId=3 +Language=English +Warn +. +MessageId=4 +Language=English +Info +. +MessageId=5 +Language=English +Debug +. +MessageId=6 +Language=English +Started +. +MessageId=7 +Language=English +Stopped +. +MessageId=8 +Language=English +Success +. +MessageId=9 +Language=English +Failure +. +MessageId=10 +Language=English +Open +. +MessageId=11 +Language=English +Close +. diff -u -N orig/ExampleEvents.mc new/ExampleEvents.mc --- orig/ExampleEvents.mc Wed Dec 31 18:00:00 1969 +++ new/ExampleEvents.mc Mon Oct 7 13:27:29 2002 @@ -0,0 +1,4 @@ +MessageId=0x1000 +Language=English +Message = (%1) +. diff -u -N orig/NTEventLogAppender.java new/NTEventLogAppender.java --- orig/NTEventLogAppender.java Mon Oct 7 13:14:05 2002 +++ new/NTEventLogAppender.java Mon Oct 7 13:27:29 2002 @@ -26,7 +26,9 @@ will get a java.lang.UnsatisfiedLinkError. @author <a href="mailto:[EMAIL PROTECTED]">Chris Taylor</a> - @author <a href="mailto:[EMAIL PROTECTED]">Jim Cakalic</a> */ + @author <a href="mailto:[EMAIL PROTECTED]">Jim Cakalic</a> + @author <a href="mailto:[EMAIL PROTECTED]">Brian Lind</a> + */ public class NTEventLogAppender extends AppenderSkeleton { private int _handle = 0; @@ -58,8 +60,18 @@ public NTEventLogAppender(String source, Layout layout) { this(null, source, layout); } - + public NTEventLogAppender(String server, String source, Layout layout) { + this(server, source, layout, null, null); + } + + public NTEventLogAppender(String server, String source, Layout layout, + String categoryMessageFile) { + this(server, source, layout, categoryMessageFile, null); + } + + public NTEventLogAppender(String server, String source, Layout layout, + String categoryMessageFile, String eventMessageFile) { if (source == null) { source = "Log4j"; } @@ -70,6 +82,10 @@ } try { + if( categoryMessageFile != null ) + setCategoryMessageFile(categoryMessageFile); + if( eventMessageFile != null ) + setEventMessageFile(eventMessageFile); _handle = registerEventSource(server, source); } catch (Exception e) { e.printStackTrace(); @@ -109,14 +125,20 @@ } } } - // Normalize the log message level into the supported categories - int nt_category = event.level.toInt(); + // Normalize the log message level into the supported NT event types + int priority = event.level.toInt(); // Anything above FATAL or below DEBUG is labeled as INFO. - //if (nt_category > FATAL || nt_category < DEBUG) { - // nt_category = INFO; + //if (priority > FATAL || priority < DEBUG) { + // priority = INFO; //} - reportEvent(_handle, sbuf.toString(), nt_category); + if( event.getMessage() instanceof CategorizedMessage ) { + CategorizedMessage extendedMsg = (CategorizedMessage)(event.getMessage()); + reportEventAndCategory(_handle, sbuf.toString(), priority, +extendedMsg.getEventCategory()); + } + else { + reportEvent(_handle, sbuf.toString(), priority); + } } @@ -149,9 +171,16 @@ } native private int registerEventSource(String server, String source); - native private void reportEvent(int handle, String message, int level); + native private void reportEvent(int handle, String message, int priority); native private void deregisterEventSource(int handle); + native private void setEventMessageFile(String dllName); + native private void setCategoryMessageFile(String dllName); + native private void reportEventAndCategory(int handle, String message, int +priority, int category); + + native public boolean isUserDisplayed(); + native public void setUserDisplayed(boolean on); + static { System.loadLibrary("NTEventLogAppender"); } diff -u -N orig/Notes.txt new/Notes.txt --- orig/Notes.txt Wed Dec 31 18:00:00 1969 +++ new/Notes.txt Mon Oct 7 13:27:29 2002 @@ -0,0 +1,36 @@ +Notes: + +The NTEventLogAppender.dll DLL still needs to be found in your PATH, even if +you use custom resource only DLL's. Your resource DLL's, of course, need to +be found in the PATH somewhere too. + + +When creating your own resource only DLL for your custom categories, you should +still include the standard log4j ones for compatability purposes. You can copy +and paste the standard ones (number 1 thru 5) from the EventLogCategories.mc file. +Be sure to start numbering yours at 6 on up or they will not show up in the Event Log. +If you leave gaps in the numbers, only the numbers show up in the Event Log instead +of the text. At least that's what I've experienced when I decided to try and start +numbering my categories at 100. Didn't work for me. + +To use custom categories you need to tell the NTEventLogAppender about you custom +resource only DLL and use the CategorizedMessage class to associate a category +number with you log message. +Example: + + Category log = Category.getInstance(appName); + NTEventLogAppender appender = + new NTEventLogAppender(null, appName, null, "MyCategories.dll"); + log.addAppender(appender); + log.info(new CategorizedMessage(6, "Hi there.")); + + +If you would like to use a custom event, not very useful at this point, you +can create a resource only DLL message file (.mc file), with one message +in it with MessageId=0x1000 and whatever you want for the text of the event. +If you don't include a %1 somewhere in the text, you'll never see the message you +passed in from Java. You specify your event message DLL in a NTEventLogAppender +contructor. +Example: + NTEventLogAppender appender = + new NTEventLogAppender(null, appName, null, "MyCategories.dll", +"MyEvent.dll"); diff -u -N orig/examplemake.bat new/examplemake.bat --- orig/examplemake.bat Wed Dec 31 18:00:00 1969 +++ new/examplemake.bat Mon Oct 7 13:27:29 2002 @@ -0,0 +1,12 @@ +@echo off + +REM Example for creating custom Event Categories and Event ID's and descriptions + +MC ExampleCategories.mc +RC -r -fo ExampleCategories.res ExampleCategories.rc +LINK /subsystem:windows /INCREMENTAL:NO /dll /noentry /out:"ExampleCategories.dll" +ExampleCategories.res + +MC ExampleEvents.mc +RC -r -fo ExampleEvents.res ExampleEvents.rc +LINK /subsystem:windows /INCREMENTAL:NO /dll /noentry /out:"ExampleEvents.dll" +ExampleEvents.res + diff -u -N orig/nteventlog.cpp new/nteventlog.cpp --- orig/nteventlog.cpp Mon Oct 7 13:14:06 2002 +++ new/nteventlog.cpp Mon Oct 7 13:36:11 2002 @@ -12,6 +12,12 @@ #include "org_apache_log4j_nt_NTEventLogAppender.h" #include <windows.h> +const DWORD defaultMessageID = 0x1000; +DWORD messageID = defaultMessageID; +char *EventMessageFile = "NTEventLogAppender.dll"; +char *CategoryMessageFile = "NTEventLogAppender.dll"; +BOOL displayUser = FALSE; + // Borrowed unabashedly from the JNI Programmer's Guide void JNU_ThrowByName(JNIEnv *env, const char *name, const char *msg) { @@ -83,8 +89,27 @@ * be displayed in the NT Event Viewer. */ WORD getCategory(jint priority) { - // Priority values map directly to EventLog category values - return (WORD)(priority + 1); + WORD ret_val = 0; + + // Map priority to a resonable category name code from EvengLogCategories.mc + switch (priority) { + case org_apache_log4j_Priority_FATAL_INT: + ret_val = 1; + break; + case org_apache_log4j_Priority_ERROR_INT: + ret_val = 2; + break; + case org_apache_log4j_Priority_WARN_INT: + ret_val = 3; + break; + case org_apache_log4j_Priority_INFO_INT: + ret_val = 4; + break; + case org_apache_log4j_Priority_DEBUG_INT: + ret_val = 5; + break; + } + return ret_val; } /* @@ -112,12 +137,13 @@ return ret_val; } -HKEY regGetKey(TCHAR *subkey, DWORD *disposition) { - HKEY hkey = 0; - RegCreateKeyEx(HKEY_LOCAL_MACHINE, subkey, 0, NULL, - REG_OPTION_NON_VOLATILE, KEY_SET_VALUE, NULL, - &hkey, disposition); - return hkey; +DWORD regGetKey(TCHAR *subkey, HKEY *hkey) { + DWORD result; + DWORD disposition; + result = RegCreateKeyEx(HKEY_LOCAL_MACHINE, subkey, 0, NULL, + REG_OPTION_NON_VOLATILE, KEY_SET_VALUE, NULL, + hkey, &disposition); + return result; } void regSetString(HKEY hkey, TCHAR *name, TCHAR *value) { @@ -133,28 +159,51 @@ */ void addRegistryInfo(char *source) { const TCHAR *prefix = "SYSTEM\\CurrentControlSet\\Services\\EventLog\\Application\\"; - DWORD disposition; + DWORD result; HKEY hkey = 0; TCHAR subkey[256]; lstrcpy(subkey, prefix); lstrcat(subkey, source); - hkey = regGetKey(subkey, &disposition); - if (disposition == REG_CREATED_NEW_KEY) { - regSetString(hkey, "EventMessageFile", "NTEventLogAppender.dll"); - regSetString(hkey, "CategoryMessageFile", "NTEventLogAppender.dll"); + result = regGetKey(subkey, &hkey); + if (result == ERROR_SUCCESS) { + regSetString(hkey, "EventMessageFile", EventMessageFile); + regSetString(hkey, "CategoryMessageFile", CategoryMessageFile); regSetDword(hkey, "TypesSupported", (DWORD)7); - regSetDword(hkey, "CategoryCount", (DWORD)8); + regSetDword(hkey, "CategoryCount", (DWORD)1000); } - //RegSetValueEx(hkey, "EventMessageFile", 0, REG_SZ, (LPBYTE)dllname, lstrlen(dllname)); - //RegSetValueEx(hkey, "CategoryMessageFile", 0, REG_SZ, (LPBYTE)dllname, lstrlen(dllname)); - //RegSetValueEx(hkey, "TypesSupported", 0, REG_DWORD, (LPBYTE)&whichTypes, sizeof(DWORD)); - //RegSetValueEx(hkey, "CategoryCount", 0, REG_DWORD, (LPBYTE)&numCategories, sizeof(DWORD)); RegCloseKey(hkey); return; } /* + * Lookup the current user's SID and return a pointer to it + */ +PSID getCurrentUserId() +{ + char user[256]; + DWORD userLen = 256; + PSID userSidPtr = NULL; + DWORD sidLen = 0; + char domain[256]; + DWORD domainLen = sizeof(domain); + SID_NAME_USE accountType; + if( GetUserName(user, &userLen) ) + { + LookupAccountName(NULL, user, userSidPtr, &sidLen, + domain, &domainLen, &accountType); + userSidPtr = (SID *)malloc(sidLen); + if( ! LookupAccountName(NULL, user, userSidPtr, &sidLen, + domain, &domainLen, &accountType) ) + { + free(userSidPtr); + userSidPtr = NULL; + } + } + return userSidPtr; +} + +/* * Class: org.apache.log4j.nt.NTEventLogAppender * Method: registerEventSource * Signature: (Ljava/lang/String;Ljava/lang/String;)I @@ -184,8 +233,40 @@ * Signature: (ILjava/lang/String;I)V */ JNIEXPORT void JNICALL Java_org_apache_log4j_nt_NTEventLogAppender_reportEvent( - JNIEnv *env, jobject java_this, jint handle, jstring jstr, jint priority) { - + JNIEnv *env, jobject java_this, jint handle, jstring jstr, jint priority) +{ + Java_org_apache_log4j_nt_NTEventLogAppender_reportEventAndCategory( + env, java_this, handle, jstr, priority, getCategory(priority)); + return; +} + +/* + * Class: org_apache_log4j_nt_NTEventLogAppender + * Method: deregisterEventSource + * Signature: (I)V + */ +JNIEXPORT void JNICALL +Java_org_apache_log4j_nt_NTEventLogAppender_deregisterEventSource( +JNIEnv *env, +jobject java_this, +jint handle) +{ + DeregisterEventSource((HANDLE)handle); +} + + +/* + * Class: org_apache_log4j_nt_NTEventLogAppender + * Method: reportEvent + * Signature: (ILjava/lang/String;II)V + */ +JNIEXPORT void JNICALL +Java_org_apache_log4j_nt_NTEventLogAppender_reportEventAndCategory + (JNIEnv *env, + jobject java_this, + jint handle, + jstring jstr, + jint priority, + jint category) +{ jboolean localHandle = JNI_FALSE; if (handle == 0) { // Client didn't give us a handle so make a local one. @@ -199,15 +280,24 @@ char *nstr = JNU_GetStringNativeChars(env, jstr); array[0] = nstr; + // lookup user + PSID userSidPtr = NULL; + if( displayUser ) + userSidPtr = getCurrentUserId(); + // This is the only message supported by the package. It is backed by // a message resource which consists of just '%1' which is replaced // by the string we just created. - const DWORD messageID = 0x1000; - ReportEvent((HANDLE)handle, getType(priority), - getCategory(priority), - messageID, NULL, 1, 0, array, NULL); + ReportEvent((HANDLE)handle, getType(priority), (WORD)category, + defaultMessageID, userSidPtr, 1, 0, array, NULL); free((void *)nstr); + + if( userSidPtr != NULL ) + { + free(userSidPtr); + } + if (localHandle == JNI_TRUE) { // Created the handle here so free it here too. DeregisterEventSource((HANDLE)handle); @@ -217,16 +307,66 @@ /* * Class: org_apache_log4j_nt_NTEventLogAppender - * Method: deregisterEventSource - * Signature: (I)V + * Method: isUserDisplayed + * Signature: ()Z */ -JNIEXPORT void JNICALL Java_org_apache_log4j_nt_NTEventLogAppender_deregisterEventSource( -JNIEnv *env, -jobject java_this, -jint handle) +JNIEXPORT jboolean JNICALL Java_org_apache_log4j_nt_NTEventLogAppender_isUserDisplayed + (JNIEnv *env, + jobject java_this) { - DeregisterEventSource((HANDLE)handle); + if( displayUser ) + return JNI_TRUE; + return JNI_FALSE; } +/* + * Class: org_apache_log4j_nt_NTEventLogAppender + * Method: setUserDisplayed + * Signature: (Z)V + */ +JNIEXPORT void JNICALL Java_org_apache_log4j_nt_NTEventLogAppender_setUserDisplayed + (JNIEnv *env, + jobject java_this, + jboolean on) +{ + if( on == JNI_TRUE ) + displayUser = TRUE; + else + displayUser = FALSE; +} + +/* + * Class: org_apache_log4j_nt_NTEventLogAppender + * Method: setEventMessageFile + * Signature: (Ljava/lang/String;)V + */ +JNIEXPORT void JNICALL Java_org_apache_log4j_nt_NTEventLogAppender_setEventMessageFile + (JNIEnv *env, + jobject java_this, + jstring dllName) +{ + char *nstr = JNU_GetStringNativeChars(env, dllName); + if( nstr != NULL && strlen(nstr) > 0 ) + { + EventMessageFile = (char *)strdup(nstr); + } +} + +/* + * Class: org_apache_log4j_nt_NTEventLogAppender + * Method: setCategoryMessageFile + * Signature: (Ljava/lang/String;)V + */ +JNIEXPORT void JNICALL +Java_org_apache_log4j_nt_NTEventLogAppender_setCategoryMessageFile + (JNIEnv *env, + jobject java_this, + jstring dllName) +{ + char *nstr = JNU_GetStringNativeChars(env, dllName); + if( nstr != NULL && strlen(nstr) > 0 ) + { + CategoryMessageFile = (char *)strdup(nstr); + } +} #endif
-- To unsubscribe, e-mail: <mailto:[EMAIL PROTECTED]> For additional commands, e-mail: <mailto:[EMAIL PROTECTED]>