001/* 002 * Licensed to the Apache Software Foundation (ASF) under one or more 003 * contributor license agreements. See the NOTICE file distributed with 004 * this work for additional information regarding copyright ownership. 005 * The ASF licenses this file to You under the Apache License, Version 2.0 006 * (the "License"); you may not use this file except in compliance with 007 * the License. You may obtain a copy of the License at 008 * 009 * http://www.apache.org/licenses/LICENSE-2.0 010 * 011 * Unless required by applicable law or agreed to in writing, software 012 * distributed under the License is distributed on an "AS IS" BASIS, 013 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 014 * See the License for the specific language governing permissions and 015 * limitations under the License. 016 */ 017 018package org.apache.log4j.nt; 019 020import org.apache.log4j.AppenderSkeleton; 021import org.apache.log4j.Layout; 022import org.apache.log4j.TTCCLayout; 023import org.apache.log4j.helpers.LogLog; 024import org.apache.log4j.spi.LoggingEvent; 025 026 027/** 028 Append to the NT event log system. 029 030 <p><b>WARNING</b> This appender can only be installed and used on a 031 Windows system. 032 033 <p>Do not forget to place NTEventLogAppender.dll, 034 NTEventLogAppender.amd64.dll, NTEventLogAppender.ia64.dll 035 or NTEventLogAppender.x86.dll as appropriate in a 036 directory that is on the PATH of the Windows system. Otherwise, you 037 will get a java.lang.UnsatisfiedLinkError. 038 039 @author <a href="mailto:cstaylor@pacbell.net">Chris Taylor</a> 040 @author <a href="mailto:jim_cakalic@na.biomerieux.com">Jim Cakalic</a> */ 041public class NTEventLogAppender extends AppenderSkeleton { 042 private int _handle = 0; 043 044 private String source = null; 045 private String server = null; 046 047 048 public NTEventLogAppender() { 049 this(null, null, null); 050 } 051 052 public NTEventLogAppender(String source) { 053 this(null, source, null); 054 } 055 056 public NTEventLogAppender(String server, String source) { 057 this(server, source, null); 058 } 059 060 public NTEventLogAppender(Layout layout) { 061 this(null, null, layout); 062 } 063 064 public NTEventLogAppender(String source, Layout layout) { 065 this(null, source, layout); 066 } 067 068 public NTEventLogAppender(String server, String source, Layout layout) { 069 if (source == null) { 070 source = "Log4j"; 071 } 072 if (layout == null) { 073 this.layout = new TTCCLayout(); 074 } else { 075 this.layout = layout; 076 } 077 078 try { 079 _handle = registerEventSource(server, source); 080 } catch (Exception e) { 081 e.printStackTrace(); 082 _handle = 0; 083 } 084 } 085 086 public 087 void close() { 088 // unregister ... 089 } 090 091 public 092 void activateOptions() { 093 if (source != null) { 094 try { 095 _handle = registerEventSource(server, source); 096 } catch (Exception e) { 097 LogLog.error("Could not register event source.", e); 098 _handle = 0; 099 } 100 } 101 } 102 103 104 public void append(LoggingEvent event) { 105 106 StringBuffer sbuf = new StringBuffer(); 107 108 sbuf.append(layout.format(event)); 109 if(layout.ignoresThrowable()) { 110 String[] s = event.getThrowableStrRep(); 111 if (s != null) { 112 int len = s.length; 113 for(int i = 0; i < len; i++) { 114 sbuf.append(s[i]); 115 } 116 } 117 } 118 // Normalize the log message level into the supported categories 119 int nt_category = event.getLevel().toInt(); 120 121 // Anything above FATAL or below DEBUG is labeled as INFO. 122 //if (nt_category > FATAL || nt_category < DEBUG) { 123 // nt_category = INFO; 124 //} 125 reportEvent(_handle, sbuf.toString(), nt_category); 126 } 127 128 129 public 130 void finalize() { 131 deregisterEventSource(_handle); 132 _handle = 0; 133 } 134 135 /** 136 The <b>Source</b> option which names the source of the event. The 137 current value of this constant is <b>Source</b>. 138 */ 139 public 140 void setSource(String source) { 141 this.source = source.trim(); 142 } 143 144 public 145 String getSource() { 146 return source; 147 } 148 149/** 150 The <code>NTEventLogAppender</code> requires a layout. Hence, 151 this method always returns <code>true</code>. */ 152 public 153 boolean requiresLayout() { 154 return true; 155 } 156 157 native private int registerEventSource(String server, String source); 158 native private void reportEvent(int handle, String message, int level); 159 native private void deregisterEventSource(int handle); 160 161 static { 162 String[] archs; 163 try { 164 archs = new String[] { System.getProperty("os.arch")}; 165 } catch(SecurityException e) { 166 archs = new String[] { "amd64", "ia64", "x86"}; 167 } 168 boolean loaded = false; 169 for(int i = 0; i < archs.length; i++) { 170 try { 171 System.loadLibrary("NTEventLogAppender." + archs[i]); 172 loaded = true; 173 break; 174 } catch(java.lang.UnsatisfiedLinkError e) { 175 loaded = false; 176 } 177 } 178 if (!loaded) { 179 System.loadLibrary("NTEventLogAppender"); 180 } 181} 182}