blob: f8e3378d9760c2276189f989a7a3a21967cd6a34 [file] [log] [blame]
/*
* Licensed to the Apache Software Foundation (ASF) under one or more
* contributor license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright ownership.
* The ASF licenses this file to You 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 org.apache.commons.jci.listeners;
import java.io.File;
import java.io.FileInputStream;
import java.util.Collection;
import java.util.HashSet;
import java.util.Set;
import org.apache.commons.io.IOUtils;
import org.apache.commons.jci.ReloadingClassLoader;
import org.apache.commons.jci.monitor.FilesystemAlterationObserver;
import org.apache.commons.jci.stores.MemoryResourceStore;
import org.apache.commons.jci.stores.ResourceStore;
import org.apache.commons.jci.stores.Transactional;
import org.apache.commons.jci.utils.ConversionUtils;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
/**
* This Listener waits for FAM events to trigger a reload of classes
* or resources.
*
* @author tcurdt
*/
public class ReloadingListener extends AbstractFilesystemAlterationListener {
private final Log log = LogFactory.getLog(ReloadingListener.class);
private final Set<ReloadNotificationListener> notificationListeners = new HashSet<ReloadNotificationListener>();
private final ResourceStore store;
public ReloadingListener() {
this(new MemoryResourceStore());
}
public ReloadingListener( final ResourceStore pStore ) {
store = pStore;
}
public ResourceStore getStore() {
return store;
}
public void addReloadNotificationListener( final ReloadNotificationListener pNotificationListener ) {
notificationListeners.add(pNotificationListener);
if (pNotificationListener instanceof ReloadingClassLoader) {
((ReloadingClassLoader)pNotificationListener).addResourceStore(store);
}
}
public boolean isReloadRequired( final FilesystemAlterationObserver pObserver ) {
boolean reload = false;
final Collection<File> created = getCreatedFiles();
final Collection<File> changed = getChangedFiles();
final Collection<File> deleted = getDeletedFiles();
log.debug("created:" + created.size() + " changed:" + changed.size() + " deleted:" + deleted.size() + " resources");
if (deleted.size() > 0) {
for (File file : deleted) {
final String resourceName = ConversionUtils.getResourceNameFromFileName(ConversionUtils.relative(pObserver.getRootDirectory(), file));
store.remove(resourceName);
}
reload = true;
}
if (created.size() > 0) {
for (File file : created) {
FileInputStream is = null;
try {
is = new FileInputStream(file);
final byte[] bytes = IOUtils.toByteArray(is);
final String resourceName = ConversionUtils.getResourceNameFromFileName(ConversionUtils.relative(pObserver.getRootDirectory(), file));
store.write(resourceName, bytes);
} catch(final Exception e) {
log.error("could not load " + file, e);
} finally {
IOUtils.closeQuietly(is);
}
}
}
if (changed.size() > 0) {
for (File file : changed) {
FileInputStream is = null;
try {
is = new FileInputStream(file);
final byte[] bytes = IOUtils.toByteArray(is);
final String resourceName = ConversionUtils.getResourceNameFromFileName(ConversionUtils.relative(pObserver.getRootDirectory(), file));
store.write(resourceName, bytes);
} catch(final Exception e) {
log.error("could not load " + file, e);
} finally {
IOUtils.closeQuietly(is);
}
}
reload = true;
}
return reload;
}
@Override
public void onStop( final FilesystemAlterationObserver pObserver ) {
if (store instanceof Transactional) {
((Transactional)store).onStart();
}
final boolean reload = isReloadRequired(pObserver);
if (store instanceof Transactional) {
((Transactional)store).onStop();
}
if (reload) {
notifyReloadNotificationListeners();
}
super.onStop(pObserver);
}
void notifyReloadNotificationListeners() {
for (ReloadNotificationListener listener : notificationListeners) {
log.debug("notifying listener " + listener);
listener.handleNotification();
}
}
@Override
public void onDirectoryCreate( final File pDir ) {
}
@Override
public void onDirectoryChange( final File pDir ) {
}
@Override
public void onDirectoryDelete( final File pDir ) {
}
}