/*
* Licensed to the Apache Software Foundation (ASF) under one
* or more contributor license agreements. See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership. The ASF licenses this file
* to you under the Apache License, Version 2.0 (the
* "License"); you may not use this file except in compliance
* with the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing,
* software distributed under the License is distributed on an
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
* KIND, either express or implied. See the License for the
* specific language governing permissions and limitations
* under the License.
*/
package groovy.lang;
import java.io.
IOException;
import java.io.
PrintWriter;
import java.io.
Writer;
/*
* This {@link Interceptor} traces method calls on the proxied object to a log.
* By default, the log is simply <pre>System.out</pre>; however, that can be
* changed with the <pre>setWriter(Writer)</pre> method.
* <p>
* A message will be written to output before a method is invoked and after a method
* is invoked. If methods are nested, and invoke one another, then indentation
* of two spaces is written.
* <p>
* Here is an example usage on the ArrayList object: <br>
* <pre class="groovyTestCase">
* def proxy = ProxyMetaClass.getInstance(ArrayList.class)
* proxy.interceptor = new TracingInterceptor()
* proxy.use {
* def list = [1, 2, 3]
* assert 3 == list.size()
* assert list.contains(1)
* }
* </pre>
* Running this code produces this output:
* <pre>
* before java.util.ArrayList.size()
* after java.util.ArrayList.size()
* before java.util.ArrayList.contains(java.lang.Integer)
* after java.util.ArrayList.contains(java.lang.Integer)
* </pre>
*/
public class
TracingInterceptor implements
Interceptor {
protected
Writer writer = new
PrintWriter(
System.
out);
private int
indent = 0;
/**
* Returns the writer associated with this interceptor.
*/
public
Writer getWriter() {
return
writer;
}
/**
* Changes the writer associated with this interceptor.
*/
public void
setWriter(
Writer writer) {
this.
writer =
writer;
}
public
Object beforeInvoke(
Object object,
String methodName,
Object[]
arguments) {
write(
object,
methodName,
arguments, "before");
indent++ ;
return null;
}
public
Object afterInvoke(
Object object,
String methodName,
Object[]
arguments,
Object result) {
indent--;
write(
object,
methodName,
arguments, "after ");
return
result;
}
public boolean
doInvoke() {
return true;
}
private
String indent(){
StringBuilder result = new
StringBuilder();
for (int
i=0;
i<
indent;
i++){
result.
append(" ");
}
return
result.
toString();
}
protected void
write(
Object object,
String methodName,
Object[]
arguments, final
String origin) {
try {
writer.
write(
indent());
writer.
write(
origin);
writer.
write(" ");
Class theClass =
object instanceof
Class ? (
Class)
object:
object.
getClass();
writeInfo(
theClass,
methodName,
arguments);
writer.
write("\n");
writer.
flush();
} catch (
IOException e) {
e.
printStackTrace();
}
}
protected void
writeInfo(final
Class aClass,
String methodName,
Object[]
arguments) throws
IOException {
writer.
write(
aClass.
getName());
writer.
write(".");
writer.
write(
methodName);
writer.
write("(");
for (int
i = 0;
i <
arguments.length;
i++) {
if (
i > 0)
writer.
write(", ");
Object argument =
arguments[
i];
writer.
write(
argument.
getClass().
getName());
}
writer.
write(")");
}
}