Java tutorial
/* * MadKitLanEdition (created by Jason MAHDJOUB (jason.mahdjoub@distri-mind.fr)) Copyright (c) * 2015 is a fork of MadKit and MadKitGroupExtension. * * Copyright or or Copr. Jason Mahdjoub, Fabien Michel, Olivier Gutknecht, Jacques Ferber (1997) * * jason.mahdjoub@distri-mind.fr * fmichel@lirmm.fr * olg@no-distance.net * ferber@lirmm.fr * * This software is a computer program whose purpose is to * provide a lightweight Java library for designing and simulating Multi-Agent Systems (MAS). * This software is governed by the CeCILL-C license under French law and * abiding by the rules of distribution of free software. You can use, * modify and/ or redistribute the software under the terms of the CeCILL-C * license as circulated by CEA, CNRS and INRIA at the following URL * "http://www.cecill.info". * As a counterpart to the access to the source code and rights to copy, * modify and redistribute granted by the license, users are provided only * with a limited warranty and the software's author, the holder of the * economic rights, and the successive licensors have only limited * liability. * * In this respect, the user's attention is drawn to the risks associated * with loading, using, modifying and/or developing or reproducing the * software by the user in light of its specific status of free software, * that may mean that it is complicated to manipulate, and that also * therefore means that it is reserved for developers and experienced * professionals having in-depth computer knowledge. Users are therefore * encouraged to load and test the software's suitability as regards their * requirements in conditions enabling the security of their systems and/or * data to be ensured and, more generally, to use and operate it in the * same conditions as regards security. * The fact that you are presently reading this means that you have had * knowledge of the CeCILL-C license and that you accept its terms. */ package com.distrimind.madkit.kernel; import java.io.*; import java.net.MalformedURLException; import java.net.NetworkInterface; import java.net.URL; import java.util.ArrayList; import java.util.Collection; import java.util.Enumeration; import java.util.Properties; import java.util.logging.Level; import java.util.logging.Logger; import org.apache.commons.codec.binary.Base64; import org.w3c.dom.Document; import org.w3c.dom.Node; import com.distrimind.madkit.gui.AgentFrame; import com.distrimind.madkit.gui.ConsoleAgent; import com.distrimind.madkit.gui.MDKDesktopFrame; import com.distrimind.madkit.i18n.ErrorMessages; import com.distrimind.madkit.i18n.SuccessMessages; import com.distrimind.madkit.kernel.network.NetworkProperties; import com.distrimind.madkit.util.MultiFormatPropertiesObjectParser; import com.distrimind.madkit.util.XMLUtilities; import com.distrimind.ood.database.DatabaseFactory; import com.distrimind.ood.database.DatabaseWrapper; import com.distrimind.ood.database.Table; import com.distrimind.ood.database.exceptions.DatabaseException; import com.distrimind.util.crypto.AbstractSecureRandom; import com.distrimind.util.crypto.SecureRandomType; import com.distrimind.util.properties.MultiFormatProperties; import com.distrimind.util.properties.PropertiesParseException; import com.distrimind.util.version.Version; import gnu.vm.jgnu.security.NoSuchAlgorithmException; import gnu.vm.jgnu.security.NoSuchProviderException; /** * The properties object used within MaDKit. * * * @author Jasopn Mahdjoub * @since MadKitLanEdition 1.0 * @version 1.1 * */ @SuppressWarnings("UnusedReturnValue") public class MadkitProperties extends MultiFormatProperties { /** * */ private static final long serialVersionUID = 2186060810090339476L; private final static Logger logger = Logger.getLogger(MadkitProperties.class.getName()); /** * Represents the current madkit version. */ public final Version madkitVersion = Madkit.getVersion(); /** * Represents the minimum MadkitLanEdition version that this instance can * accept. If a distant peer try to connect with a MadkitLanEdition version * lower than this one, than the connection will be rejected. */ public Version minimumMadkitVersion; public Class<?> madkitMainClass = Madkit.class; public URL madkitWeb; public URL madkitRepositoryURL = null; /** * Tells if kernel address must be secured. If set to true, the MAC hardware * address from which is derived the kernel address will be encrypted. */ public boolean isKernelAddressSecured = true; public boolean isKernelAddressSecured() { return isKernelAddressSecured && networkProperties.network; } /** * the desktop frame class which should be used, default is * {@link MDKDesktopFrame} */ public Class<?> desktopFrameClass = MDKDesktopFrame.class; /** * Tells if MadkitLanEdition can be launched with the desktop GUI */ public boolean desktop = false; /** * Tells if {@link #desktop} value is predominant than the Madkit choice. */ public boolean forceDesktop = false; /** * the agent frame class which should be used by the GUI manager, default is * {@link AgentFrame} */ public Class<?> agentFrameClass = AgentFrame.class; /** * the directory containing the MDK i18n files */ public File i18nDirectory = new File("com/distrimind/madkit/i18n/"); /** * Only useful for kernel developers */ public Level kernelLogLevel = Level.OFF; /** * Only useful for kernel developers */ public Level guiLogLevel = Level.OFF; /** * Can be used to make MaDKit quiet */ public Level madkitLogLevel = Level.INFO; /** * Can be used to specify multiple properties at once, using regular properties * files */ public ArrayList<File> configFiles = null; /** * If set to true, this MadKit properties will be saved into all files given by the <code>configFiles</code> list */ public boolean savePropertiesAfterKernelKill = false; public Level platformLogLevel = Level.INFO; /** * Connect to the MaDKit repository on startup. Default value is "false". */ public boolean autoConnectMadkitWebsite = false; /** * Loads all the jar files which are in the demos directory on startup. Default * value is "false". */ public boolean loadLocalDemos = false; /** * Launches the {@link ConsoleAgent} before any other. */ public boolean console = false; //public boolean noMadkitConsoleLog = false; public File MadkitLogFile = null; //public Level orgLogLevel = Level.OFF; //public boolean noOrgConsolLog = false; /** * Option defining the default agent log level for newly launched agents. * Default value is "INFO". This value could be overridden individually by * agents using {@link AbstractAgent#setLogLevel(Level)}. * <p> * Example: * <ul> * <li>--agentLogLevel OFF</li> * <li>--agentLogLevel ALL</li> * <li>--agentLogLevel FINE</li> * </ul> * * @see AbstractAgent#logger * @see java.util.logging.Logger * @see AbstractAgent#getMadkitConfig() */ public Level agentLogLevel = Level.INFO; /** * Defines if agent logging should be quiet in the default console. Default * value is "false". */ public boolean noAgentConsoleLog = false; /** * If activated, MaDKit will create a log file for every agent which has a log * level greater than {@link Level#OFF}. Default value is "false". * * @see #logDirectory */ public boolean createLogFiles = false; /** * Used to specify the directory wherein the logs should be done when the * {@link #createLogFiles} is activated. * * <pre> * SYNOPSIS * </pre> * * <code><b>--logDirectory</b></code> DIRECTORY_NAME * * <pre> * DESCRIPTION * </pre> * * Specify the desired directory. It could be an absolute or a relative path. At * runtime, a log directory named with the current date (second precision) will * be created in the log directory for each MaDKit session. E.g. * /home/neo/madkit_5/logs/2012.02.23.16.23.53 * * <pre> * DEFAULT VALUE * </pre> * * Default value is <i>"logs"</i>, so that a directory named "logs" will be * created in the application working directory. * * <pre> * EXAMPLES * </pre> * <ul> * <li>--logDirectory bin</li> * <li>--logDirectory /home/neo/madkit_logs</li> * </ul> * * @see #createLogFiles */ public File logDirectory = new File("logs"); /** * Option defining the default warning log level for newly launched agents. * Default value is "FINE". This value could be changed individually by the * agents using {@link AgentLogger#setWarningLogLevel(Level)} on their personal * logger. * <p> * Example: * <ul> * <li>--warningLogLevel OFF</li> * <li>--warningLogLevel ALL</li> * <li>--warningLogLevel FINE</li> * </ul> * * @see AbstractAgent#logger * @see java.util.logging.Logger * @see AbstractAgent#getMadkitConfig() * @since MaDKit 5 */ public Level warningLogLevel = Level.FINE; private DatabaseFactory databaseFactory; public void setDatabaseFactory(DatabaseFactory df) throws DatabaseException { if (databaseFactory != null && databaseFactory != df && !databaseFactory.getDatabaseWrapperSingleton().isClosed()) databaseFactory.getDatabaseWrapperSingleton().close(); databaseFactory = df; } public boolean isDatabaseEnabled() { return databaseFactory != null; } /** * Get the database wrapper (OOD) used by MadkitLanEdition. This wrapper * represents files storing several database. One of them is used by * MadkitLanEdition. It is possible to use this wrapper to create new database * that will be stored into the same file/directory. Moreover, it is not * recommended to use several database wrappers into the same program. We * recommend to use this wrapper to create all your database. * * @return the database wrapper used by MadkitLanEdition. * @throws DatabaseException if a problem occurs during the database connection * @see DatabaseWrapper * @see Table */ public DatabaseWrapper getDatabaseWrapper() throws DatabaseException { if (databaseFactory == null) return null; return databaseFactory.getDatabaseWrapperSingleton(); } public ArrayList<AgentToLaunch> launchAgents = null; public NetworkProperties networkProperties = new NetworkProperties(); public ArrayList<MultiFormatProperties> freeProperties = null; public static final String defaultProjectCodeName = "Unknown Project Name"; /** * Represents the current project version. */ public Version projectVersion = null; /** * Represents the minimum project version that this instance can accept. If a * distant peer try to connect with a project version lower than this one, than * the connection will be rejected. */ public Version minimumProjectVersion = null; /** * Root groups path that enable to filter asynchronous messages. * If the messages sending to differ has no group that is part of this path, * these messages are not sent. * If null is defined, all messages to differ are accepted. * However, we recommend to define this variable in order to optimize MaDKit. * The more this path is restrictive, the more MaDKit is reactive. */ public Collection<String> rootOfPathGroupUsedToFilterDifferedMessages = null; public MadkitProperties() { super(new MultiFormatPropertiesObjectParser()); this.minimumMadkitVersion = new Version(madkitVersion.getProgramName(), madkitVersion.getShortProgramName(), (short) 1, (short) 11, (short) 1, Version.Type.Stable, (short) 0, madkitVersion.getProjectStartDate(), madkitVersion.getProjectEndDate()); this.minimumMadkitVersion.setBuildNumber(100); try { madkitWeb = new URL("https://github.com/JazZ51/MaDKitLanEdition"); madkitRepositoryURL = new URL("https://github.com/JazZ51/MaDKitLanEdition");// new // URL(madkitWeb.toString()+"/repository/"+madkitVersion.getFileHeadName()+"/"); } catch (MalformedURLException e) { e.printStackTrace(); } } public void addProperty(MultiFormatProperties _property) { freeProperties.add(_property); } /** * Loads properties from an XML file. * * @param xml_file * can be absolute or relative * @throws IOException if a problem occurs during the XML file loading */ @Override public void loadXML(File xml_file) throws IOException { try { super.loadXML(xml_file); logger.fine(String.format(SuccessMessages.CONFIG_LOAD_SUCCESS.toString(), xml_file.toString())); } catch (PropertiesParseException e) { logger.log(Level.WARNING, String.format(ErrorMessages.CANT_LOAD_CONFIG_FILE.toString(), xml_file.toString()), e); } } /** * {@inheritDoc} */ @Override public void loadXML(Document document) { try { super.loadXML(document); logger.fine(String.format(SuccessMessages.CONFIG_LOAD_SUCCESS.toString(), document.toString())); } catch (PropertiesParseException e) { logger.log(Level.WARNING, String.format(ErrorMessages.CANT_LOAD_CONFIG_FILE.toString(), document.toString()), e); } } /** * Loads properties from an YAML file. * * @param yaml_file * can be absolute or relative * @throws IOException if a problem occurs during the XML file loading */ @Override public void loadYAML(File yaml_file) throws IOException { super.loadYAML(yaml_file); logger.fine(String.format(SuccessMessages.CONFIG_LOAD_SUCCESS.toString(), yaml_file.toString())); } public void load(File file) throws IOException { if (file.getName().endsWith(".xml")) loadXML(file); else if (file.getName().endsWith(".yaml")) loadYAML(file); else if (file.getName().endsWith(".properties")) { try (FileReader fr = new FileReader(file); BufferedReader br = new BufferedReader(fr)) { Properties p = new Properties(); p.load(br); loadFromProperties(p); } } } /** * {@inheritDoc} */ @Override public void saveXML(File xml_file) { saveXML(xml_file, null); } /** * {@inheritDoc} */ @Override public void saveXML(File xml_file, MultiFormatProperties referenceProperties) { try { super.saveXML(xml_file, referenceProperties); logger.fine(String.format(SuccessMessages.CONFIG_SAVE_SUCCESS.toString(), xml_file.toString())); } catch (PropertiesParseException e) { logger.log(Level.WARNING, String.format(ErrorMessages.CANT_SAVE_CONFIG_FILE.toString(), xml_file.toString()), e); } } public void save(File file) throws IOException, PropertiesParseException { save(file, null); } public void save(File file, MultiFormatProperties referenceProperties) throws IOException, PropertiesParseException { if (file.getName().endsWith(".xml")) saveXML(file, referenceProperties); else if (file.getName().endsWith(".yaml")) saveYAML(file, referenceProperties); else if (file.getName().endsWith(".properties")) { try (FileWriter fw = new FileWriter(file); BufferedWriter bw = new BufferedWriter(fw)) { convertToStringProperties(reference).store(bw, "Madkit properties"); } } } /** * {@inheritDoc} */ @Override public void saveYAML(File yaml_file) { saveYAML(yaml_file, null); } /** * {@inheritDoc} */ @Override public void saveYAML(File yaml_file, MultiFormatProperties referenceProperties) { try { super.saveYAML(yaml_file, referenceProperties); logger.fine(String.format(SuccessMessages.CONFIG_SAVE_SUCCESS.toString(), yaml_file.toString())); } catch (IOException e) { logger.log(Level.WARNING, String.format(ErrorMessages.CANT_SAVE_CONFIG_FILE.toString(), yaml_file.toString()), e); } } /** * {@inheritDoc} */ @Override public void saveXML(Document doc) { saveXML(doc, null); } /** * {@inheritDoc} */ @Override public void saveXML(Document doc, MultiFormatProperties referenceProperties) { try { super.saveXML(doc, referenceProperties); logger.fine(String.format(SuccessMessages.CONFIG_SAVE_SUCCESS.toString(), doc.toString())); } catch (PropertiesParseException e) { logger.log(Level.WARNING, String.format(ErrorMessages.CANT_SAVE_CONFIG_FILE.toString(), doc.toString()), e); } } @Override public MadkitProperties clone() { try { return (MadkitProperties) super.clone(); } catch (CloneNotSupportedException e) { e.printStackTrace(); return null; } } /* * * Loads properties from an XML file. * * @param filePath * can be absolute or relative * @throws IOException */ /* * public void loadPropertiesFromMaDKitXML(final String filePath) throws * IOException { try (InputStream is = getInputStream(filePath)) { NodeList * madkitOptionNodes = * DocumentBuilderFactory.newInstance().newDocumentBuilder().parse(is). * getDocumentElement() .getElementsByTagName(XMLUtilities.MADKIT_PROPERTIES); * for (int i = 0; i < madkitOptionNodes.getLength(); i++) { * org.w3c.dom.NamedNodeMap options = madkitOptionNodes.item(i).getAttributes(); * for (int j = 0; j < options.getLength(); j++) { * put(options.item(j).getNodeName(), options.item(j).getNodeValue()); } } * logger.fine("** Config file " + filePath + " successfully loaded **\n"); } * catch (SAXException | ParserConfigurationException e) { * logger.log(Level.WARNING, ErrorMessages.CANT_LOAD + "configuration " + * filePath, e); } } */ /* * Loads properties from a regular properties formatted file. * * @param pathname * @throws IOException */ /* * public void loadPropertiesFromPropertiesFile(final String pathname) throws * IOException { try (InputStream is = getInputStream(pathname)) { load(is); } * catch (IOException e) { throw e; } } */ /* * Loads properties from a properties file (classic or XML). * * @param pathname * @throws IOException */ /* * public void loadPropertiesFromFile(final String pathname) throws IOException * { if (pathname.endsWith(".xml")) { loadPropertiesFromMaDKitXML(pathname); } * else { loadPropertiesFromPropertiesFile(pathname); } } */ /** * Return an <code>InputStream</code> on a file. pathname could be relative to * (1) the actual MaDKit class path, which is preferable considering jar export, * or (2) the user.dir, or it could be an absolute path. The returned input * stream should be closed once done. * * @param file * A pathname string If the <code>pathname</code> argument is * <code>null</code> * @return an <code>InputStream</code> by opening a connection to an actual * file, or <code>null</code> if the file is not found. * * @throws IOException if IO problem occurs */ public static InputStream getInputStream(final File file) throws IOException { // closed when used InputStream is = file.exists() ? new FileInputStream(file) : MadkitClassLoader.getLoader().getResourceAsStream(file.toString()); if (is == null) throw new FileNotFoundException(file.toString()); return is; } @Override public Node getRootNode(Document _document) { for (int i = 0; i < _document.getChildNodes().getLength(); i++) { Node n = _document.getChildNodes().item(i); if (n.getNodeName().equals(XMLUtilities.MDK)) return n; } return null; } @Override public Node createOrGetRootNode(Document _document) { Node res = getRootNode(_document); if (res == null) { res = _document.createElement(XMLUtilities.MDK); _document.appendChild(res); } return res; } public static void main(String args[]) { MadkitProperties mp = new MadkitProperties(); mp.saveYAML(new File("madkit.yaml")); } boolean prepareCurrentRandomSeedsForBackup() { boolean change = false; if (approvedRandom != null) { savedRandomSeedForApprovedRandom = Base64.encodeBase64URLSafeString(approvedRandom.generateSeed(55)); change = true; } if (approvedRandomForKeys != null) { savedRandomSeedForApprovedRandomForKeys = Base64 .encodeBase64URLSafeString(approvedRandomForKeys.generateSeed(55)); change = true; } return change; } private String savedRandomSeedForApprovedRandom = null, savedRandomSeedForApprovedRandomForKeys = null; private SecureRandomType approvedRandomType = SecureRandomType.FORTUNA_WITH_BC_FIPS_APPROVED; private SecureRandomType approvedRandomTypeForKeys = SecureRandomType.FORTUNA_WITH_BC_FIPS_APPROVED_FOR_KEYS; private volatile AbstractSecureRandom approvedRandom = null; private volatile AbstractSecureRandom approvedRandomForKeys = null; private String nonceForApprovedRandom = "Au courant de l'amour lorsque je m'abandonne,\n" + "Dans le torrent divin quand je plonge enivr,\n" + "Et presse perdument sur mon sein qui frissonne\n" + "Un tre idoltre.\n" + "\n" + "Je sais que je n'treins qu'une forme fragile,\n" + "Qu'elle peut l'instant se glacer sous ma main,\n" + "Que ce cur tout moi, fait de flamme et d'argile,\n" + "Sera cendre demain ;\n" + "\n" + "Qu'il n'en sortira rien, rien, pas une tincelle\n" + "Qui s'lance et remonte son foyer lointain :\n" + "Un peu de terre en hte, une pierre qu'on scelle,\n" + "Et tout est bien teint.\n" + "\n" + "Et l'on viendrait serein, cette heure dernire,\n" + "Quand des restes humains le souffle a dsert,\n" + "Devant ces froids dbris, devant cette poussire\n" + "Parler d'ternit !\n"; private String nonceForApprovedRandomForKeys = "\n" + "\n" + " L Emmur.\n" + "\n" + " Sil respire il pense lencoche\n" + " Dans la tendre chaux confidente\n" + " O ses mains du soir tendent ton corps.\n" + "\n" + " Le laurier lpuise,\n" + " La privation le consolide.\n" + "\n" + " O toi, la monotone absente,\n" + " La fileuse de salptre,\n" + " Derrire des paisseurs fixes\n" + " Une chelle sans ge dploie ton voile !\n" + "\n" + " Tu vas nue, constelle dchardes,\n" + " Secrte, tide et disponible,\n" + " Attache au sol indolent,\n" + " Mais lintime de lhomme abrupt dans sa prison.\n" + "\n" + " A te mordre les jours grandissent,\n" + " Plus arides, plus imprenables que les nuages qui se dchirent au fond des os.\n" + " Jai pes de tout mon dsir\n" + " Sur ta beaut matinale\n" + " Pour quelle clate et se sauve.\n" + "\n" + " Lont suivie lalcool sans rois mages,\n" + " Le battement de ton triangle,\n" + " La main-doeuvre de tes yeux\n" + " Et le gravier debout sur lalgue.\n" + "\n" + " Un parfum dinsolation\n" + " Protge ce qui va clore.\n" + "\n" + ""; private String parameterForApprovedRandom = "J'ai rencontr trois escargots\n" + "Qui s'en allaient cartable au dos\n" + "Et dans le pr trois limaons\n" + "Qui disaient par cur leur leon.\n" + "Puis dans un champ, quatre lzards\n" + "Qui crivaient un long devoir.\n" + "\n" + "O peut se trouver leur cole ?\n" + "Au milieu des avoines folles ?\n" + "Et leur matre est-il ce corbeau\n" + "Que je vois dessiner l-haut\n" + "De belles lettres au tableau ?"; private String parameterForApprovedRandomForKeys = "Eh bien ! reprends-le donc ce peu de fange obscure\n" + "Qui pour quelques instants s'anima sous ta main ;\n" + "Dans ton ddain superbe, implacable Nature,\n" + "Brise jamais le moule humain.\n" + "\n" + "De ces tristes dbris quand tu verrais, ravie,\n" + "D'autres crations clore grands essaims,\n" + "Ton Ide clater en des formes de vie\n" + "Plus dociles tes desseins,\n" + "\n" + "Est-ce dire que Lui, ton espoir, ta chimre,\n" + "Parce qu'il fut rv, puisse un jour exister ?\n" + "Tu crois avoir conu, tu voudrais tre mre ;\n" + "A l'uvre ! il s'agit d'enfanter.\n" + "\n" + "Change en ralit ton attente sublime.\n" + "Mais quoi ! pour les franchir, malgr tous tes lans,\n" + "La distance est trop grande et trop profond l'abme\n" + "Entre ta pense et tes flancs.\n"; public SecureRandomType getApprovedRandomType() { return approvedRandomType; } public void setApprovedRandomType(SecureRandomType approvedRandomType) { this.approvedRandomType = approvedRandomType; approvedRandom = null; } public SecureRandomType getApprovedRandomTypeForKeys() { return approvedRandomTypeForKeys; } public void setApprovedRandomTypeForKeys(SecureRandomType approvedRandomTypeForKeys) { this.approvedRandomTypeForKeys = approvedRandomTypeForKeys; } private static long getMacAddress() { long result = 0; long result2 = 0; try { final Enumeration<NetworkInterface> e = NetworkInterface.getNetworkInterfaces(); while (e.hasMoreElements()) { final NetworkInterface ni = e.nextElement(); if (!ni.isLoopback()) { long val = getHardwareAddress(ni.getHardwareAddress()); if (val != 0 && val != 224) { if (ni.isPointToPoint()) { result2 = val; } else { result = val; break; } } } } } catch (Exception e) { e.printStackTrace(); } if (result == 0) result = result2; return result; } private static long getHardwareAddress(byte hardwareAddress[]) { long result = 0; if (hardwareAddress != null) { for (final byte value : hardwareAddress) { result <<= 8; result |= value & 255; } } return result; } public AbstractSecureRandom getApprovedSecureRandom() throws NoSuchAlgorithmException, NoSuchProviderException { if (approvedRandom == null) { synchronized (this) { if (approvedRandom == null) { approvedRandom = approvedRandomType.getSingleton( ((nonceForApprovedRandom + System.currentTimeMillis() + (savedRandomSeedForApprovedRandom == null ? "" : savedRandomSeedForApprovedRandom)) + getMacAddress()).getBytes(), parameterForApprovedRandom.getBytes(), true); } } } return approvedRandom; } public AbstractSecureRandom getApprovedSecureRandomForKeys() throws NoSuchAlgorithmException, NoSuchProviderException { if (approvedRandomForKeys == null) { synchronized (this) { if (approvedRandomForKeys == null) { approvedRandomForKeys = approvedRandomTypeForKeys.getSingleton( ((nonceForApprovedRandomForKeys + System.currentTimeMillis() + (savedRandomSeedForApprovedRandomForKeys == null ? "" : savedRandomSeedForApprovedRandomForKeys)) + getMacAddress()).getBytes(), parameterForApprovedRandomForKeys.getBytes(), true); } } } return approvedRandomForKeys; } public String getNonceForApprovedRandom() { return nonceForApprovedRandom; } public void setNonceForApprovedRandom(String nonceForApprovedRandom) { this.nonceForApprovedRandom = nonceForApprovedRandom; approvedRandom = null; } public String getNonceForApprovedRandomForKeys() { return nonceForApprovedRandomForKeys; } public void setNonceForApprovedRandomForKeys(String nonceForApprovedRandomForKeys) { this.nonceForApprovedRandomForKeys = nonceForApprovedRandomForKeys; approvedRandomForKeys = null; } public String getParameterForApprovedRandom() { return parameterForApprovedRandom; } public void setParameterForApprovedRandom(String parameterForApprovedRandom) { this.parameterForApprovedRandom = parameterForApprovedRandom; approvedRandom = null; } public String getParameterForApprovedRandomKeys() { return parameterForApprovedRandomForKeys; } public void setParameterForApprovedRandomKeys(String parameterForApprovedRandomKeys) { this.parameterForApprovedRandomForKeys = parameterForApprovedRandomKeys; approvedRandomForKeys = null; } private transient MadkitProperties reference = null; void setReference(MadkitProperties reference) { this.reference = reference; } public MadkitProperties getReference() { return reference; } /** * Save MadKit config into the given file. * Save only the differences between the current MaDKit config and the reference MaDKit configuration, given at the MaDKit construction * @see #getReference() * @param file the file path * @throws IOException if a problem occurs * @throws PropertiesParseException if the property file parsing failed */ public void saveConfiguration(File file) throws IOException, PropertiesParseException { if (file == null) throw new NullPointerException(); prepareCurrentRandomSeedsForBackup(); save(file, reference); } /** * Save MadKit config into the file given by {@link #configFiles}. * Save only the differences between the current MaDKit config and the reference MaDKit configuration, given at the MaDKit construction * @see #getReference() * @throws IOException if a problem occurs * @throws PropertiesParseException if the property file parsing failed */ public void saveConfiguration() throws IOException, PropertiesParseException { if (configFiles == null) return; prepareCurrentRandomSeedsForBackup(); for (File f : configFiles) save(f, reference); } }