/*
 * This library is part of OpenCms -
 * the Open Source Content Management System
 *
 * Copyright (c) Alkacon Software GmbH (http://www.alkacon.com)
 *
 * This library is free software; you can redistribute it and/or
 * modify it under the terms of the GNU Lesser General Public
 * License as published by the Free Software Foundation; either
 * version 2.1 of the License, or (at your option) any later version.
 *
 * This library 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
 * Lesser General Public License for more details.
 *
 * For further information about Alkacon Software, please see the
 * company website: http://www.alkacon.com
 *
 * For further information about OpenCms, please see the
 * project website: http://www.opencms.org
 *
 * You should have received a copy of the GNU Lesser General Public
 * License along with this library; if not, write to the Free Software
 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
 */

package org.opencms.workplace.tools.workplace.logging;

import org.opencms.jsp.CmsJspActionElement;
import org.opencms.main.CmsLog;
import org.opencms.main.CmsRuntimeException;
import org.opencms.workplace.list.A_CmsListDialog;
import org.opencms.workplace.list.CmsListColumnAlignEnum;
import org.opencms.workplace.list.CmsListColumnDefinition;
import org.opencms.workplace.list.CmsListDirectAction;
import org.opencms.workplace.list.CmsListItem;
import org.opencms.workplace.list.CmsListMetadata;
import org.opencms.workplace.list.CmsListMultiAction;
import org.opencms.workplace.list.CmsListOrderEnum;
import org.opencms.workplace.list.CmsListSearchAction;

import java.io.File;
import java.io.IOException;
import java.util.ArrayList;
import java.util.Collections;
import java.util.Comparator;
import java.util.Iterator;
import java.util.LinkedList;
import java.util.List;

import org.apache.commons.logging.Log;
import org.apache.log4j.Appender;
import org.apache.log4j.Category;
import org.apache.log4j.FileAppender;
import org.apache.log4j.Layout;
import org.apache.log4j.Level;
import org.apache.log4j.LogManager;
import org.apache.log4j.Logger;
import org.apache.log4j.Priority;

/**
 * Main logging management list view.<p>
 *
 * Defines the list columns and possible actions for logging.<p>
 *
 */
public class CmsLog4JAdminDialog extends A_CmsListDialog {

    /** List column class. */
    protected static final String COLUMN_ACTIVE = "cac";

    /** Name of the list for separate log files. */
    protected static final String COLUMN_CHANGE_LOGFILE = "Seperate Log file";

    /** Name of the logger-List. */
    protected static final String COLUMN_CHANNELS = "channels";

    /** Shortcut for the DEBUG column. */
    protected static final String COLUMN_DEBUG = "chd";

    /** Shortcut for the ERROR column. */
    protected static final String COLUMN_ERROR = "che";

    /** Shortcut for the FATAL column. */
    protected static final String COLUMN_FATAL = "chf";

    /** Shortcut for the INFO column. */
    protected static final String COLUMN_INFO = "chi";

    /** Name of the parent-list. */
    protected static final String COLUMN_LOG_FILE = "Log-File";

    /** Actual level of logging. */
    protected static final String COLUMN_LOG_LEVEL = "loggerlevel";

    /** Shortcut for the OFF column. */
    protected static final String COLUMN_OFF = "cho";

    /** Name of the parent-list. */
    protected static final String COLUMN_PARENT_CHANNELS = "parent";

    /** Shortcut for the WARN column. */
    protected static final String COLUMN_WARN = "chw";

    /** Name of the logchannel Action. */
    private static final String ACTION_ACTIVATE_LOGFILE = "activlogchannel";

    /** Name of the Debug-level Action. */
    private static final String ACTION_LOGGING_LEVEL_DEBUG = "debugchannel";

    /** Name of the Error-level Action. */
    private static final String ACTION_LOGGING_LEVEL_ERROR = "errorlevel";

    /** Name of the Fatal-level Action. */
    private static final String ACTION_LOGGING_LEVEL_FATAL = "fatallevel";

    /** Name of the Info-level Action. */
    private static final String ACTION_LOGGING_LEVEL_INFO = "infochannel";

    /** Name of the Off-level Action. */
    private static final String ACTION_LOGGING_LEVEL_OFF = "offlevel";

    /** Name of the Warn-level Action. */
    private static final String ACTION_LOGGING_LEVEL_WARN = "warnchannel";

    /** The log object for this class. */
    private static final Log LOG = CmsLog.getLog(CmsLog4JAdminDialog.class);

    /** The prefix of opencms classes. */
    private static final String OPENCMS_CLASS_PREFIX = "org.opencms";

    /** Path to the list buttons. */
    private static final String PATH_BUTTONS = "buttons/";

    /** Path to the Debug-Icon(active). */
    private static final String PATH_DEBUG_ACTIVE = PATH_BUTTONS + "log_button_debug_a_2.png";

    /** Path to the Debug-Icon(inactive). */
    private static final String PATH_DEBUG_INACTIVE = PATH_BUTTONS + "log_button_debug_i_2.png";

    /** Path to the Error-Icon(active). */
    private static final String PATH_ERROR_ACTIVE = PATH_BUTTONS + "log_button_error_a_2.png";

    /** Path to the Error-Icon(inactive). */
    private static final String PATH_ERROR_INACTIVE = PATH_BUTTONS + "log_button_error_i_2.png";

    /** Path to the Fatal-Icon(active). */
    private static final String PATH_FATAL_ACTIVE = PATH_BUTTONS + "log_button_fatal_a_2.png";

    /** Path to the Fatal-Icon(inactive). */
    private static final String PATH_FATAL_INACTIVE = PATH_BUTTONS + "log_button_fatal_i_2.png";

    /** Path to the File-Icon(active). */
    private static final String PATH_FILE_ACTIVE = PATH_BUTTONS + "log_button_file_on_2.png";

    /** Path to the File-Icon(inactive). */
    private static final String PATH_FILE_INACTIVE = PATH_BUTTONS + "log_button_file_off_2.png";

    /** Path to the Info-Icon(active). */
    private static final String PATH_INFO_ACTIVE = PATH_BUTTONS + "log_button_info_a_2.png";

    /** Path to the Info-Icon(inactive). */
    private static final String PATH_INFO_INACTIVE = PATH_BUTTONS + "log_button_info_i_2.png";

    /** Path to the Off-Icon(active). */
    private static final String PATH_OFF_ACTIVE = PATH_BUTTONS + "log_button_off_a_2.png";

    /** Path to the Off-Icon(inactive). */
    private static final String PATH_OFF_INACTIVE = PATH_BUTTONS + "log_button_off_i_2.png";

    /** Path to the Warning-Icon(active). */
    private static final String PATH_WARN_ACTIVE = PATH_BUTTONS + "log_button_warn_a_2.png";

    /** Path to the Warning-Icon(inactive). */
    private static final String PATH_WARN_INACTIVE = PATH_BUTTONS + "log_button_warn_i_2.png";

    /** Shortcut for the MultiAction (DEBUG). */
    private static final String SET_TO_DEBUG = "sd";

    /** Shortcut for the MultiAction (ERROR). */
    private static final String SET_TO_ERROR = "sr";

    /** Shortcut for the MultiAction (FATAL). */
    private static final String SET_TO_FATAL = "sf";

    /** Shortcut for the MultiAction (INFO). */
    private static final String SET_TO_INFO = "si";

    /** Shortcut for the MultiAction (OFF). */
    private static final String SET_TO_OFF = "so";

    /** Shortcut for the MultiAction (WARN). */
    private static final String SET_TO_WARN = "sw";

    /**
     * Public constructor.<p>
     *
     * @param jsp the JSP action element
     */
    public CmsLog4JAdminDialog(CmsJspActionElement jsp) {

        super(
            jsp,
            "Log Settings",
            Messages.get().container(Messages.GUI_LOG_LIST_NAME_0),
            "lo",
            CmsListOrderEnum.ORDER_ASCENDING,
            null);
    }

    /**
     * @see org.opencms.workplace.list.A_CmsListDialog#executeListMultiActions()
     */
    @Override
    public void executeListMultiActions() throws CmsRuntimeException {

        // switch the selected loggers to the logging-level

        Level newLogchannelLevel = null;
        // get the selected logging-level
        if (getParamListAction().equals(SET_TO_ERROR)) {
            newLogchannelLevel = Level.ERROR;
        } else if (getParamListAction().equals(SET_TO_DEBUG)) {
            newLogchannelLevel = Level.DEBUG;
        } else if (getParamListAction().equals(SET_TO_FATAL)) {
            newLogchannelLevel = Level.FATAL;
        } else if (getParamListAction().equals(SET_TO_INFO)) {
            newLogchannelLevel = Level.INFO;
        } else if (getParamListAction().equals(SET_TO_WARN)) {
            newLogchannelLevel = Level.WARN;
        } else if (getParamListAction().equals(SET_TO_OFF)) {
            newLogchannelLevel = Level.OFF;
        }

        // list all selected log channels
        List<CmsListItem> list = getSelectedItems();
        Iterator<CmsListItem> itItems = list.iterator();
        // iterate about all log channels to set the above selected loglevel
        while (itItems.hasNext()) {
            String logchannnelName = itItems.next().getId();
            Logger logchannel = LogManager.getLogger(logchannnelName);
            logchannel.setLevel(newLogchannelLevel);
        }

        refreshList();

    }

    /**
     * @see org.opencms.workplace.list.A_CmsListDialog#executeListSingleActions()
     */
    @Override
    public void executeListSingleActions() throws CmsRuntimeException {

        // switch a single log-channel to an other logging-level
        if (getSelectedItem() == null) {
            return;
        }
        // get the log-channel to change the level
        String logchannnelName = getSelectedItem().getId();
        Logger logchannel = LogManager.getLogger(logchannnelName);
        if (logchannel == null) {
            return;
        }
        // get the selected logging-level with the help of the row
        Level newLogchannelLevel = null;
        if (ACTION_LOGGING_LEVEL_DEBUG.equals(getParamListAction())) {
            newLogchannelLevel = Level.DEBUG;
        } else if (ACTION_LOGGING_LEVEL_INFO.equals(getParamListAction())) {
            newLogchannelLevel = Level.INFO;
        } else if (ACTION_LOGGING_LEVEL_WARN.equals(getParamListAction())) {
            newLogchannelLevel = Level.WARN;
        } else if (ACTION_LOGGING_LEVEL_ERROR.equals(getParamListAction())) {
            newLogchannelLevel = Level.ERROR;
        } else if (ACTION_LOGGING_LEVEL_FATAL.equals(getParamListAction())) {
            newLogchannelLevel = Level.FATAL;
        } else if (ACTION_LOGGING_LEVEL_OFF.equals(getParamListAction())) {
            newLogchannelLevel = Level.OFF;
        }
        if (newLogchannelLevel != null) {
            isparentlogger(logchannel);
            if (newLogchannelLevel.equals(logchannel.getParent().getLevel())) {
                logchannel.setLevel(null);
            } else {
                logchannel.setLevel(newLogchannelLevel);
            }
        }
        if (ACTION_ACTIVATE_LOGFILE.equals(getParamListAction())) {
            String filepath = "";
            Layout layout = null;
            // if the button is activated check the value of the button
            // the button was active
            if (isloggingactivated(logchannel)) {
                // remove the private Appender from logger
                logchannel.removeAllAppenders();
                // activate the heredity so the logger get the appender from parent logger
                logchannel.setAdditivity(true);

            }
            // the button was inactive
            else {
                @SuppressWarnings("unchecked")
                List<Appender> rootAppenders = Collections.list(Logger.getRootLogger().getAllAppenders());
                // get the layout and file path from root logger
                for (Appender appender : rootAppenders) {
                    if (appender instanceof FileAppender) {
                        FileAppender fapp = (FileAppender)appender;
                        filepath = fapp.getFile().substring(0, fapp.getFile().lastIndexOf(File.separatorChar));
                        layout = fapp.getLayout();
                        break;
                    }
                }

                @SuppressWarnings("unchecked")
                List<Appender> appenders = Collections.list(logchannel.getAllAppenders());
                // check if the logger has an Appender get his layout
                for (Appender appender : appenders) {
                    if (appender instanceof FileAppender) {
                        FileAppender fapp = (FileAppender)appender;
                        layout = fapp.getLayout();
                        break;
                    }
                }
                String logfilename = "";
                String temp = logchannel.getName();
                // check if the logger name begins with "org.opencms"
                if (logchannel.getName().contains(OPENCMS_CLASS_PREFIX)) {
                    // remove the prefix "org.opencms" from logger name to generate the file name
                    temp = temp.replace(OPENCMS_CLASS_PREFIX, "");
                    // if the name has suffix
                    if (temp.length() >= 1) {
                        logfilename = filepath
                            + File.separator
                            + "opencms-"
                            + temp.substring(1).replace(".", "-")
                            + ".log";
                    }
                    // if the name has no suffix
                    else {
                        logfilename = filepath + File.separator + "opencms" + temp.replace(".", "-") + ".log";
                    }
                }
                // if the logger name not begins with "org.opencms"
                else {
                    logfilename = filepath + File.separator + "opencms-" + temp.replace(".", "-") + ".log";
                }

                FileAppender fapp = null;
                try {
                    // create new FileAppender for separate log file
                    fapp = new FileAppender(layout, logfilename, true);
                    // set the log file e.g.: "C:\tomcat6\webapps\opencms\WEB-INF\logs"
                    fapp.setName(logchannnelName);
                } catch (IOException e) {
                    LOG.error(Messages.get().container(Messages.LOG_CREATING_APPENDER_0), e);
                }
                // deactivate the heredity so the logger get no longer the appender from parent logger
                logchannel.setAdditivity(false);
                // remove all active Appenders from logger
                logchannel.removeAllAppenders();
                // add the new created Appender to the logger
                logchannel.addAppender(fapp);
            }
        }
        refreshList();
    }

    /**
     * @see org.opencms.workplace.list.A_CmsListDialog#fillDetails(java.lang.String)
     */
    @Override
    protected void fillDetails(String detailId) {

        // noop
    }

    /**
     * @see org.opencms.workplace.list.A_CmsListDialog#getListItems()
     */
    @Override
    protected List<CmsListItem> getListItems() {

        // collect all the values for "Log-channels", "Log-channels-parents" and "Log-channels-level"
        List<CmsListItem> items = new LinkedList<CmsListItem>();
        List<Logger> loggers = getLoggers();
        Iterator<Logger> iterator = loggers.iterator();
        while (iterator.hasNext()) {
            Logger logger = iterator.next();
            CmsListItem item = getList().newItem(logger.getName());
            item.set(COLUMN_CHANNELS, logger.getName());
            Category parentLogger = logger.getParent();
            if (parentLogger == null) {
                item.set(COLUMN_PARENT_CHANNELS, "");
            } else {
                item.set(COLUMN_PARENT_CHANNELS, logger.getParent().getName());
            }
            item.set(COLUMN_LOG_LEVEL, String.valueOf(logger.getEffectiveLevel()));

            String test = "";
            @SuppressWarnings("unchecked")
            List<Appender> appenders = Collections.list(logger.getAllAppenders());
            Iterator<Appender> appendersIt = appenders.iterator();
            int count = 0;
            // select the Appender from logger
            while (appendersIt.hasNext()) {
                Appender appender = appendersIt.next();
                // only use file appenders
                if (appender instanceof FileAppender) {
                    FileAppender fapp = (FileAppender)appender;
                    String temp = "";
                    temp = fapp.getFile().substring(fapp.getFile().lastIndexOf(File.separatorChar) + 1);
                    test = test + temp;
                    count++;
                    break;
                }
            }
            @SuppressWarnings("unchecked")
            List<Appender> parentAppenders = Collections.list(logger.getParent().getAllAppenders());
            Iterator<Appender> parentAppendersIt = parentAppenders.iterator();
            // if no Appender found from logger, select the Appender from parent logger
            if (count == 0) {
                while (parentAppendersIt.hasNext()) {
                    Appender appender = parentAppendersIt.next();
                    // only use file appenders
                    if (appender instanceof FileAppender) {
                        FileAppender fapp = (FileAppender)appender;
                        String temp = "";
                        temp = fapp.getFile().substring(fapp.getFile().lastIndexOf(File.separatorChar) + 1);
                        test = test + temp;
                        count++;
                        break;
                    }
                }
            }

            if (count == 0) {
                @SuppressWarnings("unchecked")
                List<Appender> rootAppenders = Collections.list(Logger.getRootLogger().getAllAppenders());
                Iterator<Appender> rootAppendersIt = rootAppenders.iterator();
                // if no Appender found from parent logger, select the Appender from root logger
                while (rootAppendersIt.hasNext()) {
                    Appender appender = rootAppendersIt.next();
                    // only use file appenders
                    if (appender instanceof FileAppender) {
                        FileAppender fapp = (FileAppender)appender;
                        String temp = "";
                        temp = fapp.getFile().substring(fapp.getFile().lastIndexOf(File.separatorChar) + 1);
                        test = test + temp;
                        break;
                    }
                }

            }
            item.set(COLUMN_LOG_FILE, test);
            items.add(item);
        }
        return items;
    }

    /**
     * Simple check if the logger has the global log file <p> or a single one.
     *
     * @param logchannel the channel that has do be checked
     * @return true if the the log channel has a single log file
     * */
    protected boolean isloggingactivated(Logger logchannel) {

        boolean check = false;
        @SuppressWarnings("unchecked")
        List<Appender> appenders = Collections.list(logchannel.getAllAppenders());
        Iterator<Appender> app = appenders.iterator();
        while (app.hasNext()) {
            check = app.next().getName().equals(logchannel.getName());
        }
        return check;
    }

    /**
     * @see org.opencms.workplace.list.A_CmsListDialog#setColumns(org.opencms.workplace.list.CmsListMetadata)
     */
    @Override
    protected void setColumns(CmsListMetadata metadata) {

        //////////////////
        // FATAL COLUMN //
        //////////////////
        CmsListColumnDefinition fatalColumn = new CmsListColumnDefinition(COLUMN_FATAL);
        fatalColumn.setName(Messages.get().container(Messages.GUI_LOG_LEVEL_FATAL_0));
        fatalColumn.setAlign(CmsListColumnAlignEnum.ALIGN_CENTER);
        fatalColumn.setWidth("50");
        fatalColumn.setListItemComparator(new CmsLogLevelListItemComparator());
        fatalColumn.setPrintable(false);
        fatalColumn.setAlign(CmsListColumnAlignEnum.ALIGN_CENTER);
        fatalColumn.setListItemComparator(new CmsLogLevelListItemComparator());
        CmsListDirectAction fatalActAction = new CmsChangeLogLevelAction(ACTION_LOGGING_LEVEL_FATAL, Level.FATAL) {

            /**
             * @see org.opencms.workplace.tools.A_CmsHtmlIconButton#isVisible()
             */
            @Override
            public boolean isVisible() {

                Level actuallevel = Level.toLevel((String)getItem().get(COLUMN_LOG_LEVEL));
                if (actuallevel != null) {

                    if (actuallevel.toInt() < Priority.FATAL_INT) {
                        setIconPath(PATH_FATAL_ACTIVE);
                        setName(Messages.get().container(Messages.GUI_LOG_LEVEL_FATAL_HELP_DEACTIVATE_0));
                    } else if (actuallevel.toInt() == Priority.FATAL_INT) {
                        setIconPath(PATH_FATAL_ACTIVE);
                        setName(Messages.get().container(Messages.GUI_LOG_LEVEL_ACTIVE_0));
                    } else {
                        setIconPath(PATH_FATAL_INACTIVE);
                        setName(Messages.get().container(Messages.GUI_LOG_LEVEL_FATAL_HELP_ACTIVATE_0));
                    }
                }
                return super.isVisible();
            }
        };
        fatalActAction.setHelpText(Messages.get().container(Messages.GUI_LOG_LEVEL_FATAL_HELP_0));
        fatalColumn.addDirectAction(fatalActAction);
        metadata.addColumn(fatalColumn);

        //////////////////
        // ERROR COLUMN //
        //////////////////
        CmsListColumnDefinition errorColumn = new CmsListColumnDefinition(COLUMN_ERROR);
        errorColumn.setName(Messages.get().container(Messages.GUI_LOG_LEVEL_ERROR_0));
        errorColumn.setAlign(CmsListColumnAlignEnum.ALIGN_CENTER);
        errorColumn.setWidth("50");
        errorColumn.setPrintable(false);
        errorColumn.setAlign(CmsListColumnAlignEnum.ALIGN_CENTER);
        errorColumn.setListItemComparator(new CmsLogLevelListItemComparator());
        CmsListDirectAction errorActAction = new CmsChangeLogLevelAction(ACTION_LOGGING_LEVEL_ERROR, Level.ERROR) {

            /**
             * @see org.opencms.workplace.tools.A_CmsHtmlIconButton#isVisible()
             */
            @Override
            public boolean isVisible() {

                Level actuallevel = Level.toLevel((String)getItem().get(COLUMN_LOG_LEVEL));
                if (actuallevel != null) {
                    if ((actuallevel.toInt() < Priority.ERROR_INT)) {
                        setIconPath(PATH_ERROR_ACTIVE);
                        setName(Messages.get().container(Messages.GUI_LOG_LEVEL_ERROR_HELP_DEACTIVATE_0));
                    } else if (actuallevel.toInt() == Priority.ERROR_INT) {
                        setIconPath(PATH_ERROR_ACTIVE);
                        setName(Messages.get().container(Messages.GUI_LOG_LEVEL_ACTIVE_0));
                    } else {
                        setIconPath(PATH_ERROR_INACTIVE);
                        setName(Messages.get().container(Messages.GUI_LOG_LEVEL_ERROR_HELP_ACTIVATE_0));
                    }
                }
                return super.isVisible();
            }
        };
        errorActAction.setHelpText(Messages.get().container(Messages.GUI_LOG_LEVEL_ERROR_HELP_0));
        errorColumn.addDirectAction(errorActAction);
        metadata.addColumn(errorColumn);

        /////////////////
        // WARN COLUMN //
        /////////////////
        CmsListColumnDefinition warnColumn = new CmsListColumnDefinition(COLUMN_WARN);
        warnColumn.setName(Messages.get().container(Messages.GUI_LOG_LEVEL_WARN_0));
        warnColumn.setAlign(CmsListColumnAlignEnum.ALIGN_CENTER);
        warnColumn.setWidth("50");
        warnColumn.setPrintable(false);
        warnColumn.setAlign(CmsListColumnAlignEnum.ALIGN_CENTER);
        warnColumn.setListItemComparator(new CmsLogLevelListItemComparator());
        CmsListDirectAction warnAction = new CmsChangeLogLevelAction(ACTION_LOGGING_LEVEL_WARN, Level.WARN) {

            /**
             * @see org.opencms.workplace.tools.A_CmsHtmlIconButton#isVisible()
             */
            @Override
            public boolean isVisible() {

                Level actuallevel = Level.toLevel((String)getItem().get(COLUMN_LOG_LEVEL));
                if (actuallevel != null) {
                    if ((actuallevel.toInt() < Priority.WARN_INT)) {
                        setIconPath(PATH_WARN_ACTIVE);
                        setName(Messages.get().container(Messages.GUI_LOG_LEVEL_WARN_HELP_DEACTIVATE_0));
                    } else if (actuallevel.toInt() == Priority.WARN_INT) {
                        setIconPath(PATH_WARN_ACTIVE);
                        setName(Messages.get().container(Messages.GUI_LOG_LEVEL_ACTIVE_0));
                    } else {
                        setIconPath(PATH_WARN_INACTIVE);
                        setName(Messages.get().container(Messages.GUI_LOG_LEVEL_WARN_HELP_ACTIVATE_0));
                    }
                }
                return super.isVisible();
            }
        };
        warnAction.setHelpText(Messages.get().container(Messages.GUI_LOG_LEVEL_WARN_HELP_0));
        warnColumn.addDirectAction(warnAction);
        metadata.addColumn(warnColumn);

        /////////////////
        // INFO COLUMN //
        /////////////////
        CmsListColumnDefinition infoColumn = new CmsListColumnDefinition(COLUMN_INFO);
        infoColumn.setName(Messages.get().container(Messages.GUI_LOG_LEVEL_INFO_0));
        infoColumn.setAlign(CmsListColumnAlignEnum.ALIGN_CENTER);
        infoColumn.setWidth("50");
        infoColumn.setPrintable(false);
        infoColumn.setAlign(CmsListColumnAlignEnum.ALIGN_CENTER);
        infoColumn.setListItemComparator(new CmsLogLevelListItemComparator());
        CmsListDirectAction infoAction = new CmsChangeLogLevelAction(ACTION_LOGGING_LEVEL_INFO, Level.INFO) {

            /**
             * @see org.opencms.workplace.tools.A_CmsHtmlIconButton#isVisible()
             */
            @Override
            public boolean isVisible() {

                // check the Loglevel from hidden column and set the right icon
                Level actuallevel = Level.toLevel((String)getItem().get(COLUMN_LOG_LEVEL));
                if (actuallevel != null) {
                    if ((actuallevel.toInt() < Priority.INFO_INT)) {
                        setIconPath(PATH_INFO_ACTIVE);
                        setName(Messages.get().container(Messages.GUI_LOG_LEVEL_INFO_HELP_DEACTIVATE_0));
                    } else if (actuallevel.toInt() == Priority.INFO_INT) {
                        setIconPath(PATH_INFO_ACTIVE);
                        setName(Messages.get().container(Messages.GUI_LOG_LEVEL_ACTIVE_0));
                    } else {
                        setIconPath(PATH_INFO_INACTIVE);
                        setName(Messages.get().container(Messages.GUI_LOG_LEVEL_INFO_HELP_ACTIVATE_0));
                    }
                }
                return super.isVisible();
            }
        };
        infoAction.setHelpText(Messages.get().container(Messages.GUI_LOG_LEVEL_INFO_HELP_0));
        infoColumn.addDirectAction(infoAction);
        metadata.addColumn(infoColumn);

        //////////////////
        // DEBUG COLUMN //
        //////////////////
        CmsListColumnDefinition debugColumn = new CmsListColumnDefinition(COLUMN_DEBUG);
        debugColumn.setName(Messages.get().container(Messages.GUI_LOG_LEVEL_DEBUG_0));
        debugColumn.setAlign(CmsListColumnAlignEnum.ALIGN_CENTER);
        debugColumn.setWidth("50");
        debugColumn.setAlign(CmsListColumnAlignEnum.ALIGN_CENTER);
        debugColumn.setPrintable(false);
        debugColumn.setListItemComparator(new CmsLogLevelListItemComparator());
        // generate an Action to activate the change of a log-channel
        CmsListDirectAction debugAction = new CmsChangeLogLevelAction(ACTION_LOGGING_LEVEL_DEBUG, Level.DEBUG) {

            /**
             * @see org.opencms.workplace.tools.A_CmsHtmlIconButton#isVisible()
             */
            @Override
            public boolean isVisible() {

                Level actuallevel = Level.toLevel((String)getItem().get(COLUMN_LOG_LEVEL));
                if (actuallevel != null) {
                    if (actuallevel.toInt() < Priority.DEBUG_INT) {
                        setIconPath(PATH_DEBUG_ACTIVE);
                        setName(Messages.get().container(Messages.GUI_LOG_LEVEL_DEBUG_HELP_DEACTIVATE_0));
                    } else if (actuallevel.toInt() == Priority.DEBUG_INT) {
                        setIconPath(PATH_DEBUG_ACTIVE);
                        setName(Messages.get().container(Messages.GUI_LOG_LEVEL_ACTIVE_0));
                    } else {
                        setIconPath(PATH_DEBUG_INACTIVE);
                        setName(Messages.get().container(Messages.GUI_LOG_LEVEL_DEBUG_HELP_ACTIVATE_0));
                    }
                }
                return super.isVisible();
            }
        };
        debugAction.setHelpText(Messages.get().container(Messages.GUI_LOG_LEVEL_DEBUG_HELP_0));
        debugColumn.addDirectAction(debugAction);
        metadata.addColumn(debugColumn);

        /////////////////////
        // TRUN OFF COLUMN //
        /////////////////////
        CmsListColumnDefinition offColumn = new CmsListColumnDefinition(COLUMN_OFF);
        offColumn.setName(Messages.get().container(Messages.GUI_LOG_LEVEL_OFF_0));
        offColumn.setAlign(CmsListColumnAlignEnum.ALIGN_CENTER);
        offColumn.setWidth("50");
        offColumn.setSorteable(true);
        offColumn.setPrintable(false);
        offColumn.setAlign(CmsListColumnAlignEnum.ALIGN_CENTER);
        offColumn.setListItemComparator(new CmsLogLevelListItemComparator());
        CmsListDirectAction offAction = new CmsChangeLogLevelAction(ACTION_LOGGING_LEVEL_OFF, Level.OFF) {

            /**
             * @see org.opencms.workplace.tools.A_CmsHtmlIconButton#isVisible()
             */
            @Override
            public boolean isVisible() {

                Level actuallevel = Level.toLevel((String)getItem().get(COLUMN_LOG_LEVEL));
                if (actuallevel != null) {
                    if (actuallevel.toInt() == Priority.OFF_INT) {
                        setIconPath(PATH_OFF_ACTIVE);
                        setName(Messages.get().container(Messages.GUI_LOG_LEVEL_OFF_HELP_ACTIVATE_0));
                    } else {
                        setIconPath(PATH_OFF_INACTIVE);
                        setName(Messages.get().container(Messages.GUI_LOG_LEVEL_OFF_HELP_DEACTIVATE_0));
                    }
                }
                return super.isVisible();
            }
        };
        offAction.setHelpText(Messages.get().container(Messages.GUI_LOG_LEVEL_OFF_HELP_0));
        offColumn.addDirectAction(offAction);
        metadata.addColumn(offColumn);

        //////////////////////////////
        // CURRENT LOG LEVEL COLUMN //
        //////////////////////////////
        CmsListColumnDefinition logLevelHidden = new CmsListColumnDefinition(COLUMN_LOG_LEVEL);
        logLevelHidden.setName(Messages.get().container(Messages.GUI_LOG_LEVEL_CURRENT_0));
        logLevelHidden.setAlign(CmsListColumnAlignEnum.ALIGN_CENTER);
        logLevelHidden.setWidth("10%");
        logLevelHidden.setSorteable(true);
        logLevelHidden.setPrintable(true);
        logLevelHidden.setVisible(false);
        metadata.addColumn(logLevelHidden);

        //////////////////
        // LOG CHANNELS //
        //////////////////
        CmsListColumnDefinition channels = new CmsListColumnDefinition(COLUMN_CHANNELS);
        channels.setName(Messages.get().container(Messages.GUI_LOG_CHANNELS_0));
        channels.setAlign(CmsListColumnAlignEnum.ALIGN_LEFT);
        channels.setSorteable(true);
        channels.setWidth("50%");
        channels.setPrintable(true);
        metadata.addColumn(channels);

        ///////////////////////////////
        // PARENT LOG CHANNEL COLUMN //
        ///////////////////////////////
        CmsListColumnDefinition parentChannel = new CmsListColumnDefinition(COLUMN_PARENT_CHANNELS);
        parentChannel.setName(Messages.get().container(Messages.GUI_LOG_PARENT_CHANNEL_0));
        parentChannel.setAlign(CmsListColumnAlignEnum.ALIGN_LEFT);
        parentChannel.setSorteable(true);
        parentChannel.setWidth("20%");
        parentChannel.setPrintable(false);
        metadata.addColumn(parentChannel);

        /////////////////////
        // LOG FILE COLUMN //
        /////////////////////
        CmsListColumnDefinition selectedFile = new CmsListColumnDefinition(COLUMN_LOG_FILE);
        selectedFile.setName(Messages.get().container(Messages.GUI_LOG_FILE_SELECTED_0));
        selectedFile.setAlign(CmsListColumnAlignEnum.ALIGN_LEFT);
        selectedFile.setSorteable(true);
        selectedFile.setWidth("20%");
        selectedFile.setPrintable(false);
        metadata.addColumn(selectedFile);

        ////////////////////////
        // CHANGE FILE COLUMN //
        ////////////////////////
        CmsListColumnDefinition changeFile = new CmsListColumnDefinition(COLUMN_CHANGE_LOGFILE);
        changeFile.setName(Messages.get().container(Messages.GUI_LOG_FILE_CHANGE_FILE_0));
        changeFile.setAlign(CmsListColumnAlignEnum.ALIGN_LEFT);
        changeFile.setSorteable(false);
        changeFile.setWidth("25");
        changeFile.setPrintable(false);
        CmsListDirectAction changeFileAction = new CmsListDirectAction(ACTION_ACTIVATE_LOGFILE) {

            /**
             * @see org.opencms.workplace.tools.A_CmsHtmlIconButton#isVisible()
             */
            @Override
            public boolean isVisible() {

                Logger logger = LogManager.getLogger((String)getItem().get(COLUMN_CHANNELS));
                if (logger != null) {
                    if (isloggingactivated(logger)) {
                        setIconPath(PATH_FILE_ACTIVE);
                        setName(Messages.get().container(Messages.GUI_LOG_FILE_CHANGE_FILE_HELP_DEACTIVATE_0));
                    } else {
                        setIconPath(PATH_FILE_INACTIVE);
                        setName(Messages.get().container(Messages.GUI_LOG_FILE_CHANGE_FILE_HELP_ACTIVATE_0));
                    }
                }
                return super.isVisible();
            }
        };
        changeFileAction.setHelpText(Messages.get().container(Messages.GUI_LOG_FILE_CHANGE_FILE_HELP_0));
        changeFileAction.setIconPath(PATH_OFF_ACTIVE);
        changeFile.addDirectAction(changeFileAction);
        metadata.addColumn(changeFile);

        ///////////////////
        // SEARCH ACTION //
        ///////////////////
        CmsListSearchAction searchAction = new CmsListSearchAction(metadata.getColumnDefinition(COLUMN_CHANNELS));
        metadata.setSearchAction(searchAction);
    }

    /**
     * @see org.opencms.workplace.list.A_CmsListDialog#setIndependentActions(org.opencms.workplace.list.CmsListMetadata)
     */
    @Override
    protected void setIndependentActions(CmsListMetadata metadata) {

        // noop
    }

    /**
     * @see org.opencms.workplace.list.A_CmsListDialog#setMultiActions(org.opencms.workplace.list.CmsListMetadata)
     */
    @Override
    protected void setMultiActions(CmsListMetadata metadata) {

        // add the Fatal multi action
        CmsListMultiAction settoFatal = new CmsChangeLogLevelMultiAction(SET_TO_FATAL);
        settoFatal.setName(Messages.get().container(Messages.GUI_LOG_LEVEL_FATAL_MULTI_HELP_0));
        settoFatal.setConfirmationMessage(Messages.get().container(Messages.GUI_LOG_LEVEL_FATAL_MULTI_CONFIRMATION_0));
        settoFatal.setIconPath(PATH_FATAL_ACTIVE);
        settoFatal.setHelpText(Messages.get().container(Messages.GUI_LOG_LEVEL_FATAL_MULTI_HELP_0));
        metadata.addMultiAction(settoFatal);

        // add the Error multi action
        CmsListMultiAction settoError = new CmsChangeLogLevelMultiAction(SET_TO_ERROR);
        settoError.setName(Messages.get().container(Messages.GUI_LOG_LEVEL_ERROR_MULTI_HELP_0));
        settoError.setConfirmationMessage(Messages.get().container(Messages.GUI_LOG_LEVEL_ERROR_MULTI_CONFIRMATION_0));
        settoError.setIconPath(PATH_ERROR_ACTIVE);
        settoError.setHelpText(Messages.get().container(Messages.GUI_LOG_LEVEL_ERROR_MULTI_HELP_0));
        metadata.addMultiAction(settoError);

        // add the Warn multi action
        CmsListMultiAction settoWarn = new CmsChangeLogLevelMultiAction(SET_TO_WARN);
        settoWarn.setName(Messages.get().container(Messages.GUI_LOG_LEVEL_WARN_MULTI_HELP_0));
        settoWarn.setConfirmationMessage(Messages.get().container(Messages.GUI_LOG_LEVEL_WARN_MULTI_CONFIRMATION_0));
        settoWarn.setIconPath(PATH_WARN_ACTIVE);
        settoWarn.setHelpText(Messages.get().container(Messages.GUI_LOG_LEVEL_WARN_MULTI_HELP_0));
        metadata.addMultiAction(settoWarn);

        // add the Info multi action
        CmsListMultiAction settoInfo = new CmsChangeLogLevelMultiAction(SET_TO_INFO);
        settoInfo.setName(Messages.get().container(Messages.GUI_LOG_LEVEL_INFO_MULTI_HELP_0));
        settoInfo.setConfirmationMessage(Messages.get().container(Messages.GUI_LOG_LEVEL_INFO_MULTI_CONFIRMATION_0));
        settoInfo.setIconPath(PATH_INFO_ACTIVE);
        settoInfo.setHelpText(Messages.get().container(Messages.GUI_LOG_LEVEL_INFO_MULTI_HELP_0));
        metadata.addMultiAction(settoInfo);

        // add the Debug multi action
        CmsListMultiAction settoDebug = new CmsChangeLogLevelMultiAction(SET_TO_DEBUG);
        settoDebug.setName(Messages.get().container(Messages.GUI_LOG_LEVEL_DEBUG_MULTI_HELP_0));
        settoDebug.setConfirmationMessage(Messages.get().container(Messages.GUI_LOG_LEVEL_DEBUG_MULTI_CONFIRMATION_0));
        settoDebug.setIconPath(PATH_DEBUG_ACTIVE);
        settoDebug.setHelpText(Messages.get().container(Messages.GUI_LOG_LEVEL_DEBUG_MULTI_HELP_0));
        metadata.addMultiAction(settoDebug);

        // add the Off multi action
        CmsListMultiAction settoOff = new CmsChangeLogLevelMultiAction(SET_TO_OFF);
        settoOff.setName(Messages.get().container(Messages.GUI_LOG_LEVEL_OFF_MULTI_HELP_0));
        settoOff.setConfirmationMessage(Messages.get().container(Messages.GUI_LOG_LEVEL_OFF_MULTI_CONFIRMATION_0));
        settoOff.setIconPath(PATH_OFF_ACTIVE);
        settoOff.setHelpText(Messages.get().container(Messages.GUI_LOG_LEVEL_OFF_MULTI_HELP_0));
        metadata.addMultiAction(settoOff);
    }

    /**
     * Simple function to get the prefix of an logchannel name.<p>
     *
     * @param logname the full name of the logging channel
     *
     * @return a string array with different package prefixes
     */
    private String[] buildsufix(String logname) {

        // help String array to store all combination
        String[] prefix_temp = new String[logname.length()];
        int count = 0;
        while (logname.indexOf(".") > 1) {
            // separate the name of the logger into pieces of name and separator e.g.: "org."
            String subprefix = logname.substring(0, logname.indexOf(".") + 1);
            logname = logname.replace(subprefix, "");
            if (logname.indexOf(".") > 1) {
                if (count > 0) {
                    // build different suffixes based on the pieces separated above
                    prefix_temp[count] = prefix_temp[count - 1] + subprefix;
                } else {
                    // if it's the first piece of the name only it will be set
                    prefix_temp[count] = subprefix;

                }
            }
            count++;
        }
        // if the logger name has more then one piece
        if (count >= 1) {
            // create result string array
            String[] prefix = new String[count - 1];
            // copy all different prefixes to one array with right size
            for (int i = 0; i < (count - 1); i++) {
                prefix[i] = prefix_temp[i].substring(0, prefix_temp[i].length() - 1);
            }
            // return all different prefixes
            return prefix;
        }
        // if the logger name has only one or less piece
        else {
            // return the full logger name
            String[] nullreturn = new String[1];
            nullreturn[0] = logname;
            return nullreturn;
        }
    }

    /**
     * Help function to get all loggers from LogManager.<p>
     *
     * @return List of Logger
     */
    private List<Logger> getLoggers() {

        // list of all loggers
        List<Logger> definedLoggers = new ArrayList<Logger>();
        // list of all parent loggers
        List<Logger> packageLoggers = new ArrayList<Logger>();
        @SuppressWarnings("unchecked")
        List<Logger> curentloggerlist = Collections.list(LogManager.getCurrentLoggers());
        Iterator<Logger> it_curentlogger = curentloggerlist.iterator();
        // get all current loggers
        while (it_curentlogger.hasNext()) {
            // get the logger
            Logger log = it_curentlogger.next();
            String logname = log.getName();
            String[] prefix = buildsufix(logname);
            // create all possible package logger from given logger name
            for (int i = 0; i < prefix.length; i++) {
                // get the name of the logger without the prefix
                String temp = log.getName().replace(prefix[i], "");
                // if the name has suffix
                if (temp.length() > 1) {
                    temp = temp.substring(1);
                }
                if (temp.lastIndexOf(".") > 1) {
                    // generate new logger with "org.opencms" prefix and the next element
                    // between the points e.g.: "org.opencms.search"
                    Logger temp_logger = Logger.getLogger(prefix[i] + "." + temp.substring(0, temp.indexOf(".")));
                    // activate the heredity so the logger get the appender from parent logger
                    temp_logger.setAdditivity(true);
                    // add the logger to the packageLoggers list if it is not part of it
                    if (!packageLoggers.contains(temp_logger)) {
                        packageLoggers.add(temp_logger);
                    }
                }
            }
            definedLoggers.add(log);

        }

        Iterator<Logger> it_logger = packageLoggers.iterator();
        // iterate about all packageLoggers
        while (it_logger.hasNext()) {
            Logger temp = it_logger.next();
            // check if the logger is part of the logger list
            if (!definedLoggers.contains(temp)) {
                // add the logger to the logger list
                definedLoggers.add(temp);
            }
        }

        // sort all loggers by name
        Collections.sort(definedLoggers, new Comparator<Object>() {

            public int compare(Logger o1, Logger o2) {

                return String.CASE_INSENSITIVE_ORDER.compare(o1.getName(), o2.getName());
            }

            public int compare(Object obj, Object obj1) {

                return compare((Logger)obj, (Logger)obj1);
            }

        });
        // return all loggers
        return definedLoggers;
    }

    /**
     * Simple function to set all child loggers to the same value of parent
     * logger if the parent logger leves is changed.<p>
     *
     * @param logchannel the channel that might be the parent logger
     */
    private void isparentlogger(Logger logchannel) {

        // get all log channels
        List<Logger> referenz = getLoggers();
        Iterator<Logger> it_logger = referenz.iterator();
        while (it_logger.hasNext()) {
            Logger child_test = it_logger.next();
            // if the logchannel has the given logchannel as parent his loglevel is set to the parent one.
            if (logchannel.getName().equals(child_test.getParent().getName())) {
                isparentlogger(child_test);
                child_test.setLevel(null);
            }
        }
    }
}
