com.on_site.frizzle.debug.LoggingFunction.java Source code

Java tutorial

Introduction

Here is the source code for com.on_site.frizzle.debug.LoggingFunction.java

Source

/*
 * Copyright (c) 2013 On-Site.com.
 *
 * Permission is hereby granted, free of charge, to any person obtaining
 * a copy of this software and associated documentation files (the
 * "Software"), to deal in the Software without restriction, including
 * without limitation the rights to use, copy, modify, merge, publish,
 * distribute, sublicense, and/or sell copies of the Software, and to
 * permit persons to whom the Software is furnished to do so, subject to
 * the following conditions:
 *
 * The above copyright notice and this permission notice shall be
 * included in all copies or substantial portions of the Software.
 *
 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
 * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
 * OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE, AND NON-
 * INFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
 * LIABLE FOR ANY CLAIM, DAMAGES, OR OTHER LIABILITY, WHETHER IN AN ACTION
 * OF CONTRACT, TORT, OR OTHERWISE, ARISING FROM, OUT OF, OR IN CONNECTION
 * WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
 */

package com.on_site.frizzle.debug;

import java.util.Arrays;

import com.google.common.base.Joiner;
import com.google.common.base.Objects;
import com.google.common.base.Optional;
import com.google.common.collect.Lists;
import org.mozilla.javascript.Context;
import org.mozilla.javascript.Function;
import org.mozilla.javascript.Scriptable;

/**
 * A version of {@link Function} with extensive logging.
 *
 * @author Chris K. Jester-Young
 */
public class LoggingFunction extends ForwardingFunction {
    private class Delegate implements LoggingMixin.Delegate {
        @Override
        public boolean has(String name, Scriptable start) {
            return LoggingFunction.super.has(name, start);
        }

        @Override
        public boolean has(int index, Scriptable start) {
            return LoggingFunction.super.has(index, start);
        }

        @Override
        public Object get(String name, Scriptable start) {
            return LoggingFunction.super.get(name, start);
        }

        @Override
        public Object get(int index, Scriptable start) {
            return LoggingFunction.super.get(index, start);
        }

        @Override
        public void put(String name, Scriptable start, Object value) {
            LoggingFunction.super.put(name, start, value);
        }

        @Override
        public void put(int index, Scriptable start, Object value) {
            LoggingFunction.super.put(index, start, value);
        }

        @Override
        public void delete(String name) {
            LoggingFunction.super.delete(name);
        }

        @Override
        public void delete(int index) {
            LoggingFunction.super.delete(index);
        }

        @Override
        public String toString() {
            return Objects.toStringHelper(this).add("this", LoggingFunction.this).toString();
        }
    }

    private final String name;
    private final Function func;
    private final LoggingMixin mixin;

    public LoggingFunction(String name, Function func) {
        this.name = name;
        this.func = func;
        this.mixin = createMixin();
    }

    private LoggingMixin createMixin() {
        return new LoggingMixin(new Delegate());
    }

    @Override
    protected Function delegate() {
        return func;
    }

    @Override
    public Object get(String name, Scriptable start) {
        return mixin.get(name, start);
    }

    @Override
    public Object get(int index, Scriptable start) {
        return mixin.get(index, start);
    }

    @Override
    public boolean has(String name, Scriptable start) {
        return mixin.has(name, start);
    }

    @Override
    public boolean has(int index, Scriptable start) {
        return mixin.has(index, start);
    }

    @Override
    public void put(String name, Scriptable start, Object value) {
        mixin.put(name, start, value);
    }

    @Override
    public void put(int index, Scriptable start, Object value) {
        mixin.put(index, start, value);
    }

    @Override
    public void delete(String name) {
        mixin.delete(name);
    }

    @Override
    public void delete(int index) {
        mixin.delete(index);
    }

    @Override
    public Object call(Context cx, Scriptable scope, Scriptable thisObj, Object[] args) {
        Optional<Object> value = null;
        try {
            value = Optional.fromNullable(func.call(cx, scope, thisObj, args));
            return LoggingMixin.instrument(Object.class, name + "()", value);
        } finally {
            String lhs = thisObj == null ? name : thisObj + name;
            if (value == null) {
                LoggingMixin.log("{0}({1}) => abrupt", lhs, printableArgs(args));
            } else {
                LoggingMixin.log("{0}({1}) => {2}", lhs, printableArgs(args), value.orNull());
            }
        }
    }

    @Override
    public Scriptable construct(Context cx, Scriptable scope, Object[] args) {
        Optional<Scriptable> value = null;
        try {
            value = Optional.fromNullable(func.construct(cx, scope, args));
            return LoggingMixin.instrument(Scriptable.class, "new " + name + "()", value);
        } finally {
            if (value == null) {
                LoggingMixin.log("new {0}({1}) => abrupt", name, printableArgs(args));
            } else {
                LoggingMixin.log("new {0}({1}) => {2}", name, printableArgs(args), value.orNull());
            }
        }
    }

    private static String printableArgs(Object[] args) {
        return Joiner.on(", ")
                .join(Lists.transform(Arrays.asList(args), new com.google.common.base.Function<Object, String>() {
                    @Override
                    public String apply(Object obj) {
                        return obj instanceof String ? '"' + (String) obj + '"' : String.valueOf(obj);
                    }
                }));
    }
}