001 // Copyright 2006, 2007, 2008, 2011 The Apache Software Foundation
002 //
003 // Licensed under the Apache License, Version 2.0 (the "License");
004 // you may not use this file except in compliance with the License.
005 // You may obtain a copy of the License at
006 //
007 // http://www.apache.org/licenses/LICENSE-2.0
008 //
009 // Unless required by applicable law or agreed to in writing, software
010 // distributed under the License is distributed on an "AS IS" BASIS,
011 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
012 // See the License for the specific language governing permissions and
013 // limitations under the License.
014
015 package org.apache.tapestry5.ioc.internal.services;
016
017 import org.apache.tapestry5.ioc.services.ExceptionTracker;
018 import org.apache.tapestry5.plastic.MethodInvocation;
019 import org.slf4j.Logger;
020
021 import java.util.Iterator;
022
023 import static java.lang.String.format;
024
025 /**
026 * Used by {@link org.apache.tapestry5.ioc.internal.services.LoggingDecoratorImpl} to delegate out logging behavior to a
027 * separate object.
028 */
029 public final class MethodLogger
030 {
031 private static final int BUFFER_SIZE = 200;
032
033 private static final String ENTER = "ENTER";
034
035 private static final String EXIT = " EXIT";
036
037 private static final String FAIL = " FAIL";
038
039 private final Logger logger;
040
041 private final ExceptionTracker exceptionTracker;
042
043 public MethodLogger(Logger logger, ExceptionTracker exceptionTracker)
044 {
045 this.logger = logger;
046 this.exceptionTracker = exceptionTracker;
047 }
048
049 public boolean isDebugEnabled()
050 {
051 return logger.isDebugEnabled();
052 }
053
054 /**
055 * Invoked when a method is first entered
056 *
057 * @param invocation identifies method invoked as well as parameters passed to method
058 */
059 public void entry(MethodInvocation invocation)
060 {
061 StringBuilder buffer = new StringBuilder(BUFFER_SIZE);
062
063 buffer.append(format("[%s] %s(", ENTER, invocation.getMethod().getName()));
064
065 for (int i = 0; i < invocation.getMethod().getParameterTypes().length; i++)
066 {
067 if (i > 0) buffer.append(", ");
068
069 convert(buffer, invocation.getParameter(i));
070 }
071
072 buffer.append(")");
073
074 logger.debug(buffer.toString());
075 }
076
077 private void convert(StringBuilder buffer, Object object)
078 {
079 if (object == null)
080 {
081 buffer.append("null");
082 return;
083 }
084
085 // Minimal, alas: Doesn't handle embedded quotes and other
086 // characters. Really want to convert the string back to what it
087 // would look like as source code.
088
089 if (object instanceof String)
090 {
091 buffer.append("\"");
092 buffer.append(object.toString());
093 buffer.append("\"");
094 return;
095 }
096
097 if (object instanceof Object[])
098 {
099 Object[] values = (Object[]) object;
100 buffer.append('{');
101
102 for (int i = 0; i < values.length; i++)
103 {
104 if (i > 0) buffer.append(", ");
105
106 convert(buffer, values[i]);
107 }
108
109 buffer.append('}');
110 return;
111 }
112
113 if (object instanceof Iterable)
114 {
115 Iterable itr = (Iterable) object;
116 boolean first = true;
117
118 buffer.append('[');
119 Iterator i = itr.iterator();
120 while (i.hasNext())
121 {
122 if (!first) buffer.append(", ");
123
124 convert(buffer, i.next());
125 first = false;
126 }
127 buffer.append(']');
128 return;
129 }
130
131 // Might need to add a few more, for things like character values ...
132
133 buffer.append(object.toString());
134 }
135
136 /**
137 * Invoked when a method exits (possibly returning a value).
138 *
139 * @param invocation identifies method invocation and result value
140 */
141 public void exit(MethodInvocation invocation)
142 {
143 StringBuilder buffer = new StringBuilder(BUFFER_SIZE);
144
145 buffer.append(format("[%s] %s", EXIT, invocation.getMethod().getName()));
146
147 if (invocation.getMethod().getReturnType() != void.class)
148 {
149 buffer.append(" [");
150 convert(buffer, invocation.getReturnValue());
151 buffer.append(']');
152 }
153
154 logger.debug(buffer.toString());
155 }
156
157 /**
158 * Invoked when method invocation instead throws an exception.
159 *
160 * @param invocation identifies method invocation which failed
161 * @param t exception throws by method invocation
162 */
163 public void fail(MethodInvocation invocation, Throwable t)
164 {
165 logger.debug(
166 format("[%s] %s -- %s", FAIL,
167 invocation.getMethod().getName(),
168 t.getClass().getName()),
169 exceptionTracker.exceptionLogged(t) ? null : t);
170 }
171 }