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.Iterator;
025: import java.util.Set;
026:
027: import org.apache.commons.io.IOUtils;
028: import org.apache.commons.jci.ReloadingClassLoader;
029: import org.apache.commons.jci.monitor.FilesystemAlterationObserver;
030: import org.apache.commons.jci.stores.MemoryResourceStore;
031: import org.apache.commons.jci.stores.ResourceStore;
032: import org.apache.commons.jci.stores.Transactional;
033: import org.apache.commons.jci.utils.ConversionUtils;
034: import org.apache.commons.logging.Log;
035: import org.apache.commons.logging.LogFactory;
036:
037: /**
038: * This Listener waits for FAM events to trigger a reload of classes
039: * or resources.
040: *
041: * @author tcurdt
042: */
043: public class ReloadingListener extends
044: AbstractFilesystemAlterationListener {
045:
046: private final Log log = LogFactory.getLog(ReloadingListener.class);
047:
048: private final Set notificationListeners = new HashSet();
049: private final ResourceStore store;
050:
051: public ReloadingListener() {
052: this (new MemoryResourceStore());
053: }
054:
055: public ReloadingListener(final ResourceStore pStore) {
056: store = pStore;
057: }
058:
059: public ResourceStore getStore() {
060: return store;
061: }
062:
063: public void addReloadNotificationListener(
064: final ReloadNotificationListener pNotificationListener) {
065: notificationListeners.add(pNotificationListener);
066:
067: if (pNotificationListener instanceof ReloadingClassLoader) {
068: ((ReloadingClassLoader) pNotificationListener)
069: .addResourceStore(store);
070: }
071:
072: }
073:
074: public boolean isReloadRequired(
075: final FilesystemAlterationObserver pObserver) {
076: boolean reload = false;
077:
078: final Collection created = getCreatedFiles();
079: final Collection changed = getChangedFiles();
080: final Collection deleted = getDeletedFiles();
081:
082: log.debug("created:" + created.size() + " changed:"
083: + changed.size() + " deleted:" + deleted.size()
084: + " resources");
085:
086: if (deleted.size() > 0) {
087: for (Iterator it = deleted.iterator(); it.hasNext();) {
088: final File file = (File) it.next();
089: final String resourceName = ConversionUtils
090: .getResourceNameFromFileName(ConversionUtils
091: .relative(pObserver.getRootDirectory(),
092: file));
093: store.remove(resourceName);
094: }
095: reload = true;
096: }
097:
098: if (created.size() > 0) {
099: for (Iterator it = created.iterator(); it.hasNext();) {
100: final File file = (File) it.next();
101: FileInputStream is = null;
102: try {
103: is = new FileInputStream(file);
104: final byte[] bytes = IOUtils.toByteArray(is);
105: final String resourceName = ConversionUtils
106: .getResourceNameFromFileName(ConversionUtils
107: .relative(pObserver
108: .getRootDirectory(), file));
109: store.write(resourceName, bytes);
110: } catch (final Exception e) {
111: log.error("could not load " + file, e);
112: } finally {
113: IOUtils.closeQuietly(is);
114: }
115: }
116: }
117:
118: if (changed.size() > 0) {
119: for (Iterator it = changed.iterator(); it.hasNext();) {
120: final File file = (File) it.next();
121: FileInputStream is = null;
122: try {
123: is = new FileInputStream(file);
124: final byte[] bytes = IOUtils.toByteArray(is);
125: final String resourceName = ConversionUtils
126: .getResourceNameFromFileName(ConversionUtils
127: .relative(pObserver
128: .getRootDirectory(), file));
129: store.write(resourceName, bytes);
130: } catch (final Exception e) {
131: log.error("could not load " + file, e);
132: } finally {
133: IOUtils.closeQuietly(is);
134: }
135: }
136: reload = true;
137: }
138:
139: return reload;
140: }
141:
142: public void onStop(final FilesystemAlterationObserver pObserver) {
143:
144: if (store instanceof Transactional) {
145: ((Transactional) store).onStart();
146: }
147:
148: final boolean reload = isReloadRequired(pObserver);
149:
150: if (store instanceof Transactional) {
151: ((Transactional) store).onStop();
152: }
153:
154: if (reload) {
155: notifyReloadNotificationListeners();
156: }
157:
158: super .onStop(pObserver);
159: }
160:
161: void notifyReloadNotificationListeners() {
162:
163: for (Iterator it = notificationListeners.iterator(); it
164: .hasNext();) {
165: final ReloadNotificationListener listener = (ReloadNotificationListener) it
166: .next();
167:
168: log.debug("notifying listener " + listener);
169:
170: listener.handleNotification();
171: }
172: }
173:
174: public void onDirectoryCreate(final File pDir) {
175: }
176:
177: public void onDirectoryChange(final File pDir) {
178: }
179:
180: public void onDirectoryDelete(final File pDir) {
181: }
182: }
|