1 11 package org.eclipse.update.internal.configurator; 12 13 import java.io.*; 14 import java.net.*; 15 import java.util.ArrayList ; 16 import java.util.Arrays ; 17 import java.util.Collection ; 18 import java.util.Date ; 19 import java.util.HashMap ; 20 import java.util.Iterator ; 21 import java.util.Map ; 22 import java.util.zip.*; 23 24 import org.eclipse.core.runtime.*; 25 import org.eclipse.osgi.service.environment.*; 26 import org.eclipse.osgi.util.NLS; 27 import org.eclipse.update.configurator.*; 28 import org.eclipse.update.configurator.IPlatformConfiguration.*; 29 import org.w3c.dom.*; 30 import org.xml.sax.*; 31 32 33 public class SiteEntry implements IPlatformConfiguration.ISiteEntry, IConfigurationConstants{ 34 private static final String MAC_OS_MARKER = ".DS_Store"; 36 private URL url; private URL resolvedURL; private ISitePolicy policy; 39 private boolean updateable = true; 40 private Map featureEntries; 41 private ArrayList pluginEntries; 42 private long changeStamp; 43 private long featuresChangeStamp; 44 private long pluginsChangeStamp; 45 private String linkFileName; 46 private boolean enabled = true; 47 private Configuration config; 48 49 private static FeatureParser featureParser = new FeatureParser(); 50 private static PluginParser pluginParser = new PluginParser(); 51 private static boolean isMacOS = Utils.getOS().equals(Constants.OS_MACOSX); 52 53 public SiteEntry(URL url) { 54 this(url,null); 55 } 56 57 public SiteEntry(URL url, ISitePolicy policy) { 58 if (url == null) 59 try { 60 url = new URL("platform:/base/"); } catch (MalformedURLException e) { 62 url = PlatformConfiguration.getInstallURL(); } 64 65 if (policy == null) 66 policy = new SitePolicy(PlatformConfiguration.getDefaultPolicy(), DEFAULT_POLICY_LIST); 67 68 if (url.getProtocol().equals("file")) { try { 70 this.url = new File(url.getFile()).toURL(); 72 } catch (MalformedURLException e1) { 73 this.url = url; 74 } 75 } else 76 this.url = url; 77 78 this.policy = policy; 79 this.resolvedURL = this.url; 80 if (url.getProtocol().equals("platform")) { try { 82 resolvedURL = PlatformConfiguration.resolvePlatformURL(url); } catch (IOException e) { 84 } 86 } 87 } 88 89 public void setConfig(Configuration config) { 90 this.config = config; 91 } 92 93 public Configuration getConfig() { 94 return config; 95 } 96 97 100 public URL getURL() { 101 return url; 102 } 103 104 107 public ISitePolicy getSitePolicy() { 108 return policy; 109 } 110 111 114 public synchronized void setSitePolicy(ISitePolicy policy) { 115 if (policy == null) 116 throw new IllegalArgumentException (); 117 this.policy = policy; 118 } 119 120 123 public String [] getFeatures() { 124 return getDetectedFeatures(); 125 } 126 127 130 public String [] getPlugins() { 131 132 ISitePolicy policy = getSitePolicy(); 133 134 if (policy.getType() == ISitePolicy.USER_INCLUDE) 135 return policy.getList(); 136 137 if (policy.getType() == ISitePolicy.USER_EXCLUDE) { 138 ArrayList detectedPlugins = new ArrayList (Arrays.asList(getDetectedPlugins())); 139 String [] excludedPlugins = policy.getList(); 140 for (int i = 0; i < excludedPlugins.length; i++) { 141 if (detectedPlugins.contains(excludedPlugins[i])) 142 detectedPlugins.remove(excludedPlugins[i]); 143 } 144 return (String []) detectedPlugins.toArray(new String [0]); 145 } 146 147 if (policy.getType() == ISitePolicy.MANAGED_ONLY) { 148 PluginEntry[] managedPlugins = getManagedPlugins(); 149 String [] managedPluginsURLs = new String [managedPlugins.length]; 150 for (int i=0; i<managedPlugins.length; i++) 151 managedPluginsURLs[i] = managedPlugins[i].getURL(); 152 153 return managedPluginsURLs; 154 } 155 156 return new String [0]; 158 } 159 160 private PluginEntry[] getManagedPlugins() { 161 if (pluginEntries == null) 166 detectPlugins(); 167 if (featureEntries == null) 168 detectFeatures(); 169 170 Map cachedPlugins = new HashMap (pluginEntries.size()); 172 for (int i=0; i<pluginEntries.size(); i++) { 173 PluginEntry p = (PluginEntry)pluginEntries.get(i); 174 cachedPlugins.put(p.getVersionedIdentifier(), p); 175 } 176 177 ArrayList managedPlugins = new ArrayList (); 178 for (Iterator iterator=featureEntries.values().iterator(); iterator.hasNext();) { 179 Object feature = iterator.next(); 180 if (!(feature instanceof FeatureEntry)) 181 continue; 182 183 PluginEntry[] plugins = ((FeatureEntry)feature).getPluginEntries(); 184 for (int i=0; i<plugins.length; i++) 185 if (cachedPlugins.containsKey(plugins[i].getVersionedIdentifier())) 186 managedPlugins.add(cachedPlugins.get(plugins[i].getVersionedIdentifier())); 187 188 } 189 return (PluginEntry[])managedPlugins.toArray(new PluginEntry[managedPlugins.size()]); 190 } 191 192 public PluginEntry[] getPluginEntries() { 193 String [] pluginURLs = getPlugins(); 194 HashMap map = new HashMap (pluginURLs.length); 196 for (int i=0; i<pluginURLs.length; i++) 197 map.put(pluginURLs[i], pluginURLs[i]); 198 199 if (pluginEntries == null) 200 detectPlugins(); 201 202 ArrayList plugins = new ArrayList (pluginURLs.length); 203 for (int i=0; i<pluginEntries.size(); i++) { 204 PluginEntry p = (PluginEntry)pluginEntries.get(i); 205 if (map.containsKey(p.getURL())) 206 plugins.add(p); 207 } 208 return (PluginEntry[])plugins.toArray(new PluginEntry[plugins.size()]); 209 } 210 211 214 public long getChangeStamp() { 215 if (changeStamp == 0) 216 computeChangeStamp(); 217 return changeStamp; 218 } 219 220 223 public long getFeaturesChangeStamp() { 224 if (featuresChangeStamp == 0) 225 computeFeaturesChangeStamp(); 226 return featuresChangeStamp; 227 } 228 229 232 public long getPluginsChangeStamp() { 233 if (pluginsChangeStamp == 0) 234 computePluginsChangeStamp(); 235 return pluginsChangeStamp; 236 } 237 238 241 public boolean isUpdateable() { 242 return updateable; 243 } 244 245 public void setUpdateable(boolean updateable) { 246 this.updateable = updateable; 247 } 248 249 252 public boolean isNativelyLinked() { 253 return isExternallyLinkedSite(); 254 } 255 256 public URL getResolvedURL() { 257 return resolvedURL; 258 } 259 260 264 private void detectFeatures() { 265 266 if (featureEntries != null) 267 validateFeatureEntries(); 268 else 269 featureEntries = new HashMap (); 270 271 if (!PlatformConfiguration.supportsDetection(resolvedURL)) 272 return; 273 274 File siteRoot = new File(resolvedURL.getFile().replace('/', File.separatorChar)); 276 File featuresDir = new File(siteRoot, FEATURES); 277 if (featuresDir.exists()) { 278 File[] dirs = featuresDir.listFiles(new FileFilter() { 280 public boolean accept(File f) { 281 if (isMacOS && f.getName().equals(MAC_OS_MARKER)) 283 return false; 284 boolean valid = f.isDirectory() && (new File(f,FEATURE_XML).exists()); 285 if (!valid) 286 Utils.log(NLS.bind(Messages.SiteEntry_cannotFindFeatureInDir, (new String [] { f.getAbsolutePath() }))); 287 return valid; 288 } 289 }); 290 291 for (int index = 0; index < dirs.length; index++) { 292 try { 293 File featureXML = new File(dirs[index], FEATURE_XML); 294 if (featureXML.lastModified() <= featuresChangeStamp && 295 dirs[index].lastModified() <= featuresChangeStamp) 296 continue; 297 URL featureURL = featureXML.toURL(); 298 FeatureEntry featureEntry = featureParser.parse(featureURL); 299 if (featureEntry != null) 300 addFeatureEntry(featureEntry); 301 } catch (MalformedURLException e) { 302 Utils.log(NLS.bind(Messages.InstalledSiteParser_UnableToCreateURLForFile, (new String [] { featuresDir.getAbsolutePath() }))); 303 } 304 } 305 } 306 307 Utils.debug(resolvedURL.toString() + " located " + featureEntries.size() + " feature(s)"); } 309 310 314 private void detectPlugins() { 315 boolean compareTimeStamps = false; 316 if (pluginEntries != null) { 317 validatePluginEntries(); 318 compareTimeStamps = true; } else 320 pluginEntries = new ArrayList (); 321 322 if (!PlatformConfiguration.supportsDetection(resolvedURL)) 323 return; 324 325 File pluginsDir = new File(resolvedURL.getFile(), PLUGINS); 327 328 if (pluginsDir.exists() && pluginsDir.isDirectory()) { 329 File[] files = pluginsDir.listFiles(); 330 for (int i = 0; i < files.length; i++) { 331 if(files[i].isDirectory()){ 332 detectUnpackedPlugin(files[i], compareTimeStamps); 333 }else if(files[i].getName().endsWith(".jar")){ detectPackedPlugin(files[i], compareTimeStamps); 335 }else{ 336 } 338 } 339 } 340 341 Utils.debug(resolvedURL.toString() + " located " + pluginEntries.size() + " plugin(s)"); } 343 344 348 private void detectPackedPlugin(File file, boolean compareTimeStamps) { 349 if (compareTimeStamps && file.lastModified() <= pluginsChangeStamp) { 351 return; 352 } 353 String entryName = META_MANIFEST_MF; 354 ZipFile z = null; 355 InputStream bundleManifestIn = null; 356 InputStream pluginManifestIn = null; 357 String pluginURL = PLUGINS + "/" + file.getName(); try { 359 z = new ZipFile(file); 361 if (z.getEntry(entryName) != null) { 362 bundleManifestIn = z.getInputStream(new ZipEntry(entryName)); 363 BundleManifest manifest = new BundleManifest(bundleManifestIn, 364 pluginURL); 365 if (manifest.exists()) { 366 addPluginEntry(manifest.getPluginEntry()); 367 return; 368 } 369 } 370 entryName = PLUGIN_XML; 372 if (z.getEntry(entryName) == null) { 373 entryName = FRAGMENT_XML; 374 } 375 if (z.getEntry(entryName) != null) { 376 pluginManifestIn = z.getInputStream(new ZipEntry(entryName)); 377 PluginEntry entry1 = pluginParser.parse(pluginManifestIn, 378 pluginURL); 379 addPluginEntry(entry1); 380 } 381 } catch (IOException e5) { 382 String pluginFileString2 = pluginURL + "!" + entryName; Utils.log(NLS.bind(Messages.InstalledSiteParser_ErrorAccessing, (new String [] { pluginFileString2 }))); 384 } catch (SAXException e3) { 385 String pluginFileString1 = pluginURL + "!" + entryName; Utils.log(NLS.bind(Messages.InstalledSiteParser_ErrorParsingFile, (new String [] { pluginFileString1 }))); 387 } finally { 388 if (bundleManifestIn != null) { 389 try { 390 bundleManifestIn.close(); 391 } catch (IOException e4) { 392 } 393 } 394 if (pluginManifestIn != null) { 395 try { 396 pluginManifestIn.close(); 397 } catch (IOException e2) { 398 } 399 } 400 if (z != null) { 401 try { 402 z.close(); 403 } catch (IOException e1) { 404 } 405 } 406 } 407 } 408 412 private void detectUnpackedPlugin(File file, boolean compareTimeStamps) { 413 long dirTimestamp = file.lastModified(); 415 File pluginFile = new File(file, META_MANIFEST_MF); 416 try { 417 BundleManifest bundleManifest = new BundleManifest(pluginFile); 419 if (bundleManifest.exists()) { 420 if (compareTimeStamps 421 && dirTimestamp <= pluginsChangeStamp 422 && pluginFile.lastModified() <= pluginsChangeStamp) 423 return; 424 PluginEntry entry = bundleManifest.getPluginEntry(); 425 addPluginEntry(entry); 426 } else { 427 pluginFile = new File(file, PLUGIN_XML); 429 if (!pluginFile.exists()) { 430 pluginFile = new File(file, FRAGMENT_XML); 431 } 432 if (pluginFile.exists() && !pluginFile.isDirectory()) { 433 if (compareTimeStamps 441 && dirTimestamp <= pluginsChangeStamp 442 && pluginFile.lastModified() <= pluginsChangeStamp) 443 return; 444 PluginEntry entry = pluginParser.parse(pluginFile); 445 addPluginEntry(entry); 446 } 447 } 448 } catch (IOException e) { 449 String pluginFileString = pluginFile.getAbsolutePath(); 450 if (ConfigurationActivator.DEBUG) 451 Utils.log(Utils.newStatus(NLS.bind(Messages.InstalledSiteParser_ErrorParsingFile, (new String [] { pluginFileString })), e)); 452 else 453 Utils.log(NLS.bind(Messages.InstalledSiteParser_ErrorAccessing, (new String [] { pluginFileString }))); 454 } catch (SAXException e) { 455 String pluginFileString = pluginFile.getAbsolutePath(); 456 Utils.log(NLS.bind(Messages.InstalledSiteParser_ErrorParsingFile, (new String [] { pluginFileString }))); 457 } 458 } 459 460 463 private synchronized String [] getDetectedFeatures() { 464 if (featureEntries == null) 465 detectFeatures(); 466 String [] features = new String [featureEntries.size()]; 467 Iterator iterator = featureEntries.values().iterator(); 468 for (int i=0; i<features.length; i++) 469 features[i] = ((FeatureEntry)iterator.next()).getURL(); 470 return features; 471 } 472 473 476 private synchronized String [] getDetectedPlugins() { 477 if (pluginEntries == null) 478 detectPlugins(); 479 480 String [] plugins = new String [pluginEntries.size()]; 481 for (int i=0; i<plugins.length; i++) 482 plugins[i] = ((PluginEntry)pluginEntries.get(i)).getURL(); 483 return plugins; 484 } 485 486 private void computeChangeStamp() { 487 changeStamp = Math.max(computeFeaturesChangeStamp(), computePluginsChangeStamp()); 488 } 490 491 private synchronized long computeFeaturesChangeStamp() { 492 if (featuresChangeStamp > 0) 493 return featuresChangeStamp; 494 495 long start = 0; 496 if (ConfigurationActivator.DEBUG) 497 start = (new Date ()).getTime(); 498 String [] features = getFeatures(); 499 500 long dirStamp = 0; 502 if (PlatformConfiguration.supportsDetection(resolvedURL)) { 503 File root = new File(resolvedURL.getFile().replace('/', File.separatorChar)); 504 File featuresDir = new File(root, FEATURES); 505 dirStamp = featuresDir.lastModified(); 506 } 507 featuresChangeStamp = Math.max(dirStamp, computeStamp(features)); 508 if (ConfigurationActivator.DEBUG) { 509 long end = (new Date ()).getTime(); 510 Utils.debug(resolvedURL.toString() + " feature stamp: " + featuresChangeStamp + " in " + (end - start) + "ms"); } 512 return featuresChangeStamp; 513 } 514 515 private synchronized long computePluginsChangeStamp() { 516 if (pluginsChangeStamp > 0) 517 return pluginsChangeStamp; 518 519 if (!PlatformConfiguration.supportsDetection(resolvedURL)) { 520 Utils.log(NLS.bind(Messages.SiteEntry_computePluginStamp, (new String [] { resolvedURL.toExternalForm() }))); 521 return 0; 522 } 523 524 File root = new File(resolvedURL.getFile().replace('/', File.separatorChar)); 526 File pluginsDir = new File(root, PLUGINS); 527 if (!pluginsDir.exists() || !pluginsDir.isDirectory()) { 528 Utils.log(NLS.bind(Messages.SiteEntry_pluginsDir, (new String [] { pluginsDir.getAbsolutePath() }))); 529 return 0; 530 } 531 532 pluginsChangeStamp = pluginsDir.lastModified(); 533 return pluginsChangeStamp; 534 } 535 536 private long computeStamp(String [] targets) { 537 538 long result = 0; 539 if (!PlatformConfiguration.supportsDetection(resolvedURL)) { 540 for (int i = 0; i < targets.length; i++) 549 result ^= targets[i].hashCode(); 550 Utils.debug("*WARNING* computing stamp using URL hashcodes only"); } else { 552 File rootFile = new File(resolvedURL.getFile().replace('/', File.separatorChar)); 554 if (rootFile.exists()) { 555 File f = null; 556 for (int i = 0; i < targets.length; i++) { 557 f = new File(rootFile, targets[i]); 558 if (f.exists()) 559 result = Math.max(result, f.lastModified()); 560 } 561 } 562 } 563 564 return result; 565 } 566 567 public void setLinkFileName(String linkFileName) { 568 this.linkFileName = linkFileName; 569 } 570 571 public String getLinkFileName() { 572 return linkFileName; 573 } 574 575 public boolean isExternallyLinkedSite() { 576 return (linkFileName != null && !linkFileName.trim().equals("")); } 578 579 public synchronized void refresh() { 580 featuresChangeStamp = 0; 582 pluginsChangeStamp = 0; 583 changeStamp = 0; 584 featureEntries = null; 585 pluginEntries = null; 586 } 587 588 public void refreshPlugins() { 589 pluginsChangeStamp = 0; 591 changeStamp = 0; 592 pluginEntries = null; 593 } 594 595 public void addFeatureEntry(IFeatureEntry feature) { 596 if (featureEntries == null) 597 featureEntries = new HashMap (); 598 IFeatureEntry existing = (FeatureEntry)featureEntries.get(feature.getFeatureIdentifier()); 600 if (existing != null) { 601 VersionedIdentifier existingVersion = new VersionedIdentifier(existing.getFeatureIdentifier(), existing.getFeatureVersion()); 602 VersionedIdentifier newVersion = new VersionedIdentifier(feature.getFeatureIdentifier(), feature.getFeatureVersion()); 603 if (existingVersion.getVersion().compareTo(newVersion.getVersion()) < 0) { 604 featureEntries.put(feature.getFeatureIdentifier(), feature); 605 pluginsChangeStamp = 0; 606 } else if (existingVersion.equals(newVersion)) { 607 if (feature instanceof FeatureEntry && existing instanceof FeatureEntry && 609 !((FeatureEntry)feature).getURL().equals(((FeatureEntry)existing).getURL())) 610 Utils.log(NLS.bind(Messages.SiteEntry_duplicateFeature, (new String [] { getURL().toExternalForm(), existing.getFeatureIdentifier() }))); 611 } 612 } else { 613 featureEntries.put(feature.getFeatureIdentifier(), feature); 614 pluginsChangeStamp = 0; 615 } 616 if (feature instanceof FeatureEntry) 617 ((FeatureEntry)feature).setSite(this); 618 } 619 620 public FeatureEntry[] getFeatureEntries() { 621 if (featureEntries == null) 622 detectFeatures(); 623 624 if (featureEntries == null) 625 return new FeatureEntry[0]; 626 return (FeatureEntry[])featureEntries.values().toArray(new FeatureEntry[featureEntries.size()]); 627 } 628 629 public void addPluginEntry(PluginEntry plugin) { 630 if (pluginEntries == null) 631 pluginEntries = new ArrayList (); 632 pluginEntries.add(plugin); 634 } 635 636 public PluginEntry[] getAllPluginEntries() { 637 if (pluginEntries == null) 638 detectPlugins(); 639 return (PluginEntry[])pluginEntries.toArray(new PluginEntry[pluginEntries.size()]); 640 } 641 642 public void loadFromDisk(long lastChange) throws CoreException{ 643 featuresChangeStamp = lastChange; 644 pluginsChangeStamp = lastChange; 645 detectFeatures(); 646 detectPlugins(); 647 } 648 649 653 public Element toXML(Document doc) { 654 655 Element siteElement = doc.createElement(CFG_SITE); 656 657 if (getURL() != null) { 658 URL toPersist = (config == null || config.isTransient()) ? getURL() : Utils.makeRelative(Utils.getInstallURL(), getURL()); 659 siteElement.setAttribute(CFG_URL, toPersist.toString()); 660 } 661 662 siteElement.setAttribute(CFG_ENABLED, isEnabled() ? "true" : "false"); siteElement.setAttribute(CFG_UPDATEABLE, isUpdateable() ? "true" : "false"); if (isExternallyLinkedSite()) 665 siteElement.setAttribute(CFG_LINK_FILE, getLinkFileName().trim().replace(File.separatorChar, '/')); 666 667 int type = getSitePolicy().getType(); 668 String typeString = CFG_POLICY_TYPE_UNKNOWN; 669 try { 670 typeString = CFG_POLICY_TYPE[type]; 671 } catch (IndexOutOfBoundsException e) { 672 } 674 siteElement.setAttribute(CFG_POLICY, typeString); 675 String [] list = getSitePolicy().getList(); 676 if (list.length > 0) { 677 StringBuffer sb = new StringBuffer (256); 678 for (int i=0; i<list.length-1; i++) { 679 sb.append(list[i]); 680 sb.append(','); 681 } 682 sb.append(list[list.length-1]); 683 siteElement.setAttribute(CFG_LIST, sb.toString()); 684 } 685 687 FeatureEntry[] feats = getFeatureEntries(); 690 for (int i = 0; i < feats.length; i++) { 691 Element featureElement = feats[i].toXML(doc); 692 siteElement.appendChild(featureElement); 693 } 694 695 return siteElement; 696 } 697 698 private void validateFeatureEntries() { 699 File root = new File(resolvedURL.getFile().replace('/', File.separatorChar)); 700 Iterator iterator = featureEntries.values().iterator(); 701 Collection deletedFeatures = new ArrayList (); 702 while(iterator.hasNext()) { 703 FeatureEntry feature = (FeatureEntry)iterator.next(); 704 File featureXML = new File(root, feature.getURL()); 707 if (!featureXML.exists()) 708 deletedFeatures.add(feature.getFeatureIdentifier()); 709 } 710 for(Iterator it=deletedFeatures.iterator(); it.hasNext();){ 711 featureEntries.remove(it.next()); 712 } 713 } 714 715 private void validatePluginEntries() { 716 File root = new File(resolvedURL.getFile().replace('/', File.separatorChar)); 717 Collection deletedPlugins = new ArrayList (); 718 for (int i=0; i<pluginEntries.size(); i++) { 719 PluginEntry plugin = (PluginEntry)pluginEntries.get(i); 720 File pluginLocation = new File(root, plugin.getURL()); 723 if (!pluginLocation.exists()) 724 deletedPlugins.add(plugin); 725 } 726 for(Iterator it=deletedPlugins.iterator(); it.hasNext();){ 727 pluginEntries.remove(it.next()); 728 } 729 } 730 731 public boolean isEnabled() { 732 return enabled; 733 } 734 735 public void setEnabled(boolean enable) { 736 this.enabled = enable; 737 } 738 739 public FeatureEntry getFeatureEntry(String id) { 740 FeatureEntry[] features = getFeatureEntries(); 741 for (int i=0; i<features.length; i++) 742 if (features[i].getFeatureIdentifier().equals(id)) 743 return features[i]; 744 return null; 745 } 746 747 748 public boolean unconfigureFeatureEntry(IFeatureEntry feature) { 749 FeatureEntry existingFeature = getFeatureEntry(feature.getFeatureIdentifier()); 750 if (existingFeature != null) 751 featureEntries.remove(existingFeature.getFeatureIdentifier()); 752 return existingFeature != null; 753 } 754 755 760 void initialized() { 761 if (featureEntries == null) 762 featureEntries = new HashMap (); 763 } 764 } 765 | Popular Tags |