001/*
002 * This library is part of OpenCms -
003 * the Open Source Content Management System
004 *
005 * Copyright (c) Alkacon Software GmbH & Co. KG (http://www.alkacon.com)
006 *
007 * This library is free software; you can redistribute it and/or
008 * modify it under the terms of the GNU Lesser General Public
009 * License as published by the Free Software Foundation; either
010 * version 2.1 of the License, or (at your option) any later version.
011 *
012 * This library is distributed in the hope that it will be useful,
013 * but WITHOUT ANY WARRANTY; without even the implied warranty of
014 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
015 * Lesser General Public License for more details.
016 *
017 * For further information about Alkacon Software, please see the
018 * company website: http://www.alkacon.com
019 *
020 * For further information about OpenCms, please see the
021 * project website: http://www.opencms.org
022 *
023 * You should have received a copy of the GNU Lesser General Public
024 * License along with this library; if not, write to the Free Software
025 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
026 */
027
028package org.opencms.workplace.tools.workplace.logging;
029
030import org.opencms.jsp.CmsJspActionElement;
031import org.opencms.main.CmsLog;
032import org.opencms.main.CmsRuntimeException;
033import org.opencms.workplace.list.A_CmsListDialog;
034import org.opencms.workplace.list.CmsListColumnAlignEnum;
035import org.opencms.workplace.list.CmsListColumnDefinition;
036import org.opencms.workplace.list.CmsListDirectAction;
037import org.opencms.workplace.list.CmsListItem;
038import org.opencms.workplace.list.CmsListMetadata;
039import org.opencms.workplace.list.CmsListMultiAction;
040import org.opencms.workplace.list.CmsListOrderEnum;
041import org.opencms.workplace.list.CmsListSearchAction;
042
043import java.io.File;
044import java.util.ArrayList;
045import java.util.Collection;
046import java.util.Collections;
047import java.util.Comparator;
048import java.util.Iterator;
049import java.util.LinkedList;
050import java.util.List;
051
052import org.apache.commons.logging.Log;
053import org.apache.logging.log4j.Level;
054import org.apache.logging.log4j.LogManager;
055import org.apache.logging.log4j.core.Appender;
056import org.apache.logging.log4j.core.Layout;
057import org.apache.logging.log4j.core.Logger;
058import org.apache.logging.log4j.core.LoggerContext;
059import org.apache.logging.log4j.core.appender.FileAppender;
060import org.apache.logging.log4j.core.config.Configurator;
061
062/**
063 * Main logging management list view.<p>
064 *
065 * Defines the list columns and possible actions for logging.<p>
066 *
067 */
068public class CmsLog4JAdminDialog extends A_CmsListDialog {
069
070    /** List column class. */
071    protected static final String COLUMN_ACTIVE = "cac";
072
073    /** Name of the list for separate log files. */
074    protected static final String COLUMN_CHANGE_LOGFILE = "Seperate Log file";
075
076    /** Name of the logger-List. */
077    protected static final String COLUMN_CHANNELS = "channels";
078
079    /** Shortcut for the DEBUG column. */
080    protected static final String COLUMN_DEBUG = "chd";
081
082    /** Shortcut for the ERROR column. */
083    protected static final String COLUMN_ERROR = "che";
084
085    /** Shortcut for the FATAL column. */
086    protected static final String COLUMN_FATAL = "chf";
087
088    /** Shortcut for the INFO column. */
089    protected static final String COLUMN_INFO = "chi";
090
091    /** Name of the parent-list. */
092    protected static final String COLUMN_LOG_FILE = "Log-File";
093
094    /** Actual level of logging. */
095    protected static final String COLUMN_LOG_LEVEL = "loggerlevel";
096
097    /** Shortcut for the OFF column. */
098    protected static final String COLUMN_OFF = "cho";
099
100    /** Name of the parent-list. */
101    protected static final String COLUMN_PARENT_CHANNELS = "parent";
102
103    /** Shortcut for the WARN column. */
104    protected static final String COLUMN_WARN = "chw";
105
106    /** Name of the logchannel Action. */
107    private static final String ACTION_ACTIVATE_LOGFILE = "activlogchannel";
108
109    /** Name of the Debug-level Action. */
110    private static final String ACTION_LOGGING_LEVEL_DEBUG = "debugchannel";
111
112    /** Name of the Error-level Action. */
113    private static final String ACTION_LOGGING_LEVEL_ERROR = "errorlevel";
114
115    /** Name of the Fatal-level Action. */
116    private static final String ACTION_LOGGING_LEVEL_FATAL = "fatallevel";
117
118    /** Name of the Info-level Action. */
119    private static final String ACTION_LOGGING_LEVEL_INFO = "infochannel";
120
121    /** Name of the Off-level Action. */
122    private static final String ACTION_LOGGING_LEVEL_OFF = "offlevel";
123
124    /** Name of the Warn-level Action. */
125    private static final String ACTION_LOGGING_LEVEL_WARN = "warnchannel";
126
127    /** The log object for this class. */
128    private static final Log LOG = CmsLog.getLog(CmsLog4JAdminDialog.class);
129
130    /** The prefix of opencms classes. */
131    private static final String OPENCMS_CLASS_PREFIX = "org.opencms";
132
133    /** Path to the list buttons. */
134    private static final String PATH_BUTTONS = "buttons/";
135
136    /** Path to the Debug-Icon(active). */
137    private static final String PATH_DEBUG_ACTIVE = PATH_BUTTONS + "log_button_debug_a_2.png";
138
139    /** Path to the Debug-Icon(inactive). */
140    private static final String PATH_DEBUG_INACTIVE = PATH_BUTTONS + "log_button_debug_i_2.png";
141
142    /** Path to the Error-Icon(active). */
143    private static final String PATH_ERROR_ACTIVE = PATH_BUTTONS + "log_button_error_a_2.png";
144
145    /** Path to the Error-Icon(inactive). */
146    private static final String PATH_ERROR_INACTIVE = PATH_BUTTONS + "log_button_error_i_2.png";
147
148    /** Path to the Fatal-Icon(active). */
149    private static final String PATH_FATAL_ACTIVE = PATH_BUTTONS + "log_button_fatal_a_2.png";
150
151    /** Path to the Fatal-Icon(inactive). */
152    private static final String PATH_FATAL_INACTIVE = PATH_BUTTONS + "log_button_fatal_i_2.png";
153
154    /** Path to the File-Icon(active). */
155    private static final String PATH_FILE_ACTIVE = PATH_BUTTONS + "log_button_file_on_2.png";
156
157    /** Path to the File-Icon(inactive). */
158    private static final String PATH_FILE_INACTIVE = PATH_BUTTONS + "log_button_file_off_2.png";
159
160    /** Path to the Info-Icon(active). */
161    private static final String PATH_INFO_ACTIVE = PATH_BUTTONS + "log_button_info_a_2.png";
162
163    /** Path to the Info-Icon(inactive). */
164    private static final String PATH_INFO_INACTIVE = PATH_BUTTONS + "log_button_info_i_2.png";
165
166    /** Path to the Off-Icon(active). */
167    private static final String PATH_OFF_ACTIVE = PATH_BUTTONS + "log_button_off_a_2.png";
168
169    /** Path to the Off-Icon(inactive). */
170    private static final String PATH_OFF_INACTIVE = PATH_BUTTONS + "log_button_off_i_2.png";
171
172    /** Path to the Warning-Icon(active). */
173    private static final String PATH_WARN_ACTIVE = PATH_BUTTONS + "log_button_warn_a_2.png";
174
175    /** Path to the Warning-Icon(inactive). */
176    private static final String PATH_WARN_INACTIVE = PATH_BUTTONS + "log_button_warn_i_2.png";
177
178    /** Shortcut for the MultiAction (DEBUG). */
179    private static final String SET_TO_DEBUG = "sd";
180
181    /** Shortcut for the MultiAction (ERROR). */
182    private static final String SET_TO_ERROR = "sr";
183
184    /** Shortcut for the MultiAction (FATAL). */
185    private static final String SET_TO_FATAL = "sf";
186
187    /** Shortcut for the MultiAction (INFO). */
188    private static final String SET_TO_INFO = "si";
189
190    /** Shortcut for the MultiAction (OFF). */
191    private static final String SET_TO_OFF = "so";
192
193    /** Shortcut for the MultiAction (WARN). */
194    private static final String SET_TO_WARN = "sw";
195
196    /**
197     * Public constructor.<p>
198     *
199     * @param jsp the JSP action element
200     */
201    public CmsLog4JAdminDialog(CmsJspActionElement jsp) {
202
203        super(
204            jsp,
205            "Log Settings",
206            Messages.get().container(Messages.GUI_LOG_LIST_NAME_0),
207            "lo",
208            CmsListOrderEnum.ORDER_ASCENDING,
209            null);
210    }
211
212    /**
213     * @see org.opencms.workplace.list.A_CmsListDialog#executeListMultiActions()
214     */
215    @Override
216    public void executeListMultiActions() throws CmsRuntimeException {
217
218        // switch the selected loggers to the logging-level
219
220        Level newLogchannelLevel = null;
221        // get the selected logging-level
222        if (getParamListAction().equals(SET_TO_ERROR)) {
223            newLogchannelLevel = Level.ERROR;
224        } else if (getParamListAction().equals(SET_TO_DEBUG)) {
225            newLogchannelLevel = Level.DEBUG;
226        } else if (getParamListAction().equals(SET_TO_FATAL)) {
227            newLogchannelLevel = Level.FATAL;
228        } else if (getParamListAction().equals(SET_TO_INFO)) {
229            newLogchannelLevel = Level.INFO;
230        } else if (getParamListAction().equals(SET_TO_WARN)) {
231            newLogchannelLevel = Level.WARN;
232        } else if (getParamListAction().equals(SET_TO_OFF)) {
233            newLogchannelLevel = Level.OFF;
234        }
235
236        // list all selected log channels
237        List<CmsListItem> list = getSelectedItems();
238        Iterator<CmsListItem> itItems = list.iterator();
239        // iterate about all log channels to set the above selected loglevel
240        while (itItems.hasNext()) {
241            String logchannnelName = itItems.next().getId();
242            Configurator.setLevel(logchannnelName, newLogchannelLevel);
243        }
244
245        refreshList();
246
247    }
248
249    /**
250     * @see org.opencms.workplace.list.A_CmsListDialog#executeListSingleActions()
251     */
252    @Override
253    public void executeListSingleActions() throws CmsRuntimeException {
254
255        // switch a single log-channel to an other logging-level
256        if (getSelectedItem() == null) {
257            return;
258        }
259        // get the log-channel to change the level
260        String logchannnelName = getSelectedItem().getId();
261        Logger logchannel = getLoggerImpl(logchannnelName);
262        if (logchannel == null) {
263            return;
264        }
265        // get the selected logging-level with the help of the row
266        Level newLogchannelLevel = null;
267        if (ACTION_LOGGING_LEVEL_DEBUG.equals(getParamListAction())) {
268            newLogchannelLevel = Level.DEBUG;
269        } else if (ACTION_LOGGING_LEVEL_INFO.equals(getParamListAction())) {
270            newLogchannelLevel = Level.INFO;
271        } else if (ACTION_LOGGING_LEVEL_WARN.equals(getParamListAction())) {
272            newLogchannelLevel = Level.WARN;
273        } else if (ACTION_LOGGING_LEVEL_ERROR.equals(getParamListAction())) {
274            newLogchannelLevel = Level.ERROR;
275        } else if (ACTION_LOGGING_LEVEL_FATAL.equals(getParamListAction())) {
276            newLogchannelLevel = Level.FATAL;
277        } else if (ACTION_LOGGING_LEVEL_OFF.equals(getParamListAction())) {
278            newLogchannelLevel = Level.OFF;
279        }
280        if (newLogchannelLevel != null) {
281            isparentlogger(logchannel);
282            if (newLogchannelLevel.equals(logchannel.getParent().getLevel())) {
283                Configurator.setLevel(logchannnelName, null);
284            } else {
285                Configurator.setLevel(logchannnelName, newLogchannelLevel);
286            }
287        }
288        if (ACTION_ACTIVATE_LOGFILE.equals(getParamListAction())) {
289            String filepath = "";
290            Layout layout = null;
291            // if the button is activated check the value of the button
292            // the button was active
293            if (isloggingactivated(logchannel)) {
294                // remove the private Appender from logger
295                logchannel.getAppenders().clear();
296                // activate the heredity so the logger get the appender from parent logger
297                logchannel.setAdditive(true);
298
299            }
300            // the button was inactive
301            else {
302                Collection<Appender> rootAppenders = ((Logger)LogManager.getRootLogger()).getAppenders().values();
303                // get the layout and file path from root logger
304                for (Appender appender : rootAppenders) {
305                    if (appender instanceof FileAppender) {
306                        FileAppender fapp = (FileAppender)appender;
307                        filepath = fapp.getFileName().substring(0, fapp.getFileName().lastIndexOf(File.separatorChar));
308                        layout = fapp.getLayout();
309                        break;
310                    }
311                }
312
313                Collection<Appender> appenders = logchannel.getAppenders().values();
314                // check if the logger has an Appender get his layout
315                for (Appender appender : appenders) {
316                    if (appender instanceof FileAppender) {
317                        FileAppender fapp = (FileAppender)appender;
318                        layout = fapp.getLayout();
319                        break;
320                    }
321                }
322                String logfilename = "";
323                String temp = logchannel.getName();
324                // check if the logger name begins with "org.opencms"
325                if (logchannel.getName().contains(OPENCMS_CLASS_PREFIX)) {
326                    // remove the prefix "org.opencms" from logger name to generate the file name
327                    temp = temp.replace(OPENCMS_CLASS_PREFIX, "");
328                    // if the name has suffix
329                    if (temp.length() >= 1) {
330                        logfilename = filepath
331                            + File.separator
332                            + "opencms-"
333                            + temp.substring(1).replace(".", "-")
334                            + ".log";
335                    }
336                    // if the name has no suffix
337                    else {
338                        logfilename = filepath + File.separator + "opencms" + temp.replace(".", "-") + ".log";
339                    }
340                }
341                // if the logger name not begins with "org.opencms"
342                else {
343                    logfilename = filepath + File.separator + "opencms-" + temp.replace(".", "-") + ".log";
344                }
345
346                FileAppender fapp = null;
347                try {
348                    // create new FileAppender for separate log file
349                    fapp = ((FileAppender.Builder)FileAppender.newBuilder().withLayout(layout).withFileName(
350                        logfilename).withAppend(true).withName(logchannnelName)).build();
351
352                } catch (Exception e) {
353                    LOG.error(Messages.get().container(Messages.LOG_CREATING_APPENDER_0), e);
354                }
355                // deactivate the heredity so the logger get no longer the appender from parent logger
356                logchannel.setAdditive(false);
357                // remove all active Appenders from logger
358                logchannel.getAppenders().clear();
359                // add the new created Appender to the logger
360                logchannel.addAppender(fapp);
361            }
362        }
363        refreshList();
364    }
365
366    /**
367     * @see org.opencms.workplace.list.A_CmsListDialog#fillDetails(java.lang.String)
368     */
369    @Override
370    protected void fillDetails(String detailId) {
371
372        // noop
373    }
374
375    /**
376     * @see org.opencms.workplace.list.A_CmsListDialog#getListItems()
377     */
378    @Override
379    protected List<CmsListItem> getListItems() {
380
381        // collect all the values for "Log-channels", "Log-channels-parents" and "Log-channels-level"
382        List<CmsListItem> items = new LinkedList<CmsListItem>();
383        List<Logger> loggers = getLoggers();
384        Iterator<Logger> iterator = loggers.iterator();
385        while (iterator.hasNext()) {
386            Logger logger = iterator.next();
387            CmsListItem item = getList().newItem(logger.getName());
388            item.set(COLUMN_CHANNELS, logger.getName());
389            Logger parentLogger = logger.getParent();
390            if (parentLogger == null) {
391                item.set(COLUMN_PARENT_CHANNELS, "");
392            } else {
393                item.set(COLUMN_PARENT_CHANNELS, logger.getParent().getName());
394            }
395            item.set(COLUMN_LOG_LEVEL, String.valueOf(logger.getLevel()));
396
397            String test = "";
398            Collection<Appender> appenders = logger.getAppenders().values();
399            int count = 0;
400            // select the Appender from logger
401            for (Appender appender : appenders) {
402                // only use file appenders
403                if (appender instanceof FileAppender) {
404                    FileAppender fapp = (FileAppender)appender;
405                    String temp = "";
406                    temp = fapp.getFileName().substring(fapp.getFileName().lastIndexOf(File.separatorChar) + 1);
407                    test = test + temp;
408                    count++;
409                    break;
410                }
411            }
412            Collection<Appender> parentAppenders = logger.getParent().getAppenders().values();
413            // if no Appender found from logger, select the Appender from parent logger
414            if (count == 0) {
415                for (Appender appender : parentAppenders) {
416                    // only use file appenders
417                    if (appender instanceof FileAppender) {
418                        FileAppender fapp = (FileAppender)appender;
419                        String temp = "";
420                        temp = fapp.getFileName().substring(fapp.getFileName().lastIndexOf(File.separatorChar) + 1);
421                        test = test + temp;
422                        count++;
423                        break;
424                    }
425                }
426            }
427
428            if (count == 0) {
429                Collection<Appender> rootAppenders = ((Logger)LogManager.getRootLogger()).getAppenders().values();
430                // if no Appender found from parent logger, select the Appender from root logger
431                for (Appender appender : rootAppenders) {
432                    // only use file appenders
433                    if (appender instanceof FileAppender) {
434                        FileAppender fapp = (FileAppender)appender;
435                        String temp = "";
436                        temp = fapp.getFileName().substring(fapp.getFileName().lastIndexOf(File.separatorChar) + 1);
437                        test = test + temp;
438                        break;
439                    }
440                }
441
442            }
443            item.set(COLUMN_LOG_FILE, test);
444            items.add(item);
445        }
446        return items;
447    }
448
449    /**
450     * Simple check if the logger has the global log file <p> or a single one.
451     *
452     * @param logchannel the channel that has do be checked
453     * @return true if the the log channel has a single log file
454     * */
455    protected boolean isloggingactivated(Logger logchannel) {
456
457        return logchannel.getAppenders().containsKey(logchannel.getName());
458    }
459
460    /**
461     * @see org.opencms.workplace.list.A_CmsListDialog#setColumns(org.opencms.workplace.list.CmsListMetadata)
462     */
463    @Override
464    protected void setColumns(CmsListMetadata metadata) {
465
466        //////////////////
467        // FATAL COLUMN //
468        //////////////////
469        CmsListColumnDefinition fatalColumn = new CmsListColumnDefinition(COLUMN_FATAL);
470        fatalColumn.setName(Messages.get().container(Messages.GUI_LOG_LEVEL_FATAL_0));
471        fatalColumn.setAlign(CmsListColumnAlignEnum.ALIGN_CENTER);
472        fatalColumn.setWidth("50");
473        fatalColumn.setListItemComparator(new CmsLogLevelListItemComparator());
474        fatalColumn.setPrintable(false);
475        fatalColumn.setAlign(CmsListColumnAlignEnum.ALIGN_CENTER);
476        fatalColumn.setListItemComparator(new CmsLogLevelListItemComparator());
477        CmsListDirectAction fatalActAction = new CmsChangeLogLevelAction(ACTION_LOGGING_LEVEL_FATAL, Level.FATAL) {
478
479            /**
480             * @see org.opencms.workplace.tools.A_CmsHtmlIconButton#isVisible()
481             */
482            @Override
483            public boolean isVisible() {
484
485                Level actuallevel = Level.toLevel((String)getItem().get(COLUMN_LOG_LEVEL));
486                if (actuallevel != null) {
487
488                    if (actuallevel.intLevel() < Level.FATAL.intLevel()) {
489                        setIconPath(PATH_FATAL_ACTIVE);
490                        setName(Messages.get().container(Messages.GUI_LOG_LEVEL_FATAL_HELP_DEACTIVATE_0));
491                    } else if (actuallevel.intLevel() == Level.FATAL.intLevel()) {
492                        setIconPath(PATH_FATAL_ACTIVE);
493                        setName(Messages.get().container(Messages.GUI_LOG_LEVEL_ACTIVE_0));
494                    } else {
495                        setIconPath(PATH_FATAL_INACTIVE);
496                        setName(Messages.get().container(Messages.GUI_LOG_LEVEL_FATAL_HELP_ACTIVATE_0));
497                    }
498                }
499                return super.isVisible();
500            }
501        };
502        fatalActAction.setHelpText(Messages.get().container(Messages.GUI_LOG_LEVEL_FATAL_HELP_0));
503        fatalColumn.addDirectAction(fatalActAction);
504        metadata.addColumn(fatalColumn);
505
506        //////////////////
507        // ERROR COLUMN //
508        //////////////////
509        CmsListColumnDefinition errorColumn = new CmsListColumnDefinition(COLUMN_ERROR);
510        errorColumn.setName(Messages.get().container(Messages.GUI_LOG_LEVEL_ERROR_0));
511        errorColumn.setAlign(CmsListColumnAlignEnum.ALIGN_CENTER);
512        errorColumn.setWidth("50");
513        errorColumn.setPrintable(false);
514        errorColumn.setAlign(CmsListColumnAlignEnum.ALIGN_CENTER);
515        errorColumn.setListItemComparator(new CmsLogLevelListItemComparator());
516        CmsListDirectAction errorActAction = new CmsChangeLogLevelAction(ACTION_LOGGING_LEVEL_ERROR, Level.ERROR) {
517
518            /**
519             * @see org.opencms.workplace.tools.A_CmsHtmlIconButton#isVisible()
520             */
521            @Override
522            public boolean isVisible() {
523
524                Level actuallevel = Level.toLevel((String)getItem().get(COLUMN_LOG_LEVEL));
525                if (actuallevel != null) {
526                    if ((actuallevel.intLevel() < Level.ERROR.intLevel())) {
527                        setIconPath(PATH_ERROR_ACTIVE);
528                        setName(Messages.get().container(Messages.GUI_LOG_LEVEL_ERROR_HELP_DEACTIVATE_0));
529                    } else if (actuallevel.intLevel() == Level.ERROR.intLevel()) {
530                        setIconPath(PATH_ERROR_ACTIVE);
531                        setName(Messages.get().container(Messages.GUI_LOG_LEVEL_ACTIVE_0));
532                    } else {
533                        setIconPath(PATH_ERROR_INACTIVE);
534                        setName(Messages.get().container(Messages.GUI_LOG_LEVEL_ERROR_HELP_ACTIVATE_0));
535                    }
536                }
537                return super.isVisible();
538            }
539        };
540        errorActAction.setHelpText(Messages.get().container(Messages.GUI_LOG_LEVEL_ERROR_HELP_0));
541        errorColumn.addDirectAction(errorActAction);
542        metadata.addColumn(errorColumn);
543
544        /////////////////
545        // WARN COLUMN //
546        /////////////////
547        CmsListColumnDefinition warnColumn = new CmsListColumnDefinition(COLUMN_WARN);
548        warnColumn.setName(Messages.get().container(Messages.GUI_LOG_LEVEL_WARN_0));
549        warnColumn.setAlign(CmsListColumnAlignEnum.ALIGN_CENTER);
550        warnColumn.setWidth("50");
551        warnColumn.setPrintable(false);
552        warnColumn.setAlign(CmsListColumnAlignEnum.ALIGN_CENTER);
553        warnColumn.setListItemComparator(new CmsLogLevelListItemComparator());
554        CmsListDirectAction warnAction = new CmsChangeLogLevelAction(ACTION_LOGGING_LEVEL_WARN, Level.WARN) {
555
556            /**
557             * @see org.opencms.workplace.tools.A_CmsHtmlIconButton#isVisible()
558             */
559            @Override
560            public boolean isVisible() {
561
562                Level actuallevel = Level.toLevel((String)getItem().get(COLUMN_LOG_LEVEL));
563                if (actuallevel != null) {
564                    if ((actuallevel.intLevel() < Level.WARN.intLevel())) {
565                        setIconPath(PATH_WARN_ACTIVE);
566                        setName(Messages.get().container(Messages.GUI_LOG_LEVEL_WARN_HELP_DEACTIVATE_0));
567                    } else if (actuallevel.intLevel() == Level.WARN.intLevel()) {
568                        setIconPath(PATH_WARN_ACTIVE);
569                        setName(Messages.get().container(Messages.GUI_LOG_LEVEL_ACTIVE_0));
570                    } else {
571                        setIconPath(PATH_WARN_INACTIVE);
572                        setName(Messages.get().container(Messages.GUI_LOG_LEVEL_WARN_HELP_ACTIVATE_0));
573                    }
574                }
575                return super.isVisible();
576            }
577        };
578        warnAction.setHelpText(Messages.get().container(Messages.GUI_LOG_LEVEL_WARN_HELP_0));
579        warnColumn.addDirectAction(warnAction);
580        metadata.addColumn(warnColumn);
581
582        /////////////////
583        // INFO COLUMN //
584        /////////////////
585        CmsListColumnDefinition infoColumn = new CmsListColumnDefinition(COLUMN_INFO);
586        infoColumn.setName(Messages.get().container(Messages.GUI_LOG_LEVEL_INFO_0));
587        infoColumn.setAlign(CmsListColumnAlignEnum.ALIGN_CENTER);
588        infoColumn.setWidth("50");
589        infoColumn.setPrintable(false);
590        infoColumn.setAlign(CmsListColumnAlignEnum.ALIGN_CENTER);
591        infoColumn.setListItemComparator(new CmsLogLevelListItemComparator());
592        CmsListDirectAction infoAction = new CmsChangeLogLevelAction(ACTION_LOGGING_LEVEL_INFO, Level.INFO) {
593
594            /**
595             * @see org.opencms.workplace.tools.A_CmsHtmlIconButton#isVisible()
596             */
597            @Override
598            public boolean isVisible() {
599
600                // check the Loglevel from hidden column and set the right icon
601                Level actuallevel = Level.toLevel((String)getItem().get(COLUMN_LOG_LEVEL));
602                if (actuallevel != null) {
603                    if ((actuallevel.intLevel() < Level.INFO.intLevel())) {
604                        setIconPath(PATH_INFO_ACTIVE);
605                        setName(Messages.get().container(Messages.GUI_LOG_LEVEL_INFO_HELP_DEACTIVATE_0));
606                    } else if (actuallevel.intLevel() == Level.INFO.intLevel()) {
607                        setIconPath(PATH_INFO_ACTIVE);
608                        setName(Messages.get().container(Messages.GUI_LOG_LEVEL_ACTIVE_0));
609                    } else {
610                        setIconPath(PATH_INFO_INACTIVE);
611                        setName(Messages.get().container(Messages.GUI_LOG_LEVEL_INFO_HELP_ACTIVATE_0));
612                    }
613                }
614                return super.isVisible();
615            }
616        };
617        infoAction.setHelpText(Messages.get().container(Messages.GUI_LOG_LEVEL_INFO_HELP_0));
618        infoColumn.addDirectAction(infoAction);
619        metadata.addColumn(infoColumn);
620
621        //////////////////
622        // DEBUG COLUMN //
623        //////////////////
624        CmsListColumnDefinition debugColumn = new CmsListColumnDefinition(COLUMN_DEBUG);
625        debugColumn.setName(Messages.get().container(Messages.GUI_LOG_LEVEL_DEBUG_0));
626        debugColumn.setAlign(CmsListColumnAlignEnum.ALIGN_CENTER);
627        debugColumn.setWidth("50");
628        debugColumn.setAlign(CmsListColumnAlignEnum.ALIGN_CENTER);
629        debugColumn.setPrintable(false);
630        debugColumn.setListItemComparator(new CmsLogLevelListItemComparator());
631        // generate an Action to activate the change of a log-channel
632        CmsListDirectAction debugAction = new CmsChangeLogLevelAction(ACTION_LOGGING_LEVEL_DEBUG, Level.DEBUG) {
633
634            /**
635             * @see org.opencms.workplace.tools.A_CmsHtmlIconButton#isVisible()
636             */
637            @Override
638            public boolean isVisible() {
639
640                Level actuallevel = Level.toLevel((String)getItem().get(COLUMN_LOG_LEVEL));
641                if (actuallevel != null) {
642                    if (actuallevel.intLevel() < Level.DEBUG.intLevel()) {
643                        setIconPath(PATH_DEBUG_ACTIVE);
644                        setName(Messages.get().container(Messages.GUI_LOG_LEVEL_DEBUG_HELP_DEACTIVATE_0));
645                    } else if (actuallevel.intLevel() == Level.DEBUG.intLevel()) {
646                        setIconPath(PATH_DEBUG_ACTIVE);
647                        setName(Messages.get().container(Messages.GUI_LOG_LEVEL_ACTIVE_0));
648                    } else {
649                        setIconPath(PATH_DEBUG_INACTIVE);
650                        setName(Messages.get().container(Messages.GUI_LOG_LEVEL_DEBUG_HELP_ACTIVATE_0));
651                    }
652                }
653                return super.isVisible();
654            }
655        };
656        debugAction.setHelpText(Messages.get().container(Messages.GUI_LOG_LEVEL_DEBUG_HELP_0));
657        debugColumn.addDirectAction(debugAction);
658        metadata.addColumn(debugColumn);
659
660        /////////////////////
661        // TRUN OFF COLUMN //
662        /////////////////////
663        CmsListColumnDefinition offColumn = new CmsListColumnDefinition(COLUMN_OFF);
664        offColumn.setName(Messages.get().container(Messages.GUI_LOG_LEVEL_OFF_0));
665        offColumn.setAlign(CmsListColumnAlignEnum.ALIGN_CENTER);
666        offColumn.setWidth("50");
667        offColumn.setSorteable(true);
668        offColumn.setPrintable(false);
669        offColumn.setAlign(CmsListColumnAlignEnum.ALIGN_CENTER);
670        offColumn.setListItemComparator(new CmsLogLevelListItemComparator());
671        CmsListDirectAction offAction = new CmsChangeLogLevelAction(ACTION_LOGGING_LEVEL_OFF, Level.OFF) {
672
673            /**
674             * @see org.opencms.workplace.tools.A_CmsHtmlIconButton#isVisible()
675             */
676            @Override
677            public boolean isVisible() {
678
679                Level actuallevel = Level.toLevel((String)getItem().get(COLUMN_LOG_LEVEL));
680                if (actuallevel != null) {
681                    if (actuallevel.intLevel() == Level.OFF.intLevel()) {
682                        setIconPath(PATH_OFF_ACTIVE);
683                        setName(Messages.get().container(Messages.GUI_LOG_LEVEL_OFF_HELP_ACTIVATE_0));
684                    } else {
685                        setIconPath(PATH_OFF_INACTIVE);
686                        setName(Messages.get().container(Messages.GUI_LOG_LEVEL_OFF_HELP_DEACTIVATE_0));
687                    }
688                }
689                return super.isVisible();
690            }
691        };
692        offAction.setHelpText(Messages.get().container(Messages.GUI_LOG_LEVEL_OFF_HELP_0));
693        offColumn.addDirectAction(offAction);
694        metadata.addColumn(offColumn);
695
696        //////////////////////////////
697        // CURRENT LOG LEVEL COLUMN //
698        //////////////////////////////
699        CmsListColumnDefinition logLevelHidden = new CmsListColumnDefinition(COLUMN_LOG_LEVEL);
700        logLevelHidden.setName(Messages.get().container(Messages.GUI_LOG_LEVEL_CURRENT_0));
701        logLevelHidden.setAlign(CmsListColumnAlignEnum.ALIGN_CENTER);
702        logLevelHidden.setWidth("10%");
703        logLevelHidden.setSorteable(true);
704        logLevelHidden.setPrintable(true);
705        logLevelHidden.setVisible(false);
706        metadata.addColumn(logLevelHidden);
707
708        //////////////////
709        // LOG CHANNELS //
710        //////////////////
711        CmsListColumnDefinition channels = new CmsListColumnDefinition(COLUMN_CHANNELS);
712        channels.setName(Messages.get().container(Messages.GUI_LOG_CHANNELS_0));
713        channels.setAlign(CmsListColumnAlignEnum.ALIGN_LEFT);
714        channels.setSorteable(true);
715        channels.setWidth("50%");
716        channels.setPrintable(true);
717        metadata.addColumn(channels);
718
719        ///////////////////////////////
720        // PARENT LOG CHANNEL COLUMN //
721        ///////////////////////////////
722        CmsListColumnDefinition parentChannel = new CmsListColumnDefinition(COLUMN_PARENT_CHANNELS);
723        parentChannel.setName(Messages.get().container(Messages.GUI_LOG_PARENT_CHANNEL_0));
724        parentChannel.setAlign(CmsListColumnAlignEnum.ALIGN_LEFT);
725        parentChannel.setSorteable(true);
726        parentChannel.setWidth("20%");
727        parentChannel.setPrintable(false);
728        metadata.addColumn(parentChannel);
729
730        /////////////////////
731        // LOG FILE COLUMN //
732        /////////////////////
733        CmsListColumnDefinition selectedFile = new CmsListColumnDefinition(COLUMN_LOG_FILE);
734        selectedFile.setName(Messages.get().container(Messages.GUI_LOG_FILE_SELECTED_0));
735        selectedFile.setAlign(CmsListColumnAlignEnum.ALIGN_LEFT);
736        selectedFile.setSorteable(true);
737        selectedFile.setWidth("20%");
738        selectedFile.setPrintable(false);
739        metadata.addColumn(selectedFile);
740
741        ////////////////////////
742        // CHANGE FILE COLUMN //
743        ////////////////////////
744        CmsListColumnDefinition changeFile = new CmsListColumnDefinition(COLUMN_CHANGE_LOGFILE);
745        changeFile.setName(Messages.get().container(Messages.GUI_LOG_FILE_CHANGE_FILE_0));
746        changeFile.setAlign(CmsListColumnAlignEnum.ALIGN_LEFT);
747        changeFile.setSorteable(false);
748        changeFile.setWidth("25");
749        changeFile.setPrintable(false);
750        CmsListDirectAction changeFileAction = new CmsListDirectAction(ACTION_ACTIVATE_LOGFILE) {
751
752            /**
753             * @see org.opencms.workplace.tools.A_CmsHtmlIconButton#isVisible()
754             */
755            @Override
756            public boolean isVisible() {
757
758                Logger logger = getLoggerImpl((String)getItem().get(COLUMN_CHANNELS));
759                if (logger != null) {
760                    if (isloggingactivated(logger)) {
761                        setIconPath(PATH_FILE_ACTIVE);
762                        setName(Messages.get().container(Messages.GUI_LOG_FILE_CHANGE_FILE_HELP_DEACTIVATE_0));
763                    } else {
764                        setIconPath(PATH_FILE_INACTIVE);
765                        setName(Messages.get().container(Messages.GUI_LOG_FILE_CHANGE_FILE_HELP_ACTIVATE_0));
766                    }
767                }
768                return super.isVisible();
769            }
770        };
771        changeFileAction.setHelpText(Messages.get().container(Messages.GUI_LOG_FILE_CHANGE_FILE_HELP_0));
772        changeFileAction.setIconPath(PATH_OFF_ACTIVE);
773        changeFile.addDirectAction(changeFileAction);
774        metadata.addColumn(changeFile);
775
776        ///////////////////
777        // SEARCH ACTION //
778        ///////////////////
779        CmsListSearchAction searchAction = new CmsListSearchAction(metadata.getColumnDefinition(COLUMN_CHANNELS));
780        metadata.setSearchAction(searchAction);
781    }
782
783    /**
784     * @see org.opencms.workplace.list.A_CmsListDialog#setIndependentActions(org.opencms.workplace.list.CmsListMetadata)
785     */
786    @Override
787    protected void setIndependentActions(CmsListMetadata metadata) {
788
789        // noop
790    }
791
792    /**
793     * @see org.opencms.workplace.list.A_CmsListDialog#setMultiActions(org.opencms.workplace.list.CmsListMetadata)
794     */
795    @Override
796    protected void setMultiActions(CmsListMetadata metadata) {
797
798        // add the Fatal multi action
799        CmsListMultiAction settoFatal = new CmsChangeLogLevelMultiAction(SET_TO_FATAL);
800        settoFatal.setName(Messages.get().container(Messages.GUI_LOG_LEVEL_FATAL_MULTI_HELP_0));
801        settoFatal.setConfirmationMessage(Messages.get().container(Messages.GUI_LOG_LEVEL_FATAL_MULTI_CONFIRMATION_0));
802        settoFatal.setIconPath(PATH_FATAL_ACTIVE);
803        settoFatal.setHelpText(Messages.get().container(Messages.GUI_LOG_LEVEL_FATAL_MULTI_HELP_0));
804        metadata.addMultiAction(settoFatal);
805
806        // add the Error multi action
807        CmsListMultiAction settoError = new CmsChangeLogLevelMultiAction(SET_TO_ERROR);
808        settoError.setName(Messages.get().container(Messages.GUI_LOG_LEVEL_ERROR_MULTI_HELP_0));
809        settoError.setConfirmationMessage(Messages.get().container(Messages.GUI_LOG_LEVEL_ERROR_MULTI_CONFIRMATION_0));
810        settoError.setIconPath(PATH_ERROR_ACTIVE);
811        settoError.setHelpText(Messages.get().container(Messages.GUI_LOG_LEVEL_ERROR_MULTI_HELP_0));
812        metadata.addMultiAction(settoError);
813
814        // add the Warn multi action
815        CmsListMultiAction settoWarn = new CmsChangeLogLevelMultiAction(SET_TO_WARN);
816        settoWarn.setName(Messages.get().container(Messages.GUI_LOG_LEVEL_WARN_MULTI_HELP_0));
817        settoWarn.setConfirmationMessage(Messages.get().container(Messages.GUI_LOG_LEVEL_WARN_MULTI_CONFIRMATION_0));
818        settoWarn.setIconPath(PATH_WARN_ACTIVE);
819        settoWarn.setHelpText(Messages.get().container(Messages.GUI_LOG_LEVEL_WARN_MULTI_HELP_0));
820        metadata.addMultiAction(settoWarn);
821
822        // add the Info multi action
823        CmsListMultiAction settoInfo = new CmsChangeLogLevelMultiAction(SET_TO_INFO);
824        settoInfo.setName(Messages.get().container(Messages.GUI_LOG_LEVEL_INFO_MULTI_HELP_0));
825        settoInfo.setConfirmationMessage(Messages.get().container(Messages.GUI_LOG_LEVEL_INFO_MULTI_CONFIRMATION_0));
826        settoInfo.setIconPath(PATH_INFO_ACTIVE);
827        settoInfo.setHelpText(Messages.get().container(Messages.GUI_LOG_LEVEL_INFO_MULTI_HELP_0));
828        metadata.addMultiAction(settoInfo);
829
830        // add the Debug multi action
831        CmsListMultiAction settoDebug = new CmsChangeLogLevelMultiAction(SET_TO_DEBUG);
832        settoDebug.setName(Messages.get().container(Messages.GUI_LOG_LEVEL_DEBUG_MULTI_HELP_0));
833        settoDebug.setConfirmationMessage(Messages.get().container(Messages.GUI_LOG_LEVEL_DEBUG_MULTI_CONFIRMATION_0));
834        settoDebug.setIconPath(PATH_DEBUG_ACTIVE);
835        settoDebug.setHelpText(Messages.get().container(Messages.GUI_LOG_LEVEL_DEBUG_MULTI_HELP_0));
836        metadata.addMultiAction(settoDebug);
837
838        // add the Off multi action
839        CmsListMultiAction settoOff = new CmsChangeLogLevelMultiAction(SET_TO_OFF);
840        settoOff.setName(Messages.get().container(Messages.GUI_LOG_LEVEL_OFF_MULTI_HELP_0));
841        settoOff.setConfirmationMessage(Messages.get().container(Messages.GUI_LOG_LEVEL_OFF_MULTI_CONFIRMATION_0));
842        settoOff.setIconPath(PATH_OFF_ACTIVE);
843        settoOff.setHelpText(Messages.get().container(Messages.GUI_LOG_LEVEL_OFF_MULTI_HELP_0));
844        metadata.addMultiAction(settoOff);
845    }
846
847    /**
848     * Simple function to get the prefix of an logchannel name.<p>
849     *
850     * @param logname the full name of the logging channel
851     *
852     * @return a string array with different package prefixes
853     */
854    private String[] buildsufix(String logname) {
855
856        // help String array to store all combination
857        String[] prefix_temp = new String[logname.length()];
858        int count = 0;
859        while (logname.indexOf(".") > 1) {
860            // separate the name of the logger into pieces of name and separator e.g.: "org."
861            String subprefix = logname.substring(0, logname.indexOf(".") + 1);
862            logname = logname.replace(subprefix, "");
863            if (logname.indexOf(".") > 1) {
864                if (count > 0) {
865                    // build different suffixes based on the pieces separated above
866                    prefix_temp[count] = prefix_temp[count - 1] + subprefix;
867                } else {
868                    // if it's the first piece of the name only it will be set
869                    prefix_temp[count] = subprefix;
870
871                }
872            }
873            count++;
874        }
875        // if the logger name has more then one piece
876        if (count >= 1) {
877            // create result string array
878            String[] prefix = new String[count - 1];
879            // copy all different prefixes to one array with right size
880            for (int i = 0; i < (count - 1); i++) {
881                prefix[i] = prefix_temp[i].substring(0, prefix_temp[i].length() - 1);
882            }
883            // return all different prefixes
884            return prefix;
885        }
886        // if the logger name has only one or less piece
887        else {
888            // return the full logger name
889            String[] nullreturn = new String[1];
890            nullreturn[0] = logname;
891            return nullreturn;
892        }
893    }
894
895    /**
896     * @param logchannnelName
897     * @return
898     */
899    private Logger getLoggerImpl(String logchannnelName) {
900
901        return (Logger)LogManager.getLogger(logchannnelName);
902    }
903
904    /**
905     * Help function to get all loggers from LogManager.<p>
906     *
907     * @return List of Logger
908     */
909    private List<Logger> getLoggers() {
910
911        // list of all loggers
912        List<Logger> definedLoggers = new ArrayList<Logger>();
913        // list of all parent loggers
914        List<Logger> packageLoggers = new ArrayList<Logger>();
915        LoggerContext logContext = (LoggerContext)LogManager.getContext(false);
916        Iterator<Logger> it_curentlogger = logContext.getLoggers().iterator();
917        // get all current loggers
918        while (it_curentlogger.hasNext()) {
919            // get the logger
920            Logger log = it_curentlogger.next();
921            String logname = log.getName();
922            String[] prefix = buildsufix(logname);
923            // create all possible package logger from given logger name
924            for (int i = 0; i < prefix.length; i++) {
925                // get the name of the logger without the prefix
926                String temp = log.getName().replace(prefix[i], "");
927                // if the name has suffix
928                if (temp.length() > 1) {
929                    temp = temp.substring(1);
930                }
931                if (temp.lastIndexOf(".") > 1) {
932                    // generate new logger with "org.opencms" prefix and the next element
933                    // between the points e.g.: "org.opencms.search"
934                    Logger temp_logger = getLoggerImpl(prefix[i] + "." + temp.substring(0, temp.indexOf(".")));
935                    // activate the heredity so the logger get the appender from parent logger
936                    temp_logger.setAdditive(true);
937                    // add the logger to the packageLoggers list if it is not part of it
938                    if (!packageLoggers.contains(temp_logger)) {
939                        packageLoggers.add(temp_logger);
940                    }
941                }
942            }
943            definedLoggers.add(log);
944
945        }
946
947        Iterator<Logger> it_logger = packageLoggers.iterator();
948        // iterate about all packageLoggers
949        while (it_logger.hasNext()) {
950            Logger temp = it_logger.next();
951            // check if the logger is part of the logger list
952            if (!definedLoggers.contains(temp)) {
953                // add the logger to the logger list
954                definedLoggers.add(temp);
955            }
956        }
957
958        // sort all loggers by name
959        Collections.sort(definedLoggers, new Comparator<Object>() {
960
961            public int compare(Logger o1, Logger o2) {
962
963                return String.CASE_INSENSITIVE_ORDER.compare(o1.getName(), o2.getName());
964            }
965
966            public int compare(Object obj, Object obj1) {
967
968                return compare((Logger)obj, (Logger)obj1);
969            }
970
971        });
972        // return all loggers
973        return definedLoggers;
974    }
975
976    /**
977     * Simple function to set all child loggers to the same value of parent
978     * logger if the parent logger leves is changed.<p>
979     *
980     * @param logchannel the channel that might be the parent logger
981     */
982    private void isparentlogger(Logger logchannel) {
983
984        // get all log channels
985        List<Logger> referenz = getLoggers();
986        Iterator<Logger> it_logger = referenz.iterator();
987        while (it_logger.hasNext()) {
988            Logger child_test = it_logger.next();
989            // if the logchannel has the given logchannel as parent his loglevel is set to the parent one.
990            if (logchannel.getName().equals(child_test.getParent().getName())) {
991                isparentlogger(child_test);
992                child_test.setLevel(null);
993            }
994        }
995    }
996}