/* (c) 2016 Open Source Geospatial Foundation - all rights reserved
* This code is licensed under the GPL 2.0 license, available at the root
* application directory.
*/
package org.geogig.geoserver.web.security;
import java.util.Arrays;
import java.util.EnumMap;
import java.util.List;
import org.apache.wicket.AttributeModifier;
import org.apache.wicket.Component;
import org.apache.wicket.ajax.AjaxRequestTarget;
import org.apache.wicket.extensions.ajax.markup.html.modal.ModalWindow;
import org.apache.wicket.markup.html.basic.Label;
import org.apache.wicket.markup.html.basic.MultiLineLabel;
import org.apache.wicket.markup.html.panel.Panel;
import org.apache.wicket.model.IModel;
import org.apache.wicket.model.Model;
import org.apache.wicket.request.resource.PackageResourceReference;
import org.apache.wicket.util.file.File;
import org.geogig.geoserver.config.LogEvent;
import org.geogig.geoserver.config.LogEvent.Severity;
import org.geogig.geoserver.config.LogStore;
import org.geoserver.platform.GeoServerExtensions;
import org.geoserver.web.GeoServerBasePage;
import org.geoserver.web.wicket.GeoServerDataProvider;
import org.geoserver.web.wicket.GeoServerDataProvider.Property;
import org.geoserver.web.wicket.GeoServerTablePanel;
import org.geoserver.web.wicket.Icon;
import org.geoserver.web.wicket.SimpleAjaxLink;
import org.geotools.feature.type.DateUtil;
public class SecurityLogsPanel extends GeoServerTablePanel<LogEvent> {
private static final long serialVersionUID = 5957961031378924960L;
private static final EnumMap<Severity, PackageResourceReference> SEVERITY_ICONS = new EnumMap<>(
Severity.class);
static {
final PackageResourceReference infoIcon = new PackageResourceReference(
GeoServerBasePage.class,
"img/icons/silk/information.png");
final PackageResourceReference successIcon = new PackageResourceReference(
GeoServerBasePage.class,
"img/icons/silk/accept.png");
final PackageResourceReference errorIcon = new PackageResourceReference(
GeoServerBasePage.class,
"img/icons/silk/error.png");
SEVERITY_ICONS.put(Severity.DEBUG, infoIcon);
SEVERITY_ICONS.put(Severity.INFO, successIcon);
SEVERITY_ICONS.put(Severity.ERROR, errorIcon);
}
private final ModalWindow popupWindow;
/**
* Only to be used by {@link #logStore()}
*/
private transient LogStore logStore;
public SecurityLogsPanel(final String id) {
super(id, new LogEventProvider(), false/* selectable */);
super.setSelectable(false);
super.setSortable(true);
super.setFilterable(true);
super.setFilterVisible(true);
super.setPageable(true);
popupWindow = new ModalWindow("popupWindow");
add(popupWindow);
}
private LogStore logStore() {
if (this.logStore == null) {
this.logStore = GeoServerExtensions.bean(LogStore.class);
}
return this.logStore;
}
@Override
protected Component getComponentForProperty(final String id,
@SuppressWarnings("rawtypes") IModel<LogEvent> itemModel, Property<LogEvent> property) {
LogEvent item = (LogEvent) itemModel.getObject();
if (property == LogEventProvider.SEVERITY) {
Severity severity = item.getSeverity();
PackageResourceReference iconRef = SEVERITY_ICONS.get(severity);
return new Icon(id, iconRef);
}
if (property == LogEventProvider.REPOSITORY) {
return repositoryLink(id, item);
}
if (property == LogEventProvider.TIMESTAMP) {
return new Label(id, DateUtil.serializeDateTime(item.getTimestamp()));
}
if (property == LogEventProvider.MESSAGE) {
return messageLink(id, item);
}
return new Label(id, String.valueOf(property.getPropertyValue(item)));
}
private Component messageLink(String id, LogEvent item) {
IModel<String> messageModel = new Model<>(item.getMessage());
if (!item.getSeverity().equals(Severity.ERROR)) {
return new Label(id, messageModel);
}
SimpleAjaxLink<LogEvent> link = new SimpleAjaxLink<LogEvent>(id, new Model<>(item),
messageModel) {
private static final long serialVersionUID = 1242472443848716943L;
@Override
public void onClick(AjaxRequestTarget target) {
LogEvent event = getModelObject();
long eventId = event.getEventId();
LogStore logStore = logStore();
String stackTrace = logStore.getStackTrace(eventId);
popupWindow.setInitialHeight(525);
popupWindow.setInitialWidth(855);
popupWindow.setContent(new StackTracePanel(popupWindow.getContentId(), stackTrace));
popupWindow.show(target);
}
};
return link;
}
public static class StackTracePanel extends Panel {
private static final long serialVersionUID = 6428694990556424777L;
public StackTracePanel(String id, String stackTrace) {
super(id);
MultiLineLabel stackTraceLabel = new MultiLineLabel("trace");
add(stackTraceLabel);
if (stackTrace != null) {
stackTraceLabel.setDefaultModel(new Model<>(stackTrace));
}
}
}
private Component repositoryLink(String id, LogEvent item) {
String repositoryURL = item.getRepositoryURL();
String name = new File(repositoryURL).getName();
Label label = new Label(id, name);
label.add(AttributeModifier.replace("title", repositoryURL));
return label;
}
static class LogEventProvider extends GeoServerDataProvider<LogEvent> {
private static final long serialVersionUID = 4883560661021761394L;
// static final Property<LogEvent> EVENT_ID = new BeanProperty<LogEvent>("eventId",
// "eventId");
static final Property<LogEvent> SEVERITY = new BeanProperty<>("severity", "severity");
static final Property<LogEvent> TIMESTAMP = new BeanProperty<>("timestamp", "timestamp");
static final Property<LogEvent> REPOSITORY = new BeanProperty<>("repository",
"repositoryURL");
static final Property<LogEvent> USER = new BeanProperty<>("user", "user");
static final Property<LogEvent> MESSAGE = new BeanProperty<>("message", "message");
final List<Property<LogEvent>> PROPERTIES = Arrays.asList(/* EVENT_ID, */
SEVERITY, TIMESTAMP, REPOSITORY, USER, MESSAGE);
// private transient List<LogEvent> items;
private transient LogStore logStore;
public LogEventProvider() {
}
private LogStore logStore() {
if (logStore == null) {
logStore = GeoServerExtensions.bean(LogStore.class);
}
return logStore;
}
@Override
protected List<LogEvent> getItems() {
// ensure logstore is set
logStore();
List<LogEvent> items = logStore.getLogEntries(0, Integer.MAX_VALUE);
return items;
}
@Override
protected List<Property<LogEvent>> getProperties() {
return PROPERTIES;
}
@Override
public IModel<LogEvent> newModel(LogEvent object) {
return new Model<>(object);
}
@Override
public int fullSize() {
// ensure logstore is set
logStore();
return logStore.getFullSize();
}
}
}