001 /* 002 * Licensed to the Apache Software Foundation (ASF) under one or more 003 * contributor license agreements. See the NOTICE file distributed with 004 * this work for additional information regarding copyright ownership. 005 * The ASF licenses this file to You under the Apache License, Version 2.0 006 * (the "License"); you may not use this file except in compliance with 007 * the License. You may obtain a copy of the License at 008 * 009 * http://www.apache.org/licenses/LICENSE-2.0 010 * 011 * Unless required by applicable law or agreed to in writing, software 012 * distributed under the License is distributed on an "AS IS" BASIS, 013 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 014 * See the License for the specific language governing permissions and 015 * limitations under the License. 016 */ 017 018 package org.apache.commons.jci.listeners; 019 020 import java.io.File; 021 import java.io.FileInputStream; 022 import java.util.Collection; 023 import java.util.HashSet; 024 import java.util.Set; 025 026 import org.apache.commons.io.IOUtils; 027 import org.apache.commons.jci.ReloadingClassLoader; 028 import org.apache.commons.jci.monitor.FilesystemAlterationObserver; 029 import org.apache.commons.jci.stores.MemoryResourceStore; 030 import org.apache.commons.jci.stores.ResourceStore; 031 import org.apache.commons.jci.stores.Transactional; 032 import org.apache.commons.jci.utils.ConversionUtils; 033 import org.apache.commons.logging.Log; 034 import org.apache.commons.logging.LogFactory; 035 036 /** 037 * This Listener waits for FAM events to trigger a reload of classes 038 * or resources. 039 * 040 * @author tcurdt 041 */ 042 public class ReloadingListener extends AbstractFilesystemAlterationListener { 043 044 private final Log log = LogFactory.getLog(ReloadingListener.class); 045 046 private final Set<ReloadNotificationListener> notificationListeners = new HashSet<ReloadNotificationListener>(); 047 private final ResourceStore store; 048 049 public ReloadingListener() { 050 this(new MemoryResourceStore()); 051 } 052 053 public ReloadingListener( final ResourceStore pStore ) { 054 store = pStore; 055 } 056 057 public ResourceStore getStore() { 058 return store; 059 } 060 061 public void addReloadNotificationListener( final ReloadNotificationListener pNotificationListener ) { 062 notificationListeners.add(pNotificationListener); 063 064 if (pNotificationListener instanceof ReloadingClassLoader) { 065 ((ReloadingClassLoader)pNotificationListener).addResourceStore(store); 066 } 067 068 } 069 070 public boolean isReloadRequired( final FilesystemAlterationObserver pObserver ) { 071 boolean reload = false; 072 073 final Collection<File> created = getCreatedFiles(); 074 final Collection<File> changed = getChangedFiles(); 075 final Collection<File> deleted = getDeletedFiles(); 076 077 log.debug("created:" + created.size() + " changed:" + changed.size() + " deleted:" + deleted.size() + " resources"); 078 079 if (deleted.size() > 0) { 080 for (File file : deleted) { 081 final String resourceName = ConversionUtils.getResourceNameFromFileName(ConversionUtils.relative(pObserver.getRootDirectory(), file)); 082 store.remove(resourceName); 083 } 084 reload = true; 085 } 086 087 if (created.size() > 0) { 088 for (File file : created) { 089 FileInputStream is = null; 090 try { 091 is = new FileInputStream(file); 092 final byte[] bytes = IOUtils.toByteArray(is); 093 final String resourceName = ConversionUtils.getResourceNameFromFileName(ConversionUtils.relative(pObserver.getRootDirectory(), file)); 094 store.write(resourceName, bytes); 095 } catch(final Exception e) { 096 log.error("could not load " + file, e); 097 } finally { 098 IOUtils.closeQuietly(is); 099 } 100 } 101 } 102 103 if (changed.size() > 0) { 104 for (File file : changed) { 105 FileInputStream is = null; 106 try { 107 is = new FileInputStream(file); 108 final byte[] bytes = IOUtils.toByteArray(is); 109 final String resourceName = ConversionUtils.getResourceNameFromFileName(ConversionUtils.relative(pObserver.getRootDirectory(), file)); 110 store.write(resourceName, bytes); 111 } catch(final Exception e) { 112 log.error("could not load " + file, e); 113 } finally { 114 IOUtils.closeQuietly(is); 115 } 116 } 117 reload = true; 118 } 119 120 return reload; 121 } 122 123 @Override 124 public void onStop( final FilesystemAlterationObserver pObserver ) { 125 126 127 if (store instanceof Transactional) { 128 ((Transactional)store).onStart(); 129 } 130 131 final boolean reload = isReloadRequired(pObserver); 132 133 if (store instanceof Transactional) { 134 ((Transactional)store).onStop(); 135 } 136 137 if (reload) { 138 notifyReloadNotificationListeners(); 139 } 140 141 super.onStop(pObserver); 142 } 143 144 void notifyReloadNotificationListeners() { 145 for (ReloadNotificationListener listener : notificationListeners) { 146 log.debug("notifying listener " + listener); 147 148 listener.handleNotification(); 149 } 150 } 151 152 @Override 153 public void onDirectoryCreate( final File pDir ) { 154 } 155 @Override 156 public void onDirectoryChange( final File pDir ) { 157 } 158 @Override 159 public void onDirectoryDelete( final File pDir ) { 160 } 161 }