// Copyright 2012 Google Inc. All Rights Reserved. // // Licensed 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 com.google.enterprise.adaptor.sharepoint; import java.lang.annotation.Annotation; import java.lang.reflect.InvocationHandler; import java.lang.reflect.InvocationTargetException; import java.lang.reflect.Method; import java.lang.reflect.Proxy; import java.util.logging.Level; import java.util.logging.Logger; import javax.jws.WebMethod; import javax.jws.WebParam; import javax.xml.ws.Holder; /** * InvocationHandler that can wrap WebService instances and log input/output * values. This is more helpful than manual logging because it checks the * mode of a parameter and only prints it when appropriate. The mode of a * parameter defines when it is sent, so this logging method accurately * represents the exchange of information. */ class LoggingWSHandler implements InvocationHandler { private static final Logger log = Logger.getLogger(LoggingWSHandler.class.getName()); private final Object wrapped; public LoggingWSHandler(Object wrapped) { this.wrapped = wrapped; } public static <T> T create(Class<T> webServiceInterface, T wrapped) { InvocationHandler invokeHandler = new LoggingWSHandler(wrapped); Object oInstance = Proxy.newProxyInstance( LoggingWSHandler.class.getClassLoader(), new Class<?>[] {webServiceInterface}, invokeHandler); @SuppressWarnings("unchecked") T tInstance = (T) oInstance; return tInstance; } @Override public Object invoke(Object proxy, Method method, Object[] args) throws Throwable { final Level logLevel = Level.FINE; String inArgs = null; if (log.isLoggable(logLevel)) { WebMethod webMethod = method.getAnnotation(WebMethod.class); if (webMethod != null) { inArgs = formArgumentString(method, args, WebParam.Mode.IN); log.log(logLevel, "WS Request {0}: {1}", new Object[] {webMethod.operationName(), inArgs}); } } Object ret; long startMillis = System.currentTimeMillis(); try { ret = method.invoke(wrapped, args); } catch (IllegalAccessException ex) { throw new RuntimeException("Misconfigured LoggingWSHandler", ex); } catch (IllegalArgumentException ex) { throw new RuntimeException("Misconfigured LoggingWSHandler", ex); } catch (InvocationTargetException ex) { throw ex.getCause(); } if (log.isLoggable(logLevel)) { WebMethod webMethod = method.getAnnotation(WebMethod.class); if (webMethod != null) { String outArgs = formArgumentString(method, args, WebParam.Mode.OUT); log.log(logLevel, "WS Response {0}: {1}", new Object[] {webMethod.operationName(), outArgs}); log.log(logLevel, "Duration: WS Request {0} - {1} : {2,number,#} ms", new Object[] {webMethod.operationName(), inArgs, System.currentTimeMillis() - startMillis}); } } return ret; } private String formArgumentString(Method method, Object[] args, WebParam.Mode mode) { StringBuilder argsBuffer = new StringBuilder(); Annotation[][] annotates = method.getParameterAnnotations(); if (annotates.length != 0 && annotates.length != args.length) { throw new AssertionError(); } for (int i = 0; i < annotates.length; i++) { for (Annotation annotate : annotates[i]) { if (!(annotate instanceof WebParam)) { break; } WebParam webParam = (WebParam) annotate; if (webParam.mode() == mode || webParam.mode() == WebParam.Mode.INOUT) { argsBuffer.append(", ").append(webParam.name()).append("="); if (webParam.mode() == WebParam.Mode.IN) { argsBuffer.append("" + args[i]); } else { Holder<?> holder = (Holder<?>) args[i]; argsBuffer.append( holder == null ? "<null holder>" : "" + holder.value); } } } } return argsBuffer.length() > 1 ? argsBuffer.substring(2) : ""; } }