19 package org.sleuthkit.autopsy.datasourcesummary.ui;
21 import java.awt.Color;
22 import java.text.DateFormat;
23 import java.text.SimpleDateFormat;
24 import java.util.ArrayList;
25 import java.util.Arrays;
26 import java.util.Collections;
27 import java.util.Date;
28 import java.util.List;
29 import java.util.Locale;
30 import java.util.logging.Level;
31 import org.apache.commons.collections.CollectionUtils;
32 import org.joda.time.DateTime;
33 import org.joda.time.Interval;
34 import org.openide.util.NbBundle.Messages;
35 import org.openide.util.actions.CallableSystemAction;
70 "TimelinePanel_earliestLabel_title=Earliest",
71 "TimelinePanel_latestLabel_title=Latest",
72 "TimlinePanel_last30DaysChart_title=Last 30 Days",
73 "TimlinePanel_last30DaysChart_fileEvts_title=File Events",
74 "TimlinePanel_last30DaysChart_artifactEvts_title=Result Events",})
78 private static final long serialVersionUID = 1L;
80 private static final String EARLIEST_LATEST_FORMAT_STR =
"MMM d, yyyy";
81 private static final DateFormat EARLIEST_LATEST_FORMAT = getUtcFormat(EARLIEST_LATEST_FORMAT_STR);
82 private static final DateFormat CHART_FORMAT = getUtcFormat(
"MMM d, yyyy");
83 private static final int MOST_RECENT_DAYS_COUNT = 30;
92 return new SimpleDateFormat(formatString, Locale.getDefault());
103 private final List<LoadableComponent<?>> loadableComponents = Arrays.asList(earliestLabel, latestLabel, last30DaysChart);
120 dataFetcher = (dataSource) -> timelineData.
getData(dataSource, MOST_RECENT_DAYS_COUNT);
123 dataFetchComponents = Arrays.asList(
138 private static String
formatDate(Date date, DateFormat formatter) {
139 return date == null ? null : formatter.format(date);
142 private static final Color FILE_EVT_COLOR =
new Color(228, 22, 28);
143 private static final Color ARTIFACT_EVT_COLOR =
new Color(21, 227, 100);
154 private List<BarChartSeries>
parseChartData(List<DailyActivityAmount> recentDaysActivity,
boolean showIntermediateDates) {
156 if (CollectionUtils.isEmpty(recentDaysActivity)) {
161 List<BarChartItem> fileEvtCounts =
new ArrayList<>();
162 List<BarChartItem> artifactEvtCounts =
new ArrayList<>();
164 for (
int i = 0; i < recentDaysActivity.size(); i++) {
169 String formattedDate = (showIntermediateDates || i == 0 || i == recentDaysActivity.size() - 1)
170 ? formatDate(curItem.
getDay(), CHART_FORMAT) :
"";
174 artifactEvtCounts.add(
new BarChartItem(thisKey, artifactAmt));
177 return Arrays.asList(
178 new BarChartSeries(Bundle.TimlinePanel_last30DaysChart_fileEvts_title(), FILE_EVT_COLOR, fileEvtCounts),
179 new BarChartSeries(Bundle.TimlinePanel_last30DaysChart_artifactEvts_title(), ARTIFACT_EVT_COLOR, artifactEvtCounts));
182 private final Object timelineBtnLock =
new Object();
202 synchronized (this.timelineBtnLock) {
203 this.curTimelineData = result.
getData();
204 this.viewInTimelineBtn.setEnabled(
true);
207 synchronized (this.timelineBtnLock) {
208 this.viewInTimelineBtn.setEnabled(
false);
217 DataSource dataSource = null;
222 synchronized (this.timelineBtnLock) {
223 if (curTimelineData == null) {
232 if (maxDate != null) {
233 maxDate =
new Date(maxDate.getTime() + 1000 * 60 * 60 * 24);
238 openFilteredChart(dataSource, minDate, maxDate);
250 if (openTimelineAction == null) {
251 logger.log(Level.WARNING,
"No OpenTimelineAction provided by CallableSystemAction; taking no redirect action.");
257 Interval timeSpan = null;
262 if (dataSource != null) {
266 if (minDate != null && maxDate != null) {
267 timeSpan =
new Interval(
new DateTime(minDate),
new DateTime(maxDate));
270 logger.log(Level.WARNING,
"Unable to view time range in Timeline view", ex);
275 }
catch (TskCoreException ex) {
276 logger.log(Level.WARNING,
"An unexpected exception occurred while opening the timeline.", ex);
282 fetchInformation(dataFetchComponents, dataSource);
287 onNewDataSource(dataFetchComponents, loadableComponents, dataSource);
304 return new DefaultCellModel<>(date, (dt) -> dt == null ?
"" : EARLIEST_LATEST_FORMAT.format(dt), EARLIEST_LATEST_FORMAT_STR);
308 "TimelinePanel_getExports_sheetName=Timeline",
309 "TimelinePanel_getExports_activityRange=Activity Range",
310 "TimelinePanel_getExports_earliest=Earliest:",
311 "TimelinePanel_getExports_latest=Latest:",
312 "TimelinePanel_getExports_dateColumnHeader=Date",
313 "TimelinePanel_getExports_chartName=Last 30 Days",})
315 List<ExcelExport.ExcelSheetExport> getExports(DataSource dataSource) {
316 TimelineSummaryData summaryData = getFetchResult(dataFetcher,
"Timeline", dataSource);
317 if (summaryData == null) {
318 return Collections.emptyList();
321 return Arrays.asList(
322 new ExcelSpecialFormatExport(Bundle.TimelinePanel_getExports_sheetName(),
324 new TitledExportable(Bundle.TimelinePanel_getExports_activityRange(), Collections.emptyList()),
325 new KeyValueItemExportable(Bundle.TimelinePanel_getExports_earliest(), getEarliestLatestCell(summaryData.getMinDate())),
326 new KeyValueItemExportable(Bundle.TimelinePanel_getExports_latest(), getEarliestLatestCell(summaryData.getMaxDate())),
327 new BarChartExport(Bundle.TimelinePanel_getExports_dateColumnHeader(),
329 Bundle.TimelinePanel_getExports_chartName(),
330 parseChartData(summaryData.getMostRecentDaysActivity(),
true)))));
338 @SuppressWarnings(
"unchecked")
340 private
void initComponents() {
342 javax.swing.JScrollPane mainScrollPane =
new javax.swing.JScrollPane();
343 javax.swing.JPanel mainContentPanel =
new javax.swing.JPanel();
344 javax.swing.JPanel ingestRunningPanel = ingestRunningLabel;
345 javax.swing.JLabel activityRangeLabel =
new javax.swing.JLabel();
346 javax.swing.Box.Filler filler1 =
new javax.swing.Box.Filler(
new java.awt.Dimension(0, 2),
new java.awt.Dimension(0, 2),
new java.awt.Dimension(0, 2));
347 javax.swing.JPanel earliestLabelPanel = earliestLabel;
348 javax.swing.JPanel latestLabelPanel = latestLabel;
349 javax.swing.Box.Filler filler2 =
new javax.swing.Box.Filler(
new java.awt.Dimension(0, 20),
new java.awt.Dimension(0, 20),
new java.awt.Dimension(0, 20));
350 javax.swing.JPanel last30DaysPanel = last30DaysChart;
351 viewInTimelineBtn =
new javax.swing.JButton();
352 javax.swing.Box.Filler filler5 =
new javax.swing.Box.Filler(
new java.awt.Dimension(0, 0),
new java.awt.Dimension(0, 0),
new java.awt.Dimension(0, 32767));
354 mainContentPanel.setBorder(javax.swing.BorderFactory.createEmptyBorder(10, 10, 10, 10));
355 mainContentPanel.setLayout(
new javax.swing.BoxLayout(mainContentPanel, javax.swing.BoxLayout.PAGE_AXIS));
357 ingestRunningPanel.setAlignmentX(0.0F);
358 ingestRunningPanel.setMaximumSize(
new java.awt.Dimension(32767, 25));
359 ingestRunningPanel.setMinimumSize(
new java.awt.Dimension(10, 25));
360 ingestRunningPanel.setPreferredSize(
new java.awt.Dimension(10, 25));
361 mainContentPanel.add(ingestRunningPanel);
363 activityRangeLabel.setFont(
new java.awt.Font(
"Segoe UI", 1, 12));
364 org.openide.awt.Mnemonics.setLocalizedText(activityRangeLabel,
org.openide.util.NbBundle.getMessage(
TimelinePanel.class,
"TimelinePanel.activityRangeLabel.text"));
365 mainContentPanel.add(activityRangeLabel);
366 activityRangeLabel.getAccessibleContext().setAccessibleName(
org.openide.util.NbBundle.getMessage(
TimelinePanel.class,
"PastCasesPanel.notableFileLabel.text"));
368 filler1.setAlignmentX(0.0F);
369 mainContentPanel.add(filler1);
371 earliestLabelPanel.setAlignmentX(0.0F);
372 earliestLabelPanel.setMaximumSize(
new java.awt.Dimension(32767, 20));
373 earliestLabelPanel.setMinimumSize(
new java.awt.Dimension(100, 20));
374 earliestLabelPanel.setPreferredSize(
new java.awt.Dimension(100, 20));
375 mainContentPanel.add(earliestLabelPanel);
377 latestLabelPanel.setAlignmentX(0.0F);
378 latestLabelPanel.setMaximumSize(
new java.awt.Dimension(32767, 20));
379 latestLabelPanel.setMinimumSize(
new java.awt.Dimension(100, 20));
380 latestLabelPanel.setPreferredSize(
new java.awt.Dimension(100, 20));
381 mainContentPanel.add(latestLabelPanel);
383 filler2.setAlignmentX(0.0F);
384 mainContentPanel.add(filler2);
386 last30DaysPanel.setAlignmentX(0.0F);
387 last30DaysPanel.setMaximumSize(
new java.awt.Dimension(600, 300));
388 last30DaysPanel.setMinimumSize(
new java.awt.Dimension(600, 300));
389 last30DaysPanel.setPreferredSize(
new java.awt.Dimension(600, 300));
390 last30DaysPanel.setVerifyInputWhenFocusTarget(
false);
391 mainContentPanel.add(last30DaysPanel);
393 org.openide.awt.Mnemonics.setLocalizedText(viewInTimelineBtn,
org.openide.util.NbBundle.getMessage(
TimelinePanel.class,
"TimelinePanel.viewInTimelineBtn.text"));
394 viewInTimelineBtn.setEnabled(
false);
395 viewInTimelineBtn.addActionListener(
new java.awt.event.ActionListener() {
396 public void actionPerformed(java.awt.event.ActionEvent evt) {
397 viewInTimelineBtnActionPerformed(evt);
400 mainContentPanel.add(viewInTimelineBtn);
402 filler5.setAlignmentX(0.0F);
403 mainContentPanel.add(filler5);
405 mainScrollPane.setViewportView(mainContentPanel);
407 javax.swing.GroupLayout layout =
new javax.swing.GroupLayout(
this);
408 this.setLayout(layout);
409 layout.setHorizontalGroup(
410 layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
411 .addComponent(mainScrollPane, javax.swing.GroupLayout.DEFAULT_SIZE, 400, Short.MAX_VALUE)
413 layout.setVerticalGroup(
414 layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
415 .addComponent(mainScrollPane, javax.swing.GroupLayout.DEFAULT_SIZE, 300, Short.MAX_VALUE)
static DateFormat getUtcFormat(String formatString)
static< I, O > DataFetchResult< O > getSubResult(DataFetchResult< I > inputResult, Function< I, O > getSubResult)
javax.swing.JButton viewInTimelineBtn
ResultType getResultType()
synchronized void showTimeline(AbstractFile file, BlackboardArtifact artifact, Interval timeSpan)
final List< DataFetchComponents< DataSource,?> > dataFetchComponents
DataSource getDataSource()
long getArtifactActivityCount()
void showDataFetchResult(DataFetchResult< T > result, String errorMessage, String noResultsMessage)
void handleResult(DataFetchResult< TimelineSummaryData > result)
static String formatDate(Date date, DateFormat formatter)
void onNewDataSource(DataSource dataSource)
void viewInTimelineBtnActionPerformed(java.awt.event.ActionEvent evt)
RootFilterState getDataSourceFilterState(DataSource dataSource)
List< DailyActivityAmount > getMostRecentDaysActivity()
void openFilteredChart(DataSource dataSource, Date minDate, Date maxDate)
void fetchInformation(DataSource dataSource)
synchronized void pushFilters(RootFilterState filter)
final DataFetcher< DataSource, TimelineSummaryData > dataFetcher
static DefaultCellModel<?> getEarliestLatestCell(Date date)
static TimelineDataSourceUtils getInstance()
TimelineSummaryData getData(DataSource dataSource, int recentDaysNum)
synchronized static Logger getLogger(String name)
static TimeLineController getController()
long getFileActivityCount()
TimelinePanel(TimelineSummary timelineData)
List< BarChartSeries > parseChartData(List< DailyActivityAmount > recentDaysActivity, boolean showIntermediateDates)