/*******************************************************************************
* Copyright (c) 2012 AGETO Service GmbH and others.
* All rights reserved.
*
* This program and the accompanying materials are made available under the
* terms of the Eclipse Public License v1.0 which accompanies this distribution,
* and is available at http://www.eclipse.org/legal/epl-v10.html.
*
* Contributors:
* Gunnar Wagenknecht - initial API and implementation
* Peter Grube - rework to Admin UI
*******************************************************************************/
package org.eclipse.gyrex.admin.ui.logback.internal;
import java.util.Collection;
import org.eclipse.gyrex.admin.ui.adapter.AdapterUtil;
import org.eclipse.gyrex.admin.ui.adapter.LabelAdapter;
import org.eclipse.gyrex.admin.ui.internal.application.AdminUiUtil;
import org.eclipse.gyrex.admin.ui.internal.helper.SwtUtil;
import org.eclipse.gyrex.admin.ui.internal.widgets.AdminPageWithTree;
import org.eclipse.gyrex.admin.ui.internal.widgets.Infobox;
import org.eclipse.gyrex.admin.ui.internal.wizards.NonBlockingWizardDialog;
import org.eclipse.gyrex.logback.config.internal.LogbackConfigActivator;
import org.eclipse.gyrex.logback.config.internal.PreferenceBasedLogbackConfigStore;
import org.eclipse.gyrex.logback.config.model.Appender;
import org.eclipse.gyrex.logback.config.model.FileAppender;
import org.eclipse.gyrex.logback.config.model.LogbackConfig;
import org.eclipse.gyrex.logback.config.model.Logger;
import org.eclipse.gyrex.preferences.CloudScope;
import org.eclipse.gyrex.server.Platform;
import org.eclipse.core.runtime.IStatus;
import org.eclipse.core.runtime.Status;
import org.eclipse.core.runtime.preferences.IEclipsePreferences;
import org.eclipse.jface.util.Policy;
import org.eclipse.jface.viewers.IStructuredSelection;
import org.eclipse.jface.viewers.ITreeContentProvider;
import org.eclipse.jface.window.Window;
import org.eclipse.rap.rwt.widgets.DialogCallback;
import org.eclipse.swt.events.SelectionAdapter;
import org.eclipse.swt.events.SelectionEvent;
import org.eclipse.swt.widgets.Button;
import org.eclipse.swt.widgets.Composite;
import org.eclipse.swt.widgets.Control;
import org.eclipse.swt.widgets.Shell;
import org.osgi.service.prefs.Preferences;
import org.apache.commons.lang.text.StrBuilder;
public class LogbackConfigurationPage extends AdminPageWithTree {
private static final int COLUMN_NAME = 0;
private static final int COLUMN_LEVEL = 1;
private Button addAppenderButton;
private Button addLoggerButton;
private Button editLoggerButton;
private Button removeButton;
private Button editDefaultLoggerButton;
private Button saveConfigButton;
private LogbackConfig currentInput;
public LogbackConfigurationPage() {
super(2);
setTitle("Logback Configuration");
setTitleToolTip("Configure and assign Logback appenders and loggers.");
}
@Override
public void activate() {
super.activate();
}
void addLoggerButtonPressed() {
final LoggerSettingsDialog dialog = new LoggerSettingsDialog(getShell(), currentInput.getAppenders().values());
dialog.openNonBlocking(new DialogCallback() {
private static final long serialVersionUID = 1L;
@Override
public void dialogClosed(final int returnCode) {
if (returnCode == Window.OK) {
currentInput.addLogger(dialog.getLogger());
getTreeViewer().refresh();
}
}
});
}
@Override
protected void createButtons(final Composite buttonsPanel) {
addAppenderButton = createButton(buttonsPanel, "Add Appender...");
addAppenderButton.addSelectionListener(new SelectionAdapter() {
private static final long serialVersionUID = 1L;
@Override
public void widgetSelected(final SelectionEvent e) {
openAppenderWizard(null);
}
});
addLoggerButton = createButton(buttonsPanel, "Add Logger...");
addLoggerButton.addSelectionListener(new SelectionAdapter() {
private static final long serialVersionUID = 1L;
@Override
public void widgetSelected(final SelectionEvent e) {
addLoggerButtonPressed();
}
});
editLoggerButton = createButton(buttonsPanel, "Edit Logger...");
editLoggerButton.addSelectionListener(new SelectionAdapter() {
private static final long serialVersionUID = 1L;
@Override
public void widgetSelected(final SelectionEvent e) {
editLoggerButtonPressed();
}
});
removeButton = createButton(buttonsPanel, "Remove...");
removeButton.addSelectionListener(new SelectionAdapter() {
private static final long serialVersionUID = 1L;
@Override
public void widgetSelected(final SelectionEvent e) {
removeButtonPressed();
}
});
createButtonSeparator(buttonsPanel);
editDefaultLoggerButton = createButton(buttonsPanel, "Edit Default Logger...");
editDefaultLoggerButton.addSelectionListener(new SelectionAdapter() {
private static final long serialVersionUID = 1L;
@Override
public void widgetSelected(final SelectionEvent e) {
editDefaultLoggerButtonPressed();
}
});
createButtonSeparator(buttonsPanel);
saveConfigButton = createButton(buttonsPanel, "Save Config ...");
saveConfigButton.addSelectionListener(new SelectionAdapter() {
private static final long serialVersionUID = 1L;
@Override
public void widgetSelected(final SelectionEvent e) {
saveConfigTree(true);
}
});
}
@Override
protected ITreeContentProvider createContentProvider() {
return new LogbackConfigContentProvider();
}
@Override
protected Control createHeader(final Composite parent) {
final Infobox infobox = new Infobox(parent);
infobox.setLayoutData(AdminUiUtil.createHorzFillData());
infobox.addHeading("Logging in Gyrex");
infobox.addParagraph("Gyrex makes use of <a href=\"http://logback.qos.ch/\">Logback</a> to capture logging events from the most popular logging APIs. Logback can be configured using a configuration file. This page provides an alternate way using Gyrex cloud preferences. The log configuration is stored in a central place.");
return infobox;
}
void editDefaultLoggerButtonPressed() {
final LoggerSettingsDialog dialog = new LoggerSettingsDialog(getShell(), currentInput.getDefaultLevel(), currentInput.getDefaultAppenders(), currentInput.getAppenders().values());
dialog.openNonBlocking(new DialogCallback() {
private static final long serialVersionUID = 1L;
@Override
public void dialogClosed(final int returnCode) {
if (returnCode == Window.OK) {
currentInput.setDefaultLevel(dialog.getLogger().getLevel());
currentInput.setDefaultAppenders(dialog.getLogger().getAppenderReferences());
getTreeViewer().refresh();
}
}
});
}
void editLoggerButtonPressed() {
final Object selectedElement = getFirstSelectedElement();
if (!(selectedElement instanceof Logger))
return;
final Logger logger = (Logger) selectedElement;
final String originalName = logger.getName();
final LoggerSettingsDialog dialog = new LoggerSettingsDialog(getShell(), originalName, logger.getLevel(), logger.isInheritOtherAppenders(), logger.getAppenderReferences(), currentInput.getAppenders().values());
dialog.openNonBlocking(new DialogCallback() {
private static final long serialVersionUID = 1L;
@Override
public void dialogClosed(final int returnCode) {
if (returnCode == Window.OK) {
currentInput.getLoggers().remove(originalName);
currentInput.addLogger(dialog.getLogger());
getTreeViewer().refresh();
}
}
});
}
private String getAppenderName(final Appender element) {
if (element instanceof FileAppender) {
final FileAppender fileAppender = (FileAppender) element;
final StrBuilder text = new StrBuilder();
text.append(fileAppender.getName());
text.append(String.format(" (-> %s)", fileAppender.getFileName()));
if (null != fileAppender.getThreshold()) {
text.append(String.format(" [%s]", fileAppender.getThreshold()));
}
if (fileAppender.isSeparateLogOutputsPerMdcProperty()) {
text.append(String.format(" [mdc:%s]", fileAppender.getSiftingMdcPropertyName()));
}
return text.toString();
}
return element.getName();
}
@Override
protected String getColumnLabel(final int column) {
switch (column) {
case COLUMN_NAME:
return "Name";
case COLUMN_LEVEL:
return "Level";
default:
return null;
}
}
@Override
protected int getElementCategory(final Object element, final int column) {
if (column == COLUMN_NAME) {
if (element instanceof DefaultLogger)
return 30;
else if (element instanceof AppendersGroup)
return 10;
else if (element instanceof LoggersGroup)
return 20;
}
return 100;
}
@Override
protected String getElementLabel(final Object element, final int column) {
if (column == COLUMN_NAME) {
final LabelAdapter labelAdapter = AdapterUtil.getAdapter(element, LabelAdapter.class);
if (labelAdapter != null)
return labelAdapter.getLabel(element);
else if (element instanceof Appender)
return getAppenderName((Appender) element);
else if (element instanceof Logger)
return ((Logger) element).getName();
else if (element instanceof AppenderReference)
return ((AppenderReference) element).getAppenderRef();
else if (element instanceof DefaultLogger)
return "Default Logger";
else if (element instanceof AppendersGroup)
return "Appenders";
else if (element instanceof LoggersGroup)
return "Loggers";
} else if (column == COLUMN_LEVEL) {
if (element instanceof Logger)
return String.valueOf(((Logger) element).getLevel());
else if (element instanceof DefaultLogger)
return String.valueOf(((DefaultLogger) element).getLevel());
}
return null;
}
private Object getFirstSelectedElement() {
return ((IStructuredSelection) getTreeViewer().getSelection()).getFirstElement();
}
private Shell getShell() {
return getTreeViewer().getTree().getShell();
}
@Override
protected Object getViewerInput() {
if (null == currentInput) {
final IEclipsePreferences node = CloudScope.INSTANCE.getNode(LogbackConfigActivator.SYMBOLIC_NAME);
try {
if (node.nodeExists("config")) {
final Preferences configNode = node.node("config");
configNode.sync();
currentInput = new PreferenceBasedLogbackConfigStore().loadConfig(configNode);
} else {
currentInput = new LogbackConfig();
}
} catch (final Exception | LinkageError | AssertionError e) {
Policy.getStatusHandler().show(new Status(IStatus.ERROR, LogbackUiActivator.SYMBOLIC_NAME, "Error loading Logback configuration.", e), "Error");
currentInput = new LogbackConfig();
}
}
return currentInput;
}
@Override
protected boolean isColumnSortable(final int column) {
return column == COLUMN_NAME;
}
void openAppenderWizard(final Appender appenderToEdit) {
final NonBlockingWizardDialog dialog = new NonBlockingWizardDialog(SwtUtil.getShell(getTreeViewer().getTree()), new AddEditAppenderWizard(currentInput, appenderToEdit));
dialog.openNonBlocking(new DialogCallback() {
private static final long serialVersionUID = 1L;
@Override
public void dialogClosed(final int returnCode) {
if (returnCode == Window.OK) {
if (appenderToEdit == null) {
}
getTreeViewer().refresh(appenderToEdit);
}
}
});
}
@Override
protected void openSelectedElement() {
final Object selectedElement = getFirstSelectedElement();
if (selectedElement == null)
return;
if (selectedElement instanceof Logger) {
editLoggerButtonPressed();
} else if (selectedElement instanceof DefaultLogger) {
editDefaultLoggerButtonPressed();
} else if (selectedElement instanceof Appender) {
openAppenderWizard((Appender) selectedElement);
}
}
void removeButtonPressed() {
final Object selectedElement = getFirstSelectedElement();
if (selectedElement == null)
return;
if (selectedElement instanceof AppenderReference) {
final AppenderReference appenderRef = (AppenderReference) selectedElement;
final Object parent = appenderRef.getParent();
if (parent instanceof Logger) {
((Logger) parent).getAppenderReferences().remove(appenderRef.getAppenderRef());
} else if (parent instanceof DefaultLogger) {
((DefaultLogger) parent).getAppenderReferences().remove(appenderRef.getAppenderRef());
}
} else if (selectedElement instanceof Logger) {
currentInput.getLoggers().remove(((Logger) selectedElement).getName());
} else if (selectedElement instanceof Appender) {
final String appenderName = ((Appender) selectedElement).getName();
final Collection<Logger> loggers = currentInput.getLoggers().values();
for (final Logger logger : loggers) {
logger.getAppenderReferences().remove(appenderName);
}
currentInput.getAppenders().remove(appenderName);
}
getTreeViewer().refresh();
}
public void saveConfigTree(final boolean onSave) {
if (onSave) {
final IEclipsePreferences node = CloudScope.INSTANCE.getNode(LogbackConfigActivator.SYMBOLIC_NAME);
try {
final Preferences configNode = node.node("config");
new PreferenceBasedLogbackConfigStore().saveConfig(currentInput, configNode);
// also touch last modified
node.putLong("lastModified", System.currentTimeMillis());
node.flush();
} catch (final Exception | LinkageError | AssertionError e) {
Policy.getStatusHandler().show(new Status(IStatus.ERROR, LogbackUiActivator.SYMBOLIC_NAME, "Error saving Logback configuration.", e), "Error");
return;
}
}
}
@Override
protected void updateButtons() {
final Object selectedElement = getFirstSelectedElement();
removeButton.setEnabled((null != selectedElement) && !(selectedElement instanceof DefaultLogger));
editLoggerButton.setEnabled(selectedElement instanceof Logger);
}
}