Package com.github.zhongl.housemd.command

Source Code of com.github.zhongl.housemd.command.Inspect$FieldFilter

/*
* Copyright 2013 zhongl
*
*  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.github.zhongl.housemd.command;

import com.github.zhongl.housemd.instrument.Context;
import com.github.zhongl.housemd.instrument.Hook;
import com.github.zhongl.yascli.PrintOut;
import scala.Function0;
import scala.runtime.AbstractFunction1;

import java.lang.instrument.Instrumentation;
import java.lang.reflect.Field;
import java.util.HashSet;
import java.util.List;
import java.util.Set;

import static com.github.zhongl.housemd.misc.ReflectionUtils.simpleNameOf;
import static com.github.zhongl.yascli.JavaConvertions.manifest;
import static com.github.zhongl.yascli.JavaConvertions.none;

/**
* @author <a href="mailto:zhong.lunfu@gmail.com">zhongl<a>
*/
public class Inspect extends TransformCommand implements FieldFilterCompleter {

    private final Function0<FieldFilter> fieldFilter = parameter(
            "field-filter",
            "field filter pattern like \"ClassSimpleName.fieldName\".",
            none(FieldFilter.class),
            manifest(FieldFilter.class),
            new AbstractFunction1<String, FieldFilter>() {
                @Override
                public FieldFilter apply(String value) {
                    return new FieldFilter(value);
                }
            });

    private final Instrumentation inst;

    public Inspect(Instrumentation inst, PrintOut out) {
        super("inspect", "display fields of a class.", inst, out);
        this.inst = inst;
    }

    public Instrumentation inst() {
        return inst;
    }

    @Override
    public boolean isCandidate(Class<?> klass) {
        return fieldFilter.apply().filter(klass);
    }

    @Override
    public boolean isDecorating(Class<?> klass, String methodName) {
        return true;
    }

    @Override
    public Hook hook() {
        return new Hook() {
            private final Set<Object> targets = new HashSet<Object>();
            private final FieldFilter accessor = fieldFilter.apply();

            public void enterWith(Context context) {
            }

            public void exitWith(Context context) {
                targets.add(context.thisObject());
            }

            public void heartbeat(long now) {
                if (targets.isEmpty())
                    println("Can't inspect " + accessor + " because there's no invocation on " + accessor.classSimpleName);
                else
                    for (Object target : targets) printStat(target);
                println();
            }

            private void printStat(Object target) {
                try {
                    println(accessor + " " + accessor.getField(target) + " " + target + " " + target.getClass().getClassLoader());
                } catch (Exception e) {
                    error(e);
                }
            }

            public void finalize(scala.Option<Throwable> throwable) {
                heartbeat(0L); // last print
                targets.clear();
            }
        };
    }

    @Override
    public int complete(String buffer, int cursor, List<CharSequence> candidates) {
        return ClassSimpleNameCompleter$class.complete(this, buffer, cursor, candidates);
    }

    @Override
    public int completeClassSimpleName(String buffer, int cursor, List<CharSequence> candidates) {
        return ClassMemberCompleter$class.completeClassSimpleName(this, buffer, cursor, candidates);
    }

    @Override
    public String[] collectLoadedClassNames(String prefix) {
        return ClassMemberCompleter$class.collectLoadedClassNames(this, prefix);
    }

    @Override
    public int completeAll(String classSimpleName, int cursor, List<CharSequence> candidates) {
        return FieldFilterCompleter$class.completeAll(this, classSimpleName, cursor, candidates);
    }

    @Override
    public int complete(String simpleName, String prefix, int cursor, List<CharSequence> candidates) {
        return FieldFilterCompleter$class.complete(this, simpleName, prefix, cursor, candidates);
    }

    public int com$github$zhongl$housemd$command$ClassMemberCompleter$$super$completeClassSimpleName(
            String buffer, int cursor, List<CharSequence> candidates) {
        return ClassSimpleNameCompleter$class.completeClassSimpleName(this, buffer, cursor, candidates);
    }

    static class FieldFilter {

        private final String classSimpleName;
        private final String fieldName;

        public FieldFilter(String value) {
            String[] split = value.split("\\.");
            if (split.length != 2)
                throw new IllegalArgumentException(", it should be \"ClassSimpleName.fieldName\"");
            classSimpleName = split[0];
            fieldName = split[1];
        }

        private boolean filterOnly(String className, String superClassName, String[] interfaceNames) {
            if (classSimpleName.endsWith("+")) {
                String realname = classSimpleName.substring(0, classSimpleName.length() - 1);
                return (simpleNameOf(className).equals(realname) ||
                        superClassName != null && simpleNameOf(superClassName).equals(realname)) ||
                        contain(realname, interfaceNames);
            } else {
                return simpleNameOf(className).equals(classSimpleName);
            }
        }

        private boolean contain(String realname, String[] interfaceNames) {
            for (String interfaceName : interfaceNames) {
                if (simpleNameOf(interfaceName).equals(realname)) return true;
            }
            return false;
        }

        public boolean filter(Class<?> c) {
            String superClassName = (c.getSuperclass() == null) ? null : c.getSuperclass().getName();
            Class<?>[] interfaces = c.getInterfaces();
            String[] interfaceNames = new String[interfaces.length];
            for (int i = 0; i < interfaceNames.length; i++) {
                interfaceNames[i] = interfaces[i].getName();
            }
            return filterOnly(c.getName(), superClassName, interfaceNames);
        }

        public Object getField(Object obj) throws Exception {
            Field field = obj.getClass().getDeclaredField(fieldName);
            field.setAccessible(true);
            return field.get(obj);
        }

        @Override
        public String toString() {
            return classSimpleName + "." + fieldName;
        }
    }
}
TOP

Related Classes of com.github.zhongl.housemd.command.Inspect$FieldFilter

TOP
Copyright © 2018 www.massapi.com. All rights reserved.
All source code are property of their respective owners. Java is a trademark of Sun Microsystems, Inc and owned by ORACLE Inc. Contact coftware#gmail.com.