org.operamasks.faces.debug.Debug.java Source code

Java tutorial

Introduction

Here is the source code for org.operamasks.faces.debug.Debug.java

Source

/*
 * $$Id: Debug.java,v 1.6 2008/01/30 07:58:15 yangdong Exp $$
 *
 * Copyright (C) 2006 Operamasks Community.
 * Copyright (C) 2000-2006 Apusic Systems, Inc.
 *
 * This program is free software: you can redistribute it and/or modify
 * it under the terms of the GNU General Public License as published by
 * the Free Software Foundation, either version 3 of the License, or
 * any later version.
 *
 * This program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU General Public License for more details.
 *
 * You should have received a copy of the GNU General Public License
 * along with this program. If not, see http://www.gnu.org/licenses.
 */

package org.operamasks.faces.debug;

import java.io.OutputStream;
import java.lang.reflect.Field;
import java.lang.reflect.Method;
import java.util.HashMap;
import java.util.Map;
import java.util.logging.LogManager;
import java.util.logging.LogRecord;
import java.util.logging.Logger;
import java.util.logging.StreamHandler;
import java.util.regex.Pattern;

import javax.faces.component.UIComponent;
import javax.faces.component.UIComponentBase;
import javax.faces.context.FacesContext;

import org.apache.commons.io.output.ByteArrayOutputStream;

public class Debug {
    private static final String KEY_DEBUG_MODE = "org.operamasks.faces.DEBUG_MODE";
    private static final String NAME_DEBUG_LOGGER = "org.operamasks.faces.Debug";
    private static final String NAME_DEBUG_RESOURCES = "org.operamasks.faces.debug.Debug_Messages";

    private static String[] COMPONENT_LIFECYCLE_METHODS = new String[] { "encodeAll", "encodeBegin",
            "encodeChildren", "encodeEnd", "processDecodes", "processValidators", "processUpdates", "broadcast" };

    private static String[] RENDERER_LIFECYCLE_METHODS = new String[] { "encodeBegin", "encodeChildren",
            "encodeEnd", "decode" };

    static {
        LogManager.getLogManager().addLogger(new DebugLogger(NAME_DEBUG_LOGGER, NAME_DEBUG_RESOURCES));
    }

    public static Map<DebugMode, Object> createDefaultDebugMode() {
        Map<DebugMode, Object> debugMode = new HashMap<DebugMode, Object>();
        debugMode.put(DebugMode.RESTORE_VIEW, false);
        debugMode.put(DebugMode.APPLY_REQUEST_VALUES, false);
        debugMode.put(DebugMode.PROCESS_VALIDATIONS, false);
        debugMode.put(DebugMode.INVOKE_APPLICATION, false);
        debugMode.put(DebugMode.RENDER_RESPONSE, false);

        debugMode.put(DebugMode.INCLUDE_COMPONENT_IDS, new String[0]);
        debugMode.put(DebugMode.EXCLUDE_COMPONENT_IDS, new String[0]);
        debugMode.put(DebugMode.INCLUDE_COMPONENT_CLASSES, new String[0]);
        debugMode.put(DebugMode.EXCLUDE_COMPONENT_CLASSES, new String[0]);
        debugMode.put(DebugMode.INCLUDE_COMPONENT_METHODS, new String[0]);
        debugMode.put(DebugMode.EXCLUDE_COMPONENT_METHODS, new String[0]);

        debugMode.put(DebugMode.INCLUDE_RENDERER_TYPES, new String[0]);
        debugMode.put(DebugMode.EXCLUDE_RENDERER_TYPES, new String[0]);
        debugMode.put(DebugMode.INCLUDE_RENDERER_METHODS, new String[0]);
        debugMode.put(DebugMode.EXCLUDE_RENDERER_METHODS, new String[0]);

        debugMode.put(DebugMode.EXCEPTION, false);
        debugMode.put(DebugMode.UNCOMPRESSED_JS, false);
        debugMode.put(DebugMode.MISC, false);

        return debugMode;
    }

    @SuppressWarnings("unchecked")
    public static boolean isEnabled(FacesContext context, DebugMode mode) {
        Object obj = getValue(mode);

        if (obj == null)
            return false;

        if (obj instanceof Boolean)
            return ((Boolean) obj).booleanValue();

        return true;
    }

    public static Object getValue(FacesContext context, DebugMode mode) {
        return getDebugMode(context).get(mode);
    }

    @SuppressWarnings("unchecked")
    private static Map<DebugMode, Object> getDebugMode(FacesContext context) {
        Map<DebugMode, Object> debugMode = (Map<DebugMode, Object>) context.getExternalContext().getApplicationMap()
                .get(KEY_DEBUG_MODE);

        if (debugMode == null) {
            debugMode = createDefaultDebugMode();
            context.getExternalContext().getApplicationMap().put(KEY_DEBUG_MODE, debugMode);
        }

        return debugMode;
    }

    public static boolean isEnabled(DebugMode mode) {
        return isEnabled(FacesContext.getCurrentInstance(), mode);
    }

    public static Object getValue(DebugMode mode) {
        return getValue(FacesContext.getCurrentInstance(), mode);
    }

    public static void setValue(DebugMode mode, Object value) {
        getDebugMode(FacesContext.getCurrentInstance()).put(mode, value);
    }

    public static void setValue(FacesContext context, DebugMode mode, Object value) {
        getDebugMode(context).put(mode, value);
    }

    public static Logger getLogger() {
        return Logger.getLogger(NAME_DEBUG_LOGGER);
    }

    private static class DebugLogger extends Logger {
        protected DebugLogger(String name, String resourceBundleName) {
            super(name, resourceBundleName);
            addHandler(new DebugLogHandler());
        }

        @Override
        public void log(LogRecord record) {
            record.setSourceClassName(NAME_DEBUG_LOGGER);
            record.setSourceMethodName(null);

            super.log(record);
        }
    }

    private static final String KEY_DEBUGLOGHANDLER_OUTPUTSTREAM = "org.operamasks.faces.DebugLogHander.outputStream";

    private static class DebugLogHandler extends StreamHandler {
        @Override
        public synchronized void publish(LogRecord record) {
            FacesContext context = FacesContext.getCurrentInstance();
            if (context == null)
                return;

            OutputStream out = (OutputStream) context.getExternalContext().getRequestMap()
                    .get(KEY_DEBUGLOGHANDLER_OUTPUTSTREAM);
            if (out == null) {
                out = new ByteArrayOutputStream();
                context.getExternalContext().getRequestMap().put(KEY_DEBUGLOGHANDLER_OUTPUTSTREAM, out);
            }
            setOutputStream(out);

            super.publish(record);
        }
    }

    public static String getServerLog(FacesContext context) {
        OutputStream out = (OutputStream) context.getExternalContext().getRequestMap()
                .get(KEY_DEBUGLOGHANDLER_OUTPUTSTREAM);

        if (out != null)
            return out.toString();

        return null;
    }

    public static String getServerLog() {
        return getServerLog(FacesContext.getCurrentInstance());
    }

    public static final DebugMode[] DEBUG_MODE_LIFECYCLE_PHASES = new DebugMode[] { DebugMode.RESTORE_VIEW,
            DebugMode.APPLY_REQUEST_VALUES, DebugMode.PROCESS_VALIDATIONS, DebugMode.UPDATE_MODE_VALUES,
            DebugMode.INVOKE_APPLICATION, DebugMode.RENDER_RESPONSE };

    @SuppressWarnings("unchecked")
    public static boolean isDebugComponent(Class componentClass) {
        if (!UIComponent.class.isAssignableFrom(componentClass))
            return false;

        String[] includeComponentClasses = (String[]) getValue(DebugMode.INCLUDE_COMPONENT_CLASSES);
        String[] excludeComponentClasses = (String[]) getValue(DebugMode.EXCLUDE_COMPONENT_CLASSES);
        String componentClassName = componentClass.getName();

        if (isMatch(excludeComponentClasses, componentClassName))
            return false;

        if (isMatch(includeComponentClasses, componentClassName))
            return true;

        return false;
    }

    private static boolean isMatch(String[] regexes, String value) {
        for (String regex : regexes) {
            if (Pattern.matches(regex, value))
                return true;
        }

        return false;
    }

    public static boolean isDebugRenderer(String rendererType) {
        String[] includeRendererTypes = (String[]) getValue(DebugMode.INCLUDE_RENDERER_TYPES);
        String[] excludeRendererTypes = (String[]) getValue(DebugMode.EXCLUDE_RENDERER_TYPES);

        if (isMatch(excludeRendererTypes, rendererType))
            return false;

        if (isMatch(includeRendererTypes, rendererType))
            return true;

        return false;
    }

    public static boolean isDebugComponentMethod(Method method, UIComponent component) {
        String[] includeComponentIds = (String[]) getValue(DebugMode.INCLUDE_COMPONENT_IDS);
        String[] excludeComponentIds = (String[]) getValue(DebugMode.EXCLUDE_COMPONENT_IDS);
        String[] includeComponentMethods = (String[]) getValue(DebugMode.INCLUDE_COMPONENT_METHODS);
        String[] excludeComponentMethods = (String[]) getValue(DebugMode.EXCLUDE_COMPONENT_METHODS);

        String methodName = method.getName();
        if (!isBelongTo(COMPONENT_LIFECYCLE_METHODS, methodName))
            return false;

        if (isMatch(excludeComponentMethods, methodName))
            return false;

        String componentId = getComponentId(component);

        if (isMatch(excludeComponentIds, componentId))
            return false;

        if (isMatch(includeComponentMethods, methodName) && isMatch(includeComponentIds, componentId))
            return true;

        return false;
    }

    @SuppressWarnings("unchecked")
    private static String getComponentId(UIComponent component) {
        String componentId = "???";
        if (component instanceof UIComponentBase) {
            Class componentBaseClass = component.getClass();
            while (!componentBaseClass.equals(UIComponentBase.class) && !componentBaseClass.equals(Object.class)) {
                componentBaseClass = componentBaseClass.getSuperclass();
            }

            if (componentBaseClass.equals(UIComponentBase.class)) {
                try {
                    Field idField = componentBaseClass.getDeclaredField("id");
                    idField.setAccessible(true);
                    componentId = (String) idField.get(component);
                    idField.setAccessible(false);
                } catch (Exception e) {
                    // Can't determine component id
                }
            }
        }

        if (componentId == null)
            componentId = "???";

        return componentId;
    }

    private static boolean isBelongTo(String[] valueSet, String value) {
        for (String aValue : valueSet) {
            if (aValue.equals(value))
                return true;
        }

        return false;
    }

    public static boolean isDebugRendererMethod(Method method, Object[] args) {
        String[] includeComponentIds = (String[]) getValue(DebugMode.INCLUDE_COMPONENT_IDS);
        String[] excludeComponentIds = (String[]) getValue(DebugMode.EXCLUDE_COMPONENT_IDS);
        String[] includeRendererMethods = (String[]) getValue(DebugMode.INCLUDE_RENDERER_METHODS);
        String[] excludeRendererMethods = (String[]) getValue(DebugMode.EXCLUDE_RENDERER_METHODS);

        String methodName = method.getName();
        if (!isBelongTo(RENDERER_LIFECYCLE_METHODS, methodName))
            return false;

        if (isMatch(excludeRendererMethods, methodName))
            return false;

        UIComponent component = (UIComponent) args[1];
        String componentId = getComponentId(component);

        if (isMatch(excludeComponentIds, componentId))
            return false;

        if (isMatch(includeRendererMethods, methodName) && isMatch(includeComponentIds, componentId))
            return true;

        return false;
    }
}