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