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 */ 017package org.apache.log4j.rewrite; 018 019import org.apache.log4j.Appender; 020import org.apache.log4j.AppenderSkeleton; 021import org.apache.log4j.helpers.AppenderAttachableImpl; 022import org.apache.log4j.spi.AppenderAttachable; 023import org.apache.log4j.spi.LoggingEvent; 024import org.apache.log4j.spi.OptionHandler; 025import org.apache.log4j.xml.UnrecognizedElementHandler; 026import org.w3c.dom.Element; 027 028import java.util.Enumeration; 029import java.util.Properties; 030 031/** 032 * This appender forwards a logging request to another 033 * appender after possibly rewriting the logging event. 034 * 035 * This appender (with the appropriate policy) 036 * replaces the MapFilter, PropertyFilter and ReflectionFilter 037 * from log4j 1.3. 038 */ 039public class RewriteAppender extends AppenderSkeleton 040 implements AppenderAttachable, UnrecognizedElementHandler { 041 /** 042 * Rewrite policy. 043 */ 044 private RewritePolicy policy; 045 /** 046 * Nested appenders. 047 */ 048 private final AppenderAttachableImpl appenders; 049 050 public RewriteAppender() { 051 appenders = new AppenderAttachableImpl(); 052 } 053 054 /** 055 * {@inheritDoc} 056 */ 057 protected void append(final LoggingEvent event) { 058 LoggingEvent rewritten = event; 059 if (policy != null) { 060 rewritten = policy.rewrite(event); 061 } 062 if (rewritten != null) { 063 synchronized (appenders) { 064 appenders.appendLoopOnAppenders(rewritten); 065 } 066 } 067 } 068 069 /** 070 * Add appender. 071 * 072 * @param newAppender appender to add, may not be null. 073 */ 074 public void addAppender(final Appender newAppender) { 075 synchronized (appenders) { 076 appenders.addAppender(newAppender); 077 } 078 } 079 080 /** 081 * Get iterator over attached appenders. 082 * @return iterator or null if no attached appenders. 083 */ 084 public Enumeration getAllAppenders() { 085 synchronized (appenders) { 086 return appenders.getAllAppenders(); 087 } 088 } 089 090 /** 091 * Get appender by name. 092 * 093 * @param name name, may not be null. 094 * @return matching appender or null. 095 */ 096 public Appender getAppender(final String name) { 097 synchronized (appenders) { 098 return appenders.getAppender(name); 099 } 100 } 101 102 103 /** 104 * Close this <code>AsyncAppender</code> by interrupting the dispatcher 105 * thread which will process all pending events before exiting. 106 */ 107 public void close() { 108 closed = true; 109 // 110 // close all attached appenders. 111 // 112 synchronized (appenders) { 113 Enumeration iter = appenders.getAllAppenders(); 114 115 if (iter != null) { 116 while (iter.hasMoreElements()) { 117 Object next = iter.nextElement(); 118 119 if (next instanceof Appender) { 120 ((Appender) next).close(); 121 } 122 } 123 } 124 } 125 } 126 127 /** 128 * Determines if specified appender is attached. 129 * @param appender appender. 130 * @return true if attached. 131 */ 132 public boolean isAttached(final Appender appender) { 133 synchronized (appenders) { 134 return appenders.isAttached(appender); 135 } 136 } 137 138 /** 139 * {@inheritDoc} 140 */ 141 public boolean requiresLayout() { 142 return false; 143 } 144 145 /** 146 * Removes and closes all attached appenders. 147 */ 148 public void removeAllAppenders() { 149 synchronized (appenders) { 150 appenders.removeAllAppenders(); 151 } 152 } 153 154 /** 155 * Removes an appender. 156 * @param appender appender to remove. 157 */ 158 public void removeAppender(final Appender appender) { 159 synchronized (appenders) { 160 appenders.removeAppender(appender); 161 } 162 } 163 164 /** 165 * Remove appender by name. 166 * @param name name. 167 */ 168 public void removeAppender(final String name) { 169 synchronized (appenders) { 170 appenders.removeAppender(name); 171 } 172 } 173 174 175 public void setRewritePolicy(final RewritePolicy rewritePolicy) { 176 policy = rewritePolicy; 177 } 178 /** 179 * {@inheritDoc} 180 */ 181 public boolean parseUnrecognizedElement(final Element element, 182 final Properties props) throws Exception { 183 final String nodeName = element.getNodeName(); 184 if ("rewritePolicy".equals(nodeName)) { 185 Object rewritePolicy = 186 org.apache.log4j.xml.DOMConfigurator.parseElement( 187 element, props, RewritePolicy.class); 188 if (rewritePolicy != null) { 189 if (rewritePolicy instanceof OptionHandler) { 190 ((OptionHandler) rewritePolicy).activateOptions(); 191 } 192 this.setRewritePolicy((RewritePolicy) rewritePolicy); 193 } 194 return true; 195 } 196 return false; 197 } 198 199}