/** * i-net software provides programming examples for illustration only, without warranty * either expressed or implied, including, but not limited to, the implied warranties * of merchantability and/or fitness for a particular purpose. This programming example * assumes that you are familiar with the programming language being demonstrated and * the tools used to create and debug procedures. i-net software support professionals * can help explain the functionality of a particular procedure, but they will not modify * these examples to provide added functionality or construct procedures to meet your * specific needs. * * Copyright © 1999-2025 i-net software GmbH, Berlin, Germany. **/ package com.inet.automaticconfigrestore; import java.io.File; import java.io.FileInputStream; import java.io.FileOutputStream; import java.io.IOException; import java.io.InputStream; import java.io.OutputStream; import java.net.URL; import java.util.Properties; import java.util.concurrent.ForkJoinPool; import java.util.concurrent.atomic.AtomicBoolean; import javax.annotation.Nullable; import com.inet.classloader.BaseLocator; import com.inet.config.ConfigKey; import com.inet.config.ConfigurationChangeEvent; import com.inet.config.ConfigurationChangeListener; import com.inet.config.ConfigurationManager; import com.inet.lib.util.IOFunctions; import com.inet.logging.LogManager; /** * On configuration changes, after all vetos are over, this will store the current * configuration into the persistence * @author gamma * */ public class ConfigStoreChangeManager implements ConfigurationChangeListener { private static final String CONFIGURATION_STORE_KEY = ".automatic.configuration.backup"; private static final ConfigKey CONFIGURATION_KEY = new ConfigKey( CONFIGURATION_STORE_KEY, "", Long.class ); private static final AtomicBoolean IS_STORING_CONFIGURATION = new AtomicBoolean( false ); /** * Initialize the class and store the current configuration */ public ConfigStoreChangeManager() { storeConfigration( ConfigurationManager.getInstance().getCurrent().getProperties() ); } /** * Returns a file from the working directory of the server where the configuration will be stored * @return a file from the working directory of the server where the configuration will be stored */ @Nullable private static File getConfigurationFile() { try { URL baseURL = BaseLocator.getBaseDirectory().getURL(); File baseFile = IOFunctions.getFile( baseURL ); return new File( baseFile, CONFIGURATION_STORE_KEY ); } catch ( IOException e ) { return null; } } /** * {@inheritDoc} */ @Override public void configurationChanged( ConfigurationChangeEvent event ) { if ( !event.isCurrentConfiguration() ) { return; // do not care about other configurations } if ( IS_STORING_CONFIGURATION.compareAndSet( false, true ) ) { String value = "" + System.currentTimeMillis(); ConfigurationManager.getInstance().getCurrent().put( CONFIGURATION_KEY, value ); ForkJoinPool.commonPool().execute( () -> { IS_STORING_CONFIGURATION.set( false ); Properties configuration = event.getChangedConfiguration().getProperties(); configuration.put( CONFIGURATION_KEY.getKey(), value ); storeConfigration( configuration ); } ); } } /** * Store the current configuration properties * @param configuration the current configuration */ private void storeConfigration( Properties configuration ) { try ( OutputStream stream = new FileOutputStream( getConfigurationFile() ) ) { configuration.store( stream, null ); } catch( IOException ex ) { LogManager.getConfigLogger().error( ex ); } } /** * Returns true, if the persistence contains a stored backup and there is data present * @return true, if the persistence contains a stored backup and there is data present */ public static boolean hasStoredConfiguration() { File configurationFile = getConfigurationFile(); if ( configurationFile == null || !configurationFile.exists() ) { return false; } return getStoredConfiguration() != null; } /** * Returns the stored configuration properties, if available. Null otherwise. * After fetching the value, the persistence entry is deleted. * * @return the stored configuration properties, if available. Null otherwise. */ @Nullable public static Properties getStoredConfiguration() { Properties properties = new Properties(); try ( InputStream input = new FileInputStream( getConfigurationFile() ) ) { properties.load( input ); String marker = (String)properties.get( CONFIGURATION_KEY.getKey() ); if ( marker == null || marker.contentEquals( ConfigurationManager.getInstance().getCurrent().get( CONFIGURATION_KEY ) ) ) { return null; } return properties; } catch( IOException e ) { return null; } } }