1 10 11 package org.mmbase.util; 12 13 import java.io.File ; 14 import java.net.URL ; 15 import java.util.*; 16 17 18 import org.mmbase.core.event.*; 19 import org.mmbase.util.logging.*; 20 import org.mmbase.bridge.*; 21 22 33 public abstract class ResourceWatcher implements NodeEventListener { 34 private static final Logger log = Logging.getLoggerInstance(ResourceWatcher.class); 35 36 41 static Set resourceWatchers = new HashSet(); 42 43 46 static void setResourceBuilder() { 47 synchronized(resourceWatchers) { 48 Iterator i = resourceWatchers.iterator(); 49 while (i.hasNext()) { 50 ResourceWatcher rw = (ResourceWatcher) i.next(); 51 if (rw.running) { 52 EventManager.getInstance().addEventListener(rw); 53 } 54 Iterator j = rw.resources.iterator(); 55 while (j.hasNext()) { 56 String resource = (String ) j.next(); 57 if (rw.mapNodeNumber(resource)) { 58 log.service("ResourceBuilder is available now. Resource " + resource + " must be reloaded."); 59 rw.onChange(resource); 60 61 } 62 } 63 } 64 } 65 resourceWatchers = null; } 67 68 71 private long delay = -1; 72 73 76 protected SortedSet resources = new TreeSet(); 77 78 83 protected Map nodeNumberToResourceName = new HashMap(); 84 85 88 private boolean running = false; 89 90 93 protected Map fileWatchers = new HashMap(); 94 95 98 protected ResourceLoader resourceLoader; 99 100 101 104 protected ResourceWatcher(ResourceLoader rl) { 105 resourceLoader = rl; 106 if (resourceWatchers != null) { 107 synchronized(resourceWatchers) { 108 resourceWatchers.add(this); 109 } 110 } 111 } 112 115 protected ResourceWatcher() { 116 this(ResourceLoader.getConfigurationRoot()); 117 } 118 119 120 121 124 public Set getResources() { 125 return Collections.unmodifiableSortedSet(resources); 126 } 127 128 131 public ResourceLoader getResourceLoader() { 132 return resourceLoader; 133 } 134 135 139 public synchronized void add(String resourceName) { 140 if (resourceName == null || resourceName.equals("")) { 141 log.warn("Cannot watch resource '" + resourceName + "' " + Logging.stackTrace()); 142 return; 143 } 144 resources.add(resourceName); 145 log.service("Started watching '" + resourceName + "' for resource loader " + resourceLoader + "(now watching " + resources + ")"); 146 if (running) { 147 createFileWatcher(resourceName); 148 mapNodeNumber(resourceName); 149 } 150 } 151 152 155 public synchronized void add(URL url) { 156 if (url.getProtocol().equals(ResourceLoader.PROTOCOL)) { 157 String path = url.getPath(); 158 add(path.substring(resourceLoader.getContext().getPath().length())); 159 } else { 160 throw new UnsupportedOperationException ("Don't know how to watch " + url + " (Only URLs produced by ResourceLoader are supported)"); 161 } 162 } 163 164 168 protected synchronized void createFileWatcher(String resource) { 169 FileWatcher fileWatcher = new ResourceFileWatcher(resource); 170 if (delay != -1) { 171 fileWatcher.setDelay(delay); 172 } 173 fileWatcher.getFiles().addAll(resourceLoader.getFiles(resource)); 174 fileWatcher.start(); fileWatchers.put(resource, fileWatcher); 176 } 177 178 185 protected synchronized boolean mapNodeNumber(String resource) { 186 Node node = resourceLoader.getResourceNode(resource); 187 if (node != null) { 188 nodeNumberToResourceName.put("" + node.getNumber(), resource); 189 return true; 190 } else { 191 return false; 192 } 193 194 } 195 196 197 198 199 203 public void notify(NodeEvent event) { 204 if (event.getBuilderName().equals("resources")) { 205 String number = "" + event.getNodeNumber(); 206 switch(event.getType()) { 207 case NodeEvent.TYPE_DELETE: { 208 String name = (String ) nodeNumberToResourceName.get(number); 210 if (name != null && resources.contains(name)) { 211 nodeNumberToResourceName.remove(number); 212 log.service("Resource " + name + " changed (node removed)"); 213 onChange(name); 214 } 215 break; 216 } 217 default: { 218 Node node = ResourceLoader.resourceBuilder.getCloud().getNode(number); 219 int contextPrefix = resourceLoader.getContext().getPath().length() - 1; 220 String name = node.getStringValue(ResourceLoader.RESOURCENAME_FIELD); 221 if (name.length() > contextPrefix && resources.contains(name.substring(contextPrefix))) { 222 log.service("Resource " + name + " changed (node added or changed)"); 223 nodeNumberToResourceName.put(number, name); 224 onChange(name); 225 } 226 } 227 } 228 } 229 } 230 231 public synchronized void start() { 232 Iterator i = resources.iterator(); 234 while (i.hasNext()) { 235 String resource = (String ) i.next(); 236 mapNodeNumber(resource); 238 createFileWatcher(resource); 239 } 240 if (resourceWatchers == null) { 241 EventManager.getInstance().addEventListener(this); 242 } 243 running = true; 244 } 245 246 250 abstract public void onChange(String resourceName); 251 252 255 public final void onChange() { 256 Iterator i = resources.iterator(); 257 while (i.hasNext()) { 258 onChange((String ) i.next()); 259 } 260 } 261 262 263 266 public synchronized void setDelay(long delay) { 267 this.delay = delay; 268 Iterator i = fileWatchers.values().iterator(); 269 while (i.hasNext()) { 270 FileWatcher fw = (FileWatcher) i.next(); 271 fw.setDelay(delay); 272 } 273 } 274 275 276 278 public synchronized void remove(String resourceName) { 279 boolean wasRunning = running; 280 if (running) { exit(); 282 } 283 resources.remove(resourceName); 284 if (wasRunning) { 285 start(); 286 } 287 } 288 289 292 public synchronized void clear() { 293 if (running) { 294 exit(); 295 resources.clear(); 296 start(); 297 } else { 298 resources.clear(); 299 } 300 } 301 302 305 public synchronized void exit() { 306 Iterator i = fileWatchers.values().iterator(); 307 while (i.hasNext()) { 308 FileWatcher fw = (FileWatcher) i.next(); 309 fw.exit(); 310 i.remove(); 311 } 312 if (ResourceLoader.resourceBuilder != null) { 313 EventManager.getInstance().removeEventListener(this); 314 } 315 running = false; 316 } 317 318 319 322 public String toString() { 323 return "" + resources + " " + fileWatchers; 324 } 325 326 327 330 331 protected class ResourceFileWatcher extends FileWatcher { 332 private String resource; 333 ResourceFileWatcher(String resource) { 334 this.resource = resource; 335 } 336 public void onChange(File f) { 337 URL shadower = resourceLoader.shadowed(f, resource); 338 if (shadower == null) { 339 ResourceWatcher.this.onChange(resource); 340 } else { 341 log.warn("File " + f + " changed, but it is shadowed by " + shadower); 342 } 343 } 344 } 345 346 347 } 348 | Popular Tags |