/* * Copyright (C) 2006-2016 DLR, Germany * * All rights reserved * * http://www.rcenvironment.de/ */ package de.rcenvironment.core.utils.common; import java.io.File; import java.io.IOException; import java.io.InputStream; import org.apache.commons.logging.LogFactory; /** * A static access singleton that allows classes to use the {@link TempFileService} without introducing a dependency on RCE core classes. * <p> * TODO add remark about direct OSGi injection when it is available * * @author Robert Mischke */ public class TempFileServiceAccess { /** * A simple proxy implementation for cases when non-OSGi code fetches the service before it was initialized by the OSGi framework. * * @author Robert Mischke */ private static final class ServiceProxy implements TempFileService { public File createManagedTempDir() throws IOException { return getNullSafeInstance().createManagedTempDir(); } public File createManagedTempDir(String infoText) throws IOException { return getNullSafeInstance().createManagedTempDir(infoText); } public File createTempFileFromPattern(String filenamePattern) throws IOException { return getNullSafeInstance().createTempFileFromPattern(filenamePattern); } public File createTempFileWithFixedFilename(String filename) throws IOException { return getNullSafeInstance().createTempFileWithFixedFilename(filename); } public File writeInputStreamToTempFile(InputStream is) throws IOException { return getNullSafeInstance().writeInputStreamToTempFile(is); } public void disposeManagedTempDirOrFile(File tempFileOrDir) throws IOException { getNullSafeInstance().disposeManagedTempDirOrFile(tempFileOrDir); } private TempFileService getNullSafeInstance() { TempFileService instanceCopy = TempFileServiceAccess.instance; // important not to use getInstance() here if (instanceCopy == null) { throw new IllegalStateException("A TempFileService method was called while no global instance was available"); } return instanceCopy; } } private static volatile TempFileService instance; private static final String UNIT_TEST_RELATIVE_GLOBAL_ROOT_DIR_PATH = "rce-unittest"; private static TempFileManager currentMmanager; protected TempFileServiceAccess() {} /** * @return a {@link TempFileService} implementation; note that this may be a proxy for the actual service instance */ public static TempFileService getInstance() { // note: "instance" is volatile, so no synchronization is needed TempFileService instanceCopy = instance; // defensive copy to prevent race conditions if (instanceCopy != null) { return instanceCopy; } LogFactory.getLog(TempFileServiceAccess.class).debug( "A TempFileService instance was requested before the global instance was ready, returning a proxy"); return new ServiceProxy(); } /** * Sets the given folder as the "global root" directory to use. Inside this directory, the "instance root" directories are created and * deleted. * * @param globalTempDirectoryRoot the global root directory to use; must already exist * @param instancePrefix an arbitrary prefix to use for the instance directories created inside the provided global root directory; can * be empty or null * @throws IOException on initialization failure */ public static void setupLiveEnvironment(File globalTempDirectoryRoot, String instancePrefix) throws IOException { // TODO ignore call if already using same root? // TODO "shut down" any pre-existing instance? currentMmanager = new TempFileManager(globalTempDirectoryRoot, instancePrefix); setInstance(currentMmanager.getServiceImplementation()); } /** * Convenience method for unit tests. Sets a hard-coded sub-folder of the system temporary directory as the "global root". */ public static void setupUnitTestEnvironment() { if (TempFileServiceAccess.instance == null) { try { // TODO ignore call if already using same root? // TODO "shut down" any pre-existing instance? if (currentMmanager == null) { currentMmanager = new TempFileManager(getDefaultTestRootDir(), null, true); } setInstance(currentMmanager.getServiceImplementation()); } catch (IOException e) { // always expected to work, so using an unchecked exception for test code convenience throw new RuntimeException("Failed to initialize unittest temp directory root", e); } } } protected static void setInstance(TempFileService newInstance) { if (newInstance == null) { throw new IllegalArgumentException("Setting the global instance back to 'null' is not allowed"); } TempFileServiceAccess.instance = newInstance; } protected static File getDefaultTestRootDir() { return new File(System.getProperty("java.io.tmpdir"), UNIT_TEST_RELATIVE_GLOBAL_ROOT_DIR_PATH); } /** * "Reset" method for unit/integration tests. */ protected static void discardCurrentSetup() { currentMmanager = null; TempFileServiceAccess.instance = null; } }