1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18 package org.apache.commons.jci.listeners;
19
20 import java.io.File;
21 import java.io.FileInputStream;
22 import java.util.Collection;
23 import java.util.HashSet;
24 import java.util.Set;
25
26 import org.apache.commons.io.IOUtils;
27 import org.apache.commons.jci.ReloadingClassLoader;
28 import org.apache.commons.jci.monitor.FilesystemAlterationObserver;
29 import org.apache.commons.jci.stores.MemoryResourceStore;
30 import org.apache.commons.jci.stores.ResourceStore;
31 import org.apache.commons.jci.stores.Transactional;
32 import org.apache.commons.jci.utils.ConversionUtils;
33 import org.apache.commons.logging.Log;
34 import org.apache.commons.logging.LogFactory;
35
36
37
38
39
40
41
42 public class ReloadingListener extends AbstractFilesystemAlterationListener {
43
44 private final Log log = LogFactory.getLog(ReloadingListener.class);
45
46 private final Set<ReloadNotificationListener> notificationListeners = new HashSet<ReloadNotificationListener>();
47 private final ResourceStore store;
48
49 public ReloadingListener() {
50 this(new MemoryResourceStore());
51 }
52
53 public ReloadingListener( final ResourceStore pStore ) {
54 store = pStore;
55 }
56
57 public ResourceStore getStore() {
58 return store;
59 }
60
61 public void addReloadNotificationListener( final ReloadNotificationListener pNotificationListener ) {
62 notificationListeners.add(pNotificationListener);
63
64 if (pNotificationListener instanceof ReloadingClassLoader) {
65 ((ReloadingClassLoader)pNotificationListener).addResourceStore(store);
66 }
67
68 }
69
70 public boolean isReloadRequired( final FilesystemAlterationObserver pObserver ) {
71 boolean reload = false;
72
73 final Collection<File> created = getCreatedFiles();
74 final Collection<File> changed = getChangedFiles();
75 final Collection<File> deleted = getDeletedFiles();
76
77 log.debug("created:" + created.size() + " changed:" + changed.size() + " deleted:" + deleted.size() + " resources");
78
79 if (deleted.size() > 0) {
80 for (File file : deleted) {
81 final String resourceName = ConversionUtils.getResourceNameFromFileName(ConversionUtils.relative(pObserver.getRootDirectory(), file));
82 store.remove(resourceName);
83 }
84 reload = true;
85 }
86
87 if (created.size() > 0) {
88 for (File file : created) {
89 FileInputStream is = null;
90 try {
91 is = new FileInputStream(file);
92 final byte[] bytes = IOUtils.toByteArray(is);
93 final String resourceName = ConversionUtils.getResourceNameFromFileName(ConversionUtils.relative(pObserver.getRootDirectory(), file));
94 store.write(resourceName, bytes);
95 } catch(final Exception e) {
96 log.error("could not load " + file, e);
97 } finally {
98 IOUtils.closeQuietly(is);
99 }
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 }