package com.threatconnect.sdk.parser.service.writer; import com.threatconnect.sdk.client.reader.FileIndicatorReaderAdapter; import com.threatconnect.sdk.client.reader.ReaderAdapterFactory; import com.threatconnect.sdk.client.response.IterableResponse; import com.threatconnect.sdk.client.writer.FileIndicatorWriterAdapter; import com.threatconnect.sdk.client.writer.WriterAdapterFactory; import com.threatconnect.sdk.conn.Connection; import com.threatconnect.sdk.exception.FailedResponseException; import com.threatconnect.sdk.parser.model.File; import com.threatconnect.sdk.parser.model.FileOccurrence; import com.threatconnect.sdk.parser.service.save.SaveItemFailedException; import com.threatconnect.sdk.server.entity.Indicator.Type; import java.io.IOException; import java.util.HashMap; import java.util.Map; public class FileWriter extends TypedIndicatorWriter<File, com.threatconnect.sdk.server.entity.File> { public FileWriter(final Connection connection, final File file) { super(connection, file, com.threatconnect.sdk.server.entity.File.class, Type.File); } @Override public com.threatconnect.sdk.server.entity.File saveIndicator(String ownerName) throws SaveItemFailedException, IOException { // first, call the super class' save method com.threatconnect.sdk.server.entity.File file = super.saveIndicator(ownerName); // create a writer adapter FileIndicatorWriterAdapter writer = createWriterAdapter(); // check to see if there are file occurrences if (!indicatorSource.getFileOccurrences().isEmpty()) { // holds the map for file name to file occurrence object Map<String, com.threatconnect.sdk.server.entity.FileOccurrence> existingFileOccurrences = retrieveExistingFileOccurrences(buildID(), ownerName); // for each of the file occurrences for this file for (FileOccurrence fileOccurrence : indicatorSource.getFileOccurrences()) { // check to see if this file occurrence already exists if (existingFileOccurrences.containsKey(fileOccurrence.getFileName())) { // make sure the new date is not null if (null != fileOccurrence.getDate()) { // retrieve the existing file occurrence to see if it needs to be updated com.threatconnect.sdk.server.entity.FileOccurrence existingFileOccurrence = existingFileOccurrences.get(fileOccurrence.getFileName()); // check to see if the new date is before the existing date if (fileOccurrence.getDate().before(existingFileOccurrence.getDate())) { try { // the existing file needs to be updated with the new date existingFileOccurrence.setDate(fileOccurrence.getDate()); writer.updateFileOccurrence(buildID(), existingFileOccurrence, ownerName); } catch (FailedResponseException | IOException e) { // something went wrong updating the file occurrence so just log it // for the user to review and move on logger.warn(e.getMessage(), e); } } } } // create a new file occurrence for this file hash else { // map the file occurrence object com.threatconnect.sdk.server.entity.FileOccurrence fo = mapper.map(fileOccurrence, com.threatconnect.sdk.server.entity.FileOccurrence.class); // write the file occurrence for this file writer.createFileOccurrence(buildID(), fo); } } } return file; } @Override protected FileIndicatorWriterAdapter createWriterAdapter() { return WriterAdapterFactory.createFileIndicatorWriter(connection); } @Override protected FileIndicatorReaderAdapter createReaderAdapter() { return ReaderAdapterFactory.createFileIndicatorReader(connection); } @Override protected String buildID() { // check to see if this file has an md5 hash if (null != indicatorSource.getMd5()) { return indicatorSource.getMd5(); } // check to see if this file has a sha1 hash else if (null != indicatorSource.getSha1()) { return indicatorSource.getSha1(); } // check to see if this file has a sha256 hash else if (null != indicatorSource.getSha256()) { return indicatorSource.getSha256(); } else { // no suitable id for this file return null; } } /** * Retrieves the existing file occurrences if any exist and enters them into a hash map using * the file name as the key * * @param hash * @param ownerName * @return * @throws FailedResponseException * @throws IOException */ private Map<String, com.threatconnect.sdk.server.entity.FileOccurrence> retrieveExistingFileOccurrences( final String hash, final String ownerName) { // holds the map for file name to file occurrence object Map<String, com.threatconnect.sdk.server.entity.FileOccurrence> existingFileOccurrences = new HashMap<String, com.threatconnect.sdk.server.entity.FileOccurrence>(); try { // create a new reader adapter FileIndicatorReaderAdapter reader = createReaderAdapter(); // check to see if there are any existing file occurrences for this file IterableResponse<com.threatconnect.sdk.server.entity.FileOccurrence> fileOccurrenceResponse = reader.getFileOccurrences(hash, ownerName); // for each of the file occurrences for (com.threatconnect.sdk.server.entity.FileOccurrence fileOccurrence : fileOccurrenceResponse) { // add this file occurrence to the map existingFileOccurrences.put(fileOccurrence.getFileName(), fileOccurrence); } } catch (FailedResponseException | IOException e) { logger.warn(e.getMessage(), e); } return existingFileOccurrences; } }