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