/*
* Licensed to the Apache Software Foundation (ASF) under one or more
* contributor license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright ownership.
* The ASF licenses this file to You 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 ro.nextreports.server.web.monitor;
import java.util.ArrayList;
import java.util.List;
import org.apache.wicket.AttributeModifier;
import org.apache.wicket.ajax.AjaxRequestTarget;
import org.apache.wicket.ajax.AjaxSelfUpdatingTimerBehavior;
import org.apache.wicket.extensions.markup.html.repeater.data.grid.ICellPopulator;
import org.apache.wicket.extensions.markup.html.repeater.data.sort.SortOrder;
import org.apache.wicket.extensions.markup.html.repeater.data.table.AbstractColumn;
import org.apache.wicket.extensions.markup.html.repeater.data.table.DataTable;
import org.apache.wicket.extensions.markup.html.repeater.data.table.IColumn;
import org.apache.wicket.extensions.markup.html.repeater.data.table.PropertyColumn;
import org.apache.wicket.extensions.markup.html.repeater.util.SortableDataProvider;
import org.apache.wicket.markup.html.basic.Label;
import org.apache.wicket.markup.html.link.Link;
import org.apache.wicket.markup.html.panel.Panel;
import org.apache.wicket.markup.repeater.Item;
import org.apache.wicket.model.IModel;
import org.apache.wicket.model.Model;
import org.apache.wicket.spring.injection.annot.SpringBean;
import org.apache.wicket.util.time.Duration;
import org.joda.time.DateTimeZone;
import org.joda.time.format.DateTimeFormat;
import org.joda.time.format.DateTimeFormatter;
import org.quartz.JobDetail;
import org.quartz.Scheduler;
import ro.nextreports.server.StorageConstants;
import ro.nextreports.server.domain.ReportJobInfo;
import ro.nextreports.server.domain.RunReportHistory;
import ro.nextreports.server.domain.SchedulerJob;
import ro.nextreports.server.domain.SchedulerTime;
import ro.nextreports.server.domain.Settings;
import ro.nextreports.server.schedule.ReportJobInfoDataProvider;
import ro.nextreports.server.schedule.RunReportJob;
import ro.nextreports.server.service.ReportService;
import ro.nextreports.server.service.SchedulerService;
import ro.nextreports.server.service.StorageService;
import ro.nextreports.server.util.SchedulerUtil;
import ro.nextreports.server.util.StorageUtil;
import ro.nextreports.server.web.common.behavior.ConfirmBehavior;
import ro.nextreports.server.web.common.behavior.SimpleTooltipBehavior;
import ro.nextreports.server.web.common.panel.AbstractImageAjaxLinkPanel;
import ro.nextreports.server.web.common.table.BaseTable;
import ro.nextreports.server.web.common.table.BooleanImagePropertyColumn;
import ro.nextreports.server.web.common.table.DateColumn;
import ro.nextreports.server.web.common.table.SortableDataAdapter;
import ro.nextreports.server.web.core.table.NextRunDateColumn;
import ro.nextreports.server.web.report.RunHistoryPanel;
import ro.nextreports.server.web.schedule.ActiveSchedulerJobDataProvider;
/**
* @author decebal
*/
public class MonitorPanel extends Panel {
private static final long serialVersionUID = 1L;
@SpringBean
private ReportService reportService;
@SpringBean
private SchedulerService schedulerService;
@SpringBean
private StorageService storageService;
@SpringBean
private Scheduler scheduler;
private DataTable<ReportJobInfo, String> jobsTable;
private DataTable<SchedulerJob, String> schedulerJobsTable;
private DataTable<RunReportHistory, String> runHistoryTable;
public MonitorPanel(String id) {
super(id);
jobsTable = createJobsTable(new ReportJobInfoDataProvider());
jobsTable.setOutputMarkupId(true);
add(jobsTable);
schedulerJobsTable = createSchedulerJobsTable(new ActiveSchedulerJobDataProvider());
schedulerJobsTable.setOutputMarkupId(true);
add(schedulerJobsTable);
RunHistoryPanel runHistoryPanel = new RunHistoryPanel("runHistoryPanel", null);
runHistoryTable = runHistoryPanel.getRunHistoryTable();
runHistoryTable.setOutputMarkupId(true);
add(runHistoryPanel);
Settings settings = storageService.getSettings();
int updateInterval = settings.getUpdateInterval();
if (updateInterval > 0) {
jobsTable.add(new AjaxSelfUpdatingTimerBehavior(Duration.seconds(updateInterval)));
schedulerJobsTable.add(new AjaxSelfUpdatingTimerBehavior(Duration.seconds(updateInterval)));
runHistoryTable.add(new AjaxSelfUpdatingTimerBehavior(Duration.seconds(updateInterval)));
}
}
protected DataTable<ReportJobInfo, String> createJobsTable(ReportJobInfoDataProvider dataProvider) {
SortableDataProvider<ReportJobInfo, String> sortableDataProvider = new SortableDataAdapter<ReportJobInfo>(
dataProvider);
sortableDataProvider.setSort("startDate", SortOrder.ASCENDING);
return new BaseTable<ReportJobInfo>("jobsTable", createJobsTableColumns(), sortableDataProvider,
Integer.MAX_VALUE);
}
protected DataTable<SchedulerJob, String> createSchedulerJobsTable(ActiveSchedulerJobDataProvider dataProvider) {
SortableDataProvider<SchedulerJob, String> sortableDataProvider = new SortableDataAdapter<SchedulerJob>(
dataProvider);
sortableDataProvider.setSort("nextRun", SortOrder.ASCENDING);
return new BaseTable<SchedulerJob>("schedulerJobsTable", createActiveSchedulerJobsTableColumns(),
sortableDataProvider, Integer.MAX_VALUE);
}
protected List<IColumn<ReportJobInfo, String>> createJobsTableColumns() {
List<IColumn<ReportJobInfo, String>> columns = new ArrayList<IColumn<ReportJobInfo, String>>();
columns.add(
new PropertyColumn<ReportJobInfo, String>(new Model<String>(getString("name")), "jobName", "jobName") {
private static final long serialVersionUID = 1L;
@Override
protected IModel<?> createLabelModel(IModel<ReportJobInfo> reportJobInfoIModel) {
String basicName = reportJobInfoIModel.getObject().getBasicJobName();
return new Model<String>(basicName.substring(StorageConstants.REPORTS_ROOT.length()));
}
});
columns.add(new PropertyColumn<ReportJobInfo, String>(
new Model<String>(getString("DashboardNavigationPanel.owner")), "runner", "runner") {
private static final long serialVersionUID = 1L;
@Override
public void populateItem(Item<ICellPopulator<ReportJobInfo>> item, String componentId,
IModel<ReportJobInfo> rowModel) {
super.populateItem(item, componentId, rowModel);
item.add(AttributeModifier.replace("width", "150px"));
}
});
columns.add(new DateColumn<ReportJobInfo>(new Model<String>(getString("startDate")), "startDate", "startDate") {
private static final long serialVersionUID = 1L;
@Override
public void populateItem(Item<ICellPopulator<ReportJobInfo>> item, String componentId,
IModel<ReportJobInfo> rowModel) {
super.populateItem(item, componentId, rowModel);
item.add(AttributeModifier.replace("width", "120px"));
}
});
columns.add(new PropertyColumn<ReportJobInfo, String>(new Model<String>(getString("MonitorPanel.runTime")),
"runTime", "runTime") {
private static final long serialVersionUID = 1L;
@Override
public void populateItem(Item<ICellPopulator<ReportJobInfo>> item, String componentId,
IModel<ReportJobInfo> rowModel) {
super.populateItem(item, componentId, rowModel);
item.add(AttributeModifier.replace("width", "100px"));
}
@Override
protected IModel<?> createLabelModel(IModel<ReportJobInfo> rowModel) {
int runTime = rowModel.getObject().getRunTime();
String text = "";
if (runTime > 0) {
DateTimeFormatter formatter = DateTimeFormat.forPattern("HH:mm:ss").withZone(DateTimeZone.UTC);
text = formatter.print(runTime * 1000);
}
return new Model<String>(text);
}
});
columns.add(new AbstractColumn<ReportJobInfo, String>(new Model<String>(getString("MonitorPanel.stop"))) {
private static final long serialVersionUID = 1L;
public void populateItem(Item<ICellPopulator<ReportJobInfo>> item, String componentId,
final IModel<ReportJobInfo> rowModel) {
final String reportType = rowModel.getObject().getReportType();
final String runnerKey = rowModel.getObject().getRunnerKey();
item.add(new AbstractImageAjaxLinkPanel(componentId) {
private static final long serialVersionUID = 1L;
@Override
public String getDisplayString() {
return "";
}
@Override
public void onClick(AjaxRequestTarget target) {
reportService.stopExport(runnerKey, reportType);
target.add(jobsTable);
target.add(runHistoryTable);
}
@Override
public String getImageName() {
return "images/stop.png";
}
@Override
protected Link getLink() {
Link link = super.getLink();
link.add(new ConfirmBehavior(new Model<String>(
"Do you want to stop the execution?\\nBe aware that the cancelation process may take some time.")));
return link;
}
});
}
});
return columns;
}
protected List<IColumn<SchedulerJob, String>> createActiveSchedulerJobsTableColumns() {
List<IColumn<SchedulerJob, String>> columns = new ArrayList<IColumn<SchedulerJob, String>>();
columns.add(new PropertyColumn<SchedulerJob, String>(new Model<String>(getString("name")), "name", "name") {
@Override
protected IModel<String> createLabelModel(IModel<SchedulerJob> jobInfoIModel) {
return new Model<String>(jobInfoIModel.getObject().getName());
}
});
columns.add(new PropertyColumn<SchedulerJob, String>(new Model<String>(getString("type")), "time.type",
"time.type") {
@Override
public void populateItem(Item<ICellPopulator<SchedulerJob>> item, String componentId,
IModel<SchedulerJob> rowModel) {
SchedulerTime st = rowModel.getObject().getTime();
Label label = new Label(componentId, getString("JobPanel.type." + st.getType()));
label.add(new SimpleTooltipBehavior(SchedulerUtil.getTooltip(st)));
item.add(label);
}
});
columns.add(new PropertyColumn<SchedulerJob, String>(new Model<String>(getString("Report")), "report.path",
"report.path") {
@Override
public void populateItem(Item<ICellPopulator<SchedulerJob>> item, String componentId,
IModel<SchedulerJob> rowModel) {
String path = rowModel.getObject().getReport().getPath();
String relativePath = StorageUtil.getPathWithoutRoot(path);
String name = StorageUtil.getName(relativePath);
Label label = new Label(componentId, name);
label.add(new SimpleTooltipBehavior(relativePath));
item.add(label);
}
});
columns.add(new BooleanImagePropertyColumn<SchedulerJob>(new Model<String>(getString("MonitorPanel.running")),
"isRunning", "isRunning") {
@Override
public void populateItem(Item<ICellPopulator<SchedulerJob>> item, String componentId,
IModel<SchedulerJob> rowModel) {
super.populateItem(item, componentId, rowModel);
item.add(AttributeModifier.replace("width", "80px"));
}
});
columns.add(new PropertyColumn<SchedulerJob, String>(new Model<String>(getString("MonitorPanel.runTime")),
"runTime", "runTime") {
private static final long serialVersionUID = 1L;
@Override
public void populateItem(Item<ICellPopulator<SchedulerJob>> item, String componentId,
IModel<SchedulerJob> rowModel) {
super.populateItem(item, componentId, rowModel);
item.add(AttributeModifier.replace("width", "100px"));
}
@Override
protected IModel<?> createLabelModel(IModel<SchedulerJob> rowModel) {
int runTime = rowModel.getObject().getRunTime();
String text = "";
if (runTime > 0) {
DateTimeFormatter formatter = DateTimeFormat.forPattern("HH:mm:ss").withZone(DateTimeZone.UTC);
text = formatter.print(runTime * 1000);
}
return new Model<String>(text);
}
});
columns.add(new NextRunDateColumn<SchedulerJob>());
columns.add(new AbstractColumn<SchedulerJob, String>(new Model<String>(getString("MonitorPanel.runNow"))) {
public void populateItem(Item<ICellPopulator<SchedulerJob>> item, String componentId,
final IModel<SchedulerJob> rowModel) {
item.add(AttributeModifier.replace("width", "80px"));
item.add(new AbstractImageAjaxLinkPanel(componentId) {
@Override
public String getDisplayString() {
return "";
}
public boolean isVisible() {
return !rowModel.getObject().isRunning();
}
@Override
public void onClick(AjaxRequestTarget target) {
JobDetail job = schedulerService.getJobDetail(rowModel.getObject());
if (job != null) {
reportService.runMonitorReport(job);
}
}
@Override
public String getImageName() {
return "images/run.gif";
}
@Override
protected Link getLink() {
Link link = super.getLink();
link.add(new ConfirmBehavior(new Model<String>(getString("MonitorPanel.runNowMessage"))));
return link;
}
});
}
});
columns.add(new AbstractColumn<SchedulerJob, String>(new Model<String>(getString("MonitorPanel.stop"))) {
public void populateItem(Item<ICellPopulator<SchedulerJob>> item, String componentId,
final IModel<SchedulerJob> rowModel) {
item.add(AttributeModifier.replace("width", "80px"));
item.add(new AbstractImageAjaxLinkPanel(componentId) {
@Override
public String getDisplayString() {
return "";
}
public boolean isVisible() {
return rowModel.getObject().isRunning();
}
@Override
public void onClick(AjaxRequestTarget target) {
JobDetail job = schedulerService.getJobDetail(rowModel.getObject());
if (job != null) {
String reportType = (String) job.getJobDataMap().get(RunReportJob.REPORT_TYPE);
String runnerKey = (String) job.getJobDataMap().get(RunReportJob.RUNNER_KEY);
reportService.stopExport(runnerKey, reportType);
target.add(schedulerJobsTable);
target.add(runHistoryTable);
}
}
@Override
public String getImageName() {
if (isEnabled()) {
return "images/stop.png";
} else {
return "images/clear.gif";
}
}
@Override
protected Link getLink() {
Link link = super.getLink();
link.add(new ConfirmBehavior(new Model<String>(getString("MonitorPanel.stopMessage"))));
return link;
}
});
}
});
return columns;
}
}