/*
* Copyright 2006-2014 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.jrecruiter.web.actions.admin;
import java.io.File;
import java.io.FileInputStream;
import java.io.InputStream;
import java.util.EnumSet;
import java.util.List;
import java.util.Set;
import org.apache.struts2.convention.annotation.Action;
import org.apache.struts2.convention.annotation.Result;
import org.apache.struts2.convention.annotation.Results;
import org.jrecruiter.common.CollectionUtils;
import org.jrecruiter.web.actions.BaseAction;
import org.jrecruiter.web.actions.util.LoggingUtil;
import org.jrecruiter.web.actions.util.LoggingUtil.LogLevels;
import ch.qos.logback.classic.Level;
import ch.qos.logback.classic.Logger;
import com.opensymphony.xwork2.ModelDriven;
import com.opensymphony.xwork2.Preparable;
/**
* Show log files and allow to set log levels for the configured loggers (logback)
* to be changed dynamically at runtime.
*
* @author Gunnar Hillert
*
*/
@Results({
@Result(name="ajaxLoggingLogFileTable", location="/WEB-INF/jsp/admin/loggingLogFileTable.jsp"),
@Result(name="ajaxLoggerTable", location="/WEB-INF/jsp/admin/loggingLoggerTable.jsp"),
@Result(name="success", location="/WEB-INF/jsp/admin/logging.jsp"),
@Result(name="successRedirect", location="logging", type="redirectAction"),
@Result(name="download", location="fileToDownLoad", type="stream",
params={"contentType","text/plain",
"inputName","fileToDownLoad",
"contentDisposition","attachment; filename=logfile.txt",
"bufferSize", "1024"})
})
public class LoggingAction extends BaseAction implements Preparable, ModelDriven<LoggingForm> {
/** serialVersionUID. */
private static final long serialVersionUID = -8382245048461549536L;
/** Show all loggers or only the configured loggers */
private boolean showAll = false;
/** List of log files and associated information */
private List<LogFileInfo> logFileInfos = CollectionUtils.getArrayList();
/** List of Loggers, simplified for display purposes */
private List<LoggerInfo> configuredLoggers = CollectionUtils.getArrayList();
/** Used to stream a logfile back to the client */
private transient InputStream fileToDownLoad;
private LoggingForm model = new LoggingForm();
//~~~~~Reference Data~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
/** Defines a collection of log levels. Unfortunately logback does not use
* enums to define its log levels. */
private Set<LogLevels> logLevels = EnumSet.allOf(LogLevels.class);
//~~~~~Prepare data~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
@Override
public void prepare() {
}
public void prepareExecute() {
loadLoggers();
loadLogFiles();
}
public void prepareUpdateLagLevels() {
loadLoggers();
loadLogFiles();
}
public void prepareAddNewLogger() {
loadLoggers();
loadLogFiles();
}
//~~~~~Helper Methods~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
private void loadLoggers() {
this.configuredLoggers.clear();
final List<Logger> loggers = LoggingUtil.getLoggers(this.showAll);
for (Logger logger : loggers) {
this.configuredLoggers.add(new LoggerInfo(logger.getName(), logger.getEffectiveLevel().levelInt));
}
}
private void loadLogFiles() {
this.logFileInfos = LoggingUtil.getLogFileInfos();
}
//~~~~~Ajax Methods~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
/** Reload the data for table that displays log file data. */
@Action(value="logging-ajax-log-file-table")
public String executeAjaxLoggingLogFileTable() {
loadLogFiles();
return "ajaxLoggingLogFileTable";
}
/** Reload the data for table that displays loggers. */
@Action(value="logging-ajax-logger-table")
public String executeAjaxLoggerTable() {
loadLoggers();
return "ajaxLoggerTable";
}
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
/** Loads the page with default parameters. */
@Override
@Action("logging")
public String execute() {
return SUCCESS;
}
/** Updates loglevels for loggers */
public String updateLagLevels() {
if (this.model.getUpdatedLoggers() != null && !this.model.getUpdatedLoggers().isEmpty()) {
for (LoggerInfo loggerInfo : this.model.getUpdatedLoggers()) {
if (loggerInfo != null && loggerInfo.getNewLogLevel() != null) {
LoggingUtil.getLogger(loggerInfo.getLoggerName())
.setLevel(Level.toLevel(loggerInfo.getNewLogLevel().getLogLevel()));
}
}
//Need to refresh the loggers
loadLoggers();
}
return "successRedirect";
}
/** Adds a new logger at runtime. */
public String addNewLogger() {
if (this.model.getNewLogger() != null
&& this.model.getNewLogger().getLoggerName() != null
&& this.model.getNewLogger().getNewLogLevel() != null) {
final Logger newLogger = LoggingUtil.getLogger(this.model.getNewLogger().getLoggerName());
newLogger.setLevel(Level.toLevel(this.model.getNewLogger().getNewLogLevel().getLogLevel()));
//Need to refresh the loggers
loadLoggers();
}
return "successRedirect";
}
/**
* Retrieve the requested log file.
*
* @return
* @throws Exception
*/
@Action("downloadLogFile")
public String download() throws Exception {
if (this.model.getFileName() == null) {
throw new IllegalArgumentException("FileName must not be null.");
}
final File logFile = LoggingUtil.getLogFile(this.model.getFileName());
if (logFile != null) {
this.fileToDownLoad = new FileInputStream(logFile);
}
return "download";
}
//~~~~~Getters and Setters~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
public List<LogFileInfo> getLogFileInfos() {
return logFileInfos;
}
public InputStream getFileToDownLoad() {
return fileToDownLoad;
}
public List<LoggerInfo> getConfiguredLoggers() {
return configuredLoggers;
}
public boolean isShowAll() {
return showAll;
}
public void setShowAll(boolean showAll) {
this.showAll = showAll;
}
public Set<LogLevels> getLogLevels() {
return logLevels;
}
public LoggingForm getModel() {
return model;
}
public void setModel(LoggingForm model) {
this.model = model;
}
}