Autopsy  3.1
Graphical digital forensics platform for The Sleuth Kit and other tools.
TimeLineController.java
Go to the documentation of this file.
1 /*
2  * Autopsy Forensic Browser
3  *
4  * Copyright 2014 Basis Technology Corp.
5  * Contact: carrier <at> sleuthkit <dot> org
6  *
7  * Licensed under the Apache License, Version 2.0 (the "License");
8  * you may not use this file except in compliance with the License.
9  * You may obtain a copy of the License at
10  *
11  * http://www.apache.org/licenses/LICENSE-2.0
12  *
13  * Unless required by applicable law or agreed to in writing, software
14  * distributed under the License is distributed on an "AS IS" BASIS,
15  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
16  * See the License for the specific language governing permissions and
17  * limitations under the License.
18  */
19 package org.sleuthkit.autopsy.timeline;
20 
21 import java.awt.HeadlessException;
22 import java.beans.PropertyChangeEvent;
23 import java.beans.PropertyChangeListener;
24 import java.sql.ResultSet;
25 import java.sql.SQLException;
26 import java.text.NumberFormat;
27 import java.time.ZoneId;
28 import java.util.Collection;
29 import java.util.Map;
30 import java.util.MissingResourceException;
31 import java.util.TimeZone;
32 import java.util.concurrent.ExecutionException;
33 import java.util.concurrent.ExecutorService;
34 import java.util.concurrent.Executors;
35 import java.util.logging.Level;
36 import javafx.application.Platform;
37 import javafx.beans.Observable;
38 import javafx.beans.property.ReadOnlyBooleanProperty;
39 import javafx.beans.property.ReadOnlyBooleanWrapper;
40 import javafx.beans.property.ReadOnlyDoubleProperty;
41 import javafx.beans.property.ReadOnlyDoubleWrapper;
42 import javafx.beans.property.ReadOnlyListProperty;
43 import javafx.beans.property.ReadOnlyListWrapper;
44 import javafx.beans.property.ReadOnlyObjectProperty;
45 import javafx.beans.property.ReadOnlyObjectWrapper;
46 import javafx.beans.property.ReadOnlyStringProperty;
47 import javafx.beans.property.ReadOnlyStringWrapper;
48 import javafx.collections.FXCollections;
49 import javafx.collections.ObservableList;
50 import javafx.concurrent.Task;
51 import javax.annotation.concurrent.GuardedBy;
52 import javax.annotation.concurrent.Immutable;
53 import javax.swing.JOptionPane;
54 import javax.swing.SwingUtilities;
55 import org.joda.time.DateTime;
56 import org.joda.time.DateTimeZone;
57 import org.joda.time.Interval;
58 import org.joda.time.ReadablePeriod;
59 import org.joda.time.format.DateTimeFormat;
60 import org.joda.time.format.DateTimeFormatter;
61 import org.openide.util.NbBundle;
62 import org.openide.windows.WindowManager;
82 
97 public class TimeLineController {
98 
99  private static final Logger LOGGER = Logger.getLogger(TimeLineController.class.getName());
100 
101  private static final String DO_REPOPULATE_MESSAGE = NbBundle.getMessage(TimeLineController.class,
102  "Timeline.do_repopulate.msg");
103 
104  private static final ReadOnlyObjectWrapper<TimeZone> timeZone = new ReadOnlyObjectWrapper<>(TimeZone.getDefault());
105 
106  public static ZoneId getTimeZoneID() {
107  return timeZone.get().toZoneId();
108  }
109 
110  public static DateTimeFormatter getZonedFormatter() {
111  return DateTimeFormat.forPattern("YYYY-MM-dd HH:mm:ss").withZone(getJodaTimeZone()); // NON-NLS
112  }
113 
114  public static DateTimeZone getJodaTimeZone() {
115  return DateTimeZone.forTimeZone(getTimeZone().get());
116  }
117 
118  public static ReadOnlyObjectProperty<TimeZone> getTimeZone() {
119  return timeZone.getReadOnlyProperty();
120  }
121 
122  private final ExecutorService executor = Executors.newSingleThreadExecutor();
123 
124  private final ReadOnlyListWrapper<Task<?>> tasks = new ReadOnlyListWrapper<>(FXCollections.observableArrayList());
125 
126  private final ReadOnlyDoubleWrapper progress = new ReadOnlyDoubleWrapper(-1);
127 
128  private final ReadOnlyStringWrapper message = new ReadOnlyStringWrapper();
129 
130  private final ReadOnlyStringWrapper taskTitle = new ReadOnlyStringWrapper();
131 
132  synchronized public ReadOnlyListProperty<Task<?>> getTasks() {
133  return tasks.getReadOnlyProperty();
134  }
135 
136  synchronized public ReadOnlyDoubleProperty getProgress() {
137  return progress.getReadOnlyProperty();
138  }
139 
140  synchronized public ReadOnlyStringProperty getMessage() {
141  return message.getReadOnlyProperty();
142  }
143 
144  synchronized public ReadOnlyStringProperty getTaskTitle() {
145  return taskTitle.getReadOnlyProperty();
146  }
147 
148  @GuardedBy("this")
150 
151  //are the listeners currently attached
152  @GuardedBy("this")
153  private boolean listeningToAutopsy = false;
154 
155  private final PropertyChangeListener caseListener;
156 
157  private final PropertyChangeListener ingestJobListener = new AutopsyIngestJobListener();
158 
159  private final PropertyChangeListener ingestModuleListener = new AutopsyIngestModuleListener();
160 
161  @GuardedBy("this")
162  private final ReadOnlyObjectWrapper<VisualizationMode> viewMode = new ReadOnlyObjectWrapper<>(VisualizationMode.COUNTS);
163 
164  synchronized public ReadOnlyObjectProperty<VisualizationMode> getViewMode() {
165  return viewMode.getReadOnlyProperty();
166  }
167 
168  @GuardedBy("filteredEvents")
170 
171  @GuardedBy("eventsRepository")
173 
174  @GuardedBy("this")
176 
177  @GuardedBy("this")
178  private final History<ZoomParams> historyManager = new History<>();
179 
180  //all members should be access with the intrinsict lock of this object held
181  //selected events (ie shown in the result viewer)
182  @GuardedBy("this")
183  private final ObservableList<Long> selectedEventIDs = FXCollections.<Long>synchronizedObservableList(FXCollections.<Long>observableArrayList());
184 
188  synchronized public ObservableList<Long> getSelectedEventIDs() {
189  return selectedEventIDs;
190  }
191 
192  @GuardedBy("this")
193  private final ReadOnlyObjectWrapper<Interval> selectedTimeRange = new ReadOnlyObjectWrapper<>();
194 
198  synchronized public ReadOnlyObjectProperty<Interval> getSelectedTimeRange() {
199  return selectedTimeRange.getReadOnlyProperty();
200  }
201 
202  public ReadOnlyBooleanProperty getNewEventsFlag() {
203  return newEventsFlag.getReadOnlyProperty();
204  }
205 
206  private final ReadOnlyBooleanWrapper needsHistogramRebuild = new ReadOnlyBooleanWrapper(false);
207 
208  public ReadOnlyBooleanProperty getNeedsHistogramRebuild() {
209  return needsHistogramRebuild.getReadOnlyProperty();
210  }
211 
212  synchronized public ReadOnlyBooleanProperty getCanAdvance() {
213  return historyManager.getCanAdvance();
214  }
215 
216  synchronized public ReadOnlyBooleanProperty getCanRetreat() {
217  return historyManager.getCanRetreat();
218  }
219  private final ReadOnlyBooleanWrapper newEventsFlag = new ReadOnlyBooleanWrapper(false);
220 
222  //initalize repository and filteredEvents on creation
223  eventsRepository = new EventsRepository(historyManager.currentState());
224 
226  InitialZoomState = new ZoomParams(filteredEvents.getSpanningInterval(),
231 
232  //persistent listener instances
234  }
235 
238  return filteredEvents;
239  }
240 
241  public void applyDefaultFilters() {
243  }
244 
245  public void zoomOutToActivity() {
246  Interval boundingEventsInterval = filteredEvents.getBoundingEventsInterval();
247  advance(filteredEvents.getRequestedZoomParamters().get().withTimeRange(boundingEventsInterval));
248  }
249 
250  boolean rebuildRepo() {
252  //confirm timeline during ingest
253  if (showIngestConfirmation() != JOptionPane.YES_OPTION) {
254  return false;
255  }
256  }
257  LOGGER.log(Level.INFO, "Beginning generation of timeline"); // NON-NLS
258  try {
259  SwingUtilities.invokeLater(() -> {
260  if (mainFrame != null) {
261  mainFrame.close();
262  }
263  });
264  final SleuthkitCase sleuthkitCase = Case.getCurrentCase().getSleuthkitCase();
265  final long lastObjId = sleuthkitCase.getLastObjectId();
266  final long lastArtfID = getCaseLastArtifactID(sleuthkitCase);
267  final Boolean injestRunning = IngestManager.getInstance().isIngestRunning();
268  //TODO: verify this locking is correct? -jm
269  synchronized (eventsRepository) {
271 
272  synchronized (eventsRepository) {
276  }
277  synchronized (TimeLineController.this) {
278  needsHistogramRebuild.set(true);
279  needsHistogramRebuild.set(false);
280  showWindow();
281  }
282 
283  Platform.runLater(() -> {
284  newEventsFlag.set(false);
285  TimeLineController.this.showFullRange();
286  });
287  });
288  }
289  } catch (TskCoreException ex) {
290  LOGGER.log(Level.SEVERE, "Error when generating timeline, ", ex); // NON-NLS
291  return false;
292  }
293  return true;
294  }
295 
296  public void showFullRange() {
297  synchronized (filteredEvents) {
299  }
300  }
301 
302  synchronized public void closeTimeLine() {
303  if (mainFrame != null) {
304  listeningToAutopsy = false;
308  mainFrame.close();
309  mainFrame.setVisible(false);
310  mainFrame = null;
311  }
312  }
313 
315  synchronized void openTimeLine() {
316 
317  // listen for case changes (specifically images being added, and case changes).
318  if (Case.isCaseOpen() && !listeningToAutopsy) {
322  listeningToAutopsy = true;
323  }
324 
325  try {
326  long timeLineLastObjectId = eventsRepository.getLastObjID();
327 
328  boolean rebuildingRepo = false;
329  if (timeLineLastObjectId == -1) {
330  rebuildingRepo = rebuildRepo();
331  }
332  if (rebuildingRepo == false
334  if (showLastPopulatedWhileIngestingConfirmation() == JOptionPane.YES_OPTION) {
335  rebuildingRepo = rebuildRepo();
336  }
337  }
338  final SleuthkitCase sleuthkitCase = Case.getCurrentCase().getSleuthkitCase();
339  if ((rebuildingRepo == false)
340  && (sleuthkitCase.getLastObjectId() != timeLineLastObjectId
341  || getCaseLastArtifactID(sleuthkitCase) != eventsRepository.getLastArtfactID())) {
342  rebuildingRepo = outOfDatePromptAndRebuild();
343  }
344 
345  if (rebuildingRepo == false) {
346  showWindow();
347  showFullRange();
348  }
349 
350  } catch (TskCoreException ex) {
351  LOGGER.log(Level.SEVERE, "Error when generating timeline, ", ex); // NON-NLS
352  } catch (HeadlessException | MissingResourceException ex) {
353  LOGGER.log(Level.SEVERE, "Unexpected error when generating timeline, ", ex); // NON-NLS
354  }
355  }
356 
357  @SuppressWarnings("deprecation")
358  private long getCaseLastArtifactID(final SleuthkitCase sleuthkitCase) {
359  long caseLastArtfId = -1;
360  String query = "select Max(artifact_id) as max_id from blackboard_artifacts"; // NON-NLS
361 
362  try (CaseDbQuery dbQuery = sleuthkitCase.executeQuery(query)) {
363  ResultSet resultSet = dbQuery.getResultSet();
364  while (resultSet.next()) {
365  caseLastArtfId = resultSet.getLong("max_id"); // NON-NLS
366  }
367  } catch (TskCoreException | SQLException ex) {
368  LOGGER.log(Level.SEVERE, "Error getting last artifact id: ", ex); // NON-NLS
369  }
370  return caseLastArtfId;
371  }
372 
379  synchronized public void pushPeriod(ReadablePeriod period) {
380  synchronized (filteredEvents) {
381  final DateTime middleOf = IntervalUtils.middleOf(filteredEvents.timeRange().get());
382  pushTimeRange(IntervalUtils.getIntervalAround(middleOf, period));
383  }
384  }
385 
386  synchronized public void pushZoomOutTime() {
387  final Interval timeRange = filteredEvents.timeRange().get();
388  long toDurationMillis = timeRange.toDurationMillis() / 4;
389  DateTime start = timeRange.getStart().minus(toDurationMillis);
390  DateTime end = timeRange.getEnd().plus(toDurationMillis);
391  pushTimeRange(new Interval(start, end));
392  }
393 
394  synchronized public void pushZoomInTime() {
395  final Interval timeRange = filteredEvents.timeRange().get();
396  long toDurationMillis = timeRange.toDurationMillis() / 4;
397  DateTime start = timeRange.getStart().plus(toDurationMillis);
398  DateTime end = timeRange.getEnd().minus(toDurationMillis);
399  pushTimeRange(new Interval(start, end));
400  }
401 
402  synchronized public void setViewMode(VisualizationMode visualizationMode) {
403  if (viewMode.get() != visualizationMode) {
404  viewMode.set(visualizationMode);
405  }
406  }
407 
408  public void selectEventIDs(Collection<Long> events) {
409  final LoggedTask<Interval> selectEventIDsTask = new LoggedTask<Interval>("Select Event IDs", true) { // NON-NLS
410  @Override
411  protected Interval call() throws Exception {
412  return filteredEvents.getSpanningInterval(events);
413  }
414 
415  @Override
416  protected void succeeded() {
417  super.succeeded();
418  try {
419  synchronized (TimeLineController.this) {
420  selectedTimeRange.set(get());
421  selectedEventIDs.setAll(events);
422  }
423  } catch (InterruptedException ex) {
425  .getName()).log(Level.SEVERE, getTitle() + " interrupted unexpectedly", ex); // NON-NLS
426  } catch (ExecutionException ex) {
428  .getName()).log(Level.SEVERE, getTitle() + " unexpectedly threw " + ex.getCause(), ex); // NON-NLS
429  }
430  }
431  };
432 
433  monitorTask(selectEventIDsTask);
434  }
435 
439  synchronized private void showWindow() {
440  if (mainFrame == null) {
441  LOGGER.log(Level.WARNING, "Tried to show timeline with invalid window. Rebuilding GUI."); // NON-NLS
442  mainFrame = (TimeLineTopComponent) WindowManager.getDefault().findTopComponent(
443  NbBundle.getMessage(TimeLineTopComponent.class, "CTL_TimeLineTopComponentAction"));
444  if (mainFrame == null) {
446  }
447  mainFrame.setController(this);
448  }
449  SwingUtilities.invokeLater(() -> {
450  mainFrame.open();
451  mainFrame.setVisible(true);
452  mainFrame.toFront();
453  });
454  }
455 
456  synchronized public void pushEventTypeZoom(EventTypeZoomLevel typeZoomeLevel) {
458  if (currentZoom == null) {
459  advance(InitialZoomState.withTypeZoomLevel(typeZoomeLevel));
460  } else if (currentZoom.hasTypeZoomLevel(typeZoomeLevel) == false) {
461  advance(currentZoom.withTypeZoomLevel(typeZoomeLevel));
462  }
463  }
464 
465  synchronized public void pushTimeRange(Interval timeRange) {
466 // timeRange = this.filteredEvents.getSpanningInterval().overlap(timeRange);
468  if (currentZoom == null) {
470  } else if (currentZoom.hasTimeRange(timeRange) == false) {
471  advance(currentZoom.withTimeRange(timeRange));
472  }
473  }
474 
475  synchronized public boolean pushDescrLOD(DescriptionLOD newLOD) {
476  Map<EventType, Long> eventCounts = filteredEvents.getEventCounts(filteredEvents.getRequestedZoomParamters().get().getTimeRange());
477  final Long count = eventCounts.values().stream().reduce(0l, Long::sum);
478 
479  boolean shouldContinue = true;
480  if (newLOD == DescriptionLOD.FULL && count > 10_000) {
481 
482  int showConfirmDialog = JOptionPane.showConfirmDialog(mainFrame,
483  NbBundle.getMessage(this.getClass(),
484  "Timeline.pushDescrLOD.confdlg.msg",
485  NumberFormat.getInstance().format(count)),
486  NbBundle.getMessage(TimeLineTopComponent.class,
487  "Timeline.pushDescrLOD.confdlg.details"),
488  JOptionPane.YES_NO_OPTION);
489 
490  shouldContinue = (showConfirmDialog == JOptionPane.YES_OPTION);
491  }
492 
493  if (shouldContinue) {
495  if (currentZoom == null) {
497  } else if (currentZoom.hasDescrLOD(newLOD) == false) {
498  advance(currentZoom.withDescrLOD(newLOD));
499  }
500  }
501  return shouldContinue;
502  }
503 
504  synchronized public void pushTimeAndType(Interval timeRange, EventTypeZoomLevel typeZoom) {
505 // timeRange = this.filteredEvents.getSpanningInterval().overlap(timeRange);
507  if (currentZoom == null) {
508  advance(InitialZoomState.withTimeAndType(timeRange, typeZoom));
509  } else if (currentZoom.hasTimeRange(timeRange) == false && currentZoom.hasTypeZoomLevel(typeZoom) == false) {
510  advance(currentZoom.withTimeAndType(timeRange, typeZoom));
511  } else if (currentZoom.hasTimeRange(timeRange) == false) {
512  advance(currentZoom.withTimeRange(timeRange));
513  } else if (currentZoom.hasTypeZoomLevel(typeZoom) == false) {
514  advance(currentZoom.withTypeZoomLevel(typeZoom));
515  }
516  }
517 
518  synchronized public void pushFilters(Filter filter) {
520  if (currentZoom == null) {
522  } else if (currentZoom.hasFilter(filter) == false) {
523  advance(currentZoom.withFilter(filter.copyOf()));
524  }
525  }
526 
527  synchronized public ZoomParams advance() {
528  return historyManager.advance();
529 
530  }
531 
532  synchronized public ZoomParams retreat() {
533  return historyManager.retreat();
534  }
535 
536  synchronized private void advance(ZoomParams newState) {
537  historyManager.advance(newState);
538  }
539 
540  public void selectTimeAndType(Interval interval, EventType type) {
541  final Interval timeRange = filteredEvents.getSpanningInterval().overlap(interval);
542 
543  final LoggedTask<Collection<Long>> selectTimeAndTypeTask = new LoggedTask<Collection<Long>>("Select Time and Type", true) { // NON-NLS
544  @Override
545  protected Collection< Long> call() throws Exception {
546  synchronized (TimeLineController.this) {
547  return filteredEvents.getEventIDs(timeRange, new TypeFilter(type));
548  }
549  }
550 
551  @Override
552  protected void succeeded() {
553  super.succeeded();
554  try {
555  synchronized (TimeLineController.this) {
556  selectedTimeRange.set(timeRange);
557  selectedEventIDs.setAll(get());
558  }
559  } catch (InterruptedException ex) {
561  .getName()).log(Level.SEVERE, getTitle() + " interrupted unexpectedly", ex);// NON-NLS
562  } catch (ExecutionException ex) {
564  .getName()).log(Level.SEVERE, getTitle() + " unexpectedly threw " + ex.getCause(), ex);// NON-NLS
565  }
566  }
567  };
568 
569  monitorTask(selectTimeAndTypeTask);
570  }
571 
578  synchronized public void monitorTask(final Task<?> task) {
579  if (task != null) {
580  Platform.runLater(() -> {
581 
582  //is this actually threadsafe, could we get a finished task stuck in the list?
583  task.stateProperty().addListener((Observable observable) -> {
584  switch (task.getState()) {
585  case READY:
586  case RUNNING:
587  case SCHEDULED:
588  break;
589  case SUCCEEDED:
590  case CANCELLED:
591  case FAILED:
592  tasks.remove(task);
593  if (tasks.isEmpty() == false) {
594  progress.bind(tasks.get(0).progressProperty());
595  message.bind(tasks.get(0).messageProperty());
596  taskTitle.bind(tasks.get(0).titleProperty());
597  }
598  break;
599  }
600  });
601  tasks.add(task);
602  progress.bind(task.progressProperty());
603  message.bind(task.messageProperty());
604  taskTitle.bind(task.titleProperty());
605  switch (task.getState()) {
606  case READY:
607  executor.submit(task);
608  break;
609  case SCHEDULED:
610  case RUNNING:
611 
612  case SUCCEEDED:
613  case CANCELLED:
614  case FAILED:
615  tasks.remove(task);
616  if (tasks.isEmpty() == false) {
617  progress.bind(tasks.get(0).progressProperty());
618  message.bind(tasks.get(0).messageProperty());
619  taskTitle.bind(tasks.get(0).titleProperty());
620  }
621  break;
622  }
623  });
624  }
625  }
626 
627  static synchronized public void setTimeZone(TimeZone timeZone) {
628  TimeLineController.timeZone.set(timeZone);
629  }
630 
631  Interval getSpanningInterval(Collection<Long> eventIDs) {
632  return filteredEvents.getSpanningInterval(eventIDs);
633 
634  }
635 
639  synchronized public boolean outOfDatePromptAndRebuild() {
640  return showOutOfDateConfirmation() == JOptionPane.YES_OPTION
641  ? rebuildRepo()
642  : false;
643  }
644 
645  synchronized int showLastPopulatedWhileIngestingConfirmation() {
646  return JOptionPane.showConfirmDialog(mainFrame,
647  DO_REPOPULATE_MESSAGE,
648  NbBundle.getMessage(TimeLineTopComponent.class,
649  "Timeline.showLastPopulatedWhileIngestingConf.confDlg.details"),
650  JOptionPane.YES_NO_OPTION,
651  JOptionPane.QUESTION_MESSAGE);
652 
653  }
654 
655  synchronized int showOutOfDateConfirmation() throws MissingResourceException, HeadlessException {
656  return JOptionPane.showConfirmDialog(mainFrame,
657  NbBundle.getMessage(TimeLineController.class,
658  "Timeline.propChg.confDlg.timelineOOD.msg"),
659  NbBundle.getMessage(TimeLineController.class,
660  "Timeline.propChg.confDlg.timelineOOD.details"),
661  JOptionPane.YES_NO_OPTION);
662  }
663 
664  synchronized int showIngestConfirmation() throws MissingResourceException, HeadlessException {
665  return JOptionPane.showConfirmDialog(mainFrame,
666  NbBundle.getMessage(TimeLineController.class,
667  "Timeline.initTimeline.confDlg.genBeforeIngest.msg"),
668  NbBundle.getMessage(TimeLineController.class,
669  "Timeline.initTimeline.confDlg.genBeforeIngest.details"),
670  JOptionPane.YES_NO_OPTION);
671  }
672 
673  private class AutopsyIngestModuleListener implements PropertyChangeListener {
674 
675  @Override
676  public void propertyChange(PropertyChangeEvent evt) {
677  switch (IngestManager.IngestModuleEvent.valueOf(evt.getPropertyName())) {
678  case CONTENT_CHANGED:
679 // ((ModuleContentEvent)evt.getOldValue())????
680  //ModuleContentEvent doesn't seem to provide any usefull information...
681  break;
682  case DATA_ADDED:
683 // Collection<BlackboardArtifact> artifacts = ((ModuleDataEvent) evt.getOldValue()).getArtifacts();
684  //new artifacts, insert them into db
685  break;
686  case FILE_DONE:
687 // Long fileID = (Long) evt.getOldValue();
688  //update file (known status) for file with id
689  Platform.runLater(() -> {
690  newEventsFlag.set(true);
691  });
692  break;
693  }
694  }
695  }
696 
697  @Immutable
698  private class AutopsyIngestJobListener implements PropertyChangeListener {
699 
700  @Override
701  public void propertyChange(PropertyChangeEvent evt) {
702  switch (IngestManager.IngestJobEvent.valueOf(evt.getPropertyName())) {
703  case CANCELLED:
704  case COMPLETED:
705  //if we are doing incremental updates, drop this
707  break;
708  }
709  }
710  }
711 
712  @Immutable
713  private class AutopsyCaseListener implements PropertyChangeListener {
714 
715  @Override
716  public void propertyChange(PropertyChangeEvent evt) {
717  switch (Case.Events.valueOf(evt.getPropertyName())) {
718  case DATA_SOURCE_ADDED:
719 // Content content = (Content) evt.getNewValue();
720  //if we are doing incremental updates, drop this
722  break;
723  case CURRENT_CASE:
724  OpenTimelineAction.invalidateController();
725  closeTimeLine();
726  break;
727  }
728  }
729  }
730 }
void removeIngestModuleEventListener(final PropertyChangeListener listener)
final ReadOnlyObjectWrapper< VisualizationMode > viewMode
static synchronized IngestManager getInstance()
ZoomParams withTypeZoomLevel(EventTypeZoomLevel zoomLevel)
Definition: ZoomParams.java:90
static final ReadOnlyObjectWrapper< TimeZone > timeZone
static ReadOnlyObjectProperty< TimeZone > getTimeZone()
long getCaseLastArtifactID(final SleuthkitCase sleuthkitCase)
synchronized ReadOnlyBooleanProperty getCanRetreat()
synchronized void setController(TimeLineController controller)
synchronized boolean pushDescrLOD(DescriptionLOD newLOD)
synchronized void pushTimeAndType(Interval timeRange, EventTypeZoomLevel typeZoom)
synchronized ReadOnlyObjectProperty< Interval > getSelectedTimeRange()
void selectTimeAndType(Interval interval, EventType type)
synchronized ReadOnlyBooleanProperty getCanAdvance()
void removeIngestJobEventListener(final PropertyChangeListener listener)
final ReadOnlyObjectWrapper< Interval > selectedTimeRange
boolean hasTypeZoomLevel(EventTypeZoomLevel typeZoom)
ZoomParams withDescrLOD(DescriptionLOD descrLOD)
Definition: ZoomParams.java:98
synchronized ReadOnlyObjectProperty< Interval > timeRange()
ZoomParams withTimeRange(Interval timeRange)
Definition: ZoomParams.java:94
void addIngestJobEventListener(final PropertyChangeListener listener)
static Interval getIntervalAround(DateTime aroundInstant, ReadablePeriod period)
synchronized ReadOnlyStringProperty getMessage()
static synchronized void setTimeZone(TimeZone timeZone)
synchronized void monitorTask(final Task<?> task)
synchronized void pushPeriod(ReadablePeriod period)
synchronized ReadOnlyDoubleProperty getProgress()
Map< EventType, Long > getEventCounts(Interval timeRange)
synchronized void advance(ZoomParams newState)
synchronized ObservableList< Long > getSelectedEventIDs()
ZoomParams withTimeAndType(Interval timeRange, EventTypeZoomLevel zoomLevel)
Definition: ZoomParams.java:86
static synchronized void removePropertyChangeListener(PropertyChangeListener listener)
Definition: Case.java:837
Interval getSpanningInterval(Collection< Long > eventIDs)
boolean hasDescrLOD(DescriptionLOD newLOD)
void addIngestModuleEventListener(final PropertyChangeListener listener)
static synchronized void addPropertyChangeListener(PropertyChangeListener listener)
Definition: Case.java:833
synchronized ReadOnlyStringProperty getTaskTitle()
Set< Long > getEventIDs(Interval timeRange, Filter filter)
synchronized ReadOnlyObjectProperty< VisualizationMode > getViewMode()
synchronized void pushTimeRange(Interval timeRange)
static DateTime middleOf(Interval interval)
synchronized ReadOnlyListProperty< Task<?> > getTasks()
synchronized void setViewMode(VisualizationMode visualizationMode)
static Logger getLogger(String name)
Definition: Logger.java:131
synchronized void pushEventTypeZoom(EventTypeZoomLevel typeZoomeLevel)
synchronized ReadOnlyObjectProperty< ZoomParams > getRequestedZoomParamters()

Copyright © 2012-2015 Basis Technology. Generated on: Mon Oct 19 2015
This work is licensed under a Creative Commons Attribution-Share Alike 3.0 United States License.