19 package org.sleuthkit.datamodel;
21 import com.google.common.base.Strings;
22 import java.sql.PreparedStatement;
23 import java.sql.ResultSet;
24 import java.sql.Savepoint;
25 import java.sql.SQLException;
26 import java.sql.Statement;
27 import java.util.ArrayList;
28 import java.util.Collections;
29 import java.util.List;
30 import java.util.Optional;
31 import java.util.UUID;
73 if (transaction != null) {
105 if (Strings.isNullOrEmpty(name)) {
106 throw new TskCoreException(
"Illegal argument passed to createHost: Host name is required.");
109 CaseDbConnection connection = trans.getConnection();
110 Savepoint savepoint = null;
113 savepoint = connection.getConnection().setSavepoint();
114 String hostInsertSQL =
"INSERT INTO tsk_hosts(name) VALUES (?)";
115 PreparedStatement preparedStatement = connection.getPreparedStatement(hostInsertSQL, Statement.RETURN_GENERATED_KEYS);
117 preparedStatement.clearParameters();
118 preparedStatement.setString(1, name);
120 connection.executeUpdate(preparedStatement);
124 try (ResultSet resultSet = preparedStatement.getGeneratedKeys();) {
125 if (resultSet.next()) {
126 host =
new Host(resultSet.getLong(1), name);
128 throw new SQLException(
"Error executing " + hostInsertSQL);
133 trans.registerAddedHost(host);
136 }
catch (SQLException ex) {
137 if (savepoint != null) {
139 connection.getConnection().rollback(savepoint);
140 }
catch (SQLException ex2) {
141 throw new TskCoreException(String.format(
"Error adding host with name = %s and unable to rollback", name), ex);
147 if (optHost.isPresent()) {
148 return optHost.get();
150 throw new TskCoreException(String.format(
"Error adding host with name = %s", name), ex);
166 throw new TskCoreException(
"Illegal argument passed to updateHost: No host argument provided.");
167 }
else if (newName == null) {
168 throw new TskCoreException(String.format(
"Illegal argument passed to updateHost: Host with id %d has no name", host.getHostId()));
171 long hostId = host.getHostId();
172 Host updatedHost = null;
174 try (CaseDbConnection connection = db.getConnection()) {
176 String hostInsertSQL =
"UPDATE tsk_hosts "
178 +
" CASE WHEN db_status = " +
Host.
HostDbStatus.ACTIVE.getId() +
" THEN ? ELSE name END "
181 PreparedStatement preparedStatement = connection.getPreparedStatement(hostInsertSQL, Statement.RETURN_GENERATED_KEYS);
183 preparedStatement.clearParameters();
184 preparedStatement.setString(1, newName);
185 preparedStatement.setLong(2, hostId);
187 connection.executeUpdate(preparedStatement);
189 updatedHost =
getHostById(hostId, connection).orElseThrow(()
190 ->
new TskCoreException((String.format(
"Error while fetching newly updated host with id: %d, "))));
192 }
catch (SQLException ex) {
193 throw new TskCoreException(String.format(
"Error updating host with name = %s", newName), ex);
198 if (updatedHost != null) {
199 fireChangeEvent(updatedHost);
215 throw new TskCoreException(
"Illegal argument passed to deleteHost: Name provided must be non-null");
219 String queryString =
"SELECT COUNT(*) AS count FROM\n"
220 +
"(SELECT obj_id AS id, host_id FROM data_source_info\n"
222 +
"SELECT id, scope_host_id AS host_id FROM tsk_os_account_realms\n"
224 +
"SELECT id, host_id FROM tsk_os_account_attributes\n"
226 +
"SELECT id, host_id FROM tsk_host_address_map) children\n"
227 +
"INNER JOIN tsk_hosts h ON children.host_id = h.id WHERE LOWER(h.name)=LOWER(?)";
229 String deleteString =
"DELETE FROM tsk_hosts WHERE LOWER(name) = LOWER(?)";
234 PreparedStatement query = trans.getConnection().getPreparedStatement(queryString, Statement.NO_GENERATED_KEYS);
235 query.clearParameters();
236 query.setString(1, name);
237 try (ResultSet queryResults = query.executeQuery()) {
238 if (queryResults.next() && queryResults.getLong(
"count") > 0) {
239 throw new TskCoreException(String.format(
"Host with name '%s' has child data and cannot be deleted.", name));
244 PreparedStatement update = trans.getConnection().getPreparedStatement(deleteString, Statement.RETURN_GENERATED_KEYS);
245 update.clearParameters();
246 update.setString(1, name);
247 int numUpdated = update.executeUpdate();
252 if (numUpdated > 0) {
253 try (ResultSet updateResult = update.getGeneratedKeys()) {
254 if (updateResult.next()) {
255 hostId = updateResult.getLong(1);
263 fireDeletedEvent(
new Host(hostId, name));
265 }
catch (SQLException ex) {
266 throw new TskCoreException(String.format(
"Error deleting host with name %s", name), ex);
284 String queryString =
"SELECT * FROM data_source_info WHERE host_id = " + host.getHostId();
286 List<DataSource> dataSources =
new ArrayList<>();
288 try (CaseDbConnection connection = this.db.getConnection();
289 Statement s = connection.createStatement();
290 ResultSet rs = connection.executeQuery(s, queryString)) {
298 throw new TskCoreException(String.format(
"Error getting data sources for host %s", host.getName()), ex);
314 try (CaseDbConnection connection = db.getConnection()) {
331 String queryString =
"SELECT * FROM tsk_hosts"
332 +
" WHERE LOWER(name) = LOWER(?)"
337 PreparedStatement s = connection.getPreparedStatement(queryString, Statement.RETURN_GENERATED_KEYS);
339 s.setString(1, name);
341 try (ResultSet rs = s.executeQuery()) {
343 return Optional.empty();
345 return Optional.of(
new Host(rs.getLong(
"id"), rs.getString(
"name"), Host.HostDbStatus.fromID(rs.getInt(
"db_status"))));
348 }
catch (SQLException ex) {
349 throw new TskCoreException(String.format(
"Error getting host with name = %s", name), ex);
365 try (CaseDbConnection connection = db.getConnection()) {
382 String queryString =
"SELECT * FROM tsk_hosts WHERE id = " + id;
385 try (Statement s = connection.createStatement();
386 ResultSet rs = connection.executeQuery(s, queryString)) {
389 return Optional.of(
new Host(rs.getLong(
"id"), rs.getString(
"name"),
Host.
HostDbStatus.fromID(rs.getInt(
"db_status"))));
391 return Optional.empty();
393 }
catch (SQLException ex) {
394 throw new TskCoreException(String.format(
"Error getting host with id: " +
id), ex);
408 String queryString =
"SELECT * FROM tsk_hosts WHERE db_status = " + HostDbStatus.ACTIVE.getId();
410 List<Host> hosts =
new ArrayList<>();
412 try (CaseDbConnection connection = this.db.getConnection();
413 Statement s = connection.createStatement();
414 ResultSet rs = connection.executeQuery(s, queryString)) {
417 hosts.add(
new Host(rs.getLong(
"id"), rs.getString(
"name"),
Host.
HostDbStatus.fromID(rs.getInt(
"db_status"))));
421 }
catch (SQLException ex) {
422 throw new TskCoreException(String.format(
"Error getting hosts"), ex);
451 String queryString =
"SELECT tsk_hosts.id AS hostId, tsk_hosts.name AS name, tsk_hosts.db_status AS db_status FROM \n"
452 +
"tsk_hosts INNER JOIN data_source_info \n"
453 +
"ON tsk_hosts.id = data_source_info.host_id \n"
454 +
"WHERE data_source_info.obj_id = " + dataSourceId;
457 try (CaseDbConnection connection = this.db.getConnection();
458 Statement s = connection.createStatement();
459 ResultSet rs = connection.executeQuery(s, queryString)) {
462 throw new TskCoreException(String.format(
"Host not found for data source with ID = %d", dataSourceId));
464 return new Host(rs.getLong(
"hostId"), rs.getString(
"name"), Host.HostDbStatus.fromID(rs.getInt(
"db_status")));
466 }
catch (SQLException ex) {
467 throw new TskCoreException(String.format(
"Error getting host for data source with ID = %d", dataSourceId), ex);
498 try (Statement s = trans.getConnection().createStatement()) {
503 query =
"DELETE FROM tsk_host_address_map "
506 +
" sourceMapRow.id "
508 +
" tsk_host_address_map destMapRow "
509 +
"INNER JOIN tsk_host_address_map sourceMapRow ON destMapRow.addr_obj_id = sourceMapRow.addr_obj_id AND destMapRow.time = sourceMapRow.time "
510 +
"WHERE destMapRow.host_id = " + destHost.getHostId()
511 +
" AND sourceMapRow.host_id = " + sourceHost.getHostId() +
" )";
512 s.executeUpdate(query);
513 query = makeOsAccountUpdateQuery(
"tsk_host_address_map",
"host_id", sourceHost, destHost);
514 s.executeUpdate(query);
516 query = makeOsAccountUpdateQuery(
"tsk_os_account_attributes",
"host_id", sourceHost, destHost);
517 s.executeUpdate(query);
519 query = makeOsAccountUpdateQuery(
"data_source_info",
"host_id", sourceHost, destHost);
520 s.executeUpdate(query);
523 String mergedName = makeMergedHostName();
524 query =
"UPDATE tsk_hosts SET merged_into = " + destHost.getHostId()
526 +
", name = '" + mergedName +
"' "
527 +
" WHERE id = " + sourceHost.getHostId();
528 s.executeUpdate(query);
535 fireChangeEvent(sourceHost);
536 fireDeletedEvent(destHost);
537 }
catch (SQLException ex) {
556 private String makeOsAccountUpdateQuery(String tableName, String columnName,
Host sourceHost,
Host destHost) {
557 return "UPDATE " + tableName +
" SET " + columnName +
" = " + destHost.
getHostId() +
" WHERE " + columnName +
" = " + sourceHost.
getHostId();
565 private String makeMergedHostName() {
566 return "MERGED " + UUID.randomUUID().toString();
575 private void fireChangeEvent(Host newValue) {
576 db.fireTSKEvent(
new HostsUpdatedTskEvent(Collections.singletonList(newValue)));
585 private void fireDeletedEvent(Host deleted) {
586 db.fireTSKEvent(
new HostsDeletedTskEvent(Collections.singletonList(deleted.getHostId())));
Host getHostByDataSource(DataSource dataSource)
CaseDbTransaction beginTransaction()
List< DataSource > getDataSourcesForHost(Host host)
Optional< Host > getHostByName(String name)
Long deleteHost(String name)
OsAccountRealmManager getOsAccountRealmManager()
void releaseSingleUserCaseReadLock()
Optional< Host > getHostById(long id)
void acquireSingleUserCaseWriteLock()
void releaseSingleUserCaseWriteLock()
Host newHost(String name)
void mergeHosts(Host sourceHost, Host destHost)
void acquireSingleUserCaseReadLock()
DataSource getDataSource(long objectId)
Host updateHostName(Host host, String newName)
List< Host > getAllHosts()