001// *************************************************************************************************************************** 002// * Licensed to the Apache Software Foundation (ASF) under one or more contributor license agreements. See the NOTICE file * 003// * distributed with this work for additional information regarding copyright ownership. The ASF licenses this file * 004// * to you under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance * 005// * with the License. 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 distributed under the License is distributed on an * 010// * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the * 011// * specific language governing permissions and limitations under the License. * 012// *************************************************************************************************************************** 013package org.apache.juneau.utils; 014 015import java.lang.reflect.*; 016 017import org.apache.juneau.mstat.*; 018 019/** 020 * A wrapper around a {@link Method#invoke(Object, Object...)} method that allows for basic instrumentation. 021 */ 022public class MethodInvoker { 023 private final Method m; 024 private final MethodExecStats stats; 025 026 /** 027 * Constructor. 028 * 029 * @param m The method being wrapped. 030 * @param stats The instrumentor. 031 */ 032 public MethodInvoker(Method m, MethodExecStats stats) { 033 this.m = m; 034 this.stats = stats; 035 } 036 037 /** 038 * Returns the inner method. 039 * 040 * @return The inner method. 041 */ 042 public Method inner() { 043 return m; 044 } 045 046 /** 047 * Invokes the underlying method. 048 * 049 * @param o The object the underlying method is invoked from. 050 * @param args The arguments used for the method call. 051 * @return The result of dispatching the method represented by this object on {@code obj} with parameters {@code args} 052 * @throws IllegalAccessException Thrown from underlying method. 053 * @throws IllegalArgumentException Thrown from underlying method. 054 * @throws InvocationTargetException Thrown from underlying method. 055 */ 056 public Object invoke(Object o, Object...args) throws IllegalAccessException, IllegalArgumentException, InvocationTargetException { 057 long startTime = System.nanoTime(); 058 stats.started(); 059 try { 060 return m.invoke(o, args); 061 } catch (IllegalAccessException|IllegalArgumentException e) { 062 stats.error(e); 063 throw e; 064 } catch (InvocationTargetException e) { 065 stats.error(e.getTargetException()); 066 throw e; 067 } finally { 068 stats.finished(System.nanoTime() - startTime); 069 } 070 } 071 072 /** 073 * Convenience method for calling <c>inner().getDeclaringClass()</c> 074 * 075 * @return The declaring class of the method. 076 */ 077 public Class<?> getDeclaringClass() { 078 return m.getDeclaringClass(); 079 } 080 081 /** 082 * Convenience method for calling <c>inner().getName()</c> 083 * 084 * @return The name of the method. 085 */ 086 public String getName() { 087 return m.getName(); 088 } 089}