TempDirManager.java

package org.linkedopenactors.rdfpub.scheduler.tempdir;

import java.io.File;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.IOException;
import java.nio.charset.StandardCharsets;
import java.nio.file.Files;
import java.nio.file.Path;
import java.util.Collections;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Optional;
import java.util.stream.Collectors;

import org.apache.commons.io.IOUtils;
import org.springframework.scheduling.annotation.Scheduled;
import org.springframework.stereotype.Component;

import com.fasterxml.jackson.core.type.TypeReference;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.fasterxml.jackson.databind.exc.MismatchedInputException;

import lombok.extern.slf4j.Slf4j;

@Component
@Slf4j
public class TempDirManager {

	private static final String FILE_NAME = "tempFileManagerProperties.json";
	
	private Map<String,TempFileManager> tempFileManagerByTempDirName;

	private ObjectMapper om = new ObjectMapper();
	
	public TempDirManager() {
		initProperties();
	}

	private synchronized void initProperties() {
		tempFileManagerByTempDirName = new HashMap<>();
		loadProperties().forEach(props->{
			tempFileManagerByTempDirName.put(props.getCustomTempDirName(), new TempFileManager(props));		
		});
	}
	
	public TempFileManager createTempFileManager(TempFileManagerProperties tempFileManagerProperties) {
		List<TempFileManagerProperties> tempFileManagerPropertyList = this.tempFileManagerByTempDirName.values().stream().map(TempFileManager::getTempFileManagerProperties).collect(Collectors.toList());
		tempFileManagerPropertyList.add(tempFileManagerProperties);
		saveProperties(tempFileManagerPropertyList);
		initProperties();		
		return this.tempFileManagerByTempDirName.get(tempFileManagerProperties.getCustomTempDirName());
	}

	public Optional<TempFileManager> getTempFileManager(String dirName) {
		return Optional.ofNullable(this.tempFileManagerByTempDirName.get(dirName));
	}
	
	private File getPropertiesFile() throws IOException {
		String systemTmpDirStr = System.getProperty("java.io.tmpdir");
		Path propertiesFilePath = Path.of(systemTmpDirStr, IOUtils.DIR_SEPARATOR+"", FILE_NAME);
		if(!Files.exists(propertiesFilePath)) {
			Files.createFile(propertiesFilePath);
		}
		return propertiesFilePath.toFile();
	}

	private synchronized List<TempFileManagerProperties> loadProperties() {
		try {
			FileInputStream fis = new FileInputStream(getPropertiesFile());
			return om.readValue(fis, new TypeReference<List<TempFileManagerProperties>>(){});
		} catch (MismatchedInputException e) {
			if(e.getMessage().startsWith("No content to map due to end-of-input")) {
				return Collections.emptyList();
			} else {
				throw new RuntimeException("Error reading tempFileManagerProperties as json", e);
			}
		} catch (IOException e) {
			throw new RuntimeException("Error reading tempFileManagerProperties as json", e);
		} 
	}
	
	private synchronized void saveProperties(List<TempFileManagerProperties> tempFileManagerProperties) {
		try {
			String json = om.writeValueAsString(tempFileManagerProperties);
			FileOutputStream fos = new FileOutputStream(getPropertiesFile());
			IOUtils.write(json, fos, StandardCharsets.UTF_8);
		} catch (IOException e) {
			throw new RuntimeException("Error writing tempFileManagerProperties as json", e);
		}
	}
	
	@Scheduled(fixedDelay = 300000)
	public void cleanup() {
		this.tempFileManagerByTempDirName.values().stream().forEach(it->{
			try {
				it.cleanup();
			} catch (IOException e) {
				log.error("error cleaning " + it, e);
			}
		});
	}	
}