/** * Performs a reload operation if necessary. This method is called on each access of this * configuration. It asks the associated reloading strategy whether a reload should be performed. * If this is the case, the configuration is cleared and loaded again from its source. If this * operation causes an exception, the registered error listeners will be notified. The error event * passed to the listeners is of type <code>EVENT_RELOAD</code> and contains the exception that * caused the event. */ public void reload() { synchronized (reloadLock) { if (noReload == 0) { try { enterNoReload(); // avoid reentrant calls if (strategy.reloadingRequired()) { if (getLogger().isInfoEnabled()) { getLogger().info("Reloading configuration. URL is " + getURL()); } fireEvent(EVENT_RELOAD, null, getURL(), true); setDetailEvents(false); boolean autoSaveBak = this.isAutoSave(); // save the current state this.setAutoSave(false); // deactivate autoSave to prevent information loss try { clear(); load(); } finally { this.setAutoSave(autoSaveBak); // set autoSave to previous value setDetailEvents(true); } fireEvent(EVENT_RELOAD, null, getURL(), false); // notify the strategy strategy.reloadingPerformed(); } } catch (Exception e) { fireError(EVENT_RELOAD, null, null, e); // todo rollback the changes if the file can't be reloaded } finally { exitNoReload(); } } } }
/** * Sends an event to all registered listeners. This implementation ensures that no reloads are * performed while the listeners are invoked. So infinite loops can be avoided that can be caused * by event listeners accessing the configuration's properties when they are invoked. * * @param type the event type * @param propName the name of the property * @param propValue the value of the property * @param before the before update flag */ protected void fireEvent(int type, String propName, Object propValue, boolean before) { enterNoReload(); try { super.fireEvent(type, propName, propValue, before); } finally { exitNoReload(); } }
/** * Returns an <code>Iterator</code> with the keys contained in this configuration. This * implementation performs a reload if necessary before obtaining the keys. The <code>Iterator * </code> returned by this method points to a snapshot taken when this method was called. Later * changes at the set of keys (including those caused by a reload) won't be visible. This is * because a reload can happen at any time during iteration, and it is impossible to determine how * this reload affects the current iteration. When using the iterator a client has to be aware * that changes of the configuration are possible at any time. For instance, if after a reload * operation some keys are no longer present, the iterator will still return those keys because * they were found when it was created. * * @return an <code>Iterator</code> with the keys of this configuration */ public Iterator getKeys() { reload(); List keyList = new LinkedList(); enterNoReload(); try { for (Iterator it = super.getKeys(); it.hasNext(); ) { keyList.add(it.next()); } return keyList.iterator(); } finally { exitNoReload(); } }