Autopsy  4.9.1
Graphical digital forensics platform for The Sleuth Kit and other tools.
AbstractSqlEamDb.java
Go to the documentation of this file.
1 /*
2  * Central Repository
3  *
4  * Copyright 2015-2018 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.centralrepository.datamodel;
20 
21 import com.google.common.cache.Cache;
22 import com.google.common.cache.CacheBuilder;
23 import com.google.common.cache.CacheLoader;
24 import java.net.UnknownHostException;
25 import java.util.ArrayList;
26 import java.util.List;
27 import java.util.Collection;
28 import java.util.LinkedHashSet;
29 import java.util.stream.Collectors;
30 import java.sql.Connection;
31 import java.sql.PreparedStatement;
32 import java.sql.ResultSet;
33 import java.sql.SQLException;
34 import java.sql.Statement;
35 import java.sql.Types;
36 import java.time.LocalDate;
37 import java.util.HashMap;
38 import java.util.Map;
39 import java.util.Set;
40 import java.util.concurrent.ExecutionException;
41 import java.util.concurrent.TimeUnit;
42 import java.util.logging.Level;
44 import static org.sleuthkit.autopsy.centralrepository.datamodel.EamDbUtil.updateSchemaVersion;
48 import org.sleuthkit.datamodel.CaseDbSchemaVersionNumber;
49 import org.sleuthkit.datamodel.TskData;
50 
56 abstract class AbstractSqlEamDb implements EamDb {
57 
58  private final static Logger logger = Logger.getLogger(AbstractSqlEamDb.class.getName());
59  static final String SCHEMA_MAJOR_VERSION_KEY = "SCHEMA_VERSION";
60  static final String SCHEMA_MINOR_VERSION_KEY = "SCHEMA_MINOR_VERSION";
61  static final String CREATION_SCHEMA_MAJOR_VERSION_KEY = "CREATION_SCHEMA_MAJOR_VERSION";
62  static final String CREATION_SCHEMA_MINOR_VERSION_KEY = "CREATION_SCHEMA_MINOR_VERSION";
63  static final CaseDbSchemaVersionNumber CURRENT_DB_SCHEMA_VERSION = new CaseDbSchemaVersionNumber(1, 2);
64 
65  protected final List<CorrelationAttributeInstance.Type> defaultCorrelationTypes;
66 
67  private int bulkArtifactsCount;
68  protected int bulkArtifactsThreshold;
69  private final Map<String, Collection<CorrelationAttributeInstance>> bulkArtifacts;
70  private static final int CASE_CACHE_TIMEOUT = 5;
71  private static final int DATA_SOURCE_CACHE_TIMEOUT = 5;
72  private static final Cache<Integer, CorrelationAttributeInstance.Type> typeCache = CacheBuilder.newBuilder().build();
73  private static final Cache<String, CorrelationCase> caseCacheByUUID = CacheBuilder.newBuilder()
74  .expireAfterWrite(CASE_CACHE_TIMEOUT, TimeUnit.MINUTES).
75  build();
76  private static final Cache<Integer, CorrelationCase> caseCacheById = CacheBuilder.newBuilder()
77  .expireAfterWrite(CASE_CACHE_TIMEOUT, TimeUnit.MINUTES).
78  build();
79  private static final Cache<String, CorrelationDataSource> dataSourceCacheByDsObjectId = CacheBuilder.newBuilder()
80  .expireAfterWrite(DATA_SOURCE_CACHE_TIMEOUT, TimeUnit.MINUTES).
81  build();
82  private static final Cache<String, CorrelationDataSource> dataSourceCacheById = CacheBuilder.newBuilder()
83  .expireAfterWrite(DATA_SOURCE_CACHE_TIMEOUT, TimeUnit.MINUTES).
84  build();
85  // Maximum length for the value column in the instance tables
86  static final int MAX_VALUE_LENGTH = 256;
87 
88  // number of instances to keep in bulk queue before doing an insert.
89  // Update Test code if this changes. It's hard coded there.
90  static final int DEFAULT_BULK_THRESHHOLD = 1000;
91 
97  protected AbstractSqlEamDb() throws EamDbException {
98  bulkArtifactsCount = 0;
99  bulkArtifacts = new HashMap<>();
100 
101  defaultCorrelationTypes = CorrelationAttributeInstance.getDefaultCorrelationTypes();
102  defaultCorrelationTypes.forEach((type) -> {
103  bulkArtifacts.put(EamDbUtil.correlationTypeToInstanceTableName(type), new ArrayList<>());
104  });
105  }
106 
110  protected abstract Connection connect() throws EamDbException;
111 
120  @Override
121  public void newDbInfo(String name, String value) throws EamDbException {
122  Connection conn = connect();
123 
124  PreparedStatement preparedStatement = null;
125  String sql = "INSERT INTO db_info (name, value) VALUES (?, ?) "
126  + getConflictClause();
127  try {
128  preparedStatement = conn.prepareStatement(sql);
129  preparedStatement.setString(1, name);
130  preparedStatement.setString(2, value);
131  preparedStatement.executeUpdate();
132  } catch (SQLException ex) {
133  throw new EamDbException("Error adding new name/value pair to db_info.", ex);
134  } finally {
135  EamDbUtil.closeStatement(preparedStatement);
137  }
138 
139  }
140 
141  @Override
142  public void addDataSourceObjectId(int rowId, long dataSourceObjectId) throws EamDbException {
143  Connection conn = connect();
144  PreparedStatement preparedStatement = null;
145  String sql = "UPDATE data_sources SET datasource_obj_id=? WHERE id=?";
146  try {
147  preparedStatement = conn.prepareStatement(sql);
148  preparedStatement.setLong(1, dataSourceObjectId);
149  preparedStatement.setInt(2, rowId);
150  preparedStatement.executeUpdate();
151  } catch (SQLException ex) {
152  throw new EamDbException("Error updating data source object id for data_sources row " + rowId, ex);
153  } finally {
154  EamDbUtil.closeStatement(preparedStatement);
156  }
157  }
158 
168  @Override
169  public String getDbInfo(String name) throws EamDbException {
170  Connection conn = connect();
171 
172  PreparedStatement preparedStatement = null;
173  ResultSet resultSet = null;
174  String value = null;
175  String sql = "SELECT value FROM db_info WHERE name=?";
176  try {
177  preparedStatement = conn.prepareStatement(sql);
178  preparedStatement.setString(1, name);
179  resultSet = preparedStatement.executeQuery();
180  if (resultSet.next()) {
181  value = resultSet.getString("value");
182  }
183  } catch (SQLException ex) {
184  throw new EamDbException("Error getting value for name.", ex);
185  } finally {
186  EamDbUtil.closeStatement(preparedStatement);
187  EamDbUtil.closeResultSet(resultSet);
189  }
190 
191  return value;
192  }
193 
197  protected final void clearCaches() {
198  typeCache.invalidateAll();
199  caseCacheByUUID.invalidateAll();
200  caseCacheById.invalidateAll();
201  dataSourceCacheByDsObjectId.invalidateAll();
202  dataSourceCacheById.invalidateAll();
203  }
204 
213  @Override
214  public void updateDbInfo(String name, String value) throws EamDbException {
215  Connection conn = connect();
216 
217  PreparedStatement preparedStatement = null;
218  String sql = "UPDATE db_info SET value=? WHERE name=?";
219  try {
220  preparedStatement = conn.prepareStatement(sql);
221  preparedStatement.setString(1, value);
222  preparedStatement.setString(2, name);
223  preparedStatement.executeUpdate();
224  } catch (SQLException ex) {
225  throw new EamDbException("Error updating value for name.", ex);
226  } finally {
227  EamDbUtil.closeStatement(preparedStatement);
229  }
230  }
231 
241  @Override
242  public synchronized CorrelationCase newCase(CorrelationCase eamCase) throws EamDbException {
243 
244  // check if there is already an existing CorrelationCase for this Case
245  CorrelationCase cRCase = getCaseByUUID(eamCase.getCaseUUID());
246  if (cRCase != null) {
247  return cRCase;
248  }
249 
250  Connection conn = connect();
251  PreparedStatement preparedStatement = null;
252 
253  String sql = "INSERT INTO cases(case_uid, org_id, case_name, creation_date, case_number, "
254  + "examiner_name, examiner_email, examiner_phone, notes) "
255  + "VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?) "
256  + getConflictClause();
257  ResultSet resultSet = null;
258  try {
259  preparedStatement = conn.prepareStatement(sql, Statement.RETURN_GENERATED_KEYS);
260 
261  preparedStatement.setString(1, eamCase.getCaseUUID());
262  if (null == eamCase.getOrg()) {
263  preparedStatement.setNull(2, Types.INTEGER);
264  } else {
265  preparedStatement.setInt(2, eamCase.getOrg().getOrgID());
266  }
267  preparedStatement.setString(3, eamCase.getDisplayName());
268  preparedStatement.setString(4, eamCase.getCreationDate());
269  if ("".equals(eamCase.getCaseNumber())) {
270  preparedStatement.setNull(5, Types.INTEGER);
271  } else {
272  preparedStatement.setString(5, eamCase.getCaseNumber());
273  }
274  if ("".equals(eamCase.getExaminerName())) {
275  preparedStatement.setNull(6, Types.INTEGER);
276  } else {
277  preparedStatement.setString(6, eamCase.getExaminerName());
278  }
279  if ("".equals(eamCase.getExaminerEmail())) {
280  preparedStatement.setNull(7, Types.INTEGER);
281  } else {
282  preparedStatement.setString(7, eamCase.getExaminerEmail());
283  }
284  if ("".equals(eamCase.getExaminerPhone())) {
285  preparedStatement.setNull(8, Types.INTEGER);
286  } else {
287  preparedStatement.setString(8, eamCase.getExaminerPhone());
288  }
289  if ("".equals(eamCase.getNotes())) {
290  preparedStatement.setNull(9, Types.INTEGER);
291  } else {
292  preparedStatement.setString(9, eamCase.getNotes());
293  }
294 
295  preparedStatement.executeUpdate();
296  //update the case in the caches
297  resultSet = preparedStatement.getGeneratedKeys();
298  if (!resultSet.next()) {
299  throw new EamDbException(String.format("Failed to INSERT case %s in central repo", eamCase.getCaseUUID()));
300  }
301  int caseID = resultSet.getInt(1); //last_insert_rowid()
302  CorrelationCase correlationCase = new CorrelationCase(caseID, eamCase.getCaseUUID(), eamCase.getOrg(),
303  eamCase.getDisplayName(), eamCase.getCreationDate(), eamCase.getCaseNumber(), eamCase.getExaminerName(),
304  eamCase.getExaminerEmail(), eamCase.getExaminerPhone(), eamCase.getNotes());
305  caseCacheByUUID.put(eamCase.getCaseUUID(), correlationCase);
306  caseCacheById.put(caseID, correlationCase);
307  } catch (SQLException ex) {
308  throw new EamDbException("Error inserting new case.", ex); // NON-NLS
309  } finally {
310  EamDbUtil.closeResultSet(resultSet);
311  EamDbUtil.closeStatement(preparedStatement);
313  }
314 
315  // get a new version with the updated ID
316  return getCaseByUUID(eamCase.getCaseUUID());
317  }
318 
324  @Override
325  public CorrelationCase newCase(Case autopsyCase) throws EamDbException {
326  if (autopsyCase == null) {
327  throw new EamDbException("Case is null");
328  }
329 
330  CorrelationCase curCeCase = new CorrelationCase(
331  -1,
332  autopsyCase.getName(), // unique case ID
334  autopsyCase.getDisplayName(),
335  autopsyCase.getCreatedDate(),
336  autopsyCase.getNumber(),
337  autopsyCase.getExaminer(),
338  autopsyCase.getExaminerEmail(),
339  autopsyCase.getExaminerPhone(),
340  autopsyCase.getCaseNotes());
341  return newCase(curCeCase);
342  }
343 
344  @Override
345  public CorrelationCase getCase(Case autopsyCase) throws EamDbException {
346  return getCaseByUUID(autopsyCase.getName());
347  }
348 
354  @Override
355  public void updateCase(CorrelationCase eamCase) throws EamDbException {
356  if (eamCase == null) {
357  throw new EamDbException("Correlation case is null");
358  }
359 
360  Connection conn = connect();
361 
362  PreparedStatement preparedStatement = null;
363  String sql = "UPDATE cases "
364  + "SET org_id=?, case_name=?, creation_date=?, case_number=?, examiner_name=?, examiner_email=?, examiner_phone=?, notes=? "
365  + "WHERE case_uid=?";
366 
367  try {
368  preparedStatement = conn.prepareStatement(sql);
369 
370  if (null == eamCase.getOrg()) {
371  preparedStatement.setNull(1, Types.INTEGER);
372  } else {
373  preparedStatement.setInt(1, eamCase.getOrg().getOrgID());
374  }
375  preparedStatement.setString(2, eamCase.getDisplayName());
376  preparedStatement.setString(3, eamCase.getCreationDate());
377 
378  if ("".equals(eamCase.getCaseNumber())) {
379  preparedStatement.setNull(4, Types.INTEGER);
380  } else {
381  preparedStatement.setString(4, eamCase.getCaseNumber());
382  }
383  if ("".equals(eamCase.getExaminerName())) {
384  preparedStatement.setNull(5, Types.INTEGER);
385  } else {
386  preparedStatement.setString(5, eamCase.getExaminerName());
387  }
388  if ("".equals(eamCase.getExaminerEmail())) {
389  preparedStatement.setNull(6, Types.INTEGER);
390  } else {
391  preparedStatement.setString(6, eamCase.getExaminerEmail());
392  }
393  if ("".equals(eamCase.getExaminerPhone())) {
394  preparedStatement.setNull(7, Types.INTEGER);
395  } else {
396  preparedStatement.setString(7, eamCase.getExaminerPhone());
397  }
398  if ("".equals(eamCase.getNotes())) {
399  preparedStatement.setNull(8, Types.INTEGER);
400  } else {
401  preparedStatement.setString(8, eamCase.getNotes());
402  }
403 
404  preparedStatement.setString(9, eamCase.getCaseUUID());
405 
406  preparedStatement.executeUpdate();
407  //update the case in the cache
408  caseCacheById.put(eamCase.getID(), eamCase);
409  caseCacheByUUID.put(eamCase.getCaseUUID(), eamCase);
410  } catch (SQLException ex) {
411  throw new EamDbException("Error updating case.", ex); // NON-NLS
412  } finally {
413  EamDbUtil.closeStatement(preparedStatement);
415  }
416  }
417 
425  @Override
426  public CorrelationCase getCaseByUUID(String caseUUID) throws EamDbException {
427  try {
428  return caseCacheByUUID.get(caseUUID, () -> getCaseByUUIDFromCr(caseUUID));
429  } catch (CacheLoader.InvalidCacheLoadException ignored) {
430  //lambda valueloader returned a null value and cache can not store null values this is normal if the case does not exist in the central repo yet
431  return null;
432  } catch (ExecutionException ex) {
433  throw new EamDbException("Error getting autopsy case from Central repo", ex);
434  }
435  }
436 
444  private CorrelationCase getCaseByUUIDFromCr(String caseUUID) throws EamDbException {
445  Connection conn = connect();
446 
447  CorrelationCase eamCaseResult = null;
448  PreparedStatement preparedStatement = null;
449  ResultSet resultSet = null;
450 
451  String sql = "SELECT cases.id as case_id, case_uid, case_name, creation_date, case_number, examiner_name, "
452  + "examiner_email, examiner_phone, notes, organizations.id as org_id, org_name, poc_name, poc_email, poc_phone "
453  + "FROM cases "
454  + "LEFT JOIN organizations ON cases.org_id=organizations.id "
455  + "WHERE case_uid=?";
456 
457  try {
458  preparedStatement = conn.prepareStatement(sql);
459  preparedStatement.setString(1, caseUUID);
460  resultSet = preparedStatement.executeQuery();
461  if (resultSet.next()) {
462  eamCaseResult = getEamCaseFromResultSet(resultSet);
463  }
464  if (eamCaseResult != null) {
465  //Update the version in the other cache
466  caseCacheById.put(eamCaseResult.getID(), eamCaseResult);
467  }
468  } catch (SQLException ex) {
469  throw new EamDbException("Error getting case details.", ex); // NON-NLS
470  } finally {
471  EamDbUtil.closeStatement(preparedStatement);
472  EamDbUtil.closeResultSet(resultSet);
474  }
475 
476  return eamCaseResult;
477  }
478 
486  @Override
487  public CorrelationCase getCaseById(int caseId) throws EamDbException {
488  try {
489  return caseCacheById.get(caseId, () -> getCaseByIdFromCr(caseId));
490  } catch (CacheLoader.InvalidCacheLoadException ignored) {
491  //lambda valueloader returned a null value and cache can not store null values this is normal if the case does not exist in the central repo yet
492  return null;
493  } catch (ExecutionException ex) {
494  throw new EamDbException("Error getting autopsy case from Central repo", ex);
495  }
496  }
497 
505  private CorrelationCase getCaseByIdFromCr(int caseId) throws EamDbException {
506  Connection conn = connect();
507 
508  CorrelationCase eamCaseResult = null;
509  PreparedStatement preparedStatement = null;
510  ResultSet resultSet = null;
511 
512  String sql = "SELECT cases.id as case_id, case_uid, case_name, creation_date, case_number, examiner_name, "
513  + "examiner_email, examiner_phone, notes, organizations.id as org_id, org_name, poc_name, poc_email, poc_phone "
514  + "FROM cases "
515  + "LEFT JOIN organizations ON cases.org_id=organizations.id "
516  + "WHERE cases.id=?";
517  try {
518  preparedStatement = conn.prepareStatement(sql);
519  preparedStatement.setInt(1, caseId);
520  resultSet = preparedStatement.executeQuery();
521  if (resultSet.next()) {
522  eamCaseResult = getEamCaseFromResultSet(resultSet);
523  }
524  if (eamCaseResult != null) {
525  //Update the version in the other cache
526  caseCacheByUUID.put(eamCaseResult.getCaseUUID(), eamCaseResult);
527  }
528  } catch (SQLException ex) {
529  throw new EamDbException("Error getting case details.", ex); // NON-NLS
530  } finally {
531  EamDbUtil.closeStatement(preparedStatement);
532  EamDbUtil.closeResultSet(resultSet);
534  }
535 
536  return eamCaseResult;
537  }
538 
544  @Override
545  public List<CorrelationCase> getCases() throws EamDbException {
546  Connection conn = connect();
547 
548  List<CorrelationCase> cases = new ArrayList<>();
549  CorrelationCase eamCaseResult;
550  PreparedStatement preparedStatement = null;
551  ResultSet resultSet = null;
552 
553  String sql = "SELECT cases.id as case_id, case_uid, case_name, creation_date, case_number, examiner_name, "
554  + "examiner_email, examiner_phone, notes, organizations.id as org_id, org_name, poc_name, poc_email, poc_phone "
555  + "FROM cases "
556  + "LEFT JOIN organizations ON cases.org_id=organizations.id";
557 
558  try {
559  preparedStatement = conn.prepareStatement(sql);
560  resultSet = preparedStatement.executeQuery();
561  while (resultSet.next()) {
562  eamCaseResult = getEamCaseFromResultSet(resultSet);
563  cases.add(eamCaseResult);
564  }
565  } catch (SQLException ex) {
566  throw new EamDbException("Error getting all cases.", ex); // NON-NLS
567  } finally {
568  EamDbUtil.closeStatement(preparedStatement);
569  EamDbUtil.closeResultSet(resultSet);
571  }
572 
573  return cases;
574  }
575 
586  private static String getDataSourceByDSObjectIdCacheKey(int caseId, Long dataSourceObjectId) {
587  return "Case" + caseId + "DsObjectId" + dataSourceObjectId; //NON-NLS
588  }
589 
599  private static String getDataSourceByIdCacheKey(int caseId, int dataSourceId) {
600  return "Case" + caseId + "Id" + dataSourceId; //NON-NLS
601  }
602 
608  @Override
609  public CorrelationDataSource newDataSource(CorrelationDataSource eamDataSource) throws EamDbException {
610  if (eamDataSource.getCaseID() == -1) {
611  throw new EamDbException("Case ID is -1");
612  } else if (eamDataSource.getID() != -1) {
613  // This data source is already in the central repo
614  return eamDataSource;
615  }
616  Connection conn = connect();
617 
618  PreparedStatement preparedStatement = null;
619 
620  String sql = "INSERT INTO data_sources(device_id, case_id, name, datasource_obj_id) VALUES (?, ?, ?, ?) "
621  + getConflictClause();
622  ResultSet resultSet = null;
623  try {
624  preparedStatement = conn.prepareStatement(sql, Statement.RETURN_GENERATED_KEYS);
625 
626  preparedStatement.setString(1, eamDataSource.getDeviceID());
627  preparedStatement.setInt(2, eamDataSource.getCaseID());
628  preparedStatement.setString(3, eamDataSource.getName());
629  preparedStatement.setLong(4, eamDataSource.getDataSourceObjectID());
630 
631  preparedStatement.executeUpdate();
632  resultSet = preparedStatement.getGeneratedKeys();
633  if (!resultSet.next()) {
634  throw new EamDbException(String.format("Failed to INSERT data source %s in central repo", eamDataSource.getName()));
635  }
636  int dataSourceId = resultSet.getInt(1); //last_insert_rowid()
637  CorrelationDataSource dataSource = new CorrelationDataSource(eamDataSource.getCaseID(), dataSourceId, eamDataSource.getDeviceID(), eamDataSource.getName(), eamDataSource.getDataSourceObjectID());
638  dataSourceCacheByDsObjectId.put(getDataSourceByDSObjectIdCacheKey(dataSource.getCaseID(), dataSource.getDataSourceObjectID()), dataSource);
639  dataSourceCacheById.put(getDataSourceByIdCacheKey(dataSource.getCaseID(), dataSource.getID()), dataSource);
640  return dataSource;
641  } catch (SQLException ex) {
642  throw new EamDbException("Error inserting new data source.", ex); // NON-NLS
643  } finally {
644  EamDbUtil.closeResultSet(resultSet);
645  EamDbUtil.closeStatement(preparedStatement);
647  }
648  }
649 
661  @Override
662  public CorrelationDataSource getDataSource(CorrelationCase correlationCase, Long dataSourceObjectId) throws EamDbException {
663 
664  if (correlationCase == null) {
665  throw new EamDbException("Correlation case is null");
666  }
667  try {
668  return dataSourceCacheByDsObjectId.get(getDataSourceByDSObjectIdCacheKey(correlationCase.getID(), dataSourceObjectId), () -> getDataSourceFromCr(correlationCase, dataSourceObjectId));
669  } catch (CacheLoader.InvalidCacheLoadException ignored) {
670  //lambda valueloader returned a null value and cache can not store null values this is normal if the dataSource does not exist in the central repo yet
671  return null;
672  } catch (ExecutionException ex) {
673  throw new EamDbException("Error getting data source from central repository", ex);
674  }
675  }
676 
689  private CorrelationDataSource getDataSourceFromCr(CorrelationCase correlationCase, Long dataSourceObjectId) throws EamDbException {
690  Connection conn = connect();
691 
692  CorrelationDataSource eamDataSourceResult = null;
693  PreparedStatement preparedStatement = null;
694  ResultSet resultSet = null;
695 
696  String sql = "SELECT * FROM data_sources WHERE datasource_obj_id=? AND case_id=?"; // NON-NLS
697 
698  try {
699  preparedStatement = conn.prepareStatement(sql);
700  preparedStatement.setLong(1, dataSourceObjectId);
701  preparedStatement.setInt(2, correlationCase.getID());
702  resultSet = preparedStatement.executeQuery();
703  if (resultSet.next()) {
704  eamDataSourceResult = getEamDataSourceFromResultSet(resultSet);
705  }
706  if (eamDataSourceResult != null) {
707  dataSourceCacheById.put(getDataSourceByIdCacheKey(correlationCase.getID(), eamDataSourceResult.getID()), eamDataSourceResult);
708  }
709  } catch (SQLException ex) {
710  throw new EamDbException("Error getting data source.", ex); // NON-NLS
711  } finally {
712  EamDbUtil.closeStatement(preparedStatement);
713  EamDbUtil.closeResultSet(resultSet);
715  }
716 
717  return eamDataSourceResult;
718  }
719 
729  @Override
730  public CorrelationDataSource getDataSourceById(CorrelationCase correlationCase, int dataSourceId) throws EamDbException {
731  if (correlationCase == null) {
732  throw new EamDbException("Correlation case is null");
733  }
734  try {
735  return dataSourceCacheById.get(getDataSourceByIdCacheKey(correlationCase.getID(), dataSourceId), () -> getDataSourceByIdFromCr(correlationCase, dataSourceId));
736  } catch (CacheLoader.InvalidCacheLoadException ignored) {
737  //lambda valueloader returned a null value and cache can not store null values this is normal if the dataSource does not exist in the central repo yet
738  return null;
739  } catch (ExecutionException ex) {
740  throw new EamDbException("Error getting data source from central repository", ex);
741  }
742  }
743 
753  private CorrelationDataSource getDataSourceByIdFromCr(CorrelationCase correlationCase, int dataSourceId) throws EamDbException {
754  Connection conn = connect();
755 
756  CorrelationDataSource eamDataSourceResult = null;
757  PreparedStatement preparedStatement = null;
758  ResultSet resultSet = null;
759 
760  String sql = "SELECT * FROM data_sources WHERE id=? AND case_id=?"; // NON-NLS
761 
762  try {
763  preparedStatement = conn.prepareStatement(sql);
764  preparedStatement.setInt(1, dataSourceId);
765  preparedStatement.setInt(2, correlationCase.getID());
766  resultSet = preparedStatement.executeQuery();
767  if (resultSet.next()) {
768  eamDataSourceResult = getEamDataSourceFromResultSet(resultSet);
769  }
770  if (eamDataSourceResult != null) {
771  dataSourceCacheByDsObjectId.put(getDataSourceByDSObjectIdCacheKey(correlationCase.getID(), eamDataSourceResult.getDataSourceObjectID()), eamDataSourceResult);
772  }
773  } catch (SQLException ex) {
774  throw new EamDbException("Error getting data source.", ex); // NON-NLS
775  } finally {
776  EamDbUtil.closeStatement(preparedStatement);
777  EamDbUtil.closeResultSet(resultSet);
779  }
780 
781  return eamDataSourceResult;
782  }
783 
789  @Override
790  public List<CorrelationDataSource> getDataSources() throws EamDbException {
791  Connection conn = connect();
792 
793  List<CorrelationDataSource> dataSources = new ArrayList<>();
794  CorrelationDataSource eamDataSourceResult;
795  PreparedStatement preparedStatement = null;
796  ResultSet resultSet = null;
797 
798  String sql = "SELECT * FROM data_sources";
799 
800  try {
801  preparedStatement = conn.prepareStatement(sql);
802  resultSet = preparedStatement.executeQuery();
803  while (resultSet.next()) {
804  eamDataSourceResult = getEamDataSourceFromResultSet(resultSet);
805  dataSources.add(eamDataSourceResult);
806  }
807  } catch (SQLException ex) {
808  throw new EamDbException("Error getting all data sources.", ex); // NON-NLS
809  } finally {
810  EamDbUtil.closeStatement(preparedStatement);
811  EamDbUtil.closeResultSet(resultSet);
813  }
814 
815  return dataSources;
816  }
817 
824  @Override
825  public void addArtifactInstance(CorrelationAttributeInstance eamArtifact) throws EamDbException {
826  checkAddArtifactInstanceNulls(eamArtifact);
827 
828  Connection conn = connect();
829 
830  PreparedStatement preparedStatement = null;
831 
832  // @@@ We should cache the case and data source IDs in memory
833  String tableName = EamDbUtil.correlationTypeToInstanceTableName(eamArtifact.getCorrelationType());
834  String sql
835  = "INSERT INTO "
836  + tableName
837  + "(case_id, data_source_id, value, file_path, known_status, comment, file_obj_id) "
838  + "VALUES (?, ?, ?, ?, ?, ?, ?) "
839  + getConflictClause();
840 
841  try {
842  preparedStatement = conn.prepareStatement(sql);
843 
844  if (!eamArtifact.getCorrelationValue().isEmpty()) {
845  preparedStatement.setInt(1, eamArtifact.getCorrelationCase().getID());
846  preparedStatement.setInt(2, eamArtifact.getCorrelationDataSource().getID());
847  preparedStatement.setString(3, eamArtifact.getCorrelationValue());
848  preparedStatement.setString(4, eamArtifact.getFilePath().toLowerCase());
849  preparedStatement.setByte(5, eamArtifact.getKnownStatus().getFileKnownValue());
850 
851  if ("".equals(eamArtifact.getComment())) {
852  preparedStatement.setNull(6, Types.INTEGER);
853  } else {
854  preparedStatement.setString(6, eamArtifact.getComment());
855  }
856  preparedStatement.setLong(7, eamArtifact.getFileObjectId());
857 
858  preparedStatement.executeUpdate();
859  }
860 
861  } catch (SQLException ex) {
862  throw new EamDbException("Error inserting new artifact into artifacts table.", ex); // NON-NLS
863  } finally {
864  EamDbUtil.closeStatement(preparedStatement);
866  }
867  }
868 
869  private void checkAddArtifactInstanceNulls(CorrelationAttributeInstance eamArtifact) throws EamDbException {
870  if (eamArtifact == null) {
871  throw new EamDbException("CorrelationAttribute is null");
872  }
873  if (eamArtifact.getCorrelationType() == null) {
874  throw new EamDbException("Correlation type is null");
875  }
876  if (eamArtifact.getCorrelationValue() == null) {
877  throw new EamDbException("Correlation value is null");
878  }
879  if (eamArtifact.getCorrelationValue().length() >= MAX_VALUE_LENGTH) {
880  throw new EamDbException("Artifact value too long for central repository."
881  + "\nCorrelationArtifact ID: " + eamArtifact.getID()
882  + "\nCorrelationArtifact Type: " + eamArtifact.getCorrelationType().getDisplayName()
883  + "\nCorrelationArtifact Value: " + eamArtifact.getCorrelationValue());
884 
885  }
886  if (eamArtifact.getCorrelationCase() == null) {
887  throw new EamDbException("CorrelationAttributeInstance case is null");
888  }
889  if (eamArtifact.getCorrelationDataSource() == null) {
890  throw new EamDbException("CorrelationAttributeInstance data source is null");
891  }
892  if (eamArtifact.getKnownStatus() == null) {
893  throw new EamDbException("CorrelationAttributeInstance known status is null");
894  }
895  }
896 
908  @Override
909  public List<CorrelationAttributeInstance> getArtifactInstancesByTypeValue(CorrelationAttributeInstance.Type aType, String value) throws EamDbException, CorrelationAttributeNormalizationException {
910 
911  String normalizedValue = CorrelationAttributeNormalizer.normalize(aType, value);
912 
913  Connection conn = connect();
914 
915  List<CorrelationAttributeInstance> artifactInstances = new ArrayList<>();
916 
917  CorrelationAttributeInstance artifactInstance;
918  PreparedStatement preparedStatement = null;
919  ResultSet resultSet = null;
920 
921  String tableName = EamDbUtil.correlationTypeToInstanceTableName(aType);
922  String sql
923  = "SELECT "
924  + tableName
925  + ".id,"
926  + tableName
927  + ".value,"
928  + tableName
929  + ".file_obj_id,"
930  + " cases.case_name, cases.case_uid, data_sources.id AS data_source_id, data_sources.name, device_id, file_path, known_status, comment, data_sources.case_id, data_sources.datasource_obj_id FROM "
931  + tableName
932  + " LEFT JOIN cases ON "
933  + tableName
934  + ".case_id=cases.id"
935  + " LEFT JOIN data_sources ON "
936  + tableName
937  + ".data_source_id=data_sources.id"
938  + " WHERE value=?";
939 
940  try {
941  preparedStatement = conn.prepareStatement(sql);
942  preparedStatement.setString(1, normalizedValue);
943  resultSet = preparedStatement.executeQuery();
944  while (resultSet.next()) {
945  artifactInstance = getEamArtifactInstanceFromResultSet(resultSet, aType);
946  artifactInstances.add(artifactInstance);
947  }
948  } catch (SQLException ex) {
949  throw new EamDbException("Error getting artifact instances by artifactType and artifactValue.", ex); // NON-NLS
950  } finally {
951  EamDbUtil.closeStatement(preparedStatement);
952  EamDbUtil.closeResultSet(resultSet);
954  }
955 
956  return artifactInstances;
957  }
958 
970  @Override
971  public List<CorrelationAttributeInstance> getArtifactInstancesByPath(CorrelationAttributeInstance.Type aType, String filePath) throws EamDbException {
972  if (aType == null) {
973  throw new EamDbException("Correlation type is null");
974  }
975  if (filePath == null) {
976  throw new EamDbException("Correlation value is null");
977  }
978  Connection conn = connect();
979 
980  List<CorrelationAttributeInstance> artifactInstances = new ArrayList<>();
981 
982  CorrelationAttributeInstance artifactInstance;
983  PreparedStatement preparedStatement = null;
984  ResultSet resultSet = null;
985 
986  String tableName = EamDbUtil.correlationTypeToInstanceTableName(aType);
987  String sql
988  = "SELECT "
989  + tableName
990  + ".id, "
991  + tableName
992  + ".value,"
993  + tableName
994  + ".file_obj_id,"
995  + " cases.case_name, cases.case_uid, data_sources.id AS data_source_id, data_sources.name, device_id, file_path, known_status, comment, data_sources.case_id, data_sources.datasource_obj_id FROM "
996  + tableName
997  + " LEFT JOIN cases ON "
998  + tableName
999  + ".case_id=cases.id"
1000  + " LEFT JOIN data_sources ON "
1001  + tableName
1002  + ".data_source_id=data_sources.id"
1003  + " WHERE file_path=?";
1004 
1005  try {
1006  preparedStatement = conn.prepareStatement(sql);
1007  preparedStatement.setString(1, filePath.toLowerCase());
1008  resultSet = preparedStatement.executeQuery();
1009  while (resultSet.next()) {
1010  try {
1011  artifactInstance = getEamArtifactInstanceFromResultSet(resultSet, aType);
1012  artifactInstances.add(artifactInstance);
1014  logger.log(Level.INFO, "Unable to get artifact instance from resultset.", ex);
1015  }
1016  }
1017  } catch (SQLException ex) {
1018  throw new EamDbException("Error getting artifact instances by artifactType and artifactValue.", ex); // NON-NLS
1019  } finally {
1020  EamDbUtil.closeStatement(preparedStatement);
1021  EamDbUtil.closeResultSet(resultSet);
1022  EamDbUtil.closeConnection(conn);
1023  }
1024 
1025  return artifactInstances;
1026  }
1027 
1038  @Override
1039  public Long getCountArtifactInstancesByTypeValue(CorrelationAttributeInstance.Type aType, String value) throws EamDbException, CorrelationAttributeNormalizationException {
1040  String normalizedValue = CorrelationAttributeNormalizer.normalize(aType, value);
1041 
1042  Connection conn = connect();
1043 
1044  Long instanceCount = 0L;
1045  PreparedStatement preparedStatement = null;
1046  ResultSet resultSet = null;
1047 
1048  String tableName = EamDbUtil.correlationTypeToInstanceTableName(aType);
1049  String sql
1050  = "SELECT count(*) FROM "
1051  + tableName
1052  + " WHERE value=?";
1053 
1054  try {
1055  preparedStatement = conn.prepareStatement(sql);
1056  preparedStatement.setString(1, normalizedValue);
1057  resultSet = preparedStatement.executeQuery();
1058  resultSet.next();
1059  instanceCount = resultSet.getLong(1);
1060  } catch (SQLException ex) {
1061  throw new EamDbException("Error getting count of artifact instances by artifactType and artifactValue.", ex); // NON-NLS
1062  } finally {
1063  EamDbUtil.closeStatement(preparedStatement);
1064  EamDbUtil.closeResultSet(resultSet);
1065  EamDbUtil.closeConnection(conn);
1066  }
1067 
1068  return instanceCount;
1069  }
1070 
1071  @Override
1072  public int getFrequencyPercentage(CorrelationAttributeInstance corAttr) throws EamDbException, CorrelationAttributeNormalizationException {
1073  if (corAttr == null) {
1074  throw new EamDbException("CorrelationAttribute is null");
1075  }
1076  Double uniqueTypeValueTuples = getCountUniqueCaseDataSourceTuplesHavingTypeValue(corAttr.getCorrelationType(), corAttr.getCorrelationValue()).doubleValue();
1077  Double uniqueCaseDataSourceTuples = getCountUniqueDataSources().doubleValue();
1078  Double commonalityPercentage = uniqueTypeValueTuples / uniqueCaseDataSourceTuples * 100;
1079  return commonalityPercentage.intValue();
1080  }
1081 
1092  @Override
1093  public Long getCountUniqueCaseDataSourceTuplesHavingTypeValue(CorrelationAttributeInstance.Type aType, String value) throws EamDbException, CorrelationAttributeNormalizationException {
1094  String normalizedValue = CorrelationAttributeNormalizer.normalize(aType, value);
1095 
1096  Connection conn = connect();
1097 
1098  Long instanceCount = 0L;
1099  PreparedStatement preparedStatement = null;
1100  ResultSet resultSet = null;
1101 
1102  String tableName = EamDbUtil.correlationTypeToInstanceTableName(aType);
1103  String sql
1104  = "SELECT count(*) FROM (SELECT DISTINCT case_id, data_source_id FROM "
1105  + tableName
1106  + " WHERE value=?) AS "
1107  + tableName
1108  + "_distinct_case_data_source_tuple";
1109 
1110  try {
1111  preparedStatement = conn.prepareStatement(sql);
1112  preparedStatement.setString(1, normalizedValue);
1113  resultSet = preparedStatement.executeQuery();
1114  resultSet.next();
1115  instanceCount = resultSet.getLong(1);
1116  } catch (SQLException ex) {
1117  throw new EamDbException("Error counting unique caseDisplayName/dataSource tuples having artifactType and artifactValue.", ex); // NON-NLS
1118  } finally {
1119  EamDbUtil.closeStatement(preparedStatement);
1120  EamDbUtil.closeResultSet(resultSet);
1121  EamDbUtil.closeConnection(conn);
1122  }
1123 
1124  return instanceCount;
1125  }
1126 
1127  @Override
1128  public Long getCountUniqueDataSources() throws EamDbException {
1129  Connection conn = connect();
1130 
1131  Long instanceCount = 0L;
1132  PreparedStatement preparedStatement = null;
1133  ResultSet resultSet = null;
1134 
1135  String stmt = "SELECT count(*) FROM data_sources";
1136 
1137  try {
1138  preparedStatement = conn.prepareStatement(stmt);
1139  resultSet = preparedStatement.executeQuery();
1140  resultSet.next();
1141  instanceCount = resultSet.getLong(1);
1142  } catch (SQLException ex) {
1143  throw new EamDbException("Error counting data sources.", ex); // NON-NLS
1144  } finally {
1145  EamDbUtil.closeStatement(preparedStatement);
1146  EamDbUtil.closeResultSet(resultSet);
1147  EamDbUtil.closeConnection(conn);
1148  }
1149 
1150  return instanceCount;
1151  }
1152 
1164  @Override
1165  public Long getCountArtifactInstancesByCaseDataSource(CorrelationDataSource correlationDataSource) throws EamDbException {
1166  Connection conn = connect();
1167 
1168  Long instanceCount = 0L;
1169  List<CorrelationAttributeInstance.Type> artifactTypes = getDefinedCorrelationTypes();
1170  PreparedStatement preparedStatement = null;
1171  ResultSet resultSet = null;
1172 
1173  //Create query to get count of all instances in the database for the specified case specific data source
1174  String sql = "SELECT 0 ";
1175 
1176  for (CorrelationAttributeInstance.Type type : artifactTypes) {
1177  String table_name = EamDbUtil.correlationTypeToInstanceTableName(type);
1178  sql
1179  += "+ (SELECT count(*) FROM "
1180  + table_name
1181  + " WHERE data_source_id=" + correlationDataSource.getID() + ")";
1182  }
1183  try {
1184  preparedStatement = conn.prepareStatement(sql);
1185 
1186  resultSet = preparedStatement.executeQuery();
1187  resultSet.next();
1188  instanceCount = resultSet.getLong(1);
1189  } catch (SQLException ex) {
1190  throw new EamDbException("Error counting artifact instances by caseName/dataSource.", ex); // NON-NLS
1191  } finally {
1192  EamDbUtil.closeStatement(preparedStatement);
1193  EamDbUtil.closeResultSet(resultSet);
1194  EamDbUtil.closeConnection(conn);
1195  }
1196 
1197  return instanceCount;
1198  }
1199 
1207  @Override
1208  public void addAttributeInstanceBulk(CorrelationAttributeInstance eamArtifact) throws EamDbException {
1209 
1210  if (eamArtifact.getCorrelationType() == null) {
1211  throw new EamDbException("Correlation type is null");
1212  }
1213 
1214  synchronized (bulkArtifacts) {
1215  bulkArtifacts.get(EamDbUtil.correlationTypeToInstanceTableName(eamArtifact.getCorrelationType())).add(eamArtifact);
1216  bulkArtifactsCount++;
1217 
1218  if (bulkArtifactsCount >= bulkArtifactsThreshold) {
1219  commitAttributeInstancesBulk();
1220  }
1221  }
1222  }
1223 
1229  protected abstract String getConflictClause();
1230 
1235  @Override
1236  public void commitAttributeInstancesBulk() throws EamDbException {
1237  List<CorrelationAttributeInstance.Type> artifactTypes = getDefinedCorrelationTypes();
1238 
1239  Connection conn = connect();
1240  PreparedStatement bulkPs = null;
1241 
1242  try {
1243  synchronized (bulkArtifacts) {
1244  if (bulkArtifactsCount == 0) {
1245  return;
1246  }
1247 
1248  for (String tableName : bulkArtifacts.keySet()) {
1249 
1250  String sql
1251  = "INSERT INTO "
1252  + tableName
1253  + " (case_id, data_source_id, value, file_path, known_status, comment, file_obj_id) "
1254  + "VALUES ((SELECT id FROM cases WHERE case_uid=? LIMIT 1), "
1255  + "(SELECT id FROM data_sources WHERE datasource_obj_id=? AND case_id=? LIMIT 1), ?, ?, ?, ?, ?) "
1256  + getConflictClause();
1257 
1258  bulkPs = conn.prepareStatement(sql);
1259 
1260  Collection<CorrelationAttributeInstance> eamArtifacts = bulkArtifacts.get(tableName);
1261  for (CorrelationAttributeInstance eamArtifact : eamArtifacts) {
1262 
1263  if (!eamArtifact.getCorrelationValue().isEmpty()) {
1264 
1265  if (eamArtifact.getCorrelationCase() == null) {
1266  throw new EamDbException("CorrelationAttributeInstance case is null for: "
1267  + "\n\tCorrelationArtifact ID: " + eamArtifact.getID()
1268  + "\n\tCorrelationArtifact Type: " + eamArtifact.getCorrelationType().getDisplayName()
1269  + "\n\tCorrelationArtifact Value: " + eamArtifact.getCorrelationValue());
1270  }
1271  if (eamArtifact.getCorrelationDataSource() == null) {
1272  throw new EamDbException("CorrelationAttributeInstance data source is null for: "
1273  + "\n\tCorrelationArtifact ID: " + eamArtifact.getID()
1274  + "\n\tCorrelationArtifact Type: " + eamArtifact.getCorrelationType().getDisplayName()
1275  + "\n\tCorrelationArtifact Value: " + eamArtifact.getCorrelationValue());
1276  }
1277  if (eamArtifact.getKnownStatus() == null) {
1278  throw new EamDbException("CorrelationAttributeInstance known status is null for: "
1279  + "\n\tCorrelationArtifact ID: " + eamArtifact.getID()
1280  + "\n\tCorrelationArtifact Type: " + eamArtifact.getCorrelationType().getDisplayName()
1281  + "\n\tCorrelationArtifact Value: " + eamArtifact.getCorrelationValue()
1282  + "\n\tEam Instance: "
1283  + "\n\t\tCaseId: " + eamArtifact.getCorrelationDataSource().getCaseID()
1284  + "\n\t\tDeviceID: " + eamArtifact.getCorrelationDataSource().getDeviceID());
1285  }
1286 
1287  if (eamArtifact.getCorrelationValue().length() < MAX_VALUE_LENGTH) {
1288  bulkPs.setString(1, eamArtifact.getCorrelationCase().getCaseUUID());
1289  bulkPs.setLong(2, eamArtifact.getCorrelationDataSource().getDataSourceObjectID());
1290  bulkPs.setInt(3, eamArtifact.getCorrelationDataSource().getCaseID());
1291  bulkPs.setString(4, eamArtifact.getCorrelationValue());
1292  bulkPs.setString(5, eamArtifact.getFilePath());
1293  bulkPs.setByte(6, eamArtifact.getKnownStatus().getFileKnownValue());
1294  if ("".equals(eamArtifact.getComment())) {
1295  bulkPs.setNull(7, Types.INTEGER);
1296  } else {
1297  bulkPs.setString(7, eamArtifact.getComment());
1298  }
1299  bulkPs.setLong(8, eamArtifact.getFileObjectId());
1300  bulkPs.addBatch();
1301  } else {
1302  logger.log(Level.WARNING, ("Artifact value too long for central repository."
1303  + "\n\tCorrelationArtifact ID: " + eamArtifact.getID()
1304  + "\n\tCorrelationArtifact Type: " + eamArtifact.getCorrelationType().getDisplayName()
1305  + "\n\tCorrelationArtifact Value: " + eamArtifact.getCorrelationValue())
1306  + "\n\tEam Instance: "
1307  + "\n\t\tCaseId: " + eamArtifact.getCorrelationDataSource().getCaseID()
1308  + "\n\t\tDeviceID: " + eamArtifact.getCorrelationDataSource().getDeviceID()
1309  + "\n\t\tFilePath: " + eamArtifact.getFilePath());
1310  }
1311  }
1312 
1313  }
1314 
1315  bulkPs.executeBatch();
1316  bulkArtifacts.get(tableName).clear();
1317  }
1318 
1319  TimingMetric timingMetric = HealthMonitor.getTimingMetric("Correlation Engine: Bulk insert");
1320  HealthMonitor.submitTimingMetric(timingMetric);
1321 
1322  // Reset state
1323  bulkArtifactsCount = 0;
1324  }
1325  } catch (SQLException ex) {
1326  throw new EamDbException("Error inserting bulk artifacts.", ex); // NON-NLS
1327  } finally {
1328  EamDbUtil.closeStatement(bulkPs);
1329  EamDbUtil.closeConnection(conn);
1330  }
1331  }
1332 
1336  @Override
1337  public void bulkInsertCases(List<CorrelationCase> cases) throws EamDbException {
1338  if (cases == null) {
1339  throw new EamDbException("cases argument is null");
1340  }
1341 
1342  if (cases.isEmpty()) {
1343  return;
1344  }
1345 
1346  Connection conn = connect();
1347 
1348  int counter = 0;
1349  PreparedStatement bulkPs = null;
1350  try {
1351  String sql = "INSERT INTO cases(case_uid, org_id, case_name, creation_date, case_number, "
1352  + "examiner_name, examiner_email, examiner_phone, notes) "
1353  + "VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?) "
1354  + getConflictClause();
1355  bulkPs = conn.prepareStatement(sql);
1356 
1357  for (CorrelationCase eamCase : cases) {
1358  bulkPs.setString(1, eamCase.getCaseUUID());
1359  if (null == eamCase.getOrg()) {
1360  bulkPs.setNull(2, Types.INTEGER);
1361  } else {
1362  bulkPs.setInt(2, eamCase.getOrg().getOrgID());
1363  }
1364  bulkPs.setString(3, eamCase.getDisplayName());
1365  bulkPs.setString(4, eamCase.getCreationDate());
1366 
1367  if ("".equals(eamCase.getCaseNumber())) {
1368  bulkPs.setNull(5, Types.INTEGER);
1369  } else {
1370  bulkPs.setString(5, eamCase.getCaseNumber());
1371  }
1372  if ("".equals(eamCase.getExaminerName())) {
1373  bulkPs.setNull(6, Types.INTEGER);
1374  } else {
1375  bulkPs.setString(6, eamCase.getExaminerName());
1376  }
1377  if ("".equals(eamCase.getExaminerEmail())) {
1378  bulkPs.setNull(7, Types.INTEGER);
1379  } else {
1380  bulkPs.setString(7, eamCase.getExaminerEmail());
1381  }
1382  if ("".equals(eamCase.getExaminerPhone())) {
1383  bulkPs.setNull(8, Types.INTEGER);
1384  } else {
1385  bulkPs.setString(8, eamCase.getExaminerPhone());
1386  }
1387  if ("".equals(eamCase.getNotes())) {
1388  bulkPs.setNull(9, Types.INTEGER);
1389  } else {
1390  bulkPs.setString(9, eamCase.getNotes());
1391  }
1392 
1393  bulkPs.addBatch();
1394 
1395  counter++;
1396 
1397  // limit a batch's max size to bulkArtifactsThreshold
1398  if (counter >= bulkArtifactsThreshold) {
1399  bulkPs.executeBatch();
1400  counter = 0;
1401  }
1402  }
1403  // send the remaining batch records
1404  bulkPs.executeBatch();
1405  } catch (SQLException ex) {
1406  throw new EamDbException("Error inserting bulk cases.", ex); // NON-NLS
1407  } finally {
1408  EamDbUtil.closeStatement(bulkPs);
1409  EamDbUtil.closeConnection(conn);
1410  }
1411  }
1412 
1422  @Override
1423  public void updateAttributeInstanceComment(CorrelationAttributeInstance eamArtifact) throws EamDbException {
1424 
1425  if (eamArtifact == null) {
1426  throw new EamDbException("CorrelationAttributeInstance is null");
1427  }
1428  if (eamArtifact.getCorrelationCase() == null) {
1429  throw new EamDbException("Correlation case is null");
1430  }
1431  if (eamArtifact.getCorrelationDataSource() == null) {
1432  throw new EamDbException("Correlation data source is null");
1433  }
1434  Connection conn = connect();
1435  PreparedStatement preparedQuery = null;
1436  String tableName = EamDbUtil.correlationTypeToInstanceTableName(eamArtifact.getCorrelationType());
1437  String sqlUpdate
1438  = "UPDATE "
1439  + tableName
1440  + " SET comment=? "
1441  + "WHERE case_id=? "
1442  + "AND data_source_id=? "
1443  + "AND value=? "
1444  + "AND file_path=?";
1445 
1446  try {
1447  preparedQuery = conn.prepareStatement(sqlUpdate);
1448  preparedQuery.setString(1, eamArtifact.getComment());
1449  preparedQuery.setInt(2, eamArtifact.getCorrelationCase().getID());
1450  preparedQuery.setInt(3, eamArtifact.getCorrelationDataSource().getID());
1451  preparedQuery.setString(4, eamArtifact.getCorrelationValue());
1452  preparedQuery.setString(5, eamArtifact.getFilePath().toLowerCase());
1453  preparedQuery.executeUpdate();
1454  } catch (SQLException ex) {
1455  throw new EamDbException("Error getting/setting artifact instance comment=" + eamArtifact.getComment(), ex); // NON-NLS
1456  } finally {
1457  EamDbUtil.closeStatement(preparedQuery);
1458  EamDbUtil.closeConnection(conn);
1459  }
1460  }
1461 
1476  @Override
1477  public CorrelationAttributeInstance getCorrelationAttributeInstance(CorrelationAttributeInstance.Type type, CorrelationCase correlationCase,
1478  CorrelationDataSource correlationDataSource, long objectID) throws EamDbException, CorrelationAttributeNormalizationException {
1479 
1480  if (correlationCase == null) {
1481  throw new EamDbException("Correlation case is null");
1482  }
1483 
1484  Connection conn = connect();
1485 
1486  PreparedStatement preparedStatement = null;
1487  ResultSet resultSet = null;
1488  CorrelationAttributeInstance correlationAttributeInstance = null;
1489 
1490  try {
1491 
1492  String tableName = EamDbUtil.correlationTypeToInstanceTableName(type);
1493  String sql
1494  = "SELECT id, value, file_path, known_status, comment FROM "
1495  + tableName
1496  + " WHERE case_id=?"
1497  + " AND file_obj_id=?";
1498 
1499  preparedStatement = conn.prepareStatement(sql);
1500  preparedStatement.setInt(1, correlationCase.getID());
1501  preparedStatement.setInt(2, (int) objectID);
1502  resultSet = preparedStatement.executeQuery();
1503  if (resultSet.next()) {
1504  int instanceId = resultSet.getInt(1);
1505  String value = resultSet.getString(2);
1506  String filePath = resultSet.getString(3);
1507  int knownStatus = resultSet.getInt(4);
1508  String comment = resultSet.getString(5);
1509 
1510  correlationAttributeInstance = new CorrelationAttributeInstance(type, value,
1511  instanceId, correlationCase, correlationDataSource, filePath, comment, TskData.FileKnown.valueOf((byte) knownStatus), objectID);
1512  }
1513  } catch (SQLException ex) {
1514  throw new EamDbException("Error getting notable artifact instances.", ex); // NON-NLS
1515  } finally {
1516  EamDbUtil.closeStatement(preparedStatement);
1517  EamDbUtil.closeResultSet(resultSet);
1518  EamDbUtil.closeConnection(conn);
1519  }
1520 
1521  return correlationAttributeInstance;
1522  }
1523 
1538  @Override
1539  public CorrelationAttributeInstance getCorrelationAttributeInstance(CorrelationAttributeInstance.Type type, CorrelationCase correlationCase,
1540  CorrelationDataSource correlationDataSource, String value, String filePath) throws EamDbException, CorrelationAttributeNormalizationException {
1541 
1542  if (correlationCase == null) {
1543  throw new EamDbException("Correlation case is null");
1544  }
1545  if (correlationDataSource == null) {
1546  throw new EamDbException("Correlation data source is null");
1547  }
1548  if (filePath == null) {
1549  throw new EamDbException("Correlation file path is null");
1550  }
1551 
1552  Connection conn = connect();
1553 
1554  PreparedStatement preparedStatement = null;
1555  ResultSet resultSet = null;
1556  CorrelationAttributeInstance correlationAttributeInstance = null;
1557 
1558  try {
1559  String normalizedValue = CorrelationAttributeNormalizer.normalize(type, value);
1560 
1561  String tableName = EamDbUtil.correlationTypeToInstanceTableName(type);
1562  String sql
1563  = "SELECT id, known_status, comment FROM "
1564  + tableName
1565  + " WHERE case_id=?"
1566  + " AND data_source_id=?"
1567  + " AND value=?"
1568  + " AND file_path=?";
1569 
1570  preparedStatement = conn.prepareStatement(sql);
1571  preparedStatement.setInt(1, correlationCase.getID());
1572  preparedStatement.setInt(2, correlationDataSource.getID());
1573  preparedStatement.setString(3, normalizedValue);
1574  preparedStatement.setString(4, filePath.toLowerCase());
1575  resultSet = preparedStatement.executeQuery();
1576  if (resultSet.next()) {
1577  int instanceId = resultSet.getInt(1);
1578  int knownStatus = resultSet.getInt(2);
1579  String comment = resultSet.getString(3);
1580  //null objectId used because we only fall back to using this method when objectID was not available
1581  correlationAttributeInstance = new CorrelationAttributeInstance(type, value,
1582  instanceId, correlationCase, correlationDataSource, filePath, comment, TskData.FileKnown.valueOf((byte) knownStatus), null);
1583  }
1584  } catch (SQLException ex) {
1585  throw new EamDbException("Error getting notable artifact instances.", ex); // NON-NLS
1586  } finally {
1587  EamDbUtil.closeStatement(preparedStatement);
1588  EamDbUtil.closeResultSet(resultSet);
1589  EamDbUtil.closeConnection(conn);
1590  }
1591 
1592  return correlationAttributeInstance;
1593  }
1594 
1605  @Override
1606  public void setAttributeInstanceKnownStatus(CorrelationAttributeInstance eamArtifact, TskData.FileKnown knownStatus) throws EamDbException {
1607  if (eamArtifact == null) {
1608  throw new EamDbException("CorrelationAttribute is null");
1609  }
1610  if (knownStatus == null) {
1611  throw new EamDbException("Known status is null");
1612  }
1613 
1614  if (eamArtifact.getCorrelationCase() == null) {
1615  throw new EamDbException("Correlation case is null");
1616  }
1617  if (eamArtifact.getCorrelationDataSource() == null) {
1618  throw new EamDbException("Correlation data source is null");
1619  }
1620 
1621  Connection conn = connect();
1622 
1623  PreparedStatement preparedUpdate = null;
1624  PreparedStatement preparedQuery = null;
1625  ResultSet resultSet = null;
1626 
1627  String tableName = EamDbUtil.correlationTypeToInstanceTableName(eamArtifact.getCorrelationType());
1628 
1629  String sqlQuery
1630  = "SELECT id FROM "
1631  + tableName
1632  + " WHERE case_id=? "
1633  + "AND data_source_id=? "
1634  + "AND value=? "
1635  + "AND file_path=?";
1636 
1637  String sqlUpdate
1638  = "UPDATE "
1639  + tableName
1640  + " SET known_status=?, comment=? "
1641  + "WHERE id=?";
1642 
1643  try {
1644  preparedQuery = conn.prepareStatement(sqlQuery);
1645  preparedQuery.setInt(1, eamArtifact.getCorrelationCase().getID());
1646  preparedQuery.setInt(2, eamArtifact.getCorrelationDataSource().getID());
1647  preparedQuery.setString(3, eamArtifact.getCorrelationValue());
1648  preparedQuery.setString(4, eamArtifact.getFilePath());
1649  resultSet = preparedQuery.executeQuery();
1650  if (resultSet.next()) {
1651  int instance_id = resultSet.getInt("id");
1652  preparedUpdate = conn.prepareStatement(sqlUpdate);
1653 
1654  preparedUpdate.setByte(1, knownStatus.getFileKnownValue());
1655  // NOTE: if the user tags the same instance as BAD multiple times,
1656  // the comment from the most recent tagging is the one that will
1657  // prevail in the DB.
1658  if ("".equals(eamArtifact.getComment())) {
1659  preparedUpdate.setNull(2, Types.INTEGER);
1660  } else {
1661  preparedUpdate.setString(2, eamArtifact.getComment());
1662  }
1663  preparedUpdate.setInt(3, instance_id);
1664 
1665  preparedUpdate.executeUpdate();
1666  } else {
1667  // In this case, the user is tagging something that isn't in the database,
1668  // which means the case and/or datasource may also not be in the database.
1669  // We could improve effiency by keeping a list of all datasources and cases
1670  // in the database, but we don't expect the user to be tagging large numbers
1671  // of items (that didn't have the CE ingest module run on them) at once.
1672  CorrelationCase correlationCaseWithId = getCaseByUUID(eamArtifact.getCorrelationCase().getCaseUUID());
1673  if (null == correlationCaseWithId) {
1674  correlationCaseWithId = newCase(eamArtifact.getCorrelationCase());
1675  }
1676  if (null == getDataSource(correlationCaseWithId, eamArtifact.getCorrelationDataSource().getDataSourceObjectID())) {
1677  newDataSource(eamArtifact.getCorrelationDataSource());
1678  }
1679  eamArtifact.setKnownStatus(knownStatus);
1680  addArtifactInstance(eamArtifact);
1681  }
1682 
1683  } catch (SQLException ex) {
1684  throw new EamDbException("Error getting/setting artifact instance knownStatus=" + knownStatus.getName(), ex); // NON-NLS
1685  } finally {
1686  EamDbUtil.closeStatement(preparedUpdate);
1687  EamDbUtil.closeStatement(preparedQuery);
1688  EamDbUtil.closeResultSet(resultSet);
1689  EamDbUtil.closeConnection(conn);
1690  }
1691  }
1692 
1702  @Override
1703  public List<CorrelationAttributeInstance> getArtifactInstancesKnownBad(CorrelationAttributeInstance.Type aType, String value) throws EamDbException, CorrelationAttributeNormalizationException {
1704  String normalizedValue = CorrelationAttributeNormalizer.normalize(aType, value);
1705 
1706  Connection conn = connect();
1707 
1708  List<CorrelationAttributeInstance> artifactInstances = new ArrayList<>();
1709 
1710  CorrelationAttributeInstance artifactInstance;
1711  PreparedStatement preparedStatement = null;
1712  ResultSet resultSet = null;
1713 
1714  String tableName = EamDbUtil.correlationTypeToInstanceTableName(aType);
1715  String sql
1716  = "SELECT "
1717  + tableName
1718  + ".id, "
1719  + tableName
1720  + ".value, "
1721  + tableName
1722  + ".file_obj_id,"
1723  + "cases.case_name, cases.case_uid, data_sources.id AS data_source_id, data_sources.name, device_id, file_path, known_status, comment, data_sources.case_id, data_sources.datasource_obj_id FROM "
1724  + tableName
1725  + " LEFT JOIN cases ON "
1726  + tableName
1727  + ".case_id=cases.id"
1728  + " LEFT JOIN data_sources ON "
1729  + tableName
1730  + ".data_source_id=data_sources.id"
1731  + " WHERE value=? AND known_status=?";
1732 
1733  try {
1734  preparedStatement = conn.prepareStatement(sql);
1735  preparedStatement.setString(1, normalizedValue);
1736  preparedStatement.setByte(2, TskData.FileKnown.BAD.getFileKnownValue());
1737  resultSet = preparedStatement.executeQuery();
1738  while (resultSet.next()) {
1739  artifactInstance = getEamArtifactInstanceFromResultSet(resultSet, aType);
1740  artifactInstances.add(artifactInstance);
1741  }
1742  } catch (SQLException ex) {
1743  throw new EamDbException("Error getting notable artifact instances.", ex); // NON-NLS
1744  } finally {
1745  EamDbUtil.closeStatement(preparedStatement);
1746  EamDbUtil.closeResultSet(resultSet);
1747  EamDbUtil.closeConnection(conn);
1748  }
1749 
1750  return artifactInstances;
1751  }
1752 
1764  @Override
1765  public List<CorrelationAttributeInstance> getArtifactInstancesKnownBad(CorrelationAttributeInstance.Type aType) throws EamDbException {
1766  if (aType == null) {
1767  throw new EamDbException("Correlation type is null");
1768  }
1769 
1770  Connection conn = connect();
1771 
1772  List<CorrelationAttributeInstance> artifactInstances = new ArrayList<>();
1773 
1774  CorrelationAttributeInstance artifactInstance;
1775  PreparedStatement preparedStatement = null;
1776  ResultSet resultSet = null;
1777 
1778  String tableName = EamDbUtil.correlationTypeToInstanceTableName(aType);
1779  String sql
1780  = "SELECT cases.case_name, cases.case_uid, data_sources.name, device_id, file_path, known_status, comment, data_sources.case_id, id, value, file_obj_id, data_sources.datasource_obj_id FROM "
1781  + tableName
1782  + " LEFT JOIN cases ON "
1783  + tableName
1784  + ".case_id=cases.id"
1785  + " LEFT JOIN data_sources ON "
1786  + tableName
1787  + ".data_source_id=data_sources.id"
1788  + " WHERE known_status=?"
1789  + " GROUP BY "
1790  + tableName
1791  + ".value";
1792 
1793  try {
1794  preparedStatement = conn.prepareStatement(sql);
1795  preparedStatement.setByte(1, TskData.FileKnown.BAD.getFileKnownValue());
1796  resultSet = preparedStatement.executeQuery();
1797  while (resultSet.next()) {
1798  try {
1799  artifactInstance = getEamArtifactInstanceFromResultSet(resultSet, aType);
1800  artifactInstances.add(artifactInstance);
1802  logger.log(Level.INFO, "Unable to get artifact instance from resultset.", ex);
1803  }
1804  }
1805  } catch (SQLException ex) {
1806  throw new EamDbException("Error getting notable artifact instances.", ex); // NON-NLS
1807  } finally {
1808  EamDbUtil.closeStatement(preparedStatement);
1809  EamDbUtil.closeResultSet(resultSet);
1810  EamDbUtil.closeConnection(conn);
1811  }
1812 
1813  return artifactInstances;
1814  }
1815 
1824  @Override
1825  public Long getCountArtifactInstancesKnownBad(CorrelationAttributeInstance.Type aType, String value) throws EamDbException, CorrelationAttributeNormalizationException {
1826 
1827  String normalizedValue = CorrelationAttributeNormalizer.normalize(aType, value);
1828 
1829  Connection conn = connect();
1830 
1831  Long badInstances = 0L;
1832  PreparedStatement preparedStatement = null;
1833  ResultSet resultSet = null;
1834 
1835  String tableName = EamDbUtil.correlationTypeToInstanceTableName(aType);
1836  String sql
1837  = "SELECT count(*) FROM "
1838  + tableName
1839  + " WHERE value=? AND known_status=?";
1840 
1841  try {
1842  preparedStatement = conn.prepareStatement(sql);
1843  preparedStatement.setString(1, normalizedValue);
1844  preparedStatement.setByte(2, TskData.FileKnown.BAD.getFileKnownValue());
1845  resultSet = preparedStatement.executeQuery();
1846  resultSet.next();
1847  badInstances = resultSet.getLong(1);
1848  } catch (SQLException ex) {
1849  throw new EamDbException("Error getting count of notable artifact instances.", ex); // NON-NLS
1850  } finally {
1851  EamDbUtil.closeStatement(preparedStatement);
1852  EamDbUtil.closeResultSet(resultSet);
1853  EamDbUtil.closeConnection(conn);
1854  }
1855 
1856  return badInstances;
1857  }
1858 
1871  @Override
1872  public List<String> getListCasesHavingArtifactInstancesKnownBad(CorrelationAttributeInstance.Type aType, String value) throws EamDbException, CorrelationAttributeNormalizationException {
1873 
1874  String normalizedValue = CorrelationAttributeNormalizer.normalize(aType, value);
1875 
1876  Connection conn = connect();
1877 
1878  Collection<String> caseNames = new LinkedHashSet<>();
1879 
1880  PreparedStatement preparedStatement = null;
1881  ResultSet resultSet = null;
1882 
1883  String tableName = EamDbUtil.correlationTypeToInstanceTableName(aType);
1884  String sql
1885  = "SELECT DISTINCT case_name FROM "
1886  + tableName
1887  + " INNER JOIN cases ON "
1888  + tableName
1889  + ".case_id=cases.id WHERE "
1890  + tableName
1891  + ".value=? AND "
1892  + tableName
1893  + ".known_status=?";
1894 
1895  try {
1896  preparedStatement = conn.prepareStatement(sql);
1897  preparedStatement.setString(1, normalizedValue);
1898  preparedStatement.setByte(2, TskData.FileKnown.BAD.getFileKnownValue());
1899  resultSet = preparedStatement.executeQuery();
1900  while (resultSet.next()) {
1901  caseNames.add(resultSet.getString("case_name"));
1902  }
1903  } catch (SQLException ex) {
1904  throw new EamDbException("Error getting notable artifact instances.", ex); // NON-NLS
1905  } finally {
1906  EamDbUtil.closeStatement(preparedStatement);
1907  EamDbUtil.closeResultSet(resultSet);
1908  EamDbUtil.closeConnection(conn);
1909  }
1910 
1911  return caseNames.stream().collect(Collectors.toList());
1912  }
1913 
1921  @Override
1922  public void deleteReferenceSet(int referenceSetID) throws EamDbException {
1923  deleteReferenceSetEntries(referenceSetID);
1924  deleteReferenceSetEntry(referenceSetID);
1925  }
1926 
1934  private void deleteReferenceSetEntry(int referenceSetID) throws EamDbException {
1935  Connection conn = connect();
1936 
1937  PreparedStatement preparedStatement = null;
1938  String sql = "DELETE FROM reference_sets WHERE id=?";
1939 
1940  try {
1941  preparedStatement = conn.prepareStatement(sql);
1942  preparedStatement.setInt(1, referenceSetID);
1943  preparedStatement.executeUpdate();
1944  } catch (SQLException ex) {
1945  throw new EamDbException("Error deleting reference set " + referenceSetID, ex); // NON-NLS
1946  } finally {
1947  EamDbUtil.closeStatement(preparedStatement);
1948  EamDbUtil.closeConnection(conn);
1949  }
1950  }
1951 
1960  private void deleteReferenceSetEntries(int referenceSetID) throws EamDbException {
1961  Connection conn = connect();
1962 
1963  PreparedStatement preparedStatement = null;
1964  String sql = "DELETE FROM %s WHERE reference_set_id=?";
1965 
1966  // When other reference types are added, this will need to loop over all the tables
1967  String fileTableName = EamDbUtil.correlationTypeToReferenceTableName(getCorrelationTypeById(CorrelationAttributeInstance.FILES_TYPE_ID));
1968 
1969  try {
1970  preparedStatement = conn.prepareStatement(String.format(sql, fileTableName));
1971  preparedStatement.setInt(1, referenceSetID);
1972  preparedStatement.executeUpdate();
1973  } catch (SQLException ex) {
1974  throw new EamDbException("Error deleting files from reference set " + referenceSetID, ex); // NON-NLS
1975  } finally {
1976  EamDbUtil.closeStatement(preparedStatement);
1977  EamDbUtil.closeConnection(conn);
1978  }
1979  }
1980 
1994  @Override
1995  public boolean referenceSetIsValid(int referenceSetID, String setName, String version) throws EamDbException {
1996  EamGlobalSet refSet = this.getReferenceSetByID(referenceSetID);
1997  if (refSet == null) {
1998  return false;
1999  }
2000 
2001  return (refSet.getSetName().equals(setName) && refSet.getVersion().equals(version));
2002  }
2003 
2015  @Override
2016  public boolean isFileHashInReferenceSet(String hash, int referenceSetID) throws EamDbException, CorrelationAttributeNormalizationException {
2017  return isValueInReferenceSet(hash, referenceSetID, CorrelationAttributeInstance.FILES_TYPE_ID);
2018  }
2019 
2029  @Override
2030  public boolean isValueInReferenceSet(String value, int referenceSetID, int correlationTypeID) throws EamDbException, CorrelationAttributeNormalizationException {
2031 
2032  String normalizeValued = CorrelationAttributeNormalizer.normalize(this.getCorrelationTypeById(correlationTypeID), value);
2033 
2034  Connection conn = connect();
2035 
2036  Long matchingInstances = 0L;
2037  PreparedStatement preparedStatement = null;
2038  ResultSet resultSet = null;
2039  String sql = "SELECT count(*) FROM %s WHERE value=? AND reference_set_id=?";
2040 
2041  String fileTableName = EamDbUtil.correlationTypeToReferenceTableName(getCorrelationTypeById(correlationTypeID));
2042 
2043  try {
2044  preparedStatement = conn.prepareStatement(String.format(sql, fileTableName));
2045  preparedStatement.setString(1, normalizeValued);
2046  preparedStatement.setInt(2, referenceSetID);
2047  resultSet = preparedStatement.executeQuery();
2048  resultSet.next();
2049  matchingInstances = resultSet.getLong(1);
2050  } catch (SQLException ex) {
2051  throw new EamDbException("Error determining if value (" + normalizeValued + ") is in reference set " + referenceSetID, ex); // NON-NLS
2052  } finally {
2053  EamDbUtil.closeStatement(preparedStatement);
2054  EamDbUtil.closeResultSet(resultSet);
2055  EamDbUtil.closeConnection(conn);
2056  }
2057 
2058  return 0 < matchingInstances;
2059  }
2060 
2069  @Override
2070  public boolean isArtifactKnownBadByReference(CorrelationAttributeInstance.Type aType, String value) throws EamDbException, CorrelationAttributeNormalizationException {
2071 
2072  //this should be done here so that we can be certain that aType and value are valid before we proceed
2073  String normalizeValued = CorrelationAttributeNormalizer.normalize(aType, value);
2074 
2075  // TEMP: Only support file correlation type
2076  if (aType.getId() != CorrelationAttributeInstance.FILES_TYPE_ID) {
2077  return false;
2078  }
2079 
2080  Connection conn = connect();
2081 
2082  Long badInstances = 0L;
2083  PreparedStatement preparedStatement = null;
2084  ResultSet resultSet = null;
2085  String sql = "SELECT count(*) FROM %s WHERE value=? AND known_status=?";
2086 
2087  try {
2088  preparedStatement = conn.prepareStatement(String.format(sql, EamDbUtil.correlationTypeToReferenceTableName(aType)));
2089  preparedStatement.setString(1, normalizeValued);
2090  preparedStatement.setByte(2, TskData.FileKnown.BAD.getFileKnownValue());
2091  resultSet = preparedStatement.executeQuery();
2092  resultSet.next();
2093  badInstances = resultSet.getLong(1);
2094  } catch (SQLException ex) {
2095  throw new EamDbException("Error determining if artifact is notable by reference.", ex); // NON-NLS
2096  } finally {
2097  EamDbUtil.closeStatement(preparedStatement);
2098  EamDbUtil.closeResultSet(resultSet);
2099  EamDbUtil.closeConnection(conn);
2100  }
2101 
2102  return 0 < badInstances;
2103  }
2104 
2113  @Override
2114  public void processInstanceTable(CorrelationAttributeInstance.Type type, InstanceTableCallback instanceTableCallback) throws EamDbException {
2115  if (type == null) {
2116  throw new EamDbException("Correlation type is null");
2117  }
2118 
2119  if (instanceTableCallback == null) {
2120  throw new EamDbException("Callback interface is null");
2121  }
2122 
2123  Connection conn = connect();
2124  PreparedStatement preparedStatement = null;
2125  ResultSet resultSet = null;
2126  String tableName = EamDbUtil.correlationTypeToInstanceTableName(type);
2127  StringBuilder sql = new StringBuilder();
2128  sql.append("select * from ");
2129  sql.append(tableName);
2130 
2131  try {
2132  preparedStatement = conn.prepareStatement(sql.toString());
2133  resultSet = preparedStatement.executeQuery();
2134  instanceTableCallback.process(resultSet);
2135  } catch (SQLException ex) {
2136  throw new EamDbException("Error getting all artifact instances from instances table", ex);
2137  } finally {
2138  EamDbUtil.closeStatement(preparedStatement);
2139  EamDbUtil.closeResultSet(resultSet);
2140  EamDbUtil.closeConnection(conn);
2141  }
2142  }
2143 
2153  @Override
2154  public void processInstanceTableWhere(CorrelationAttributeInstance.Type type, String whereClause, InstanceTableCallback instanceTableCallback) throws EamDbException {
2155  if (type == null) {
2156  throw new EamDbException("Correlation type is null");
2157  }
2158 
2159  if (instanceTableCallback == null) {
2160  throw new EamDbException("Callback interface is null");
2161  }
2162 
2163  if (whereClause == null) {
2164  throw new EamDbException("Where clause is null");
2165  }
2166 
2167  Connection conn = connect();
2168  PreparedStatement preparedStatement = null;
2169  ResultSet resultSet = null;
2170  String tableName = EamDbUtil.correlationTypeToInstanceTableName(type);
2171  StringBuilder sql = new StringBuilder(300);
2172  sql.append("select * from ")
2173  .append(tableName)
2174  .append(" WHERE ")
2175  .append(whereClause);
2176 
2177  try {
2178  preparedStatement = conn.prepareStatement(sql.toString());
2179  resultSet = preparedStatement.executeQuery();
2180  instanceTableCallback.process(resultSet);
2181  } catch (SQLException ex) {
2182  throw new EamDbException("Error getting all artifact instances from instances table", ex);
2183  } finally {
2184  EamDbUtil.closeStatement(preparedStatement);
2185  EamDbUtil.closeResultSet(resultSet);
2186  EamDbUtil.closeConnection(conn);
2187  }
2188  }
2189 
2190  @Override
2191  public EamOrganization newOrganization(EamOrganization eamOrg) throws EamDbException {
2192  if (eamOrg == null) {
2193  throw new EamDbException("EamOrganization is null");
2194  } else if (eamOrg.getOrgID() != -1) {
2195  throw new EamDbException("EamOrganization already has an ID");
2196  }
2197 
2198  Connection conn = connect();
2199  ResultSet generatedKeys = null;
2200  PreparedStatement preparedStatement = null;
2201  String sql = "INSERT INTO organizations(org_name, poc_name, poc_email, poc_phone) VALUES (?, ?, ?, ?) "
2202  + getConflictClause();
2203 
2204  try {
2205  preparedStatement = conn.prepareStatement(sql, Statement.RETURN_GENERATED_KEYS);
2206  preparedStatement.setString(1, eamOrg.getName());
2207  preparedStatement.setString(2, eamOrg.getPocName());
2208  preparedStatement.setString(3, eamOrg.getPocEmail());
2209  preparedStatement.setString(4, eamOrg.getPocPhone());
2210 
2211  preparedStatement.executeUpdate();
2212  generatedKeys = preparedStatement.getGeneratedKeys();
2213  if (generatedKeys.next()) {
2214  eamOrg.setOrgID((int) generatedKeys.getLong(1));
2215  return eamOrg;
2216  } else {
2217  throw new SQLException("Creating user failed, no ID obtained.");
2218  }
2219  } catch (SQLException ex) {
2220  throw new EamDbException("Error inserting new organization.", ex); // NON-NLS
2221  } finally {
2222  EamDbUtil.closeStatement(preparedStatement);
2223  EamDbUtil.closeResultSet(generatedKeys);
2224  EamDbUtil.closeConnection(conn);
2225  }
2226  }
2227 
2235  @Override
2236  public List<EamOrganization> getOrganizations() throws EamDbException {
2237  Connection conn = connect();
2238 
2239  List<EamOrganization> orgs = new ArrayList<>();
2240  PreparedStatement preparedStatement = null;
2241  ResultSet resultSet = null;
2242  String sql = "SELECT * FROM organizations";
2243 
2244  try {
2245  preparedStatement = conn.prepareStatement(sql);
2246  resultSet = preparedStatement.executeQuery();
2247  while (resultSet.next()) {
2248  orgs.add(getEamOrganizationFromResultSet(resultSet));
2249  }
2250  return orgs;
2251 
2252  } catch (SQLException ex) {
2253  throw new EamDbException("Error getting all organizations.", ex); // NON-NLS
2254  } finally {
2255  EamDbUtil.closeStatement(preparedStatement);
2256  EamDbUtil.closeResultSet(resultSet);
2257  EamDbUtil.closeConnection(conn);
2258  }
2259  }
2260 
2270  @Override
2271  public EamOrganization getOrganizationByID(int orgID) throws EamDbException {
2272  Connection conn = connect();
2273 
2274  PreparedStatement preparedStatement = null;
2275  ResultSet resultSet = null;
2276  String sql = "SELECT * FROM organizations WHERE id=?";
2277 
2278  try {
2279  preparedStatement = conn.prepareStatement(sql);
2280  preparedStatement.setInt(1, orgID);
2281  resultSet = preparedStatement.executeQuery();
2282  resultSet.next();
2283  return getEamOrganizationFromResultSet(resultSet);
2284 
2285  } catch (SQLException ex) {
2286  throw new EamDbException("Error getting organization by id.", ex); // NON-NLS
2287  } finally {
2288  EamDbUtil.closeStatement(preparedStatement);
2289  EamDbUtil.closeResultSet(resultSet);
2290  EamDbUtil.closeConnection(conn);
2291  }
2292  }
2293 
2303  @Override
2304  public EamOrganization getReferenceSetOrganization(int referenceSetID) throws EamDbException {
2305 
2306  EamGlobalSet globalSet = getReferenceSetByID(referenceSetID);
2307  if (globalSet == null) {
2308  throw new EamDbException("Reference set with ID " + referenceSetID + " not found");
2309  }
2310  return (getOrganizationByID(globalSet.getOrgID()));
2311  }
2312 
2320  private void testArgument(EamOrganization org) throws EamDbException {
2321  if (org == null) {
2322  throw new EamDbException("EamOrganization is null");
2323  } else if (org.getOrgID() == -1) {
2324  throw new EamDbException("Organization has -1 row ID");
2325  }
2326  }
2327 
2336  @Override
2337  public void updateOrganization(EamOrganization updatedOrganization) throws EamDbException {
2338  testArgument(updatedOrganization);
2339 
2340  Connection conn = connect();
2341  PreparedStatement preparedStatement = null;
2342  String sql = "UPDATE organizations SET org_name = ?, poc_name = ?, poc_email = ?, poc_phone = ? WHERE id = ?";
2343  try {
2344  preparedStatement = conn.prepareStatement(sql);
2345  preparedStatement.setString(1, updatedOrganization.getName());
2346  preparedStatement.setString(2, updatedOrganization.getPocName());
2347  preparedStatement.setString(3, updatedOrganization.getPocEmail());
2348  preparedStatement.setString(4, updatedOrganization.getPocPhone());
2349  preparedStatement.setInt(5, updatedOrganization.getOrgID());
2350  preparedStatement.executeUpdate();
2351  } catch (SQLException ex) {
2352  throw new EamDbException("Error updating organization.", ex); // NON-NLS
2353  } finally {
2354  EamDbUtil.closeStatement(preparedStatement);
2355  EamDbUtil.closeConnection(conn);
2356  }
2357  }
2358 
2359  @Override
2360  public void deleteOrganization(EamOrganization organizationToDelete) throws EamDbException {
2361  testArgument(organizationToDelete);
2362 
2363  Connection conn = connect();
2364  PreparedStatement checkIfUsedStatement = null;
2365  ResultSet resultSet = null;
2366  String checkIfUsedSql = "SELECT (select count(*) FROM cases WHERE org_id=?) + (select count(*) FROM reference_sets WHERE org_id=?)";
2367  PreparedStatement deleteOrgStatement = null;
2368  String deleteOrgSql = "DELETE FROM organizations WHERE id=?";
2369  try {
2370  checkIfUsedStatement = conn.prepareStatement(checkIfUsedSql);
2371  checkIfUsedStatement.setInt(1, organizationToDelete.getOrgID());
2372  checkIfUsedStatement.setInt(2, organizationToDelete.getOrgID());
2373  resultSet = checkIfUsedStatement.executeQuery();
2374  resultSet.next();
2375  if (resultSet.getLong(1) > 0) {
2376  throw new EamDbException("Can not delete organization which is currently in use by a case or reference set in the central repository.");
2377  }
2378  deleteOrgStatement = conn.prepareStatement(deleteOrgSql);
2379  deleteOrgStatement.setInt(1, organizationToDelete.getOrgID());
2380  deleteOrgStatement.executeUpdate();
2381  } catch (SQLException ex) {
2382  throw new EamDbException("Error executing query when attempting to delete organization by id.", ex); // NON-NLS
2383  } finally {
2384  EamDbUtil.closeStatement(checkIfUsedStatement);
2385  EamDbUtil.closeStatement(deleteOrgStatement);
2386  EamDbUtil.closeResultSet(resultSet);
2387  EamDbUtil.closeConnection(conn);
2388  }
2389  }
2390 
2400  @Override
2401  public int newReferenceSet(EamGlobalSet eamGlobalSet) throws EamDbException {
2402  if (eamGlobalSet == null) {
2403  throw new EamDbException("EamGlobalSet is null");
2404  }
2405 
2406  if (eamGlobalSet.getFileKnownStatus() == null) {
2407  throw new EamDbException("File known status on the EamGlobalSet is null");
2408  }
2409 
2410  if (eamGlobalSet.getType() == null) {
2411  throw new EamDbException("Type on the EamGlobalSet is null");
2412  }
2413 
2414  Connection conn = connect();
2415 
2416  PreparedStatement preparedStatement1 = null;
2417  PreparedStatement preparedStatement2 = null;
2418  ResultSet resultSet = null;
2419  String sql1 = "INSERT INTO reference_sets(org_id, set_name, version, known_status, read_only, type, import_date) VALUES (?, ?, ?, ?, ?, ?, ?) "
2420  + getConflictClause();
2421  String sql2 = "SELECT id FROM reference_sets WHERE org_id=? AND set_name=? AND version=? AND import_date=? LIMIT 1";
2422 
2423  try {
2424  preparedStatement1 = conn.prepareStatement(sql1);
2425  preparedStatement1.setInt(1, eamGlobalSet.getOrgID());
2426  preparedStatement1.setString(2, eamGlobalSet.getSetName());
2427  preparedStatement1.setString(3, eamGlobalSet.getVersion());
2428  preparedStatement1.setInt(4, eamGlobalSet.getFileKnownStatus().getFileKnownValue());
2429  preparedStatement1.setBoolean(5, eamGlobalSet.isReadOnly());
2430  preparedStatement1.setInt(6, eamGlobalSet.getType().getId());
2431  preparedStatement1.setString(7, eamGlobalSet.getImportDate().toString());
2432 
2433  preparedStatement1.executeUpdate();
2434 
2435  preparedStatement2 = conn.prepareStatement(sql2);
2436  preparedStatement2.setInt(1, eamGlobalSet.getOrgID());
2437  preparedStatement2.setString(2, eamGlobalSet.getSetName());
2438  preparedStatement2.setString(3, eamGlobalSet.getVersion());
2439  preparedStatement2.setString(4, eamGlobalSet.getImportDate().toString());
2440 
2441  resultSet = preparedStatement2.executeQuery();
2442  resultSet.next();
2443  return resultSet.getInt("id");
2444 
2445  } catch (SQLException ex) {
2446  throw new EamDbException("Error inserting new global set.", ex); // NON-NLS
2447  } finally {
2448  EamDbUtil.closeStatement(preparedStatement1);
2449  EamDbUtil.closeStatement(preparedStatement2);
2450  EamDbUtil.closeResultSet(resultSet);
2451  EamDbUtil.closeConnection(conn);
2452  }
2453  }
2454 
2464  @Override
2465  public EamGlobalSet getReferenceSetByID(int referenceSetID) throws EamDbException {
2466  Connection conn = connect();
2467 
2468  PreparedStatement preparedStatement1 = null;
2469  ResultSet resultSet = null;
2470  String sql1 = "SELECT * FROM reference_sets WHERE id=?";
2471 
2472  try {
2473  preparedStatement1 = conn.prepareStatement(sql1);
2474  preparedStatement1.setInt(1, referenceSetID);
2475  resultSet = preparedStatement1.executeQuery();
2476  if (resultSet.next()) {
2477  return getEamGlobalSetFromResultSet(resultSet);
2478  } else {
2479  return null;
2480  }
2481 
2482  } catch (SQLException ex) {
2483  throw new EamDbException("Error getting reference set by id.", ex); // NON-NLS
2484  } finally {
2485  EamDbUtil.closeStatement(preparedStatement1);
2486  EamDbUtil.closeResultSet(resultSet);
2487  EamDbUtil.closeConnection(conn);
2488  }
2489  }
2490 
2500  @Override
2501  public List<EamGlobalSet> getAllReferenceSets(CorrelationAttributeInstance.Type correlationType) throws EamDbException {
2502 
2503  if (correlationType == null) {
2504  throw new EamDbException("Correlation type is null");
2505  }
2506 
2507  List<EamGlobalSet> results = new ArrayList<>();
2508  Connection conn = connect();
2509 
2510  PreparedStatement preparedStatement1 = null;
2511  ResultSet resultSet = null;
2512  String sql1 = "SELECT * FROM reference_sets WHERE type=" + correlationType.getId();
2513 
2514  try {
2515  preparedStatement1 = conn.prepareStatement(sql1);
2516  resultSet = preparedStatement1.executeQuery();
2517  while (resultSet.next()) {
2518  results.add(getEamGlobalSetFromResultSet(resultSet));
2519  }
2520 
2521  } catch (SQLException ex) {
2522  throw new EamDbException("Error getting reference sets.", ex); // NON-NLS
2523  } finally {
2524  EamDbUtil.closeStatement(preparedStatement1);
2525  EamDbUtil.closeResultSet(resultSet);
2526  EamDbUtil.closeConnection(conn);
2527  }
2528  return results;
2529  }
2530 
2540  @Override
2541  public void addReferenceInstance(EamGlobalFileInstance eamGlobalFileInstance, CorrelationAttributeInstance.Type correlationType) throws EamDbException {
2542  if (eamGlobalFileInstance.getKnownStatus() == null) {
2543  throw new EamDbException("Known status of EamGlobalFileInstance is null");
2544  }
2545  if (correlationType == null) {
2546  throw new EamDbException("Correlation type is null");
2547  }
2548 
2549  Connection conn = connect();
2550 
2551  PreparedStatement preparedStatement = null;
2552 
2553  String sql = "INSERT INTO %s(reference_set_id, value, known_status, comment) VALUES (?, ?, ?, ?) "
2554  + getConflictClause();
2555 
2556  try {
2557  preparedStatement = conn.prepareStatement(String.format(sql, EamDbUtil.correlationTypeToReferenceTableName(correlationType)));
2558  preparedStatement.setInt(1, eamGlobalFileInstance.getGlobalSetID());
2559  preparedStatement.setString(2, eamGlobalFileInstance.getMD5Hash());
2560  preparedStatement.setByte(3, eamGlobalFileInstance.getKnownStatus().getFileKnownValue());
2561  preparedStatement.setString(4, eamGlobalFileInstance.getComment());
2562  preparedStatement.executeUpdate();
2563  } catch (SQLException ex) {
2564  throw new EamDbException("Error inserting new reference instance into reference_ table.", ex); // NON-NLS
2565  } finally {
2566  EamDbUtil.closeStatement(preparedStatement);
2567  EamDbUtil.closeConnection(conn);
2568  }
2569  }
2570 
2583  @Override
2584  public boolean referenceSetExists(String referenceSetName, String version) throws EamDbException {
2585  Connection conn = connect();
2586 
2587  PreparedStatement preparedStatement1 = null;
2588  ResultSet resultSet = null;
2589  String sql1 = "SELECT * FROM reference_sets WHERE set_name=? AND version=?";
2590 
2591  try {
2592  preparedStatement1 = conn.prepareStatement(sql1);
2593  preparedStatement1.setString(1, referenceSetName);
2594  preparedStatement1.setString(2, version);
2595  resultSet = preparedStatement1.executeQuery();
2596  return (resultSet.next());
2597 
2598  } catch (SQLException ex) {
2599  throw new EamDbException("Error testing whether reference set exists (name: " + referenceSetName
2600  + " version: " + version, ex); // NON-NLS
2601  } finally {
2602  EamDbUtil.closeStatement(preparedStatement1);
2603  EamDbUtil.closeResultSet(resultSet);
2604  EamDbUtil.closeConnection(conn);
2605  }
2606  }
2607 
2613  @Override
2614  public void bulkInsertReferenceTypeEntries(Set<EamGlobalFileInstance> globalInstances, CorrelationAttributeInstance.Type contentType) throws EamDbException {
2615  if (contentType == null) {
2616  throw new EamDbException("Correlation type is null");
2617  }
2618  if (globalInstances == null) {
2619  throw new EamDbException("Null set of EamGlobalFileInstance");
2620  }
2621 
2622  Connection conn = connect();
2623 
2624  PreparedStatement bulkPs = null;
2625  try {
2626  conn.setAutoCommit(false);
2627 
2628  // FUTURE: have a separate global_files table for each Type.
2629  String sql = "INSERT INTO %s(reference_set_id, value, known_status, comment) VALUES (?, ?, ?, ?) "
2630  + getConflictClause();
2631 
2632  bulkPs = conn.prepareStatement(String.format(sql, EamDbUtil.correlationTypeToReferenceTableName(contentType)));
2633 
2634  for (EamGlobalFileInstance globalInstance : globalInstances) {
2635  if (globalInstance.getKnownStatus() == null) {
2636  throw new EamDbException("EamGlobalFileInstance with value " + globalInstance.getMD5Hash() + " has null known status");
2637  }
2638 
2639  bulkPs.setInt(1, globalInstance.getGlobalSetID());
2640  bulkPs.setString(2, globalInstance.getMD5Hash());
2641  bulkPs.setByte(3, globalInstance.getKnownStatus().getFileKnownValue());
2642  bulkPs.setString(4, globalInstance.getComment());
2643  bulkPs.addBatch();
2644  }
2645 
2646  bulkPs.executeBatch();
2647  conn.commit();
2648  } catch (SQLException | EamDbException ex) {
2649  try {
2650  conn.rollback();
2651  } catch (SQLException ex2) {
2652  // We're alredy in an error state
2653  }
2654  throw new EamDbException("Error inserting bulk artifacts.", ex); // NON-NLS
2655  } finally {
2656  EamDbUtil.closeStatement(bulkPs);
2657  EamDbUtil.closeConnection(conn);
2658  }
2659  }
2660 
2671  @Override
2672  public List<EamGlobalFileInstance> getReferenceInstancesByTypeValue(CorrelationAttributeInstance.Type aType, String aValue) throws EamDbException, CorrelationAttributeNormalizationException {
2673  String normalizeValued = CorrelationAttributeNormalizer.normalize(aType, aValue);
2674 
2675  Connection conn = connect();
2676 
2677  List<EamGlobalFileInstance> globalFileInstances = new ArrayList<>();
2678  PreparedStatement preparedStatement1 = null;
2679  ResultSet resultSet = null;
2680  String sql1 = "SELECT * FROM %s WHERE value=?";
2681 
2682  try {
2683  preparedStatement1 = conn.prepareStatement(String.format(sql1, EamDbUtil.correlationTypeToReferenceTableName(aType)));
2684  preparedStatement1.setString(1, normalizeValued);
2685  resultSet = preparedStatement1.executeQuery();
2686  while (resultSet.next()) {
2687  globalFileInstances.add(getEamGlobalFileInstanceFromResultSet(resultSet));
2688  }
2689 
2690  } catch (SQLException ex) {
2691  throw new EamDbException("Error getting reference instances by type and value.", ex); // NON-NLS
2692  } finally {
2693  EamDbUtil.closeStatement(preparedStatement1);
2694  EamDbUtil.closeResultSet(resultSet);
2695  EamDbUtil.closeConnection(conn);
2696  }
2697 
2698  return globalFileInstances;
2699  }
2700 
2710  @Override
2711  public int newCorrelationType(CorrelationAttributeInstance.Type newType) throws EamDbException {
2712  if (newType == null) {
2713  throw new EamDbException("Correlation type is null");
2714  }
2715  int typeId;
2716  if (-1 == newType.getId()) {
2717  typeId = newCorrelationTypeNotKnownId(newType);
2718  } else {
2719  typeId = newCorrelationTypeKnownId(newType);
2720  }
2721 
2722  return typeId;
2723  }
2724 
2735  public int newCorrelationTypeNotKnownId(CorrelationAttributeInstance.Type newType) throws EamDbException {
2736  Connection conn = connect();
2737 
2738  PreparedStatement preparedStatement = null;
2739  PreparedStatement preparedStatementQuery = null;
2740  ResultSet resultSet = null;
2741  int typeId = 0;
2742  String insertSql;
2743  String querySql;
2744  // if we have a known ID, use it, if not (is -1) let the db assign it.
2745  insertSql = "INSERT INTO correlation_types(display_name, db_table_name, supported, enabled) VALUES (?, ?, ?, ?) " + getConflictClause();
2746 
2747  querySql = "SELECT * FROM correlation_types WHERE display_name=? AND db_table_name=?";
2748 
2749  try {
2750  preparedStatement = conn.prepareStatement(insertSql);
2751 
2752  preparedStatement.setString(1, newType.getDisplayName());
2753  preparedStatement.setString(2, newType.getDbTableName());
2754  preparedStatement.setInt(3, newType.isSupported() ? 1 : 0);
2755  preparedStatement.setInt(4, newType.isEnabled() ? 1 : 0);
2756 
2757  preparedStatement.executeUpdate();
2758 
2759  preparedStatementQuery = conn.prepareStatement(querySql);
2760  preparedStatementQuery.setString(1, newType.getDisplayName());
2761  preparedStatementQuery.setString(2, newType.getDbTableName());
2762 
2763  resultSet = preparedStatementQuery.executeQuery();
2764  if (resultSet.next()) {
2765  CorrelationAttributeInstance.Type correlationType = getCorrelationTypeFromResultSet(resultSet);
2766  typeId = correlationType.getId();
2767  }
2768  } catch (SQLException ex) {
2769  throw new EamDbException("Error inserting new correlation type.", ex); // NON-NLS
2770  } finally {
2771  EamDbUtil.closeStatement(preparedStatement);
2772  EamDbUtil.closeStatement(preparedStatementQuery);
2773  EamDbUtil.closeResultSet(resultSet);
2774  EamDbUtil.closeConnection(conn);
2775  }
2776  return typeId;
2777  }
2778 
2788  private int newCorrelationTypeKnownId(CorrelationAttributeInstance.Type newType) throws EamDbException {
2789  Connection conn = connect();
2790 
2791  PreparedStatement preparedStatement = null;
2792  PreparedStatement preparedStatementQuery = null;
2793  ResultSet resultSet = null;
2794  int typeId = 0;
2795  String insertSql;
2796  String querySql;
2797  // if we have a known ID, use it, if not (is -1) let the db assign it.
2798  insertSql = "INSERT INTO correlation_types(id, display_name, db_table_name, supported, enabled) VALUES (?, ?, ?, ?, ?) " + getConflictClause();
2799 
2800  querySql = "SELECT * FROM correlation_types WHERE display_name=? AND db_table_name=?";
2801 
2802  try {
2803  preparedStatement = conn.prepareStatement(insertSql);
2804 
2805  preparedStatement.setInt(1, newType.getId());
2806  preparedStatement.setString(2, newType.getDisplayName());
2807  preparedStatement.setString(3, newType.getDbTableName());
2808  preparedStatement.setInt(4, newType.isSupported() ? 1 : 0);
2809  preparedStatement.setInt(5, newType.isEnabled() ? 1 : 0);
2810 
2811  preparedStatement.executeUpdate();
2812 
2813  preparedStatementQuery = conn.prepareStatement(querySql);
2814  preparedStatementQuery.setString(1, newType.getDisplayName());
2815  preparedStatementQuery.setString(2, newType.getDbTableName());
2816 
2817  resultSet = preparedStatementQuery.executeQuery();
2818  if (resultSet.next()) {
2819  CorrelationAttributeInstance.Type correlationType = getCorrelationTypeFromResultSet(resultSet);
2820  typeId = correlationType.getId();
2821  }
2822  } catch (SQLException ex) {
2823  throw new EamDbException("Error inserting new correlation type.", ex); // NON-NLS
2824  } finally {
2825  EamDbUtil.closeStatement(preparedStatement);
2826  EamDbUtil.closeStatement(preparedStatementQuery);
2827  EamDbUtil.closeResultSet(resultSet);
2828  EamDbUtil.closeConnection(conn);
2829  }
2830  return typeId;
2831  }
2832 
2833  @Override
2834  public List<CorrelationAttributeInstance.Type> getDefinedCorrelationTypes() throws EamDbException {
2835  Connection conn = connect();
2836 
2837  List<CorrelationAttributeInstance.Type> aTypes = new ArrayList<>();
2838  PreparedStatement preparedStatement = null;
2839  ResultSet resultSet = null;
2840  String sql = "SELECT * FROM correlation_types";
2841 
2842  try {
2843  preparedStatement = conn.prepareStatement(sql);
2844  resultSet = preparedStatement.executeQuery();
2845  while (resultSet.next()) {
2846  aTypes.add(getCorrelationTypeFromResultSet(resultSet));
2847  }
2848  return aTypes;
2849 
2850  } catch (SQLException ex) {
2851  throw new EamDbException("Error getting all correlation types.", ex); // NON-NLS
2852  } finally {
2853  EamDbUtil.closeStatement(preparedStatement);
2854  EamDbUtil.closeResultSet(resultSet);
2855  EamDbUtil.closeConnection(conn);
2856  }
2857  }
2858 
2868  @Override
2869  public List<CorrelationAttributeInstance.Type> getEnabledCorrelationTypes() throws EamDbException {
2870  Connection conn = connect();
2871 
2872  List<CorrelationAttributeInstance.Type> aTypes = new ArrayList<>();
2873  PreparedStatement preparedStatement = null;
2874  ResultSet resultSet = null;
2875  String sql = "SELECT * FROM correlation_types WHERE enabled=1";
2876 
2877  try {
2878  preparedStatement = conn.prepareStatement(sql);
2879  resultSet = preparedStatement.executeQuery();
2880  while (resultSet.next()) {
2881  aTypes.add(getCorrelationTypeFromResultSet(resultSet));
2882  }
2883  return aTypes;
2884 
2885  } catch (SQLException ex) {
2886  throw new EamDbException("Error getting enabled correlation types.", ex); // NON-NLS
2887  } finally {
2888  EamDbUtil.closeStatement(preparedStatement);
2889  EamDbUtil.closeResultSet(resultSet);
2890  EamDbUtil.closeConnection(conn);
2891  }
2892  }
2893 
2903  @Override
2904  public List<CorrelationAttributeInstance.Type> getSupportedCorrelationTypes() throws EamDbException {
2905  Connection conn = connect();
2906 
2907  List<CorrelationAttributeInstance.Type> aTypes = new ArrayList<>();
2908  PreparedStatement preparedStatement = null;
2909  ResultSet resultSet = null;
2910  String sql = "SELECT * FROM correlation_types WHERE supported=1";
2911 
2912  try {
2913  preparedStatement = conn.prepareStatement(sql);
2914  resultSet = preparedStatement.executeQuery();
2915  while (resultSet.next()) {
2916  aTypes.add(getCorrelationTypeFromResultSet(resultSet));
2917  }
2918  return aTypes;
2919 
2920  } catch (SQLException ex) {
2921  throw new EamDbException("Error getting supported correlation types.", ex); // NON-NLS
2922  } finally {
2923  EamDbUtil.closeStatement(preparedStatement);
2924  EamDbUtil.closeResultSet(resultSet);
2925  EamDbUtil.closeConnection(conn);
2926  }
2927  }
2928 
2936  @Override
2937  public void updateCorrelationType(CorrelationAttributeInstance.Type aType) throws EamDbException {
2938  Connection conn = connect();
2939 
2940  PreparedStatement preparedStatement = null;
2941  String sql = "UPDATE correlation_types SET display_name=?, db_table_name=?, supported=?, enabled=? WHERE id=?";
2942 
2943  try {
2944  preparedStatement = conn.prepareStatement(sql);
2945  preparedStatement.setString(1, aType.getDisplayName());
2946  preparedStatement.setString(2, aType.getDbTableName());
2947  preparedStatement.setInt(3, aType.isSupported() ? 1 : 0);
2948  preparedStatement.setInt(4, aType.isEnabled() ? 1 : 0);
2949  preparedStatement.setInt(5, aType.getId());
2950  preparedStatement.executeUpdate();
2951  typeCache.put(aType.getId(), aType);
2952  } catch (SQLException ex) {
2953  throw new EamDbException("Error updating correlation type.", ex); // NON-NLS
2954  } finally {
2955  EamDbUtil.closeStatement(preparedStatement);
2956  EamDbUtil.closeConnection(conn);
2957  }
2958 
2959  }
2960 
2970  @Override
2971  public CorrelationAttributeInstance.Type getCorrelationTypeById(int typeId) throws EamDbException {
2972  try {
2973  return typeCache.get(typeId, () -> getCorrelationTypeByIdFromCr(typeId));
2974  } catch (CacheLoader.InvalidCacheLoadException ignored) {
2975  //lambda valueloader returned a null value and cache can not store null values this is normal if the correlation type does not exist in the central repo yet
2976  return null;
2977  } catch (ExecutionException ex) {
2978  throw new EamDbException("Error getting correlation type", ex);
2979  }
2980  }
2981 
2991  private CorrelationAttributeInstance.Type getCorrelationTypeByIdFromCr(int typeId) throws EamDbException {
2992  Connection conn = connect();
2993 
2995  PreparedStatement preparedStatement = null;
2996  ResultSet resultSet = null;
2997  String sql = "SELECT * FROM correlation_types WHERE id=?";
2998 
2999  try {
3000  preparedStatement = conn.prepareStatement(sql);
3001  preparedStatement.setInt(1, typeId);
3002  resultSet = preparedStatement.executeQuery();
3003  if (resultSet.next()) {
3004  aType = getCorrelationTypeFromResultSet(resultSet);
3005  return aType;
3006  } else {
3007  throw new EamDbException("Failed to find entry for correlation type ID = " + typeId);
3008  }
3009 
3010  } catch (SQLException ex) {
3011  throw new EamDbException("Error getting correlation type by id.", ex); // NON-NLS
3012  } finally {
3013  EamDbUtil.closeStatement(preparedStatement);
3014  EamDbUtil.closeResultSet(resultSet);
3015  EamDbUtil.closeConnection(conn);
3016  }
3017  }
3018 
3029  private CorrelationCase getEamCaseFromResultSet(ResultSet resultSet) throws SQLException {
3030  if (null == resultSet) {
3031  return null;
3032  }
3033 
3034  EamOrganization eamOrg = null;
3035 
3036  resultSet.getInt("org_id");
3037  if (!resultSet.wasNull()) {
3038 
3039  eamOrg = new EamOrganization(resultSet.getInt("org_id"),
3040  resultSet.getString("org_name"),
3041  resultSet.getString("poc_name"),
3042  resultSet.getString("poc_email"),
3043  resultSet.getString("poc_phone"));
3044  }
3045 
3046  CorrelationCase eamCase = new CorrelationCase(resultSet.getInt("case_id"), resultSet.getString("case_uid"), eamOrg, resultSet.getString("case_name"),
3047  resultSet.getString("creation_date"), resultSet.getString("case_number"), resultSet.getString("examiner_name"),
3048  resultSet.getString("examiner_email"), resultSet.getString("examiner_phone"), resultSet.getString("notes"));
3049 
3050  return eamCase;
3051  }
3052 
3053  private CorrelationDataSource getEamDataSourceFromResultSet(ResultSet resultSet) throws SQLException {
3054  if (null == resultSet) {
3055  return null;
3056  }
3057 
3058  CorrelationDataSource eamDataSource = new CorrelationDataSource(
3059  resultSet.getInt("case_id"),
3060  resultSet.getInt("id"),
3061  resultSet.getString("device_id"),
3062  resultSet.getString("name"),
3063  resultSet.getLong("datasource_obj_id")
3064  );
3065 
3066  return eamDataSource;
3067  }
3068 
3069  private CorrelationAttributeInstance.Type getCorrelationTypeFromResultSet(ResultSet resultSet) throws EamDbException, SQLException {
3070  if (null == resultSet) {
3071  return null;
3072  }
3073 
3075  resultSet.getInt("id"),
3076  resultSet.getString("display_name"),
3077  resultSet.getString("db_table_name"),
3078  resultSet.getBoolean("supported"),
3079  resultSet.getBoolean("enabled")
3080  );
3081 
3082  return eamArtifactType;
3083  }
3084 
3095  private CorrelationAttributeInstance getEamArtifactInstanceFromResultSet(ResultSet resultSet, CorrelationAttributeInstance.Type aType) throws SQLException, EamDbException, CorrelationAttributeNormalizationException {
3096  if (null == resultSet) {
3097  return null;
3098  }
3099  return new CorrelationAttributeInstance(
3100  aType,
3101  resultSet.getString("value"),
3102  resultSet.getInt("id"),
3103  new CorrelationCase(resultSet.getInt("case_id"), resultSet.getString("case_uid"), resultSet.getString("case_name")),
3104  new CorrelationDataSource(resultSet.getInt("case_id"), resultSet.getInt("data_source_id"), resultSet.getString("device_id"), resultSet.getString("name"), resultSet.getLong("datasource_obj_id")),
3105  resultSet.getString("file_path"),
3106  resultSet.getString("comment"),
3107  TskData.FileKnown.valueOf(resultSet.getByte("known_status")),
3108  resultSet.getLong("file_obj_id"));
3109  }
3110 
3111  private EamOrganization getEamOrganizationFromResultSet(ResultSet resultSet) throws SQLException {
3112  if (null == resultSet) {
3113  return null;
3114  }
3115 
3116  return new EamOrganization(
3117  resultSet.getInt("id"),
3118  resultSet.getString("org_name"),
3119  resultSet.getString("poc_name"),
3120  resultSet.getString("poc_email"),
3121  resultSet.getString("poc_phone")
3122  );
3123  }
3124 
3125  private EamGlobalSet getEamGlobalSetFromResultSet(ResultSet resultSet) throws SQLException, EamDbException {
3126  if (null == resultSet) {
3127  return null;
3128  }
3129 
3130  return new EamGlobalSet(
3131  resultSet.getInt("id"),
3132  resultSet.getInt("org_id"),
3133  resultSet.getString("set_name"),
3134  resultSet.getString("version"),
3135  TskData.FileKnown.valueOf(resultSet.getByte("known_status")),
3136  resultSet.getBoolean("read_only"),
3137  EamDb.getInstance().getCorrelationTypeById(resultSet.getInt("type")),
3138  LocalDate.parse(resultSet.getString("import_date"))
3139  );
3140  }
3141 
3142  private EamGlobalFileInstance getEamGlobalFileInstanceFromResultSet(ResultSet resultSet) throws SQLException, EamDbException, CorrelationAttributeNormalizationException {
3143  if (null == resultSet) {
3144  return null;
3145  }
3146 
3147  return new EamGlobalFileInstance(
3148  resultSet.getInt("id"),
3149  resultSet.getInt("reference_set_id"),
3150  resultSet.getString("value"),
3151  TskData.FileKnown.valueOf(resultSet.getByte("known_status")),
3152  resultSet.getString("comment")
3153  );
3154  }
3155 
3166  abstract boolean doesColumnExist(Connection conn, String tableName, String columnName) throws SQLException;
3167 
3173  @Override
3174  public void upgradeSchema() throws EamDbException, SQLException {
3175 
3176  ResultSet resultSet = null;
3177  Statement statement = null;
3178  PreparedStatement preparedStatement = null;
3179  Connection conn = null;
3180  try {
3181 
3182  conn = connect();
3183  conn.setAutoCommit(false);
3184  statement = conn.createStatement();
3185 
3186  int minorVersion = 0;
3187  String minorVersionStr = null;
3188  resultSet = statement.executeQuery("SELECT value FROM db_info WHERE name='" + AbstractSqlEamDb.SCHEMA_MINOR_VERSION_KEY + "'");
3189  if (resultSet.next()) {
3190  minorVersionStr = resultSet.getString("value");
3191  try {
3192  minorVersion = Integer.parseInt(minorVersionStr);
3193  } catch (NumberFormatException ex) {
3194  throw new EamDbException("Bad value for schema minor version (" + minorVersionStr + ") - database is corrupt", ex);
3195  }
3196  } else {
3197  throw new EamDbException("Failed to read schema minor version from db_info table");
3198  }
3199 
3200  int majorVersion = 0;
3201  String majorVersionStr = null;
3202  resultSet = statement.executeQuery("SELECT value FROM db_info WHERE name='" + AbstractSqlEamDb.SCHEMA_MAJOR_VERSION_KEY + "'");
3203  if (resultSet.next()) {
3204  majorVersionStr = resultSet.getString("value");
3205  try {
3206  majorVersion = Integer.parseInt(majorVersionStr);
3207  } catch (NumberFormatException ex) {
3208  throw new EamDbException("Bad value for schema version (" + majorVersionStr + ") - database is corrupt", ex);
3209  }
3210  } else {
3211  throw new EamDbException("Failed to read schema major version from db_info table");
3212  }
3213 
3214  /*
3215  * IMPORTANT: The code that follows had a bug in it prior to Autopsy
3216  * 4.10.0. The consequence of the bug is that the schema version
3217  * number is always reset to 1.0 or 1.1 if a Central Repository is
3218  * opened by an Autopsy 4.9.1 or earlier client. To cope with this,
3219  * there is an effort in updates to 1.2 and greater to not retry
3220  * schema updates that may already have been done once.
3221  */
3222  CaseDbSchemaVersionNumber dbSchemaVersion = new CaseDbSchemaVersionNumber(majorVersion, minorVersion);
3223  if (dbSchemaVersion.equals(CURRENT_DB_SCHEMA_VERSION)) {
3224  logger.log(Level.INFO, "Central Repository is up to date");
3225  return;
3226  }
3227  if (dbSchemaVersion.compareTo(CURRENT_DB_SCHEMA_VERSION) > 0) {
3228  logger.log(Level.INFO, "Central Repository is of newer version than software creates");
3229  return;
3230  }
3231 
3233 
3234  /*
3235  * Update to 1.1
3236  */
3237  if (dbSchemaVersion.compareTo(new CaseDbSchemaVersionNumber(1, 1)) < 0) {
3238  statement.execute("ALTER TABLE reference_sets ADD COLUMN known_status INTEGER;"); //NON-NLS
3239  statement.execute("ALTER TABLE reference_sets ADD COLUMN read_only BOOLEAN;"); //NON-NLS
3240  statement.execute("ALTER TABLE reference_sets ADD COLUMN type INTEGER;"); //NON-NLS
3241 
3242  // There's an outide chance that the user has already made an organization with the default name,
3243  // and the default org being missing will not impact any database operations, so continue on
3244  // regardless of whether this succeeds.
3245  EamDbUtil.insertDefaultOrganization(conn);
3246  }
3247 
3248  /*
3249  * Update to 1.2
3250  */
3251  if (dbSchemaVersion.compareTo(new CaseDbSchemaVersionNumber(1, 2)) < 0) {
3252  final String addIntegerColumnTemplate = "ALTER TABLE %s ADD COLUMN %s INTEGER;"; //NON-NLS
3253  final String addSsidTableTemplate;
3254  final String addCaseIdIndexTemplate;
3255  final String addDataSourceIdIndexTemplate;
3256  final String addValueIndexTemplate;
3257  final String addKnownStatusIndexTemplate;
3258  final String addObjectIdIndexTemplate;
3259 
3260  final String addAttributeSql;
3261  //get the data base specific code for creating a new _instance table
3262  switch (selectedPlatform) {
3263  case POSTGRESQL:
3264  addAttributeSql = "INSERT INTO correlation_types(id, display_name, db_table_name, supported, enabled) VALUES (?, ?, ?, ?, ?) " + getConflictClause(); //NON-NLS
3265 
3266  addSsidTableTemplate = PostgresEamDbSettings.getCreateArtifactInstancesTableTemplate();
3267  addCaseIdIndexTemplate = PostgresEamDbSettings.getAddCaseIdIndexTemplate();
3268  addDataSourceIdIndexTemplate = PostgresEamDbSettings.getAddDataSourceIdIndexTemplate();
3269  addValueIndexTemplate = PostgresEamDbSettings.getAddValueIndexTemplate();
3270  addKnownStatusIndexTemplate = PostgresEamDbSettings.getAddKnownStatusIndexTemplate();
3271  addObjectIdIndexTemplate = PostgresEamDbSettings.getAddObjectIdIndexTemplate();
3272  break;
3273  case SQLITE:
3274  addAttributeSql = "INSERT OR IGNORE INTO correlation_types(id, display_name, db_table_name, supported, enabled) VALUES (?, ?, ?, ?, ?)"; //NON-NLS
3275 
3276  addSsidTableTemplate = SqliteEamDbSettings.getCreateArtifactInstancesTableTemplate();
3277  addCaseIdIndexTemplate = SqliteEamDbSettings.getAddCaseIdIndexTemplate();
3278  addDataSourceIdIndexTemplate = SqliteEamDbSettings.getAddDataSourceIdIndexTemplate();
3279  addValueIndexTemplate = SqliteEamDbSettings.getAddValueIndexTemplate();
3280  addKnownStatusIndexTemplate = SqliteEamDbSettings.getAddKnownStatusIndexTemplate();
3281  addObjectIdIndexTemplate = SqliteEamDbSettings.getAddObjectIdIndexTemplate();
3282  break;
3283  default:
3284  throw new EamDbException("Currently selected database platform \"" + selectedPlatform.name() + "\" can not be upgraded.");
3285  }
3286  final String dataSourcesTableName = "data_sources";
3287  final String dataSourceObjectIdColumnName = "datasource_obj_id";
3288  if (!doesColumnExist(conn, dataSourcesTableName, dataSourceObjectIdColumnName)) {
3289  statement.execute(String.format(addIntegerColumnTemplate, dataSourcesTableName, dataSourceObjectIdColumnName)); //NON-NLS
3290  }
3291  final String dataSourceObjectIdIndexTemplate = "CREATE INDEX IF NOT EXISTS datasource_object_id ON data_sources (%s)";
3292  statement.execute(String.format(dataSourceObjectIdIndexTemplate, dataSourceObjectIdColumnName));
3293  List<String> instaceTablesToAdd = new ArrayList<>();
3294  //update central repository to be able to store new correlation attributes
3295  final String wirelessNetworksDbTableName = "wireless_networks";
3296  instaceTablesToAdd.add(wirelessNetworksDbTableName + "_instances");
3297  final String macAddressDbTableName = "mac_address";
3298  instaceTablesToAdd.add(macAddressDbTableName + "_instances");
3299  final String imeiNumberDbTableName = "imei_number";
3300  instaceTablesToAdd.add(imeiNumberDbTableName + "_instances");
3301  final String iccidNumberDbTableName = "iccid_number";
3302  instaceTablesToAdd.add(iccidNumberDbTableName + "_instances");
3303  final String imsiNumberDbTableName = "imsi_number";
3304  instaceTablesToAdd.add(imsiNumberDbTableName + "_instances");
3305 
3306  //add the wireless_networks attribute to the correlation_types table
3307  preparedStatement = conn.prepareStatement(addAttributeSql);
3308  preparedStatement.setInt(1, CorrelationAttributeInstance.SSID_TYPE_ID);
3309  preparedStatement.setString(2, Bundle.CorrelationType_SSID_displayName());
3310  preparedStatement.setString(3, wirelessNetworksDbTableName);
3311  preparedStatement.setInt(4, 1);
3312  preparedStatement.setInt(5, 1);
3313  preparedStatement.execute();
3314 
3315  //add the mac_address attribute to the correlation_types table
3316  preparedStatement = conn.prepareStatement(addAttributeSql);
3317  preparedStatement.setInt(1, CorrelationAttributeInstance.MAC_TYPE_ID);
3318  preparedStatement.setString(2, Bundle.CorrelationType_MAC_displayName());
3319  preparedStatement.setString(3, macAddressDbTableName);
3320  preparedStatement.setInt(4, 1);
3321  preparedStatement.setInt(5, 1);
3322  preparedStatement.execute();
3323 
3324  //add the imei_number attribute to the correlation_types table
3325  preparedStatement = conn.prepareStatement(addAttributeSql);
3326  preparedStatement.setInt(1, CorrelationAttributeInstance.IMEI_TYPE_ID);
3327  preparedStatement.setString(2, Bundle.CorrelationType_IMEI_displayName());
3328  preparedStatement.setString(3, imeiNumberDbTableName);
3329  preparedStatement.setInt(4, 1);
3330  preparedStatement.setInt(5, 1);
3331  preparedStatement.execute();
3332 
3333  //add the imsi_number attribute to the correlation_types table
3334  preparedStatement = conn.prepareStatement(addAttributeSql);
3335  preparedStatement.setInt(1, CorrelationAttributeInstance.IMSI_TYPE_ID);
3336  preparedStatement.setString(2, Bundle.CorrelationType_IMSI_displayName());
3337  preparedStatement.setString(3, imsiNumberDbTableName);
3338  preparedStatement.setInt(4, 1);
3339  preparedStatement.setInt(5, 1);
3340  preparedStatement.execute();
3341 
3342  //add the iccid_number attribute to the correlation_types table
3343  preparedStatement = conn.prepareStatement(addAttributeSql);
3344  preparedStatement.setInt(1, CorrelationAttributeInstance.ICCID_TYPE_ID);
3345  preparedStatement.setString(2, Bundle.CorrelationType_ICCID_displayName());
3346  preparedStatement.setString(3, iccidNumberDbTableName);
3347  preparedStatement.setInt(4, 1);
3348  preparedStatement.setInt(5, 1);
3349  preparedStatement.execute();
3350 
3351  //create a new _instances tables and add indexes for their columns
3352  for (String tableName : instaceTablesToAdd) {
3353  statement.execute(String.format(addSsidTableTemplate, tableName, tableName));
3354  statement.execute(String.format(addCaseIdIndexTemplate, tableName, tableName));
3355  statement.execute(String.format(addDataSourceIdIndexTemplate, tableName, tableName));
3356  statement.execute(String.format(addValueIndexTemplate, tableName, tableName));
3357  statement.execute(String.format(addKnownStatusIndexTemplate, tableName, tableName));
3358  }
3359 
3360  //add file_obj_id column to _instances table which do not already have it
3361  String instance_type_dbname;
3362  final String objectIdColumnName = "file_obj_id";
3364  instance_type_dbname = EamDbUtil.correlationTypeToInstanceTableName(type);
3365  if (!doesColumnExist(conn, instance_type_dbname, objectIdColumnName)) {
3366  statement.execute(String.format(addIntegerColumnTemplate, instance_type_dbname, objectIdColumnName)); //NON-NLS
3367  }
3368  statement.execute(String.format(addObjectIdIndexTemplate, instance_type_dbname, instance_type_dbname));
3369  }
3370 
3371  /*
3372  * Add hash columns to the data_sources table.
3373  */
3374  if (!doesColumnExist(conn, dataSourcesTableName, "md5")) {
3375  statement.execute("ALTER TABLE data_sources ADD COLUMN md5 TEXT DEFAULT NULL");
3376  }
3377  if (!doesColumnExist(conn, dataSourcesTableName, "sha1")) {
3378  statement.execute("ALTER TABLE data_sources ADD COLUMN sha1 TEXT DEFAULT NULL");
3379  }
3380  if (!doesColumnExist(conn, dataSourcesTableName, "sha256")) {
3381  statement.execute("ALTER TABLE data_sources ADD COLUMN sha256 TEXT DEFAULT NULL");
3382  }
3383 
3384  /*
3385  * Drop the db_info table and add it back in with the name
3386  * column having a UNIQUE constraint. The name column could now
3387  * be used as the primary key, but the essentially useless id
3388  * column is retained for the sake of backwards compatibility.
3389  * Note that the creation schema version number is set to 0.0
3390  * to indicate that it is unknown.
3391  */
3392  String creationMajorVer;
3393  resultSet = statement.executeQuery("SELECT value FROM db_info WHERE name = '" + AbstractSqlEamDb.CREATION_SCHEMA_MAJOR_VERSION_KEY + "'");
3394  if (resultSet.next()) {
3395  creationMajorVer = resultSet.getString("value");
3396  } else {
3397  creationMajorVer = "0";
3398  }
3399  String creationMinorVer;
3400  resultSet = statement.executeQuery("SELECT value FROM db_info WHERE name = '" + AbstractSqlEamDb.CREATION_SCHEMA_MINOR_VERSION_KEY + "'");
3401  if (resultSet.next()) {
3402  creationMinorVer = resultSet.getString("value");
3403  } else {
3404  creationMinorVer = "0";
3405  }
3406  statement.execute("DROP TABLE db_info");
3407  if (selectedPlatform == EamDbPlatformEnum.POSTGRESQL) {
3408  statement.execute("CREATE TABLE db_info (id SERIAL, name TEXT UNIQUE NOT NULL, value TEXT NOT NULL)");
3409  } else {
3410  statement.execute("CREATE TABLE db_info (id INTEGER PRIMARY KEY, name TEXT UNIQUE NOT NULL, value TEXT NOT NULL)");
3411  }
3412  statement.execute("INSERT INTO db_info (name, value) VALUES ('" + AbstractSqlEamDb.SCHEMA_MAJOR_VERSION_KEY + "','" + majorVersionStr + "')");
3413  statement.execute("INSERT INTO db_info (name, value) VALUES ('" + AbstractSqlEamDb.SCHEMA_MINOR_VERSION_KEY + "','" + minorVersionStr + "')");
3414  statement.execute("INSERT INTO db_info (name, value) VALUES ('" + AbstractSqlEamDb.CREATION_SCHEMA_MAJOR_VERSION_KEY + "','" + creationMajorVer + "')");
3415  statement.execute("INSERT INTO db_info (name, value) VALUES ('" + AbstractSqlEamDb.CREATION_SCHEMA_MINOR_VERSION_KEY + "','" + creationMinorVer + "')");
3416  }
3417 
3418  updateSchemaVersion(conn);
3419  conn.commit();
3420  logger.log(Level.INFO, String.format("Central Repository schema updated to version %s", CURRENT_DB_SCHEMA_VERSION));
3421 
3422  } catch (SQLException | EamDbException ex) {
3423  try {
3424  if (conn != null) {
3425  conn.rollback();
3426  }
3427  } catch (SQLException ex2) {
3428  logger.log(Level.SEVERE, String.format("Central Repository rollback of failed schema update to %s failed", CURRENT_DB_SCHEMA_VERSION), ex2);
3429  }
3430  throw ex;
3431  } finally {
3432  EamDbUtil.closeResultSet(resultSet);
3433  EamDbUtil.closeStatement(preparedStatement);
3434  EamDbUtil.closeStatement(statement);
3435  EamDbUtil.closeConnection(conn);
3436  }
3437  }
3438 
3439 }
static String correlationTypeToInstanceTableName(CorrelationAttributeInstance.Type type)
Definition: EamDbUtil.java:325
static TimingMetric getTimingMetric(String name)
static String normalize(CorrelationAttributeInstance.Type attributeType, String data)
CorrelationAttributeInstance.Type getCorrelationTypeById(int typeId)
static void submitTimingMetric(TimingMetric metric)
synchronized static Logger getLogger(String name)
Definition: Logger.java:124
static String correlationTypeToReferenceTableName(CorrelationAttributeInstance.Type type)
Definition: EamDbUtil.java:336

Copyright © 2012-2018 Basis Technology. Generated on: Tue Dec 18 2018
This work is licensed under a Creative Commons Attribution-Share Alike 3.0 United States License.