Logs.java revision 7b2b76255593f0ecfbe2d7f996712fefb391dfed
1/*
2 * Copyright (C) 2013 DroidDriver committers
3 *
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7 *
8 *      http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 */
16
17package com.google.android.droiddriver.util;
18
19import android.util.Log;
20
21import com.google.common.base.Joiner;
22import com.google.common.base.Preconditions;
23import com.google.common.reflect.Reflection;
24
25import java.lang.annotation.ElementType;
26import java.lang.annotation.Retention;
27import java.lang.annotation.RetentionPolicy;
28import java.lang.annotation.Target;
29import java.lang.reflect.InvocationHandler;
30import java.lang.reflect.InvocationTargetException;
31import java.lang.reflect.Method;
32
33/**
34 * Internal helper for logging.
35 */
36public class Logs {
37  public static final String TAG = "DroidDriver";
38  public static final boolean DEBUG = Log.isLoggable(TAG, Log.DEBUG);
39
40  // support TYPE as well?
41  @Target({ElementType.METHOD, ElementType.CONSTRUCTOR})
42  @Retention(RetentionPolicy.RUNTIME)
43  public @interface Loggable {
44    int priority() default Log.DEBUG;
45  }
46
47  /**
48   * An {@link InvocationHandler} that logs invocations of {@link Loggable}
49   * methods.
50   */
51  public static class LoggingWrapper implements InvocationHandler {
52    private final Object wrapped;
53
54    public LoggingWrapper(Object wrapped) {
55      this.wrapped = Preconditions.checkNotNull(wrapped);
56      assert !(wrapped instanceof LoggingWrapper); // prevent recursion
57    }
58
59    @Override
60    public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
61      if (method.isAnnotationPresent(Loggable.class)) {
62        Log.println(
63            method.getAnnotation(Loggable.class).priority(),
64            TAG,
65            String.format("Invoking %s.%s(%s)", method.getDeclaringClass().getName(),
66                method.getName(), Joiner.on(",").join(args)));
67      }
68      try {
69        return method.invoke(wrapped, args);
70        // TODO: log return value as well
71      } catch (InvocationTargetException e) {
72        throw e.getTargetException();
73      }
74    }
75  }
76
77  /**
78   * Wraps {@code obj} in a {@link LoggingWrapper}.
79   */
80  public static <I> I wrap(Class<I> interfaceType, I obj) {
81    return Reflection.newProxy(interfaceType, new LoggingWrapper(obj));
82  }
83
84  private Logs() {}
85}
86