public HashMap<String, DataFile> getRepoFileData(
            String repositoryName, 
            String baseUrl) throws IOException {
        
        if (!repoDownloadLocks.containsKey(repositoryName)) {
            // Create a lock object for this repo name if we don't already have one
            repoDownloadLocks.put(repositoryName, new ReentrantLock(true));
        }
        
        // Get the lock object associated with this repo (want to prevent multiple threads downloading from the same repo at the same time)
        ReentrantLock downloadLock = repoDownloadLocks.get(repositoryName);
        HashMap<String, DataFile> fileData = repoFileCache.getIfPresent(repositoryName);
        
        if (downloadLock.isLocked() && fileData != null) {
            // We are currently downloading for this repo, but we already have something cached, so return that
            return fileData;
        }

        String organizationName = ApplicationProperties.getProperties().getProperty(PropertiesConstants.GITHUB_ORGANIZATION);
        Repository repository = getRepository(organizationName, repositoryName);
        Release latestRelease = getLatestRelease(repository);
        
        if (requiresDownload(repository, latestRelease)) {
            try {
                // Lock as we don't want multiple threads downloading from the same repo at once
                downloadLock.lock();
                
                // Check again if we need to do a download.
                // We may have a case where one thread has locked this code and is doing the download, and another thread is waiting behind the lock (i.e. requiresDownload returned true for the second thread).
                // This can happen if we are downloading the data for the first time (i.e. repoFileCache is empty while the first thread does the download).
                // In this case, the waiting thread should not download the data _again_ and should instead return the data from the cache once it's 
                //   done waiting for the first thread to finish the download.
                if (!requiresDownload(repository, latestRelease)) {
                    fileData = repoFileCache.getIfPresent(repositoryName);
                    if (fileData == null) {
                        // We should have this cached now. If not, something weird has happened
                        throw new IllegalStateException();
                    }
                    return fileData;
                }

                // Download and cache the repository data files
                logger.log(Level.INFO, "Downloading and caching data for repository {0}.", repository.getName());
                HashMap<String, byte[]> dataFiles = downloadFromGitHub(repository, latestRelease);
                HashMap<String, DataFile> repositoryData = indexer.createRepositoryData(repositoryName, baseUrl, null, dataFiles);
                repoFileCache.put(repositoryName, repositoryData);
            }
            finally {
                // Done! Unlock in a finally block as we don't want to leave anything locked if there's an exception...
                downloadLock.unlock();
            }
        }

        fileData = repoFileCache.getIfPresent(repositoryName);
        if (fileData == null) {
            // We should have this cached now. If not, something weird has happened
            throw new IllegalStateException();
        }
        return fileData;
    }