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.Date;
27 import java.util.List;
28 import java.util.Locale;
29 import java.util.logging.Level;
30 import org.apache.commons.collections.CollectionUtils;
31 import org.joda.time.DateTime;
32 import org.joda.time.Interval;
33 import org.openide.util.NbBundle.Messages;
34 import org.openide.util.actions.CallableSystemAction;
62 "TimelinePanel_earliestLabel_title=Earliest",
63 "TimelinePanel_latestLabel_title=Latest",
64 "TimlinePanel_last30DaysChart_title=Last 30 Days",
65 "TimlinePanel_last30DaysChart_fileEvts_title=File Events",
66 "TimlinePanel_last30DaysChart_artifactEvts_title=Result Events",})
70 private static final long serialVersionUID = 1L;
71 private static final DateFormat EARLIEST_LATEST_FORMAT = getUtcFormat(
"MMM d, yyyy");
72 private static final DateFormat CHART_FORMAT = getUtcFormat(
"MMM d, yyyy");
73 private static final int MOST_RECENT_DAYS_COUNT = 30;
82 return new SimpleDateFormat(formatString, Locale.getDefault());
93 private final List<LoadableComponent<?>> loadableComponents = Arrays.asList(earliestLabel, latestLabel, last30DaysChart);
109 dataFetchComponents = Arrays.asList(
111 (dataSource) -> timelineData.
getData(dataSource, MOST_RECENT_DAYS_COUNT),
112 (result) -> handleResult(result))
127 private static String
formatDate(Date date, DateFormat formatter) {
128 return date == null ? null : formatter.format(date);
131 private static final Color FILE_EVT_COLOR =
new Color(228, 22, 28);
132 private static final Color ARTIFACT_EVT_COLOR =
new Color(21, 227, 100);
141 private List<BarChartSeries>
parseChartData(List<DailyActivityAmount> recentDaysActivity) {
143 if (CollectionUtils.isEmpty(recentDaysActivity)) {
148 List<BarChartItem> fileEvtCounts =
new ArrayList<>();
149 List<BarChartItem> artifactEvtCounts =
new ArrayList<>();
151 for (
int i = 0; i < recentDaysActivity.size(); i++) {
156 String formattedDate = (i == 0 || i == recentDaysActivity.size() - 1)
157 ? formatDate(curItem.
getDay(), CHART_FORMAT) :
"";
161 artifactEvtCounts.add(
new BarChartItem(thisKey, artifactAmt));
164 return Arrays.asList(
165 new BarChartSeries(Bundle.TimlinePanel_last30DaysChart_fileEvts_title(), FILE_EVT_COLOR, fileEvtCounts),
166 new BarChartSeries(Bundle.TimlinePanel_last30DaysChart_artifactEvts_title(), ARTIFACT_EVT_COLOR, artifactEvtCounts));
169 private final Object timelineBtnLock =
new Object();
189 synchronized (this.timelineBtnLock) {
190 this.curTimelineData = result.
getData();
191 this.viewInTimelineBtn.setEnabled(
true);
194 synchronized (this.timelineBtnLock) {
195 this.viewInTimelineBtn.setEnabled(
false);
204 DataSource dataSource = null;
209 synchronized (this.timelineBtnLock) {
210 if (curTimelineData == null) {
219 if (maxDate != null) {
220 maxDate =
new Date(maxDate.getTime() + 1000 * 60 * 60 * 24);
225 openFilteredChart(dataSource, minDate, maxDate);
237 if (openTimelineAction == null) {
238 logger.log(Level.WARNING,
"No OpenTimelineAction provided by CallableSystemAction; taking no redirect action.");
244 Interval timeSpan = null;
249 if (dataSource != null) {
253 if (minDate != null && maxDate != null) {
254 timeSpan =
new Interval(
new DateTime(minDate),
new DateTime(maxDate));
257 logger.log(Level.WARNING,
"Unable to view time range in Timeline view", ex);
262 }
catch (TskCoreException ex) {
263 logger.log(Level.WARNING,
"An unexpected exception occurred while opening the timeline.", ex);
269 fetchInformation(dataFetchComponents, dataSource);
274 onNewDataSource(dataFetchComponents, loadableComponents, dataSource);
288 @SuppressWarnings(
"unchecked")
290 private
void initComponents() {
292 javax.swing.JScrollPane mainScrollPane =
new javax.swing.JScrollPane();
293 javax.swing.JPanel mainContentPanel =
new javax.swing.JPanel();
294 javax.swing.JPanel ingestRunningPanel = ingestRunningLabel;
295 javax.swing.JLabel activityRangeLabel =
new javax.swing.JLabel();
296 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));
297 javax.swing.JPanel earliestLabelPanel = earliestLabel;
298 javax.swing.JPanel latestLabelPanel = latestLabel;
299 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));
300 javax.swing.JPanel last30DaysPanel = last30DaysChart;
301 viewInTimelineBtn =
new javax.swing.JButton();
302 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));
304 mainContentPanel.setBorder(javax.swing.BorderFactory.createEmptyBorder(10, 10, 10, 10));
305 mainContentPanel.setLayout(
new javax.swing.BoxLayout(mainContentPanel, javax.swing.BoxLayout.PAGE_AXIS));
307 ingestRunningPanel.setAlignmentX(0.0F);
308 ingestRunningPanel.setMaximumSize(
new java.awt.Dimension(32767, 25));
309 ingestRunningPanel.setMinimumSize(
new java.awt.Dimension(10, 25));
310 ingestRunningPanel.setPreferredSize(
new java.awt.Dimension(10, 25));
311 mainContentPanel.add(ingestRunningPanel);
313 activityRangeLabel.setFont(
new java.awt.Font(
"Segoe UI", 1, 12));
314 org.openide.awt.Mnemonics.setLocalizedText(activityRangeLabel,
org.openide.util.NbBundle.getMessage(
TimelinePanel.class,
"TimelinePanel.activityRangeLabel.text"));
315 mainContentPanel.add(activityRangeLabel);
316 activityRangeLabel.getAccessibleContext().setAccessibleName(
org.openide.util.NbBundle.getMessage(
TimelinePanel.class,
"PastCasesPanel.notableFileLabel.text"));
318 filler1.setAlignmentX(0.0F);
319 mainContentPanel.add(filler1);
321 earliestLabelPanel.setAlignmentX(0.0F);
322 earliestLabelPanel.setMaximumSize(
new java.awt.Dimension(32767, 20));
323 earliestLabelPanel.setMinimumSize(
new java.awt.Dimension(100, 20));
324 earliestLabelPanel.setPreferredSize(
new java.awt.Dimension(100, 20));
325 mainContentPanel.add(earliestLabelPanel);
327 latestLabelPanel.setAlignmentX(0.0F);
328 latestLabelPanel.setMaximumSize(
new java.awt.Dimension(32767, 20));
329 latestLabelPanel.setMinimumSize(
new java.awt.Dimension(100, 20));
330 latestLabelPanel.setPreferredSize(
new java.awt.Dimension(100, 20));
331 mainContentPanel.add(latestLabelPanel);
333 filler2.setAlignmentX(0.0F);
334 mainContentPanel.add(filler2);
336 last30DaysPanel.setAlignmentX(0.0F);
337 last30DaysPanel.setMaximumSize(
new java.awt.Dimension(600, 300));
338 last30DaysPanel.setMinimumSize(
new java.awt.Dimension(600, 300));
339 last30DaysPanel.setPreferredSize(
new java.awt.Dimension(600, 300));
340 last30DaysPanel.setVerifyInputWhenFocusTarget(
false);
341 mainContentPanel.add(last30DaysPanel);
343 org.openide.awt.Mnemonics.setLocalizedText(viewInTimelineBtn,
org.openide.util.NbBundle.getMessage(
TimelinePanel.class,
"TimelinePanel.viewInTimelineBtn.text"));
344 viewInTimelineBtn.setEnabled(
false);
345 viewInTimelineBtn.addActionListener(
new java.awt.event.ActionListener() {
346 public void actionPerformed(java.awt.event.ActionEvent evt) {
347 viewInTimelineBtnActionPerformed(evt);
350 mainContentPanel.add(viewInTimelineBtn);
352 filler5.setAlignmentX(0.0F);
353 mainContentPanel.add(filler5);
355 mainScrollPane.setViewportView(mainContentPanel);
357 javax.swing.GroupLayout layout =
new javax.swing.GroupLayout(
this);
358 this.setLayout(layout);
359 layout.setHorizontalGroup(
360 layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
361 .addComponent(mainScrollPane, javax.swing.GroupLayout.DEFAULT_SIZE, 400, Short.MAX_VALUE)
363 layout.setVerticalGroup(
364 layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
365 .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< BarChartSeries > parseChartData(List< DailyActivityAmount > recentDaysActivity)
List< DailyActivityAmount > getMostRecentDaysActivity()
void openFilteredChart(DataSource dataSource, Date minDate, Date maxDate)
void fetchInformation(DataSource dataSource)
synchronized void pushFilters(RootFilterState filter)
static TimelineDataSourceUtils getInstance()
TimelineSummaryData getData(DataSource dataSource, int recentDaysNum)
synchronized static Logger getLogger(String name)
static TimeLineController getController()
long getFileActivityCount()
TimelinePanel(TimelineSummary timelineData)