Skip to content
Snippets Groups Projects
Commit 4640fd73 authored by ribeaudc's avatar ribeaudc
Browse files

change:

- If 'RoleBasedAccessController' is configured using a file, this file will be watched for changes.
add:
- 'FileWatcher' and 'FileWatcherSynchronizer' in common
remove:
- TODO

SVN: 1368
parent f6efab7b
No related branches found
No related tags found
No related merge requests found
/*
* Copyright 2007 ETH Zuerich, CISD
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package ch.systemsx.cisd.common.utilities;
import java.io.File;
import java.util.TimerTask;
import org.apache.log4j.Logger;
import ch.systemsx.cisd.common.logging.LogCategory;
import ch.systemsx.cisd.common.logging.LogFactory;
/**
* A <code>TimerTask</code> extension that watch a given file.
*
* @author Christian Ribeaud
*/
public abstract class FileWatcher extends TimerTask
{
private static final Logger operationLog = LogFactory.getLogger(LogCategory.OPERATION, FileWatcher.class);
/** The default <code>FileWatcherState</code> implementation used. */
private static final IFileWatcherState DEFAULT_FILE_WATCHER_STATE = new LastModifiedState();
private final File fileToWatch;
private final IFileWatcherState fileWatcherState;
/** Whether the user has already been warned. */
private boolean warnedAlready = false;
public FileWatcher(File fileToWatch)
{
this(fileToWatch, DEFAULT_FILE_WATCHER_STATE);
}
public FileWatcher(File fileToWatch, IFileWatcherState fileWatcherState)
{
this.fileToWatch = fileToWatch;
this.fileWatcherState = fileWatcherState;
fileWatcherState.saveInitialState(fileToWatch);
}
public final File getFileToWatch()
{
return fileToWatch;
}
/** The action we should perform when the file we are watching has changed its state. */
protected abstract void onChange();
//
// TimerTask
//
@Override
public final void run()
{
boolean fileExists = false;
try
{
fileExists = fileToWatch.exists();
} catch (SecurityException e)
{
operationLog.warn(String.format("Was not allowed to check existence of file '%s'.", fileToWatch), e);
return;
}
if (fileExists)
{
if (fileWatcherState.stateChanged(fileToWatch))
{
if (operationLog.isDebugEnabled())
{
operationLog.debug(String.format("Watched file '%s' has changed.", fileToWatch));
}
onChange();
warnedAlready = false;
} else
{
if (operationLog.isDebugEnabled())
{
operationLog.debug(String.format("Watched file '%s' did not change.", fileToWatch));
}
}
} else
{
if (warnedAlready == false)
{
operationLog.warn(String.format("Given file '%s' does not exist.", fileToWatch));
warnedAlready = true;
}
}
}
/**
* Specifies the file property (or character) we are watching.
*
* @author Christian Ribeaud
*/
public static interface IFileWatcherState
{
/**
* Saves the initial state of given <var>fileToWatch</var>.
* <p>
* This method is called when <code>FileWatcher</code> gets instantiated.
* </p>
*/
public void saveInitialState(File fileToWatch);
/**
* Whether the file state has changed.
* <p>
* If the file state has changed, each implementation should save the new state before returning
* <code>true</code>.
* </p>
*/
public boolean stateChanged(File fileToWatch);
}
/**
* A <code>FileWatcherState</code> implementation that works with the value returned by
* {@link File#lastModified()}.
*
* @author Christian Ribeaud
*/
public final static class LastModifiedState implements IFileWatcherState
{
private long lastModified;
//
// FileWatcherCondition
//
public final void saveInitialState(File fileToWatch)
{
lastModified = fileToWatch.lastModified();
}
public final boolean stateChanged(File fileToWatch)
{
long current = fileToWatch.lastModified();
if (current > lastModified)
{
lastModified = current;
return true;
}
return false;
}
}
}
/*
* Copyright 2007 ETH Zuerich, CISD
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package ch.systemsx.cisd.common.utilities;
import java.io.File;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.TimerTask;
import javax.swing.event.ChangeEvent;
import javax.swing.event.ChangeListener;
import org.apache.log4j.Logger;
import ch.systemsx.cisd.common.logging.LogCategory;
import ch.systemsx.cisd.common.logging.LogFactory;
/**
* Kind of <code>FileWatcher</code> extension that allow registration of multiple <code>ChangeListener</code> for
* one file watched.
* <p>
* You can use this class as <i>singleton</i> calling {@link #getInstance()} or you may instance it with a constructor.
* Note that access to this class is <i>synchronized</i>.
* </p>
*
* @author Christian Ribeaud
*/
public final class FileWatcherSynchronizer extends TimerTask
{
private static final Logger operationLog =
LogFactory.getLogger(LogCategory.OPERATION, FileWatcherSynchronizer.class);
private static FileWatcherSynchronizer instance;
private final Map<FileWatcher, List<ChangeListener>> fileWatcherListeners;
private final Map<File, FileWatcher> fileWatchers;
public FileWatcherSynchronizer()
{
fileWatcherListeners = new HashMap<FileWatcher, List<ChangeListener>>();
fileWatchers = new HashMap<File, FileWatcher>();
}
public final static synchronized FileWatcherSynchronizer getInstance()
{
if (instance == null)
{
instance = new FileWatcherSynchronizer();
}
return instance;
}
public final synchronized void addChangeListener(final File file, final ChangeListener changeListener)
{
FileWatcher fileWatcher = fileWatchers.get(file);
if (fileWatcher == null)
{
fileWatcher = new FileWatcher(file)
{
//
// FileWatcher
//
@Override
protected final void onChange()
{
fireStateChanged(this);
}
};
if (operationLog.isDebugEnabled())
{
operationLog.debug(String.format("A new watcher has been created for file '%s'", file));
}
fileWatchers.put(file, fileWatcher);
}
List<ChangeListener> listeners = fileWatcherListeners.get(fileWatcher);
if (listeners == null)
{
listeners = new ArrayList<ChangeListener>();
fileWatcherListeners.put(fileWatcher, listeners);
}
listeners.add(changeListener);
if (operationLog.isDebugEnabled())
{
operationLog.debug(String.format(
"A new listener has been registered for file '%s'. Currently %d listeners registered.", file,
listeners.size()));
}
}
public final synchronized void removeChangeListener(final File file, final ChangeListener changeListener)
{
FileWatcher fileWatcher = fileWatchers.get(file);
if (fileWatcher == null)
{
return;
}
List<ChangeListener> listeners = fileWatcherListeners.get(fileWatcher);
if (listeners == null)
{
return;
}
listeners.remove(changeListener);
if (operationLog.isDebugEnabled())
{
operationLog.debug(String.format(
"A listener for file '%s' has been removed. Currently %d listeners registered.", file, listeners
.size()));
}
}
private final synchronized void fireStateChanged(FileWatcher fileWatcher)
{
final ChangeEvent event = new ChangeEvent(fileWatcher.getFileToWatch());
for (ChangeListener listener : fileWatcherListeners.get(fileWatcher))
{
listener.stateChanged(event);
}
}
//
// TimerTask
//
@Override
public final synchronized void run()
{
for (FileWatcher fileWatcher : fileWatcherListeners.keySet())
{
fileWatcher.run();
}
}
}
\ No newline at end of file
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment