1 19 package org.java.plugin.standard; 20 21 import java.io.BufferedInputStream ; 22 import java.io.BufferedOutputStream ; 23 import java.io.File ; 24 import java.io.FileFilter ; 25 import java.io.FileInputStream ; 26 import java.io.FileOutputStream ; 27 import java.io.IOException ; 28 import java.io.InputStream ; 29 import java.io.OutputStream ; 30 import java.net.JarURLConnection ; 31 import java.net.MalformedURLException ; 32 import java.net.URL ; 33 import java.net.URLConnection ; 34 import java.text.DateFormat ; 35 import java.text.ParseException ; 36 import java.text.SimpleDateFormat ; 37 import java.util.Calendar ; 38 import java.util.Collection ; 39 import java.util.Date ; 40 import java.util.Enumeration ; 41 import java.util.HashMap ; 42 import java.util.HashSet ; 43 import java.util.Iterator ; 44 import java.util.LinkedList ; 45 import java.util.Locale ; 46 import java.util.Map ; 47 import java.util.Properties ; 48 import java.util.Set ; 49 import java.util.StringTokenizer ; 50 import java.util.regex.Pattern ; 51 import java.util.zip.ZipEntry ; 52 import java.util.zip.ZipFile ; 53 import java.util.zip.ZipInputStream ; 54 55 import org.apache.commons.logging.Log; 56 import org.apache.commons.logging.LogFactory; 57 import org.java.plugin.registry.Identity; 58 import org.java.plugin.registry.Library; 59 import org.java.plugin.registry.PluginAttribute; 60 import org.java.plugin.registry.PluginDescriptor; 61 import org.java.plugin.registry.PluginElement; 62 import org.java.plugin.registry.PluginFragment; 63 import org.java.plugin.registry.UniqueIdentity; 64 import org.java.plugin.util.ExtendedProperties; 65 import org.java.plugin.util.IoUtil; 66 67 109 public class ShadingPathResolver extends StandardPathResolver { 110 private static final String UNPACK_MODE_ALWAIS = "always"; private static final String UNPACK_MODE_NEVER = "never"; private static final String UNPACK_MODE_SMART = "smart"; 114 private File shadowFolder; 115 private String unpackMode; 116 private Map shadowUrlMap = new HashMap (); private Map unpackModeMap = new HashMap (); private ShadowDataController controller; 119 120 123 public synchronized void configure(final ExtendedProperties config) 124 throws Exception { 125 super.configure(config); 126 String folder = config.getProperty("shadowFolder"); if ((folder != null) && (folder.length() > 0)) { 128 try { 129 shadowFolder = new File (folder).getCanonicalFile(); 130 } catch (IOException ioe) { 131 log.warn("failed initializing shadow folder " + folder + ", falling back to the default folder", ioe); } 134 } 135 if (shadowFolder == null) { 136 shadowFolder = new File (System.getProperty("java.io.tmpdir"), ".jpf-shadow"); } 139 log.debug("shadow folder is " + shadowFolder); if (!shadowFolder.exists()) { 141 shadowFolder.mkdirs(); 142 } 143 unpackMode = config.getProperty("unpackMode", UNPACK_MODE_SMART); log.debug("unpack mode parameter value is " + unpackMode); controller = ShadowDataController.init(shadowFolder, 146 buildFileFilter(config)); 147 log.info("configured, shadow folder is " + shadowFolder); } 149 150 private FileFilter buildFileFilter(final ExtendedProperties config) { 151 final FileFilter includesFilter; 152 String patterns = config.getProperty("includes"); if ((patterns != null) && (patterns.trim().length() > 0)) { 154 includesFilter = new RegexpFileFilter(patterns); 155 } else { 156 includesFilter = null; 157 } 158 final FileFilter excludesFilter; 159 patterns = config.getProperty("excludes"); if ((patterns != null) && (patterns.trim().length() > 0)) { 161 excludesFilter = new RegexpFileFilter(patterns); 162 } else { 163 excludesFilter = null; 164 } 165 if ((excludesFilter == null) && (includesFilter == null)) { 166 return null; 167 } 168 return new CombinedFileFilter(includesFilter, excludesFilter); 169 } 170 171 175 public void registerContext(Identity idt, URL url) { 176 super.registerContext(idt, url); 177 Boolean mode; 178 if (UNPACK_MODE_ALWAIS.equalsIgnoreCase(unpackMode)) { 179 mode = Boolean.TRUE; 180 } else if (UNPACK_MODE_NEVER.equalsIgnoreCase(unpackMode)) { 181 mode = Boolean.FALSE; 182 } else { 183 PluginDescriptor descr = null; 184 PluginFragment fragment = null; 185 if (idt instanceof PluginDescriptor) { 186 descr = (PluginDescriptor) idt; 187 } else if (idt instanceof PluginFragment) { 188 fragment = (PluginFragment) idt; 189 descr = fragment.getRegistry().getPluginDescriptor( 190 fragment.getPluginId()); 191 } else if (idt instanceof PluginElement) { 192 PluginElement element = (PluginElement) idt; 193 descr = element.getDeclaringPluginDescriptor(); 194 fragment = element.getDeclaringPluginFragment(); 195 } else { 196 throw new IllegalArgumentException ("unknown identity class " + idt.getClass().getName()); 198 } 199 mode = getUnpackMode(descr, fragment); 200 } 201 log.debug("unpack mode for " + idt + " is " + mode); unpackModeMap.put(idt.getId(), mode); 203 } 204 205 private Boolean getUnpackMode(final PluginDescriptor descr, 206 final PluginFragment fragment) { 207 for (Iterator it = filterCollection(descr.getAttributes("unpack"), fragment).iterator(); it.hasNext();) { 209 return Boolean.valueOf("false".equalsIgnoreCase( ((PluginAttribute) it.next()).getValue())); 211 } 212 for (Iterator it = filterCollection(descr.getLibraries(), 213 fragment).iterator(); it.hasNext();) { 214 Library lib = (Library) it.next(); 215 if (lib.isCodeLibrary() && (lib.getPath().toLowerCase( 216 Locale.getDefault()).endsWith(".jar") || lib.getPath().toLowerCase( 218 Locale.getDefault()).endsWith(".zip"))) { return Boolean.TRUE; 220 } 221 } 222 return Boolean.FALSE; 223 } 224 225 private Collection filterCollection(final Collection coll, 226 final PluginFragment fragment) { 227 if (fragment == null) { 228 return coll; 229 } 230 LinkedList result = new LinkedList (); 231 for (Iterator it = coll.iterator(); it.hasNext();) { 232 PluginElement element = (PluginElement) it.next(); 233 if (fragment.equals(element.getDeclaringPluginFragment())) { 234 result.add(element); 235 } 236 } 237 return result; 238 } 239 240 244 public void unregisterContext(String id) { 245 shadowUrlMap.remove(id); 246 unpackModeMap.remove(id); 247 super.unregisterContext(id); 248 } 249 250 254 public URL resolvePath(final Identity idt, final String path) { 255 URL baseUrl; 256 if (idt instanceof PluginDescriptor) { 257 baseUrl = getBaseUrl((PluginDescriptor) idt); 258 } else if (idt instanceof PluginFragment) { 259 baseUrl = getBaseUrl((PluginFragment) idt); 260 } else if (idt instanceof PluginElement) { 261 PluginElement element = (PluginElement) idt; 262 if (element.getDeclaringPluginFragment() != null) { 263 baseUrl = getBaseUrl( 264 element.getDeclaringPluginFragment()); 265 } else { 266 baseUrl = getBaseUrl( 267 element.getDeclaringPluginDescriptor()); 268 } 269 } else { 270 throw new IllegalArgumentException ("unknown identity class " + idt.getClass().getName()); 272 } 273 return resolvePath(baseUrl, path); 274 } 275 276 protected synchronized URL getBaseUrl(final UniqueIdentity uid) { 277 URL result = (URL ) shadowUrlMap.get(uid.getId()); 278 if (result != null) { 279 return result; 280 } 281 result = controller.shadowResource(getRegisteredContext(uid.getId()), 282 uid.getUniqueId(), 283 ((Boolean ) unpackModeMap.get(uid.getId())).booleanValue()); 284 shadowUrlMap.put(uid.getId(), result); 285 return result; 286 } 287 } 288 289 final class ShadingUtil { 290 static String getExtension(final String name) { 291 if ((name == null) || (name.length() == 0)) { 292 return null; 293 } 294 int p = name.lastIndexOf('.'); 295 if ((p != -1) && (p > 0) && (p < name.length() - 1)) { 296 return name.substring(p + 1); 297 } 298 return null; 299 } 300 301 static void unpack(final ZipFile zipFile, 302 final File destFolder) throws IOException { 303 for (Enumeration en = zipFile.entries(); en.hasMoreElements();) { 304 ZipEntry entry = (ZipEntry ) en.nextElement(); 305 String name = entry.getName(); 306 File entryFile = 307 new File (destFolder.getCanonicalPath() + "/" + name); if (name.endsWith("/")) { if (!entryFile.exists() && !entryFile.mkdirs()) { 310 throw new IOException ("can't create folder " + entryFile); } 312 } else { 313 File folder = entryFile.getParentFile(); 314 if (!folder.exists() && !folder.mkdirs()) { 315 throw new IOException ("can't create folder " + folder); } 317 OutputStream out = new BufferedOutputStream ( 318 new FileOutputStream (entryFile, false)); 319 try { 320 InputStream in = zipFile.getInputStream(entry); 321 try { 322 IoUtil.copyStream(in, out, 1024); 323 } finally { 324 in.close(); 325 } 326 } finally { 327 out.close(); 328 } 329 } 330 entryFile.setLastModified(entry.getTime()); 331 } 332 } 333 334 static void unpack(final InputStream strm, 335 final File destFolder) throws IOException { 336 ZipInputStream zipStrm = new ZipInputStream (strm); 337 ZipEntry entry = zipStrm.getNextEntry(); 338 while (entry != null) { 339 String name = entry.getName(); 340 File entryFile = 341 new File (destFolder.getCanonicalPath() + "/" + name); if (name.endsWith("/")) { if (!entryFile.exists() && !entryFile.mkdirs()) { 344 throw new IOException ("can't create folder " + entryFile); } 346 } else { 347 File folder = entryFile.getParentFile(); 348 if (!folder.exists() && !folder.mkdirs()) { 349 throw new IOException ("can't create folder " + folder); } 351 OutputStream out = new BufferedOutputStream ( 352 new FileOutputStream (entryFile, false)); 353 try { 354 IoUtil.copyStream(zipStrm, out, 1024); 355 } finally { 356 out.close(); 357 } 358 } 359 entryFile.setLastModified(entry.getTime()); 360 entry = zipStrm.getNextEntry(); 361 } 362 } 363 364 static boolean deleteFile(final File file) { 365 if (file.isDirectory()) { 366 IoUtil.emptyFolder(file); 367 } 368 return file.delete(); 369 } 370 371 static Date getLastModified(final URL url) throws IOException { 372 long result = 0; 373 File sourceFile = null; 374 if ("jar".equalsIgnoreCase(url.getProtocol())) { String urlStr = url.toExternalForm(); 376 int p = urlStr.indexOf("!/"); if (p != -1) { 378 sourceFile = IoUtil.url2file(new URL (urlStr.substring(4, p))); 379 } 380 } 381 if (sourceFile == null) { 382 sourceFile = IoUtil.url2file(url); 383 } 384 if (sourceFile != null) { 385 result = sourceFile.lastModified(); 386 } else { 387 URLConnection cnn = url.openConnection(); 388 try { 389 cnn.setUseCaches(false); 390 result = cnn.getLastModified(); 391 } finally { 392 cnn.getInputStream().close(); 393 } 394 } 395 if (result == 0) { 396 throw new IOException ( 397 "can't retrieve modification date for resource " + url); 399 } 400 Calendar cldr = Calendar.getInstance(Locale.ENGLISH); 402 cldr.setTime(new Date (result)); 403 cldr.set(Calendar.MILLISECOND, 0); 404 return cldr.getTime(); 405 } 406 407 private static String getRelativePath(final File base, final File file) 408 throws IOException { 409 String basePath; 410 String filePath = file.getCanonicalPath(); 411 if (base.isFile()) { 412 File baseParent = base.getParentFile(); 413 if (baseParent == null) { 414 return null; 415 } 416 basePath = baseParent.getCanonicalPath(); 417 } else { 418 basePath = base.getCanonicalPath(); 419 } 420 if (!basePath.endsWith(File.separator)) { 421 basePath += File.separator; 422 } 423 int p = basePath.indexOf(File.separatorChar); 424 String prefix = null; 425 while (p != -1) { 426 String newPrefix = basePath.substring(0, p + 1); 427 if (!filePath.startsWith(newPrefix)) { 428 break; 429 } 430 prefix = newPrefix; 431 p = basePath.indexOf(File.separatorChar, p + 1); 432 } 433 if (prefix == null) { 434 return null; 435 } 436 filePath = filePath.substring(prefix.length()); 437 if (prefix.length() == basePath.length()) { 438 return filePath; 439 } 440 int c = 0; 441 p = basePath.indexOf(File.separatorChar, prefix.length()); 442 while (p != -1) { 443 c++; 444 p = basePath.indexOf(File.separatorChar, p + 1); 445 } 446 for (int i = 0; i < c; i++) { 447 filePath = ".." + File.separator + filePath; } 449 return filePath; 450 } 451 452 private static String getRelativeUrl(final File base, final File file) 453 throws IOException { 454 String result = ShadingUtil.getRelativePath(base, file); 455 if (result == null) { 456 return null; 457 } 458 result = result.replace('\\', '/'); 459 if (file.isDirectory() && !result.endsWith("/")) { result += "/"; } 462 return result; 463 } 464 465 static String getRelativeUrl(final File base, final URL url) 466 throws IOException { 467 File file = IoUtil.url2file(url); 468 if (file != null) { 469 String result = getRelativeUrl(base, file); 470 if (result != null) { 471 return result; 472 } 473 } 474 if ("jar".equalsIgnoreCase(url.getProtocol())) { String urlStr = url.toExternalForm(); 476 int p = urlStr.indexOf("!/"); if (p != -1) { 478 return "jar:" + getRelativeUrl(base, new URL (urlStr.substring(4, p))) 480 + urlStr.substring(p); 481 } 482 } 483 return url.toExternalForm(); 484 } 485 486 static URL buildURL(final URL base, final String url) 487 throws MalformedURLException { 488 if (!url.toLowerCase(Locale.ENGLISH).startsWith("jar:")) { return new URL (base, url); 490 } 491 int p = url.indexOf("!/"); if (p == -1) { 493 return new URL (base, url); 494 } 495 return new URL ("jar:" + new URL (base, url.substring(4, p)).toExternalForm() 497 + url.substring(p)); 498 } 499 500 private ShadingUtil() { 501 } 503 } 504 505 final class ShadowDataController { 506 private static final String META_FILE_NAME = ".meta"; 508 private final Log log = LogFactory.getLog(ShadowDataController.class); 509 private final File shadowFolder; 510 private final URL shadowFolderUrl; 511 private final Properties metaData; 512 private final DateFormat dtf = new SimpleDateFormat ("yyyy-MM-dd HH:mm:ss"); private final FileFilter fileFilter; 514 515 static ShadowDataController init(final File shadowFolder, 516 final FileFilter filter) throws IOException { 517 ShadowDataController result = 518 new ShadowDataController(shadowFolder, filter); 519 result.quickCheck(); 520 result.save(); 521 return result; 522 } 523 524 private ShadowDataController(final File folder, final FileFilter filter) 525 throws IOException { 526 shadowFolder = folder; 527 fileFilter = filter; 528 shadowFolderUrl = IoUtil.file2url(folder); 529 File metaFile = new File (shadowFolder, META_FILE_NAME); 530 metaData = new Properties (); 531 if (metaFile.isFile()) { 532 try { 533 InputStream in = new FileInputStream (metaFile); 534 try { 535 metaData.load(in); 536 } finally { 537 in.close(); 538 } 539 if (log.isDebugEnabled()) { 540 log.debug("meta-data loaded from file " + metaFile); } 542 } catch (IOException ioe) { 543 log.warn("failed loading meta-data from file " + metaFile, ioe); } 545 } 546 } 547 548 private void save() { 549 File metaFile = new File (shadowFolder, META_FILE_NAME); 550 try { 551 OutputStream out = new FileOutputStream (metaFile, false); 552 try { 553 metaData.store(out, "This is automatically generated file."); } finally { 555 out.close(); 556 } 557 if (log.isDebugEnabled()) { 558 log.debug("meta-data saved to file " + metaFile); } 560 } catch (IOException ioe) { 561 log.warn("failed saving meta-data to file " + metaFile, ioe); } 563 } 564 565 private void quickCheck() { 566 File [] files = shadowFolder.listFiles(new ShadowFileFilter()); 567 for (int i = 0; i < files.length; i++) { 568 File file = files[i]; 569 if (metaData.containsValue(file.getName())) { 570 continue; 571 } 572 if (ShadingUtil.deleteFile(file)) { 573 if (log.isDebugEnabled()) { 574 log.debug("deleted shadow file " + file); } 576 } else { 577 log.warn("can't delete shadow file " + file); } 579 } 580 Set uids = new HashSet (); 581 for (Iterator it = metaData.entrySet().iterator(); it.hasNext();) { 582 Map.Entry entry = (Map.Entry ) it.next(); 583 String key = (String ) entry.getKey(); 584 if (!key.startsWith("uid:")) { continue; 586 } 587 uids.add(entry.getValue()); 588 } 589 for (Iterator it = uids.iterator(); it.hasNext();) { 590 quickCheck((String ) it.next()); 591 } 592 } 593 594 private void quickCheck(final String uid) { 595 if (log.isDebugEnabled()) { 596 log.debug("quick check of UID " + uid); } 598 String url = metaData.getProperty("source:" + uid, null); String file = metaData.getProperty("file:" + uid, null); String modified = metaData.getProperty("modified:" + uid, null); if ((url == null) || (file == null) || (modified == null)) { 602 if (log.isDebugEnabled()) { 603 log.debug("meta-data incomplete, UID=" + uid); } 605 remove(uid); 606 return; 607 } 608 try { 609 if (!dtf.parse(modified).equals(ShadingUtil.getLastModified( 610 ShadingUtil.buildURL(shadowFolderUrl, url)))) { 611 if (log.isDebugEnabled()) { 612 log.debug("source modification detected, UID=" + uid + ", source=" + url); } 615 remove(uid); 616 } 617 } catch (IOException ioe) { 618 log.warn("quick check failed", ioe); remove(uid); 620 } catch (ParseException pe) { 621 log.warn("quick check failed", pe); remove(uid); 623 } 624 } 625 626 private void remove(final String uid) { 627 String file = metaData.getProperty("file:" + uid, null); if (file != null) { 629 File lostFile = new File (shadowFolder, file); 630 if (ShadingUtil.deleteFile(lostFile)) { 631 if (log.isDebugEnabled()) { 632 log.debug("deleted lost file " + file); } 634 } else { 635 log.warn("can't delete lost file " + file); } 637 } 638 boolean removed = metaData.remove("uid:" + uid) != null; removed |= metaData.remove("source:" + uid) != null; removed |= metaData.remove("file:" + uid) != null; removed |= metaData.remove("modified:" + uid) != null; if (removed && log.isDebugEnabled()) { 643 log.debug("removed meta-data, UID=" + uid); } 645 } 646 647 private URL add(final String uid, final URL sourceUrl, final File file, 648 final Date modified) throws IOException { 649 URL result = IoUtil.file2url(file); 650 metaData.setProperty("uid:" + uid, uid); String source = ShadingUtil.getRelativeUrl(shadowFolder, sourceUrl); 652 metaData.setProperty("source:" + uid, source); metaData.setProperty("file:" + uid, file.getName()); metaData.setProperty("modified:" + uid, dtf.format(modified)); save(); 656 if (log.isDebugEnabled()) { 657 log.debug("shading done, UID=" + uid + ", source=" + source + ", file=" + result + ", modified=" + dtf.format(modified)); } 661 return result; 662 } 663 664 URL shadowResource(final URL source, final String uid, 665 final boolean unpack) { 666 try { 667 URL result = deepCheck(source, uid); 668 if (result != null) { 669 if (log.isDebugEnabled()) { 670 log.debug("got actual shaded resource, UID=" + uid + ", source=" + source + ", file=" + result); } 674 return result; 675 } 676 } catch (Exception e) { 677 log.warn("deep check failed, UID=" + uid + ", URL=" + source, e); remove(uid); 680 } 681 Date lastModified; 682 try { 683 lastModified = ShadingUtil.getLastModified(source); 684 } catch (IOException ioe) { 685 log.error("shading failed, can't get modification date for " + source, ioe); 687 return source; 688 } 689 File file = IoUtil.url2file(source); 690 if ((file != null) && file.isDirectory()) { 691 try { 693 File rootFolder = new File (shadowFolder, uid); 694 IoUtil.copyFolder(file, rootFolder, true, true, fileFilter); 695 return add(uid, source, rootFolder, lastModified); 696 } catch (IOException ioe) { 697 log.error("failed shading local folder " + file, ioe); return source; 699 } 700 } 701 try { 702 if ("jar".equalsIgnoreCase(source.getProtocol())) { String urlStr = source.toExternalForm(); 704 int p = urlStr.indexOf("!/"); if (p == -1) { 706 p = urlStr.length(); 707 } 708 URL jarFileURL = new URL (urlStr.substring(4, p)); 709 if (!unpack) { 710 String ext = ShadingUtil.getExtension(jarFileURL.getFile()); 711 if (ext == null) { 712 ext = "jar"; } 714 File shadowFile = new File (shadowFolder, uid + '.' + ext); 715 File sourceFile = IoUtil.url2file(jarFileURL); 716 InputStream in; 717 if (sourceFile != null) { 718 in = new BufferedInputStream ( 719 new FileInputStream (sourceFile)); 720 } else { 721 in = jarFileURL.openStream(); 722 } 723 try { 724 OutputStream out = 725 new FileOutputStream (shadowFile, false); 726 try { 727 IoUtil.copyStream(in, out, 1024); 728 } finally { 729 out.close(); 730 } 731 } finally { 732 in.close(); 733 } 734 return add(uid, source, shadowFile, lastModified); 735 } 736 URLConnection cnn = null; 737 try { 738 File sourceFile = IoUtil.url2file(jarFileURL); 739 ZipFile zipFile; 740 if (sourceFile != null) { 741 zipFile = new ZipFile (sourceFile); 742 } else { 743 cnn = source.openConnection(); 744 cnn.setUseCaches(false); 745 zipFile = ((JarURLConnection ) cnn).getJarFile(); 746 } 747 File rootFolder = new File (shadowFolder, uid); 748 try { 749 ShadingUtil.unpack(zipFile, rootFolder); 750 } finally { 751 zipFile.close(); 752 } 753 return add(uid, source, rootFolder, lastModified); 754 } finally { 755 if (cnn != null) { 756 cnn.getInputStream().close(); 757 } 758 } 759 } 760 } catch (IOException ioe) { 761 log.error("failed shading URL connection " + source, ioe); return source; 763 } 764 String fileName = source.getFile(); 765 if (fileName == null) { 766 log.warn("can't get file name from resource " + source + ", shading failed"); return source; 769 } 770 String ext = ShadingUtil.getExtension(fileName); 771 if (ext == null) { 772 log.warn("can't get file name extension for resource " + source + ", shading failed"); return source; 775 } 776 if (unpack && ("jar".equalsIgnoreCase(ext) || "zip".equalsIgnoreCase(ext))) { try { 779 InputStream strm = source.openStream(); 780 File rootFolder = new File (shadowFolder, uid); 781 try { 782 ShadingUtil.unpack(strm, rootFolder); 783 } finally { 784 strm.close(); 785 } 786 return add(uid, source, rootFolder, lastModified); 787 } catch (IOException ioe) { 788 log.error("failed shading packed resource " + source, ioe); return source; 790 } 791 } 792 try { 793 File shadowFile = new File (shadowFolder, uid + '.' + ext); 794 InputStream in = source.openStream(); 795 try { 796 OutputStream out = new FileOutputStream (shadowFile, false); 797 try { 798 IoUtil.copyStream(in, out, 1024); 799 } finally { 800 out.close(); 801 } 802 } finally { 803 in.close(); 804 } 805 return add(uid, source, shadowFile, lastModified); 806 } catch (IOException ioe) { 807 log.error("failed shading resource file " + source, ioe); return source; 809 } 810 } 811 812 private URL deepCheck(final URL source, final String uid) throws Exception { 813 String url = metaData.getProperty("source:" + uid, null); if (url == null) { 815 if (log.isDebugEnabled()) { 816 log.debug("URL not found in meta-data, UID=" + uid); } 818 remove(uid); 819 return null; 820 } 821 if (log.isDebugEnabled()) { 822 log.debug("URL found in meta-data, UID=" + uid + ", source=" + source + ", storedURL=" + url); } 826 URL storedSource = ShadingUtil.buildURL(shadowFolderUrl, url); 827 if (!storedSource.equals(source)) { 828 if (log.isDebugEnabled()) { 829 log.debug("inconsistent URL found in meta-data, UID=" + uid + ", source=" + source + ", storedSource=" + storedSource); } 833 remove(uid); 834 return null; 835 } 836 String modified = metaData.getProperty("modified:" + uid, null); if (modified == null) { 838 if (log.isDebugEnabled()) { 839 log.debug("modification info not found in meta-data, UID=" + uid); 841 } 842 remove(uid); 843 return null; 844 } 845 if (!ShadingUtil.getLastModified(source).equals(dtf.parse(modified))) { 846 if (log.isDebugEnabled()) { 847 log.debug("source modification detected, UID=" + uid + ", source=" + source); } 850 remove(uid); 851 return null; 852 } 853 String fileStr = metaData.getProperty("file:" + uid, null); if (fileStr == null) { 855 if (log.isDebugEnabled()) { 856 log.debug("file info not found in meta-data, UID=" + uid); } 858 remove(uid); 859 return null; 860 } 861 File file = new File (shadowFolder, fileStr); 862 if (!file.exists()) { 863 if (log.isDebugEnabled()) { 864 log.debug("shadow file not found, UID=" + uid + ", source=" + source + ", file=" + file); } 868 remove(uid); 869 return null; 870 } 871 File sourceFile = IoUtil.url2file(source); 872 if ((sourceFile != null) && sourceFile.isDirectory()) { 873 IoUtil.synchronizeFolders(sourceFile, file, fileFilter); 874 if (log.isDebugEnabled()) { 875 log.debug("folders synchronized, UID=" + uid + ", srcFile=" + sourceFile + ", destFile=" + file); } 879 } else { 880 if (log.isDebugEnabled()) { 881 log.debug("source " + source + " (file is " + sourceFile + ") is not local folder, " + "skipping synchronization, UID=" + uid); } 885 } 886 return IoUtil.file2url(file); 887 } 888 889 static class ShadowFileFilter implements FileFilter { 890 893 public boolean accept(final File file) { 894 return !META_FILE_NAME.equals(file.getName()); 895 } 896 } 897 } 898 899 final class RegexpFileFilter implements FileFilter { 900 private final Pattern [] patterns; 901 902 RegexpFileFilter(final String str) { 903 StringTokenizer st = new StringTokenizer (str, "|", false); patterns = new Pattern [st.countTokens()]; 905 for (int i = 0; i < patterns.length; i++) { 906 String pattern = st.nextToken(); 907 if ((pattern == null) || (pattern.trim().length() == 0)) { 908 continue; 909 } 910 patterns[i] = Pattern.compile(pattern.trim()); 911 } 912 } 913 914 917 public boolean accept(final File file) { 918 for (int i = 0; i < patterns.length; i++) { 919 if (patterns[i] == null) { 920 continue; 921 } 922 if (patterns[i].matcher(file.getName()).matches()) { 923 return true; 924 } 925 } 926 return false; 927 } 928 } 929 930 final class CombinedFileFilter implements FileFilter { 931 private final FileFilter includesFilter; 932 private final FileFilter excludesFilter; 933 934 CombinedFileFilter(final FileFilter includes, final FileFilter excludes) { 935 includesFilter = includes; 936 excludesFilter = excludes; 937 } 938 939 942 public boolean accept(final File file) { 943 if (includesFilter != null) { 944 if (includesFilter.accept(file)) { 945 return true; 946 } 947 } 948 if ((excludesFilter != null) && excludesFilter.accept(file)) { 949 return false; 950 } 951 return true; 952 } 953 } 954 | Popular Tags |