55public final class OsAccountManager {
58 private final Object osAcctInstancesCacheLock;
59 private final NavigableMap<OsAccountInstanceKey, OsAccountInstance> osAccountInstanceCache;
69 osAcctInstancesCacheLock =
new Object();
70 osAccountInstanceCache =
new ConcurrentSkipListMap<>();
89 if (Strings.isNullOrEmpty(uniqueAccountId)) {
106 }
catch (SQLException ex) {
112 Optional<OsAccount> osAccount = this.getOsAccountByAddr(uniqueAccountId, realm);
113 if (osAccount.isPresent()) {
114 return osAccount.get();
118 throw new TskCoreException(String.format(
"Error creating OsAccount with uniqueAccountId = %s in realm id = %d", uniqueAccountId, realm.getRealmId()), ex);
156 if (realmScope ==
null) {
157 throw new TskCoreException(
"RealmScope cannot be null. Use UNKNOWN if scope is not known.");
159 if (referringHost ==
null) {
160 throw new TskCoreException(
"A referring host is required to create an account.");
164 if ((StringUtils.isBlank(sid) || sid.equalsIgnoreCase(WindowsAccountUtils.WINDOWS_NULL_SID))
165 && StringUtils.isBlank(loginName)) {
166 throw new TskCoreException(
"Cannot create OS account with both uniqueId and loginName as null.");
169 if ((StringUtils.isBlank(sid) || sid.equalsIgnoreCase(WindowsAccountUtils.WINDOWS_NULL_SID))
170 && StringUtils.isBlank(realmName)) {
171 throw new TskCoreException(
"Realm name or SID is required to create a Windows account.");
174 if (!StringUtils.isBlank(sid) && !sid.equalsIgnoreCase(WindowsAccountUtils.WINDOWS_NULL_SID) && !WindowsAccountUtils.isWindowsUserSid(sid)) {
175 throw new OsAccountManager.NotUserSIDException(String.format(
"SID = %s is not a user SID.", sid));
179 if (StringUtils.isBlank(sid)
180 && !StringUtils.isBlank(loginName) && !StringUtils.isBlank(realmName)
181 && WindowsAccountUtils.isWindowsWellKnownAccountName(loginName, realmName)) {
182 sid = WindowsAccountUtils.getWindowsWellKnownAccountSid(loginName, realmName);
186 if (StringUtils.isNotBlank(sid)) {
188 sid = sid.toUpperCase(Locale.ENGLISH);
190 if (StringUtils.isNotBlank(loginName)) {
192 loginName = loginName.toLowerCase(Locale.ENGLISH);
194 if (StringUtils.isNotBlank(realmName)) {
196 realmName = realmName.toLowerCase(Locale.ENGLISH);
201 Optional<OsAccountRealm> anotherRealmWithSameName = Optional.empty();
202 Optional<OsAccountRealm> anotherRealmWithSameAddr = Optional.empty();
206 try (CaseDbConnection connection = db.getConnection()) {
207 realmUpdateResult = db.getOsAccountRealmManager().getAndUpdateWindowsRealm(sid, realmName, referringHost, connection);
209 Optional<OsAccountRealm> realmOptional = realmUpdateResult.
getUpdatedRealm();
210 if (realmOptional.isPresent()) {
211 realm = realmOptional.get();
219 anotherRealmWithSameName = db.getOsAccountRealmManager().getAnotherRealmByName(realmOptional.get(), realmName, referringHost, connection);
220 if (anotherRealmWithSameName.isPresent() && anotherRealmWithSameName.get().getRealmAddr().isPresent()) {
222 anotherRealmWithSameName = Optional.empty();
226 anotherRealmWithSameAddr = db.getOsAccountRealmManager().getAnotherRealmByAddr(realmOptional.get(), realmName, referringHost, connection);
227 if (anotherRealmWithSameAddr.isPresent() && !anotherRealmWithSameAddr.get().getRealmNames().isEmpty()) {
229 anotherRealmWithSameName = Optional.empty();
237 realm = db.getOsAccountRealmManager().newWindowsRealm(sid, realmName, referringHost, realmScope);
240 if (anotherRealmWithSameName.isPresent() || anotherRealmWithSameAddr.isPresent()) {
244 if (anotherRealmWithSameName.isPresent()) {
245 db.getOsAccountRealmManager().mergeRealms(anotherRealmWithSameName.get(), realm, trans);
247 if (anotherRealmWithSameAddr.isPresent()) {
248 db.getOsAccountRealmManager().mergeRealms(anotherRealmWithSameAddr.get(), realm, trans);
283 if ((StringUtils.isBlank(sid) || sid.equalsIgnoreCase(WindowsAccountUtils.WINDOWS_NULL_SID))
284 && StringUtils.isBlank(loginName)) {
285 throw new TskCoreException(
"Cannot create OS account with both uniqueId and loginName as null.");
288 if (!StringUtils.isBlank(sid) && !sid.equalsIgnoreCase(WindowsAccountUtils.WINDOWS_NULL_SID) && !WindowsAccountUtils.isWindowsUserSid(sid)) {
289 throw new OsAccountManager.NotUserSIDException(String.format(
"SID = %s is not a user SID.", sid));
293 String resolvedLoginName = WindowsAccountUtils.toWellknownEnglishLoginName(loginName);
299 String uniqueId = (!StringUtils.isBlank(sid) && !sid.equalsIgnoreCase(WindowsAccountUtils.WINDOWS_NULL_SID)) ? sid :
null;
300 if (!StringUtils.isBlank(sid) && !sid.equalsIgnoreCase(WindowsAccountUtils.WINDOWS_NULL_SID) && isWindowsWellKnownSid(sid)) {
302 String wellKnownLoginName = WindowsAccountUtils.getWindowsWellKnownSidLoginName(sid);
303 if (!StringUtils.isEmpty(wellKnownLoginName)) {
304 resolvedLoginName = wellKnownLoginName;
311 if (!StringUtils.isBlank(sid) && !sid.equalsIgnoreCase(WindowsAccountUtils.WINDOWS_NULL_SID) && isWindowsWellKnownSid(sid)) {
312 String fullName = getWindowsWellKnownSidFullName(sid);
313 if (StringUtils.isNotBlank(fullName)) {
323 }
catch (SQLException ex) {
329 Optional<OsAccount> osAccount;
332 if (!Strings.isNullOrEmpty(sid)) {
333 osAccount = getOsAccountByAddr(sid, realm);
334 if (osAccount.isPresent()) {
335 return osAccount.get();
340 if (!Strings.isNullOrEmpty(resolvedLoginName)) {
341 osAccount = getOsAccountByLoginName(resolvedLoginName, realm);
342 if (osAccount.isPresent()) {
343 return osAccount.get();
348 throw new TskCoreException(String.format(
"Error creating OsAccount with sid = %s, loginName = %s, realm = %s, referring host = %s",
349 (sid !=
null) ? sid :
"Null",
350 (resolvedLoginName !=
null) ? resolvedLoginName :
"Null",
380 if (referringHost ==
null) {
381 throw new TskCoreException(
"A referring host is required to create a local OS account.");
385 if (StringUtils.isBlank(uid) && StringUtils.isBlank(loginName)) {
386 throw new TskCoreException(
"Cannot create OS account with both uniqueId and loginName as null.");
389 OsAccountRealm localRealm = db.getOsAccountRealmManager().newLocalLinuxRealm(referringHost);
400 }
catch (SQLException ex) {
406 Optional<OsAccount> osAccount;
409 if (!Strings.isNullOrEmpty(uid)) {
410 osAccount = getOsAccountByAddr(uid, localRealm);
411 if (osAccount.isPresent()) {
412 return osAccount.get();
417 if (!Strings.isNullOrEmpty(loginName)) {
418 osAccount = getOsAccountByLoginName(loginName, localRealm);
419 if (osAccount.isPresent()) {
420 return osAccount.get();
425 throw new TskCoreException(String.format(
"Error creating OsAccount with uid = %s, loginName = %s, realm = %s, referring host = %s",
426 (uid !=
null) ? uid :
"Null",
427 (loginName !=
null) ? loginName :
"Null",
455 if (Objects.isNull(realm)) {
459 String signature = getOsAccountSignature(uniqueId, loginName);
462 CaseDbConnection connection = trans.getConnection();
467 long parentObjId = 0;
469 int objTypeId = TskData.ObjectType.OS_ACCOUNT.getObjectType();
470 long osAccountObjId = db.addObject(parentObjId, objTypeId, connection);
472 String accountInsertSQL =
"INSERT INTO tsk_os_accounts(os_account_obj_id, login_name, realm_id, addr, signature, status)"
473 +
" VALUES (?, ?, ?, ?, ?, ?)";
475 PreparedStatement preparedStatement = connection.getPreparedStatement(accountInsertSQL, Statement.NO_GENERATED_KEYS);
476 preparedStatement.clearParameters();
478 preparedStatement.setLong(1, osAccountObjId);
480 preparedStatement.setString(2, loginName);
481 preparedStatement.setLong(3, realm.getRealmId());
483 preparedStatement.setString(4, uniqueId);
484 preparedStatement.setString(5, signature);
485 preparedStatement.setInt(6, accountStatus.getId());
487 connection.executeUpdate(preparedStatement);
489 account =
new OsAccount(db, osAccountObjId, realm.getRealmId(), loginName, uniqueId, signature,
490 null,
null,
null, accountStatus, OsAccount.OsAccountDbStatus.ACTIVE);
492 trans.registerAddedOsAccount(account);
507 private Optional<OsAccount> getOsAccountByAddr(String addr, Host host)
throws TskCoreException {
509 try (CaseDbConnection connection = db.getConnection()) {
510 return getOsAccountByAddr(addr, host, connection);
526 private Optional<OsAccount> getOsAccountByAddr(String uniqueId, Host host, CaseDbConnection connection)
throws TskCoreException {
528 String whereHostClause = (host ==
null)
530 :
" ( realms.scope_host_id = " + host.getHostId() +
" OR realms.scope_host_id IS NULL) ";
532 String queryString =
"SELECT accounts.os_account_obj_id as os_account_obj_id, accounts.login_name, accounts.full_name, "
533 +
" accounts.realm_id, accounts.addr, accounts.signature, "
534 +
" accounts.type, accounts.status, accounts.created_date, accounts.db_status, "
535 +
" realms.realm_name as realm_name, realms.realm_addr as realm_addr, realms.realm_signature, realms.scope_host_id, realms.scope_confidence, realms.db_status as realm_db_status "
536 +
" FROM tsk_os_accounts as accounts"
537 +
" LEFT JOIN tsk_os_account_realms as realms"
538 +
" ON accounts.realm_id = realms.id"
539 +
" WHERE " + whereHostClause
540 +
" AND accounts.db_status = " + OsAccount.OsAccountDbStatus.ACTIVE.getId()
541 +
" AND accounts.addr = '" + uniqueId +
"'";
543 db.acquireSingleUserCaseReadLock();
544 try (Statement s = connection.createStatement();
545 ResultSet rs = connection.executeQuery(s, queryString)) {
548 return Optional.empty();
550 return Optional.of(osAccountFromResultSet(rs));
552 }
catch (SQLException ex) {
553 throw new TskCoreException(String.format(
"Error getting OS account for unique id = %s and host = %s", uniqueId, (host !=
null ? host.getName() :
"null")), ex);
555 db.releaseSingleUserCaseReadLock();
572 String queryString =
"SELECT * FROM tsk_os_accounts"
573 +
" WHERE addr = '" + uniqueId +
"'"
575 +
" AND realm_id = " + realm.getRealmId();
578 try (CaseDbConnection connection = this.db.getConnection();
579 Statement s = connection.createStatement();
580 ResultSet rs = connection.executeQuery(s, queryString)) {
583 return Optional.empty();
585 return Optional.of(osAccountFromResultSet(rs));
587 }
catch (SQLException ex) {
588 throw new TskCoreException(String.format(
"Error getting OS account for realm = %s and uniqueId = %s.", (realm !=
null) ? realm.getSignature() :
"NULL", uniqueId), ex);
607 String queryString =
"SELECT * FROM tsk_os_accounts"
608 +
" WHERE login_name = '" + loginName +
"'"
610 +
" AND realm_id = " + realm.getRealmId();
613 try (CaseDbConnection connection = this.db.getConnection();
614 Statement s = connection.createStatement();
615 ResultSet rs = connection.executeQuery(s, queryString)) {
618 return Optional.empty();
620 return Optional.of(osAccountFromResultSet(rs));
622 }
catch (SQLException ex) {
623 throw new TskCoreException(String.format(
"Error getting OS account for realm = %s and loginName = %s.", (realm !=
null) ? realm.getSignature() :
"NULL", loginName), ex);
640 try (CaseDbConnection connection = this.db.getConnection()) {
657 String queryString =
"SELECT * FROM tsk_os_accounts"
658 +
" WHERE os_account_obj_id = " + osAccountObjId;
661 try (Statement s = connection.createStatement();
662 ResultSet rs = connection.executeQuery(s, queryString)) {
665 throw new TskCoreException(String.format(
"No account found with obj id = %d ", osAccountObjId));
667 return osAccountFromResultSet(rs);
669 }
catch (SQLException ex) {
670 throw new TskCoreException(String.format(
"Error getting account with obj id = %d ", osAccountObjId), ex);
701 if (osAccount ==
null) {
702 throw new TskCoreException(
"Cannot create account instance with null account.");
704 if (dataSource ==
null) {
705 throw new TskCoreException(
"Cannot create account instance with null data source.");
709 Optional<OsAccountInstance> existingInstance = cachedAccountInstance(osAccount.getId(), dataSource.getId(), instanceType);
710 if (existingInstance.isPresent()) {
711 return existingInstance.get();
714 try (CaseDbConnection connection = this.db.getConnection()) {
736 Optional<OsAccountInstance> existingInstance = cachedAccountInstance(osAccountId, dataSourceObjId, instanceType);
737 if (existingInstance.isPresent()) {
738 return existingInstance.get();
746 String accountInsertSQL = db.getInsertOrIgnoreSQL(
"INTO tsk_os_account_instances(os_account_obj_id, data_source_obj_id, instance_type)"
747 +
" VALUES (?, ?, ?)");
748 PreparedStatement preparedStatement = connection.getPreparedStatement(accountInsertSQL, Statement.RETURN_GENERATED_KEYS);
749 preparedStatement.clearParameters();
750 preparedStatement.setLong(1, osAccountId);
751 preparedStatement.setLong(2, dataSourceObjId);
752 preparedStatement.setInt(3, instanceType.getId());
753 connection.executeUpdate(preparedStatement);
754 try (ResultSet resultSet = preparedStatement.getGeneratedKeys();) {
755 if (resultSet.next()) {
756 OsAccountInstance accountInstance =
new OsAccountInstance(db, resultSet.getLong(1), osAccountId, dataSourceObjId, instanceType);
757 synchronized (osAcctInstancesCacheLock) {
758 OsAccountInstanceKey key =
new OsAccountInstanceKey(osAccountId, dataSourceObjId);
760 for (OsAccountInstance.OsAccountInstanceType type : OsAccountInstance.OsAccountInstanceType.values()) {
761 if (accountInstance.getInstanceType().compareTo(type) < 0) {
762 osAccountInstanceCache.remove(key);
766 osAccountInstanceCache.put(key, accountInstance);
785 return accountInstance;
790 Optional<OsAccountInstance> existingInstanceRetry = cachedAccountInstance(osAccountId, dataSourceObjId, instanceType);
791 if (existingInstanceRetry.isPresent()) {
792 return existingInstanceRetry.get();
796 }
catch (SQLException ex) {
797 throw new TskCoreException(String.format(
"Error adding OS account instance for OS account object id = %d, data source object id = %d", osAccountId, dataSourceObjId), ex);
805 String whereClause =
" tsk_os_account_instances.os_account_obj_id = " + osAccountId
806 +
" AND tsk_os_account_instances.data_source_obj_id = " + dataSourceObjId;
807 List<OsAccountInstance> instances = getOsAccountInstances(whereClause);
808 if (instances.isEmpty()) {
809 throw new TskCoreException(String.format(
"Could not get autogen key after row insert or reload instance for OS account instance. OS account object id = %d, data source object id = %d", osAccountId, dataSourceObjId));
813 synchronized (osAcctInstancesCacheLock) {
814 OsAccountInstanceKey key =
new OsAccountInstanceKey(osAccountId, dataSourceObjId);
817 if (accountInstance.getInstanceType().compareTo(type) < 0) {
818 osAccountInstanceCache.remove(key);
822 osAccountInstanceCache.put(key, accountInstance);
824 return accountInstance;
852 synchronized (osAcctInstancesCacheLock) {
853 OsAccountInstanceKey key =
new OsAccountInstanceKey(osAccountId, dataSourceObjId);
855 if (instance !=
null) {
857 if (instanceType.compareTo(instance.getInstanceType()) >= 0) {
858 return Optional.of(instance);
861 return Optional.empty();
875 String queryString =
"SELECT * FROM tsk_os_accounts accounts "
876 +
"WHERE accounts.os_account_obj_id IN "
877 +
"(SELECT instances.os_account_obj_id "
878 +
"FROM tsk_os_account_instances instances "
879 +
"INNER JOIN data_source_info datasources ON datasources.obj_id = instances.data_source_obj_id "
880 +
"WHERE datasources.host_id = " + host.getHostId() +
") "
883 db.acquireSingleUserCaseReadLock();
884 try (CaseDbConnection connection = this.db.getConnection();
885 Statement s = connection.createStatement();
886 ResultSet rs = connection.executeQuery(s, queryString)) {
888 List<OsAccount> accounts =
new ArrayList<>();
890 accounts.add(osAccountFromResultSet(rs));
893 }
catch (SQLException ex) {
894 throw new TskCoreException(String.format(
"Error getting OS accounts for host id = %d", host.getHostId()), ex);
896 db.releaseSingleUserCaseReadLock();
910 String queryString =
"SELECT * FROM tsk_os_accounts acc "
911 +
"WHERE acc.os_account_obj_id IN "
912 +
"(SELECT instance.os_account_obj_id "
913 +
"FROM tsk_os_account_instances instance "
914 +
"WHERE instance.data_source_obj_id = " + dataSourceId +
") "
917 db.acquireSingleUserCaseReadLock();
918 try (CaseDbConnection connection = this.db.getConnection();
919 Statement s = connection.createStatement();
920 ResultSet rs = connection.executeQuery(s, queryString)) {
922 List<OsAccount> accounts =
new ArrayList<>();
924 accounts.add(osAccountFromResultSet(rs));
927 }
catch (SQLException ex) {
928 throw new TskCoreException(String.format(
"Error getting OS accounts for data source id = %d", dataSourceId), ex);
930 db.releaseSingleUserCaseReadLock();
947 List<OsAccount> destinationAccounts = getOsAccounts(destRealm, trans.getConnection());
948 List<OsAccount> sourceAccounts = getOsAccounts(sourceRealm, trans.getConnection());
950 for (
OsAccount sourceAccount : sourceAccounts) {
957 if (sourceAccount.getAddr().isPresent() && sourceAccount.getLoginName().isPresent()) {
958 List<OsAccount> duplicateDestAccounts = destinationAccounts.stream()
959 .filter(p -> p.getAddr().equals(sourceAccount.getAddr())
960 || (p.getLoginName().equals(sourceAccount.getLoginName()) && (!p.getAddr().isPresent())))
961 .collect(Collectors.toList());
962 if (duplicateDestAccounts.size() > 1) {
963 OsAccount combinedDestAccount = duplicateDestAccounts.get(0);
964 duplicateDestAccounts.remove(combinedDestAccount);
965 for (
OsAccount dupeDestAccount : duplicateDestAccounts) {
966 mergeOsAccounts(dupeDestAccount, combinedDestAccount, trans);
975 Optional<OsAccount> matchingDestAccount = getMatchingAccountForMerge(sourceAccount, destinationAccounts,
true);
978 if (matchingDestAccount.isPresent()) {
979 mergeOsAccounts(sourceAccount, matchingDestAccount.get(), trans);
981 String query =
"UPDATE tsk_os_accounts SET realm_id = " + destRealm.getRealmId() +
" WHERE os_account_obj_id = " + sourceAccount.getId();
982 try (Statement s = trans.getConnection().createStatement()) {
983 s.executeUpdate(query);
984 }
catch (SQLException ex) {
987 trans.registerChangedOsAccount(sourceAccount);
999 private Optional<OsAccount> getMatchingAccountForMerge(
OsAccount sourceAccount, List<OsAccount> destinationAccounts,
boolean ignoreCase) {
1004 if (sourceAccount.getAddr().isPresent()) {
1005 List<OsAccount> matchingDestAccounts = destinationAccounts.stream()
1006 .filter(p -> p.getAddr().equals(sourceAccount.getAddr()))
1007 .collect(Collectors.toList());
1008 if (!matchingDestAccounts.isEmpty()) {
1009 matchingDestAccount = matchingDestAccounts.get(0);
1018 if (matchingDestAccount ==
null && sourceAccount.getLoginName().isPresent()) {
1019 List<OsAccount> matchingDestAccounts = destinationAccounts.stream()
1020 .filter(p -> p.getLoginName().isPresent())
1021 .filter(p -> ( ( ignoreCase ? p.getLoginName().get().equalsIgnoreCase(sourceAccount.getLoginName().get())
1022 : p.getLoginName().get().equals(sourceAccount.getLoginName().get()) )
1023 && ((!sourceAccount.getAddr().isPresent()) || (!p.getAddr().isPresent()))))
1024 .collect(Collectors.toList());
1025 if (!matchingDestAccounts.isEmpty()) {
1026 matchingDestAccount = matchingDestAccounts.get(0);
1030 return Optional.ofNullable(matchingDestAccount);
1043 Long realmId = account.getRealmId();
1047 List<OsAccount> osAccounts = getOsAccounts(realm, trans.getConnection());
1048 osAccounts.removeIf(acc -> Objects.equals(acc.getId(), account.getId()));
1051 Optional<OsAccount> matchingAccount = getMatchingAccountForMerge(account, osAccounts, ignoreCase);
1054 if (matchingAccount.isPresent()) {
1055 mergeOsAccounts(matchingAccount.get(), account, trans);
1076 try (Statement s = trans.getConnection().createStatement()) {
1079 query = makeOsAccountUpdateQuery(
"tsk_os_account_attributes", sourceAccount, destAccount);
1080 s.executeUpdate(query);
1084 query =
"DELETE FROM tsk_os_account_instances "
1087 +
" sourceAccountInstance.id "
1089 +
" tsk_os_account_instances destAccountInstance "
1090 +
"INNER JOIN tsk_os_account_instances sourceAccountInstance ON destAccountInstance.data_source_obj_id = sourceAccountInstance.data_source_obj_id "
1091 +
"WHERE destAccountInstance.os_account_obj_id = " + destAccount.getId()
1092 +
" AND sourceAccountInstance.os_account_obj_id = " + sourceAccount.getId()
1093 +
" AND sourceAccountInstance.instance_type = destAccountInstance.instance_type" +
")";
1095 s.executeUpdate(query);
1097 query = makeOsAccountUpdateQuery(
"tsk_os_account_instances", sourceAccount, destAccount);
1098 s.executeUpdate(query);
1099 synchronized (osAcctInstancesCacheLock) {
1100 osAccountInstanceCache.clear();
1103 query = makeOsAccountUpdateQuery(
"tsk_files", sourceAccount, destAccount);
1104 s.executeUpdate(query);
1106 query = makeOsAccountUpdateQuery(
"tsk_data_artifacts", sourceAccount, destAccount);
1107 s.executeUpdate(query);
1111 trans.registerMergedOsAccount(sourceAccount.getId(), destAccount.getId());
1114 String mergedSignature = makeMergedOsAccountSignature();
1115 query =
"UPDATE tsk_os_accounts SET merged_into = " + destAccount.getId()
1117 +
", signature = '" + mergedSignature +
"' "
1118 +
" WHERE os_account_obj_id = " + sourceAccount.getId();
1120 s.executeUpdate(query);
1121 trans.registerDeletedOsAccount(sourceAccount.getId());
1126 mergeOsAccountObjectsAndUpdateDestAccount(sourceAccount, destAccount, trans);
1127 }
catch (SQLException ex) {
1137 private String makeMergedOsAccountSignature() {
1138 return "MERGED " + UUID.randomUUID().toString();
1150 private String makeOsAccountUpdateQuery(String tableName,
OsAccount sourceAccount,
OsAccount destAccount) {
1151 return "UPDATE " + tableName +
" SET os_account_obj_id = " + destAccount.getId() +
" WHERE os_account_obj_id = " + sourceAccount.getId();
1167 OsAccount mergedDestAccount = destAccount;
1169 String destLoginName =
null;
1170 String destAddr =
null;
1173 if (!destAccount.getLoginName().isPresent() && sourceAccount.getLoginName().isPresent()) {
1174 destLoginName = sourceAccount.getLoginName().get();
1177 if (!destAccount.getAddr().isPresent() && sourceAccount.getAddr().isPresent()) {
1178 destAddr = sourceAccount.getAddr().get();
1182 OsAccountUpdateResult updateStatus = this.updateOsAccountCore(destAccount, destAddr, destLoginName, trans);
1184 if (updateStatus.getUpdateStatusCode() == OsAccountUpdateStatus.UPDATED && updateStatus.getUpdatedAccount().isPresent()) {
1185 mergedDestAccount = updateStatus.getUpdatedAccount().get();
1188 String destFullName =
null;
1189 Long destCreationTime =
null;
1190 if (!destAccount.getFullName().isPresent() && sourceAccount.getFullName().isPresent()) {
1191 destFullName = sourceAccount.getFullName().get();
1194 if (!destAccount.getCreationTime().isPresent() && sourceAccount.getCreationTime().isPresent()) {
1195 destCreationTime = sourceAccount.getCreationTime().get();
1199 updateStatus = this.updateStandardOsAccountAttributes(destAccount, destFullName,
null,
null, destCreationTime, trans);
1201 if (updateStatus.getUpdateStatusCode() == OsAccountUpdateStatus.UPDATED && updateStatus.getUpdatedAccount().isPresent()) {
1202 mergedDestAccount = updateStatus.getUpdatedAccount().get();
1205 return mergedDestAccount;
1219 String queryString =
"SELECT * FROM tsk_os_accounts"
1220 +
" WHERE realm_id = " + realm.getRealmId()
1222 +
" ORDER BY os_account_obj_id";
1224 try (Statement s = connection.createStatement();
1225 ResultSet rs = connection.executeQuery(s, queryString)) {
1227 List<OsAccount> accounts =
new ArrayList<>();
1229 accounts.add(osAccountFromResultSet(rs));
1232 }
catch (SQLException ex) {
1233 throw new TskCoreException(String.format(
"Error getting OS accounts for realm id = %d", realm.getRealmId()), ex);
1245 String queryString =
"SELECT * FROM tsk_os_accounts"
1248 db.acquireSingleUserCaseReadLock();
1249 try (CaseDbConnection connection = this.db.getConnection();
1250 Statement s = connection.createStatement();
1251 ResultSet rs = connection.executeQuery(s, queryString)) {
1253 List<OsAccount> accounts =
new ArrayList<>();
1255 accounts.add(osAccountFromResultSet(rs));
1258 }
catch (SQLException ex) {
1259 throw new TskCoreException(String.format(
"Error getting OS accounts"), ex);
1261 db.releaseSingleUserCaseReadLock();
1285 if (referringHost ==
null) {
1286 throw new TskCoreException(
"A referring host is required to get an account.");
1290 if ((StringUtils.isBlank(sid) || (sid.equalsIgnoreCase(WindowsAccountUtils.WINDOWS_NULL_SID)) ) && StringUtils.isBlank(loginName)) {
1291 throw new TskCoreException(
"Cannot get an OS account with both SID and loginName as null.");
1295 if (StringUtils.isBlank(sid)
1296 && !StringUtils.isBlank(loginName) && !StringUtils.isBlank(realmName)
1297 && WindowsAccountUtils.isWindowsWellKnownAccountName(loginName, realmName)) {
1298 sid = WindowsAccountUtils.getWindowsWellKnownAccountSid(loginName, realmName);
1303 if (StringUtils.isNotBlank(sid)) {
1305 sid = sid.toUpperCase(Locale.ENGLISH);
1307 if (StringUtils.isNotBlank(loginName)) {
1309 loginName = loginName.toLowerCase(Locale.ENGLISH);
1311 if (StringUtils.isNotBlank(realmName)) {
1313 realmName = realmName.toLowerCase(Locale.ENGLISH);
1317 Optional<OsAccountRealm> realm = db.getOsAccountRealmManager().getWindowsRealm(sid, realmName, referringHost);
1318 if (!realm.isPresent()) {
1319 return Optional.empty();
1323 if (!Strings.isNullOrEmpty(sid) && !(sid.equalsIgnoreCase(WindowsAccountUtils.WINDOWS_NULL_SID))) {
1324 if (!WindowsAccountUtils.isWindowsUserSid(sid)) {
1325 throw new OsAccountManager.NotUserSIDException(String.format(
"SID = %s is not a user SID.", sid));
1328 Optional<OsAccount> account = this.getOsAccountByAddr(sid, realm.get());
1329 if (account.isPresent()) {
1335 if (!Strings.isNullOrEmpty(loginName)) {
1336 String resolvedLoginName = WindowsAccountUtils.toWellknownEnglishLoginName(loginName);
1337 return this.getOsAccountByLoginName(resolvedLoginName, realm.get());
1339 return Optional.empty();
1358 if (referringHost ==
null) {
1359 throw new TskCoreException(
"A referring host is required to get an account.");
1363 if (StringUtils.isBlank(uid) && StringUtils.isBlank(loginName)) {
1364 throw new TskCoreException(
"Cannot get an OS account with both UID and loginName as null.");
1368 Optional<OsAccountRealm> realm = db.getOsAccountRealmManager().getLocalLinuxRealm(referringHost);
1369 if (!realm.isPresent()) {
1370 return Optional.empty();
1374 if (!Strings.isNullOrEmpty(uid)) {
1375 Optional<OsAccount> account = this.getOsAccountByAddr(uid, realm.get());
1376 if (account.isPresent()) {
1382 if (!Strings.isNullOrEmpty(loginName)) {
1383 return this.getOsAccountByLoginName(loginName, realm.get());
1385 return Optional.empty();
1389 private final Object osAccountLockObj =
new Object();
1401 synchronized (osAccountLockObj) {
1402 db.acquireSingleUserCaseWriteLock();
1404 try (CaseDbConnection connection = db.getConnection()) {
1407 String attributeInsertSQL =
"INSERT INTO tsk_os_account_attributes(os_account_obj_id, host_id, source_obj_id, attribute_type_id, value_type, value_byte, value_text, value_int32, value_int64, value_double)"
1408 +
" VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?)";
1410 PreparedStatement preparedStatement = connection.getPreparedStatement(attributeInsertSQL, Statement.RETURN_GENERATED_KEYS);
1411 preparedStatement.clearParameters();
1413 preparedStatement.setLong(1, account.getId());
1414 if (accountAttribute.getHostId().isPresent()) {
1415 preparedStatement.setLong(2, accountAttribute.getHostId().get());
1417 preparedStatement.setNull(2, java.sql.Types.NULL);
1419 if (accountAttribute.getSourceObjectId().isPresent()) {
1420 preparedStatement.setLong(3, accountAttribute.getSourceObjectId().get());
1422 preparedStatement.setNull(3, java.sql.Types.NULL);
1425 preparedStatement.setLong(4, accountAttribute.getAttributeType().getTypeID());
1426 preparedStatement.setLong(5, accountAttribute.getAttributeType().getValueType().getType());
1429 preparedStatement.setBytes(6, accountAttribute.getValueBytes());
1431 preparedStatement.setBytes(6,
null);
1436 preparedStatement.setString(7, accountAttribute.getValueString());
1438 preparedStatement.setString(7,
null);
1441 preparedStatement.setInt(8, accountAttribute.getValueInt());
1443 preparedStatement.setNull(8, java.sql.Types.NULL);
1448 preparedStatement.setLong(9, accountAttribute.getValueLong());
1450 preparedStatement.setNull(9, java.sql.Types.NULL);
1454 preparedStatement.setDouble(10, accountAttribute.getValueDouble());
1456 preparedStatement.setNull(10, java.sql.Types.NULL);
1459 connection.executeUpdate(preparedStatement);
1461 }
catch (SQLException ex) {
1462 throw new TskCoreException(String.format(
"Error adding OS Account attribute for account id = %d", account.getId()), ex);
1464 db.releaseSingleUserCaseWriteLock();
1467 List<OsAccountAttribute> currentAttribsList = getOsAccountAttributes(account);
1468 account.setAttributesInternal(currentAttribsList);
1470 fireChangeEvent(account);
1484 String queryString =
"SELECT attributes.os_account_obj_id as os_account_obj_id, attributes.host_id as host_id, attributes.source_obj_id as source_obj_id, "
1485 +
" attributes.attribute_type_id as attribute_type_id, attributes.value_type as value_type, attributes.value_byte as value_byte, "
1486 +
" attributes.value_text as value_text, attributes.value_int32 as value_int32, attributes.value_int64 as value_int64, attributes.value_double as value_double, "
1487 +
" hosts.id, hosts.name as host_name, hosts.db_status as host_status "
1488 +
" FROM tsk_os_account_attributes as attributes"
1489 +
" LEFT JOIN tsk_hosts as hosts "
1490 +
" ON attributes.host_id = hosts.id "
1491 +
" WHERE os_account_obj_id = " + account.getId();
1494 try (CaseDbConnection connection = this.db.getConnection();
1495 Statement s = connection.createStatement();
1496 ResultSet rs = connection.executeQuery(s, queryString)) {
1498 List<OsAccountAttribute> attributes =
new ArrayList<>();
1502 long hostId = rs.getLong(
"host_id");
1503 if (!rs.wasNull()) {
1507 Content sourceContent =
null;
1508 long sourceObjId = rs.getLong(
"source_obj_id");
1509 if (!rs.wasNull()) {
1513 OsAccountAttribute attribute = account.new OsAccountAttribute(attributeType, rs.getInt(
"value_int32"), rs.getLong(
"value_int64"),
1514 rs.getDouble(
"value_double"), rs.getString(
"value_text"), rs.getBytes(
"value_byte"),
1515 db, account, host, sourceContent);
1517 attributes.add(attribute);
1520 }
catch (SQLException ex) {
1521 throw new TskCoreException(String.format(
"Error getting OS account attributes for account obj id = %d", account.getId()), ex);
1537 String whereClause =
" tsk_os_account_instances.os_account_obj_id = " + account.getId();
1552 String instanceIds = instanceIDs.stream().map(
id ->
id.toString()).collect(Collectors.joining(
","));
1554 List<OsAccountInstance> osAcctInstances =
new ArrayList<>();
1556 String querySQL =
"SELECT * FROM tsk_os_account_instances "
1557 +
" WHERE tsk_os_account_instances.id IN (" + instanceIds +
")";
1559 db.acquireSingleUserCaseReadLock();
1560 try (CaseDbConnection connection = db.getConnection();
1561 PreparedStatement preparedStatement = connection.getPreparedStatement(querySQL, Statement.NO_GENERATED_KEYS);
1562 ResultSet results = connection.executeQuery(preparedStatement)) {
1564 osAcctInstances = getOsAccountInstancesFromResultSet(results);
1566 }
catch (SQLException ex) {
1567 throw new TskCoreException(
"Failed to get OsAccountInstances (SQL = " + querySQL +
")", ex);
1569 db.releaseSingleUserCaseReadLock();
1571 return osAcctInstances;
1587 private List<OsAccountInstance> getOsAccountInstances(String whereClause)
throws TskCoreException {
1588 List<OsAccountInstance> osAcctInstances =
new ArrayList<>();
1591 =
"SELECT tsk_os_account_instances.* "
1592 +
" FROM tsk_os_account_instances "
1593 +
" INNER JOIN ( SELECT os_account_obj_id, data_source_obj_id, MIN(instance_type) AS min_instance_type "
1594 +
" FROM tsk_os_account_instances"
1595 +
" GROUP BY os_account_obj_id, data_source_obj_id ) grouped_instances "
1596 +
" ON tsk_os_account_instances.os_account_obj_id = grouped_instances.os_account_obj_id "
1597 +
" AND tsk_os_account_instances.instance_type = grouped_instances.min_instance_type "
1598 +
" WHERE " + whereClause;
1601 try (CaseDbConnection connection = db.getConnection();
1602 PreparedStatement preparedStatement = connection.getPreparedStatement(querySQL, Statement.NO_GENERATED_KEYS);
1603 ResultSet results = connection.executeQuery(preparedStatement)) {
1605 osAcctInstances = getOsAccountInstancesFromResultSet(results);
1607 }
catch (SQLException ex) {
1608 throw new TskCoreException(
"Failed to get OsAccountInstances (SQL = " + querySQL +
")", ex);
1612 return osAcctInstances;
1624 private List<OsAccountInstance> getOsAccountInstancesFromResultSet(ResultSet results)
throws SQLException {
1626 List<OsAccountInstance> osAcctInstances =
new ArrayList<>();
1627 while (results.next()) {
1628 long instanceId = results.getLong(
"id");
1629 long osAccountObjID = results.getLong(
"os_account_obj_id");
1630 long dataSourceObjId = results.getLong(
"data_source_obj_id");
1631 int instanceType = results.getInt(
"instance_type");
1635 return osAcctInstances;
1663 return updateStatus;
1665 if (trans !=
null) {
1690 OsAccountUpdateStatus updateStatusCode = OsAccountUpdateStatus.NO_CHANGE;
1693 CaseDbConnection connection = trans.getConnection();
1695 if (!StringUtils.isBlank(fullName)) {
1696 updateAccountColumn(osAccount.getId(),
"full_name", fullName, connection);
1697 updateStatusCode = OsAccountUpdateStatus.UPDATED;
1700 if (Objects.nonNull(accountType)) {
1701 updateAccountColumn(osAccount.getId(),
"type", accountType.getId(), connection);
1702 updateStatusCode = OsAccountUpdateStatus.UPDATED;
1705 if (Objects.nonNull(accountStatus)) {
1706 updateAccountColumn(osAccount.getId(),
"status", accountStatus.getId(), connection);
1707 updateStatusCode = OsAccountUpdateStatus.UPDATED;
1710 if (Objects.nonNull(creationTime)) {
1711 updateAccountColumn(osAccount.getId(),
"created_date", creationTime, connection);
1712 updateStatusCode = OsAccountUpdateStatus.UPDATED;
1716 if (updateStatusCode == OsAccountUpdateStatus.NO_CHANGE) {
1717 return new OsAccountUpdateResult(updateStatusCode,
null);
1721 OsAccount updatedAccount = getOsAccountByObjectId(osAccount.getId(), connection);
1724 trans.registerChangedOsAccount(updatedAccount);
1726 return new OsAccountUpdateResult(updateStatusCode, updatedAccount);
1728 }
catch (SQLException ex) {
1729 throw new TskCoreException(String.format(
"Error updating account with addr = %s, account id = %d", osAccount.getAddr().orElse(
"Unknown"), osAccount.getId()), ex);
1746 private <T>
void updateAccountColumn(
long accountObjId, String colName, T colValue, CaseDbConnection connection)
throws SQLException,
TskCoreException {
1748 String updateSQL =
"UPDATE tsk_os_accounts "
1749 +
" SET " + colName +
" = ? "
1750 +
" WHERE os_account_obj_id = ?";
1754 PreparedStatement preparedStatement = connection.getPreparedStatement(updateSQL, Statement.NO_GENERATED_KEYS);
1755 preparedStatement.clearParameters();
1757 if (Objects.isNull(colValue)) {
1758 preparedStatement.setNull(1, Types.NULL);
1760 if (colValue instanceof String) {
1761 preparedStatement.setString(1, (String) colValue);
1762 }
else if (colValue instanceof Long) {
1763 preparedStatement.setLong(1, (Long) colValue);
1764 }
else if (colValue instanceof Integer) {
1765 preparedStatement.setInt(1, (Integer) colValue);
1767 throw new TskCoreException(String.format(
"Unhandled column data type received while updating the account (%d) ", accountObjId));
1771 preparedStatement.setLong(2, accountObjId);
1773 connection.executeUpdate(preparedStatement);
1789 private void updateAccountSignature(
long accountObjId, String signature, CaseDbConnection connection)
throws SQLException {
1791 String updateSQL =
"UPDATE tsk_os_accounts SET "
1794 +
" WHERE os_account_obj_id = ?";
1796 PreparedStatement preparedStatement = connection.getPreparedStatement(updateSQL, Statement.NO_GENERATED_KEYS);
1797 preparedStatement.clearParameters();
1799 preparedStatement.setString(1, signature);
1800 preparedStatement.setLong(2, accountObjId);
1802 connection.executeUpdate(preparedStatement);
1832 if (StringUtils.isNotBlank(accountSid)) {
1834 accountSid = accountSid.toUpperCase(Locale.ENGLISH);
1836 if (StringUtils.isNotBlank(loginName)) {
1838 loginName = loginName.toLowerCase(Locale.ENGLISH);
1840 if (StringUtils.isNotBlank(realmName)) {
1842 realmName = realmName.toLowerCase(Locale.ENGLISH);
1849 return updateStatus;
1851 if (trans !=
null) {
1880 if ((!StringUtils.isBlank(accountSid) && !accountSid.equalsIgnoreCase(WindowsAccountUtils.WINDOWS_NULL_SID)) || !StringUtils.isBlank(realmName)) {
1882 String resolvedRealmName = WindowsAccountUtils.toWellknownEnglishRealmName(realmName);
1888 Optional<OsAccountRealm> realmOptional = realmUpdateResult.
getUpdatedRealm();
1890 if (realmOptional.isPresent()) {
1897 Optional<OsAccountRealm> anotherRealmWithSameName = db.
getOsAccountRealmManager().getAnotherRealmByName(realmOptional.get(), realmName, referringHost, trans.getConnection());
1898 if (anotherRealmWithSameName.isPresent() && anotherRealmWithSameName.get().getRealmAddr().isPresent()) {
1900 anotherRealmWithSameName = Optional.empty();
1904 Optional<OsAccountRealm> anotherRealmWithSameAddr = db.
getOsAccountRealmManager().getAnotherRealmByAddr(realmOptional.get(), realmName, referringHost, trans.getConnection());
1905 if (anotherRealmWithSameAddr.isPresent() && !anotherRealmWithSameAddr.get().getRealmNames().isEmpty()) {
1907 anotherRealmWithSameName = Optional.empty();
1910 if (anotherRealmWithSameName.isPresent()) {
1913 if (anotherRealmWithSameAddr.isPresent()) {
1921 String resolvedLoginName = WindowsAccountUtils.toWellknownEnglishLoginName(loginName);
1922 OsAccountUpdateResult updateStatus = this.updateOsAccountCore(osAccount, accountSid, resolvedLoginName, trans);
1924 Optional<OsAccount> updatedAccount = updateStatus.getUpdatedAccount();
1925 if (updatedAccount.isPresent() && updateStatus.updateStatus != OsAccountUpdateStatus.NO_CHANGE) {
1927 mergeOsAccount(updatedAccount.get(),
true, trans);
1930 return updateStatus;
1957 return updateStatus;
1959 if (trans !=
null) {
1986 OsAccountUpdateResult updateStatus = this.updateOsAccountCore(osAccount, uid, loginName, trans);
1988 Optional<OsAccount> updatedAccount = updateStatus.getUpdatedAccount();
1989 if (updatedAccount.isPresent()) {
1991 mergeOsAccount(updatedAccount.get(),
false, trans);
1994 return updateStatus;
2019 private OsAccountUpdateResult updateOsAccountCore(OsAccount osAccount, String address, String loginName, CaseDbTransaction trans)
throws TskCoreException {
2021 OsAccountUpdateStatus updateStatusCode = OsAccountUpdateStatus.NO_CHANGE;
2022 OsAccount updatedAccount;
2025 CaseDbConnection connection = trans.getConnection();
2028 if (!StringUtils.isBlank(address) && !address.equalsIgnoreCase(WindowsAccountUtils.WINDOWS_NULL_SID) && !StringUtils.isBlank(osAccount.getAddr().orElse(
null)) && !address.equalsIgnoreCase(osAccount.getAddr().orElse(
""))) {
2029 throw new TskCoreException(String.format(
"Account (%d) already has an address (%s), address cannot be updated.", osAccount.getId(), osAccount.getAddr().orElse(
"NULL")));
2032 if (StringUtils.isBlank(osAccount.getAddr().orElse(
null)) && !StringUtils.isBlank(address) && !address.equalsIgnoreCase(WindowsAccountUtils.WINDOWS_NULL_SID)) {
2033 updateAccountColumn(osAccount.getId(),
"addr", address, connection);
2034 updateStatusCode = OsAccountUpdateStatus.UPDATED;
2037 if (StringUtils.isBlank(osAccount.getLoginName().orElse(
null)) && !StringUtils.isBlank(loginName)) {
2038 updateAccountColumn(osAccount.getId(),
"login_name", loginName, connection);
2039 updateStatusCode = OsAccountUpdateStatus.UPDATED;
2043 if (updateStatusCode == OsAccountUpdateStatus.NO_CHANGE) {
2044 return new OsAccountUpdateResult(updateStatusCode, osAccount);
2048 OsAccount currAccount = getOsAccountByObjectId(osAccount.getId(), connection);
2049 String newAddress = currAccount.getAddr().orElse(
null);
2050 String newLoginName = currAccount.getLoginName().orElse(
null);
2052 String newSignature = getOsAccountSignature(newAddress, newLoginName);
2055 updateAccountSignature(osAccount.getId(), newSignature, connection);
2056 }
catch (SQLException ex) {
2065 if (osAccount.getAddr().isEmpty() && !StringUtils.isBlank(address)) {
2067 Optional<OsAccount> matchingAddrAcct = getOsAccountByAddr(address, realm.getScopeHost().get(), connection);
2068 if (matchingAddrAcct.isEmpty()
2069 || matchingAddrAcct.get().getId() == osAccount.getId()
2070 || matchingAddrAcct.get().getLoginName().isPresent()) {
2076 mergeOsAccounts(matchingAddrAcct.get(), osAccount, trans);
2081 updatedAccount = getOsAccountByObjectId(osAccount.getId(), connection);
2084 trans.registerChangedOsAccount(updatedAccount);
2086 return new OsAccountUpdateResult(updateStatusCode, updatedAccount);
2088 }
catch (SQLException ex) {
2089 throw new TskCoreException(String.format(
"Error updating account with unique id = %s, account id = %d", osAccount.getAddr().orElse(
"Unknown"), osAccount.getId()), ex);
2103 List<Host> hostList =
new ArrayList<>();
2105 String query =
"SELECT tsk_hosts.id AS hostId, name, db_status FROM tsk_hosts "
2106 +
" JOIN data_source_info ON tsk_hosts.id = data_source_info.host_id"
2107 +
" JOIN tsk_os_account_instances ON data_source_info.obj_id = tsk_os_account_instances.data_source_obj_id"
2108 +
" WHERE os_account_obj_id = " + account.getId();
2110 db.acquireSingleUserCaseReadLock();
2111 try (CaseDbConnection connection = db.getConnection();
2112 Statement s = connection.createStatement();
2113 ResultSet rs = connection.executeQuery(s, query)) {
2119 }
catch (SQLException ex) {
2120 throw new TskCoreException(String.format(
"Failed to get host list for os account %d", account.getId()), ex);
2122 db.releaseSingleUserCaseReadLock();
2138 private OsAccount osAccountFromResultSet(ResultSet rs)
throws SQLException {
2141 int typeId = rs.getInt(
"type");
2142 if (!rs.wasNull()) {
2146 Long creationTime = rs.getLong(
"created_date");
2148 creationTime =
null;
2151 return new OsAccount(db, rs.getLong(
"os_account_obj_id"), rs.getLong(
"realm_id"), rs.getString(
"login_name"), rs.getString(
"addr"),
2152 rs.getString(
"signature"), rs.getString(
"full_name"), creationTime, accountType, OsAccount.OsAccountStatus.fromID(rs.getInt(
"status")),
2153 OsAccount.OsAccountDbStatus.fromID(rs.getInt(
"db_status")));
2163 private void fireChangeEvent(OsAccount account) {
2164 db.fireTSKEvent(
new OsAccountsUpdatedTskEvent(Collections.singletonList(account)));
2181 static String getOsAccountSignature(String uniqueId, String loginName)
throws TskCoreException {
2184 if (Strings.isNullOrEmpty(uniqueId) ==
false) {
2185 signature = uniqueId;
2186 }
else if (Strings.isNullOrEmpty(loginName) ==
false) {
2187 signature = loginName;
2189 throw new TskCoreException(
"OS Account must have either a uniqueID or a login name.");
2200 private static final long serialVersionUID = 1L;
2206 super(
"No error message available.");
2243 public final static class OsAccountUpdateResult {
2249 this.updateStatus = updateStatus;
2250 this.updatedAccount = updatedAccount;
2254 return updateStatus;
2258 return Optional.ofNullable(updatedAccount);
2266 private class OsAccountInstanceKey
implements Comparable<OsAccountInstanceKey>{
2268 private final long osAccountId;
2269 private final long dataSourceId;
2271 OsAccountInstanceKey(
long osAccountId,
long dataSourceId) {
2272 this.osAccountId = osAccountId;
2273 this.dataSourceId = dataSourceId;
2277 public boolean equals(Object other) {
2278 if (
this == other) {
2281 if (other ==
null) {
2284 if (getClass() != other.getClass()) {
2288 final OsAccountInstanceKey otherKey = (OsAccountInstanceKey) other;
2290 if (osAccountId != otherKey.osAccountId) {
2294 return dataSourceId == otherKey.dataSourceId;
2298 public int hashCode() {
2300 hash = 53 * hash + (int) (this.osAccountId ^ (this.osAccountId >>> 32));
2301 hash = 53 * hash + (int) (this.dataSourceId ^ (this.dataSourceId >>> 32));
2306 public int compareTo(OsAccountInstanceKey other) {
2307 if(this.equals(other)) {
2311 if (dataSourceId != other.dataSourceId) {
2312 return Long.compare(dataSourceId, other.dataSourceId);
2315 return Long.compare(osAccountId, other.osAccountId);