19 package org.sleuthkit.autopsy.datasourcesummary.ui;
21 import java.awt.Color;
22 import java.text.DateFormat;
23 import java.util.ArrayList;
24 import java.util.Arrays;
25 import java.util.Date;
26 import java.util.List;
27 import java.util.logging.Level;
28 import org.apache.commons.collections.CollectionUtils;
29 import org.joda.time.DateTime;
30 import org.joda.time.Interval;
31 import org.openide.util.NbBundle.Messages;
32 import org.openide.util.actions.CallableSystemAction;
60 "TimelinePanel_earliestLabel_title=Earliest",
61 "TimelinePanel_latestLabel_title=Latest",
62 "TimlinePanel_last30DaysChart_title=Last 30 Days",
63 "TimlinePanel_last30DaysChart_fileEvts_title=File Events",
64 "TimlinePanel_last30DaysChart_artifactEvts_title=Result Events",})
68 private static final long serialVersionUID = 1L;
70 private static final String EARLIEST_LATEST_FORMAT_STR =
"MMM d, yyyy";
73 private static final int MOST_RECENT_DAYS_COUNT = 30;
83 private final List<LoadableComponent<?>> loadableComponents = Arrays.asList(earliestLabel, latestLabel, last30DaysChart);
100 dataFetcher = (dataSource) -> timelineData.
getData(dataSource, MOST_RECENT_DAYS_COUNT);
103 dataFetchComponents = Arrays.asList(
109 private static final Color FILE_EVT_COLOR =
new Color(228, 22, 28);
110 private static final Color ARTIFACT_EVT_COLOR =
new Color(21, 227, 100);
123 private List<BarChartSeries>
parseChartData(List<DailyActivityAmount> recentDaysActivity,
boolean showIntermediateDates) {
125 if (CollectionUtils.isEmpty(recentDaysActivity)) {
130 List<BarChartItem> fileEvtCounts =
new ArrayList<>();
131 List<BarChartItem> artifactEvtCounts =
new ArrayList<>();
133 for (
int i = 0; i < recentDaysActivity.size(); i++) {
138 String formattedDate = (showIntermediateDates || i == 0 || i == recentDaysActivity.size() - 1)
143 artifactEvtCounts.add(
new BarChartItem(thisKey, artifactAmt));
146 return Arrays.asList(
147 new BarChartSeries(Bundle.TimlinePanel_last30DaysChart_fileEvts_title(), FILE_EVT_COLOR, fileEvtCounts),
148 new BarChartSeries(Bundle.TimlinePanel_last30DaysChart_artifactEvts_title(), ARTIFACT_EVT_COLOR, artifactEvtCounts));
151 private final Object timelineBtnLock =
new Object();
171 synchronized (this.timelineBtnLock) {
172 this.curTimelineData = result.
getData();
173 this.viewInTimelineBtn.setEnabled(
true);
176 synchronized (this.timelineBtnLock) {
177 this.viewInTimelineBtn.setEnabled(
false);
186 DataSource dataSource = null;
191 synchronized (this.timelineBtnLock) {
192 if (curTimelineData == null) {
201 if (maxDate != null) {
202 maxDate =
new Date(maxDate.getTime() + 1000 * 60 * 60 * 24);
207 openFilteredChart(dataSource, minDate, maxDate);
219 if (openTimelineAction == null) {
220 logger.log(Level.WARNING,
"No OpenTimelineAction provided by CallableSystemAction; taking no redirect action.");
226 Interval timeSpan = null;
231 if (dataSource != null) {
235 if (minDate != null && maxDate != null) {
236 timeSpan =
new Interval(
new DateTime(minDate),
new DateTime(maxDate));
238 }
catch (TskCoreException ex) {
239 logger.log(Level.WARNING,
"Unable to view time range in Timeline view", ex);
244 }
catch (TskCoreException ex) {
245 logger.log(Level.WARNING,
"An unexpected exception occurred while opening the timeline.", ex);
251 fetchInformation(dataFetchComponents, dataSource);
256 onNewDataSource(dataFetchComponents, loadableComponents, dataSource);
270 @SuppressWarnings(
"unchecked")
272 private
void initComponents() {
274 javax.swing.JScrollPane mainScrollPane =
new javax.swing.JScrollPane();
275 javax.swing.JPanel mainContentPanel =
new javax.swing.JPanel();
276 javax.swing.JPanel ingestRunningPanel = ingestRunningLabel;
277 javax.swing.JLabel activityRangeLabel =
new javax.swing.JLabel();
278 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));
279 javax.swing.JPanel earliestLabelPanel = earliestLabel;
280 javax.swing.JPanel latestLabelPanel = latestLabel;
281 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));
282 javax.swing.JPanel last30DaysPanel = last30DaysChart;
283 viewInTimelineBtn =
new javax.swing.JButton();
284 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));
286 mainContentPanel.setBorder(javax.swing.BorderFactory.createEmptyBorder(10, 10, 10, 10));
287 mainContentPanel.setLayout(
new javax.swing.BoxLayout(mainContentPanel, javax.swing.BoxLayout.PAGE_AXIS));
289 ingestRunningPanel.setAlignmentX(0.0F);
290 ingestRunningPanel.setMaximumSize(
new java.awt.Dimension(32767, 25));
291 ingestRunningPanel.setMinimumSize(
new java.awt.Dimension(10, 25));
292 ingestRunningPanel.setPreferredSize(
new java.awt.Dimension(10, 25));
293 mainContentPanel.add(ingestRunningPanel);
295 activityRangeLabel.setFont(
new java.awt.Font(
"Segoe UI", 1, 12));
296 org.openide.awt.Mnemonics.setLocalizedText(activityRangeLabel,
org.openide.util.NbBundle.getMessage(
TimelinePanel.class,
"TimelinePanel.activityRangeLabel.text"));
297 mainContentPanel.add(activityRangeLabel);
298 activityRangeLabel.getAccessibleContext().setAccessibleName(
org.openide.util.NbBundle.getMessage(
TimelinePanel.class,
"PastCasesPanel.notableFileLabel.text"));
300 filler1.setAlignmentX(0.0F);
301 mainContentPanel.add(filler1);
303 earliestLabelPanel.setAlignmentX(0.0F);
304 earliestLabelPanel.setMaximumSize(
new java.awt.Dimension(32767, 20));
305 earliestLabelPanel.setMinimumSize(
new java.awt.Dimension(100, 20));
306 earliestLabelPanel.setPreferredSize(
new java.awt.Dimension(100, 20));
307 mainContentPanel.add(earliestLabelPanel);
309 latestLabelPanel.setAlignmentX(0.0F);
310 latestLabelPanel.setMaximumSize(
new java.awt.Dimension(32767, 20));
311 latestLabelPanel.setMinimumSize(
new java.awt.Dimension(100, 20));
312 latestLabelPanel.setPreferredSize(
new java.awt.Dimension(100, 20));
313 mainContentPanel.add(latestLabelPanel);
315 filler2.setAlignmentX(0.0F);
316 mainContentPanel.add(filler2);
318 last30DaysPanel.setAlignmentX(0.0F);
319 last30DaysPanel.setMaximumSize(
new java.awt.Dimension(600, 300));
320 last30DaysPanel.setMinimumSize(
new java.awt.Dimension(600, 300));
321 last30DaysPanel.setPreferredSize(
new java.awt.Dimension(600, 300));
322 last30DaysPanel.setVerifyInputWhenFocusTarget(
false);
323 mainContentPanel.add(last30DaysPanel);
325 org.openide.awt.Mnemonics.setLocalizedText(viewInTimelineBtn,
org.openide.util.NbBundle.getMessage(
TimelinePanel.class,
"TimelinePanel.viewInTimelineBtn.text"));
326 viewInTimelineBtn.setEnabled(
false);
327 viewInTimelineBtn.addActionListener(
new java.awt.event.ActionListener() {
328 public void actionPerformed(java.awt.event.ActionEvent evt) {
329 viewInTimelineBtnActionPerformed(evt);
332 mainContentPanel.add(viewInTimelineBtn);
334 filler5.setAlignmentX(0.0F);
335 mainContentPanel.add(filler5);
337 mainScrollPane.setViewportView(mainContentPanel);
339 javax.swing.GroupLayout layout =
new javax.swing.GroupLayout(
this);
340 this.setLayout(layout);
341 layout.setHorizontalGroup(
342 layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
343 .addComponent(mainScrollPane, javax.swing.GroupLayout.DEFAULT_SIZE, 400, Short.MAX_VALUE)
345 layout.setVerticalGroup(
346 layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
347 .addComponent(mainScrollPane, javax.swing.GroupLayout.DEFAULT_SIZE, 300, Short.MAX_VALUE)
TimelineSummaryData getData(DataSource dataSource, int recentDaysNum)
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()
static DateFormat getUtcFormat(String formatString)
long getArtifactActivityCount()
void showDataFetchResult(DataFetchResult< T > result, String errorMessage, String noResultsMessage)
void handleResult(DataFetchResult< TimelineSummaryData > result)
void onNewDataSource(DataSource dataSource)
void viewInTimelineBtnActionPerformed(java.awt.event.ActionEvent evt)
TimelinePanel(TimelineSummaryGetter timelineData)
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 TimelineDataSourceUtils getInstance()
synchronized static Logger getLogger(String name)
static TimeLineController getController()
long getFileActivityCount()
static String formatDate(Date date, DateFormat formatter)
List< BarChartSeries > parseChartData(List< DailyActivityAmount > recentDaysActivity, boolean showIntermediateDates)