001: // THIS SOFTWARE IS PROVIDED BY SOFTARIS PTY.LTD. AND OTHER METABOSS
002: // CONTRIBUTORS ``AS IS'' AND ANY EXPRESSED OR IMPLIED WARRANTIES, INCLUDING,
003: // BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
004: // FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL SOFTARIS PTY.LTD.
005: // OR OTHER METABOSS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
006: // INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
007: // LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA,
008: // OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
009: // LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
010: // NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE,
011: // EVEN IF SOFTARIS PTY.LTD. OR OTHER METABOSS CONTRIBUTORS ARE ADVISED OF THE
012: // POSSIBILITY OF SUCH DAMAGE.
013: //
014: // Copyright 2000-2005 © Softaris Pty.Ltd. All Rights Reserved.
015: package com.metaboss.componentproxy.logging;
016:
017: import java.lang.reflect.InvocationHandler;
018: import java.lang.reflect.InvocationTargetException;
019: import java.lang.reflect.Method;
020: import java.util.Collections;
021: import java.util.HashSet;
022: import java.util.Set;
023:
024: import org.apache.commons.logging.Log;
025: import org.apache.commons.logging.LogFactory;
026:
027: /** This is the generic logging proxy, which just logs method invocations */
028: public class LoggingProxyImpl implements InvocationHandler {
029: private static Set sDisplayedWarningsMap = Collections
030: .synchronizedSet(new HashSet());
031: private static final String sWarningText = "Debug level logging for the {0} is switched off. Component method invocations will not be reported.";
032: private static long sCallCounter = 0; // Each method invocation gets unique counter
033: private Object mUnderlyingObject = null;
034: private Class mUnderlyingObjectClass = null;
035: private String mUnderlyingObjectClassName = null;
036: private static Log sProxyLogger = LogFactory
037: .getLog(LoggingProxyImpl.class);
038: private Log mUnderlyingObjectLogger = null;
039:
040: /** The only available constructor. Sets the proxy up for the particular underlying object */
041: public LoggingProxyImpl(Object pUnderlyingObject) {
042: mUnderlyingObject = pUnderlyingObject;
043: mUnderlyingObjectClass = mUnderlyingObject.getClass();
044: mUnderlyingObjectClassName = mUnderlyingObjectClass.getName();
045: mUnderlyingObjectLogger = LogFactory
046: .getLog(mUnderlyingObjectClass);
047: if (mUnderlyingObjectLogger.isDebugEnabled() == false
048: && sDisplayedWarningsMap
049: .contains(mUnderlyingObjectClassName) == false) {
050: // Usual pattern to guard against racing
051: synchronized (sDisplayedWarningsMap) {
052: if (sDisplayedWarningsMap
053: .contains(mUnderlyingObjectClassName) == false) {
054: String lFormattedWarningText = java.text.MessageFormat
055: .format(
056: sWarningText,
057: new String[] { mUnderlyingObjectClassName });
058: if (sProxyLogger.isWarnEnabled())
059: sProxyLogger.warn(lFormattedWarningText);
060: else if (sProxyLogger.isInfoEnabled())
061: sProxyLogger.info(lFormattedWarningText);
062: else
063: System.err.println(lFormattedWarningText);
064: sDisplayedWarningsMap
065: .add(mUnderlyingObjectClassName);
066: }
067: }
068: }
069: }
070:
071: /** Generic handler method processed every invocation of every method */
072: public Object invoke(Object proxy, Method method, Object[] args)
073: throws Throwable {
074: long lCallCounter = ++sCallCounter;
075: if (mUnderlyingObjectLogger.isDebugEnabled()) {
076: // Special pattern to surround the method invocation with the logging messages
077: try {
078: mUnderlyingObjectLogger.debug("[" + lCallCounter
079: + "] About to invoke "
080: + mUnderlyingObjectClassName + "."
081: + method.getName());
082: try {
083: Object lReturn = method.invoke(mUnderlyingObject,
084: args);
085: mUnderlyingObjectLogger.debug("[" + lCallCounter
086: + "] Invocation complete");
087: return lReturn;
088: } catch (InvocationTargetException e) {
089: // Make this proxy "invisible"
090: throw e.getCause();
091: }
092: } catch (Throwable t) {
093: mUnderlyingObjectLogger.debug("[" + lCallCounter
094: + "] Invocation has resulted in exception.", t);
095: throw t;
096: }
097: } else {
098: try {
099: return method.invoke(mUnderlyingObject, args);
100: } catch (InvocationTargetException e) {
101: // Make this proxy "invisible"
102: throw e.getCause();
103: }
104: }
105: }
106: }
|