1 16 package org.apache.commons.vfs.impl; 17 18 import org.apache.commons.logging.Log; 19 import org.apache.commons.logging.LogFactory; 20 import org.apache.commons.vfs.FileListener; 21 import org.apache.commons.vfs.FileMonitor; 22 import org.apache.commons.vfs.FileName; 23 import org.apache.commons.vfs.FileObject; 24 import org.apache.commons.vfs.FileSystemException; 25 import org.apache.commons.vfs.FileType; 26 import org.apache.commons.vfs.provider.AbstractFileSystem; 27 28 import java.util.HashMap ; 29 import java.util.Map ; 30 import java.util.Stack ; 31 32 83 public class DefaultFileMonitor implements Runnable , FileMonitor 84 { 85 private final static Log log = LogFactory.getLog(DefaultFileMonitor.class); 86 87 90 private final Map monitorMap = new HashMap (); 91 92 95 private Thread monitorThread; 96 97 100 private Stack deleteStack = new Stack (); 101 102 105 private Stack addStack = new Stack (); 106 107 110 private boolean shouldRun = true; 111 112 115 private boolean recursive = false; 116 117 120 private long delay = 1000; 121 122 125 private int checksPerRun = 1000; 126 127 130 private final FileListener listener; 131 132 public DefaultFileMonitor(final FileListener listener) 133 { 134 this.listener = listener; 135 } 136 137 140 public boolean isRecursive() 141 { 142 return this.recursive; 143 } 144 145 148 public void setRecursive(final boolean newRecursive) 149 { 150 this.recursive = newRecursive; 151 } 152 153 157 FileListener getFileListener() 158 { 159 return this.listener; 160 } 161 162 165 public void addFile(final FileObject file) 166 { 167 synchronized (this.monitorMap) 168 { 169 if (this.monitorMap.get(file.getName()) == null) 170 { 171 this.monitorMap.put(file.getName(), new FileMonitorAgent(this, 172 file)); 173 174 try 175 { 176 if (this.listener != null) 177 { 178 file.getFileSystem().addListener(file, this.listener); 179 } 180 181 if (file.getType().hasChildren() && this.recursive) 182 { 183 final FileObject[] children = file.getChildren(); 185 for (int i = 0; i < children.length; i++) 186 { 187 this.addFile(children[i]); } 189 } 190 191 } 192 catch (FileSystemException fse) 193 { 194 log.error(fse.getLocalizedMessage(), fse); 195 } 196 197 } 198 } 199 } 200 201 204 public void removeFile(final FileObject file) 205 { 206 synchronized (this.monitorMap) 207 { 208 FileName fn = file.getName(); 209 if (this.monitorMap.get(fn) != null) 210 { 211 FileObject parent; 212 try 213 { 214 parent = file.getParent(); 215 } 216 catch (FileSystemException fse) 217 { 218 parent = null; 219 } 220 221 this.monitorMap.remove(fn); 222 223 if (parent != null) 224 { FileMonitorAgent parentAgent = 226 (FileMonitorAgent) this.monitorMap.get(parent.getName()); 227 if (parentAgent != null) 228 { 229 parentAgent.resetChildrenList(); 230 } 231 } 232 } 233 } 234 } 235 236 239 protected void queueRemoveFile(final FileObject file) 240 { 241 this.deleteStack.push(file); 242 } 243 244 247 public long getDelay() 248 { 249 return delay; 250 } 251 252 255 public void setDelay(long delay) 256 { 257 if (delay > 0) 258 { 259 this.delay = delay; 260 } 261 else 262 { 263 this.delay = 1000; 264 } 265 } 266 267 270 public int getChecksPerRun() 271 { 272 return checksPerRun; 273 } 274 275 281 public void setChecksPerRun(int checksPerRun) 282 { 283 this.checksPerRun = checksPerRun; 284 } 285 286 289 protected void queueAddFile(final FileObject file) 290 { 291 this.addStack.push(file); 292 } 293 294 297 public void start() 298 { 299 if (this.monitorThread == null) 300 { 301 this.monitorThread = new Thread (this); 302 this.monitorThread.setDaemon(true); 303 this.monitorThread.setPriority(Thread.MIN_PRIORITY); 304 } 305 this.monitorThread.start(); 306 } 307 308 311 public void stop() 312 { 313 this.shouldRun = false; 314 } 315 316 319 public void run() 320 { 321 mainloop: 322 while (!Thread.currentThread().isInterrupted() && this.shouldRun) 323 { 324 while (!this.deleteStack.empty()) 325 { 326 this.removeFile((FileObject) this.deleteStack.pop()); 327 } 328 329 Object fileNames[]; 331 synchronized (this.monitorMap) 332 { 333 fileNames = this.monitorMap.keySet().toArray(); 334 } 335 for (int iterFileNames = 0; iterFileNames < fileNames.length; 336 iterFileNames++) 337 { 338 FileName fileName = (FileName) fileNames[iterFileNames]; 339 FileMonitorAgent agent; 340 synchronized (this.monitorMap) 341 { 342 agent = (FileMonitorAgent) this.monitorMap.get(fileName); 343 } 344 if (agent != null) 345 { 346 agent.check(); 347 } 348 349 if (getChecksPerRun() > 0) 350 { 351 if ((iterFileNames % getChecksPerRun()) == 0) 352 { 353 try 354 { 355 Thread.sleep(getDelay()); 356 } 357 catch (InterruptedException e) 358 { 359 360 } 361 } 362 } 363 364 if (Thread.currentThread().isInterrupted() || !this.shouldRun) 365 { 366 continue mainloop; 367 } 368 } 369 370 while (!this.addStack.empty()) 371 { 372 this.addFile((FileObject) this.addStack.pop()); 373 } 374 375 try 376 { 377 Thread.sleep(getDelay()); 378 } 379 catch (InterruptedException e) 380 { 381 continue; 382 } 383 } 384 385 this.shouldRun = true; 386 } 387 388 391 private static class FileMonitorAgent 392 { 393 private final FileObject file; 394 private final DefaultFileMonitor fm; 395 396 private boolean exists; 397 private long timestamp; 398 private Map children = null; 399 400 private FileMonitorAgent(DefaultFileMonitor fm, FileObject file) 401 { 402 this.fm = fm; 403 this.file = file; 404 405 this.refresh(); 406 this.resetChildrenList(); 407 408 try 409 { 410 this.exists = this.file.exists(); 411 } 412 catch (FileSystemException fse) 413 { 414 this.exists = false; 415 } 416 417 try 418 { 419 this.timestamp = this.file.getContent().getLastModifiedTime(); 420 } 421 catch (FileSystemException fse) 422 { 423 this.timestamp = -1; 424 } 425 426 } 427 428 private void resetChildrenList() 429 { 430 try 431 { 432 if (this.file.getType() == FileType.FOLDER) 433 { 434 this.children = new HashMap (); 435 FileObject[] childrenList = this.file.getChildren(); 436 for (int i = 0; i < childrenList.length; i++) 437 { 438 this.children.put(childrenList[i].getName(), new 439 Object ()); } 441 } 442 } 443 catch (FileSystemException fse) 444 { 445 this.children = null; 446 } 447 } 448 449 450 453 private void refresh() 454 { 455 try 456 { 457 459 this.file.close(); 462 } 463 catch (FileSystemException fse) 464 { 465 log.error(fse.getLocalizedMessage(), fse); 466 } 467 } 468 469 470 475 private void fireAllCreate(FileObject child) 476 { 477 if (this.fm.getFileListener() != null) 479 { 480 child.getFileSystem().addListener(child, this.fm.getFileListener()); 481 } 482 483 ((AbstractFileSystem) child.getFileSystem()).fireFileCreated(child); 484 485 if (this.fm.getFileListener() != null) 487 { 488 child.getFileSystem().removeListener(child, 489 this.fm.getFileListener()); 490 } 491 492 this.fm.queueAddFile(child); 494 try 495 { 496 497 if (this.fm.isRecursive()) 498 { 499 if (child.getType() == FileType.FOLDER) 500 { 501 FileObject[] newChildren = child.getChildren(); 502 for (int i = 0; i < newChildren.length; i++) 503 { 504 fireAllCreate(newChildren[i]); 505 } 506 } 507 } 508 509 } 510 catch (FileSystemException fse) 511 { 512 log.error(fse.getLocalizedMessage(), fse); 513 } 514 } 515 516 520 private void checkForNewChildren() 521 { 522 try 523 { 524 if (this.file.getType() == FileType.FOLDER) 525 { 526 FileObject[] newChildren = this.file.getChildren(); 527 if (this.children != null) 528 { 529 Map newChildrenMap = new HashMap (); 531 Stack missingChildren = new Stack (); 532 533 for (int i = 0; i < newChildren.length; i++) 534 { 535 newChildrenMap.put(newChildren[i].getName(), new 536 Object ()); if 539 (!this.children.containsKey(newChildren[i].getName())) 540 { 541 missingChildren.push(newChildren[i]); 542 } 543 } 544 545 this.children = newChildrenMap; 546 547 if (!missingChildren.empty()) 549 { 550 551 while (!missingChildren.empty()) 552 { 553 FileObject child = (FileObject) 554 missingChildren.pop(); 555 this.fireAllCreate(child); 556 } 557 } 558 559 } 560 else 561 { 562 if (newChildren.length > 0) 564 { 565 this.children = new HashMap (); 566 } 567 for (int i = 0; i < newChildren.length; i++) 568 { 569 this.children.put(newChildren[i].getName(), new 570 Object ()); this.fireAllCreate(newChildren[i]); 572 } 573 } 574 } 575 } 576 catch (FileSystemException fse) 577 { 578 log.error(fse.getLocalizedMessage(), fse); 579 } 580 } 581 582 private void check() 583 { 584 this.refresh(); 585 586 try 587 { 588 if (this.exists && !this.file.exists()) 590 { 591 this.exists = this.file.exists(); 592 this.timestamp = -1; 593 594 596 ((AbstractFileSystem) 597 this.file.getFileSystem()).fireFileDeleted(this.file); 598 599 if (this.fm.getFileListener() != null) 601 { 602 this.file.getFileSystem().removeListener(this.file, 603 this.fm.getFileListener()); 604 } 605 606 this.fm.queueRemoveFile(this.file); 608 } 609 else if (this.exists && this.file.exists()) 610 { 611 612 if (this.timestamp != 614 this.file.getContent().getLastModifiedTime()) 615 { 616 this.timestamp = 617 this.file.getContent().getLastModifiedTime(); 618 620 if (this.file.getType() != FileType.FOLDER) 623 { 624 ((AbstractFileSystem) 625 this.file.getFileSystem()).fireFileChanged(this.file); 626 } 627 } 628 629 } 630 631 this.checkForNewChildren(); 632 633 } 634 catch (FileSystemException fse) 635 { 636 log.error(fse.getLocalizedMessage(), fse); 637 } 638 } 639 640 } 641 642 } | Popular Tags |