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 018 package org.apache.commons.proxy.interceptor; 019 020 import org.apache.commons.logging.Log; 021 import org.apache.commons.proxy.ProxyUtils; 022 import org.apache.commons.proxy.Interceptor; 023 import org.apache.commons.proxy.Invocation; 024 025 /** 026 * An interceptor which logs each method invocation. 027 * <b>Note</b>: The implementation of this class was borrowed from 028 * HiveMind's logging interceptor. 029 * 030 * <p> 031 * <b>Dependencies</b>: 032 * <ul> 033 * <li>Apache Commons Logging version 1.0.4 or greater</li> 034 * </ul> 035 * </p> 036 * @author James Carman 037 * @since 1.0 038 */ 039 public class LoggingInterceptor implements Interceptor 040 { 041 //---------------------------------------------------------------------------------------------------------------------- 042 // Fields 043 //---------------------------------------------------------------------------------------------------------------------- 044 045 private static final int BUFFER_SIZE = 100; 046 private Log log; 047 048 //---------------------------------------------------------------------------------------------------------------------- 049 // Constructors 050 //---------------------------------------------------------------------------------------------------------------------- 051 052 public LoggingInterceptor( Log log ) 053 { 054 this.log = log; 055 } 056 057 //---------------------------------------------------------------------------------------------------------------------- 058 // MethodInterceptor Implementation 059 //---------------------------------------------------------------------------------------------------------------------- 060 061 public Object intercept( Invocation invocation ) throws Throwable 062 { 063 if( log.isDebugEnabled() ) 064 { 065 final String methodName = invocation.getMethod().getName(); 066 entry( methodName, invocation.getArguments() ); 067 try 068 { 069 Object result = invocation.proceed(); 070 if( Void.TYPE.equals( invocation.getMethod().getReturnType() ) ) 071 { 072 voidExit( methodName ); 073 } 074 else 075 { 076 exit( methodName, result ); 077 } 078 return result; 079 } 080 catch( Throwable t ) 081 { 082 exception( methodName, t ); 083 throw t; 084 } 085 } 086 else 087 { 088 return invocation.proceed(); 089 } 090 } 091 092 //---------------------------------------------------------------------------------------------------------------------- 093 // Other Methods 094 //---------------------------------------------------------------------------------------------------------------------- 095 096 private void entry( String methodName, Object[] args ) 097 { 098 StringBuffer buffer = new StringBuffer( BUFFER_SIZE ); 099 buffer.append( "BEGIN " ); 100 buffer.append( methodName ); 101 buffer.append( "(" ); 102 int count = args.length; 103 for( int i = 0; i < count; i++ ) 104 { 105 Object arg = args[i]; 106 if( i > 0 ) 107 { 108 buffer.append( ", " ); 109 } 110 convert( buffer, arg ); 111 } 112 buffer.append( ")" ); 113 log.debug( buffer.toString() ); 114 } 115 116 private void convert( StringBuffer buffer, Object input ) 117 { 118 if( input == null ) 119 { 120 buffer.append( "<null>" ); 121 return; 122 } 123 124 // Primitive types, and non-object arrays 125 // use toString(). Less than ideal for int[], etc., but 126 // that's a lot of work for a rare case. 127 if( !( input instanceof Object[] ) ) 128 { 129 buffer.append( input.toString() ); 130 return; 131 } 132 buffer.append( "(" ); 133 buffer.append( ProxyUtils.getJavaClassName( input.getClass() ) ); 134 buffer.append( "){" ); 135 Object[] array = ( Object[] ) input; 136 int count = array.length; 137 for( int i = 0; i < count; i++ ) 138 { 139 if( i > 0 ) 140 { 141 buffer.append( ", " ); 142 } 143 144 // We use convert() again, because it could be a multi-dimensional array 145 // (god help us) where each element must be converted. 146 convert( buffer, array[i] ); 147 } 148 buffer.append( "}" ); 149 } 150 151 private void exception( String methodName, Throwable t ) 152 { 153 StringBuffer buffer = new StringBuffer( BUFFER_SIZE ); 154 buffer.append( "EXCEPTION " ); 155 buffer.append( methodName ); 156 buffer.append( "() -- " ); 157 buffer.append( t.getClass().getName() ); 158 log.debug( buffer.toString(), t ); 159 } 160 161 private void exit( String methodName, Object result ) 162 { 163 StringBuffer buffer = new StringBuffer( BUFFER_SIZE ); 164 buffer.append( "END " ); 165 buffer.append( methodName ); 166 buffer.append( "() [" ); 167 convert( buffer, result ); 168 buffer.append( "]" ); 169 log.debug( buffer.toString() ); 170 } 171 172 private void voidExit( String methodName ) 173 { 174 StringBuffer buffer = new StringBuffer( BUFFER_SIZE ); 175 buffer.append( "END " ); 176 buffer.append( methodName ); 177 buffer.append( "()" ); 178 log.debug( buffer.toString() ); 179 } 180 } 181