1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34 package info.magnolia.resourceloader;
35
36 import info.magnolia.resourceloader.util.ResourceTreeWalker;
37
38 import java.io.BufferedReader;
39 import java.io.IOException;
40 import java.io.InputStream;
41 import java.io.InputStreamReader;
42 import java.io.Reader;
43 import java.nio.charset.Charset;
44 import java.util.List;
45 import java.util.Set;
46
47 import org.slf4j.Logger;
48 import org.slf4j.LoggerFactory;
49
50 import com.google.common.collect.Sets;
51
52
53
54
55
56
57
58
59 public abstract class AbstractResourceOrigin<P extends AbstractResource> implements ResourceOrigin<P> {
60
61 private static final Logger log = LoggerFactory.getLogger(AbstractResourceOrigin.class);
62
63 private final String name;
64
65 private final Set<ResourceChangeHandler> resourceChangeHandlers = Sets.newConcurrentHashSet();
66
67 private boolean isResourceMonitoringInitialized = false;
68
69 protected AbstractResourceOrigin(String name) {
70 this.name = name;
71 }
72
73 @Override
74 public String getName() {
75 return name;
76 }
77
78 @Override
79 public void traverseWith(ResourceVisitor visitor) {
80 new ResourceTreeWalker(visitor).traverse(getRoot());
81 }
82
83
84
85
86 @Override
87 @Deprecated
88 public void watchForChanges(final ResourceVisitor visitor) {
89
90
91
92
93 registerResourceChangeHandler(new ResourceChangeHandler() {
94 @Override
95 public void onResourceChanged(ResourceOriginChange change) {
96 switch (change.getType()) {
97 case MODIFIED: case ADDED:
98 try {
99 final Resource resource = getByPath(change.getRelatedResourcePath());
100 if (resource.isDirectory()) {
101 visitor.visitDirectory(resource);
102 } else {
103 visitor.visitFile(resource);
104 }
105 } catch (ResourceNotFoundException e) {
106 log.error("Failed to dispatch resource change via deprecated ResourceVisitor for resource at [{}]: {}. Invoking visitor for a resource stub object", change.getRelatedResourcePath(), e.getMessage(), e);
107 visitor.visitFile(ResourceStub.withPath(change.getRelatedResourcePath()));
108 }
109 break;
110 case REMOVED:
111 visitor.visitFile(ResourceStub.withPath(change.getRelatedResourcePath()));
112 break;
113 }
114 }
115 });
116 }
117
118 @Override
119 public ResourceChangeHandlerRegistration registerResourceChangeHandler(ResourceChangeHandler changeHandler) {
120 resourceChangeHandlers.add(changeHandler);
121
122 if (!isResourceMonitoringInitialized) {
123 isResourceMonitoringInitialized = true;
124 initializeResourceChangeMonitoring();
125 }
126
127 return new SimpleChangeHandlerRegistration(changeHandler);
128 }
129
130 public final void dispatchResourceChange(ResourceOriginChange change) {
131 for (final ResourceChangeHandler resourceChangeHandler : resourceChangeHandlers) {
132 resourceChangeHandler.onResourceChanged(change);
133 }
134 }
135
136
137
138
139 protected void initializeResourceChangeMonitoring() {}
140
141
142
143
144 protected abstract boolean isFile(P resource);
145
146
147
148
149 protected abstract boolean isDirectory(P resource);
150
151
152
153
154 protected boolean isEditable(P resource) {
155 return false;
156 }
157
158
159
160
161 protected abstract String getPath(P resource);
162
163
164
165
166 protected abstract String getName(P resource);
167
168
169
170
171 protected abstract long getLastModified(P resource);
172
173
174
175
176 protected abstract List<P> listChildren(P resource);
177
178
179
180
181 protected abstract P getParent(P resource);
182
183
184
185
186 protected InputStream openStream(P resource) throws IOException {
187 if (resource.isDirectory()) {
188 throw new IllegalStateException("Can not open stream on directory " + resource);
189 }
190 final InputStream inputStream = doOpenStream(resource);
191 if (inputStream == null) {
192 throw new IllegalStateException("InputStream is null for " + resource);
193 }
194 return inputStream;
195 }
196
197 protected abstract InputStream doOpenStream(P resource) throws IOException;
198
199
200
201
202 protected Reader openReader(P resource) throws IOException {
203 final InputStream in = openStream(resource);
204 final Charset charset = getCharsetFor(resource);
205 final Reader reader = new InputStreamReader(in, charset);
206 return new BufferedReader(reader);
207 }
208
209
210
211
212 protected abstract Charset getCharsetFor(P resource);
213
214
215
216
217 class SimpleChangeHandlerRegistration implements ResourceChangeHandlerRegistration {
218 private final ResourceChangeHandler changeHandler;
219
220 public SimpleChangeHandlerRegistration(ResourceChangeHandler changeHandler) {
221 this.changeHandler = changeHandler;
222 }
223
224 @Override
225 public void unRegister() {
226 resourceChangeHandlers.remove(changeHandler);
227 }
228 }
229 }