| 1 12 package org.eclipse.update.internal.configurator; 13 14 import java.io.BufferedWriter ; 15 import java.io.File ; 16 import java.io.FileFilter ; 17 import java.io.FileInputStream ; 18 import java.io.FileOutputStream ; 19 import java.io.IOException ; 20 import java.io.OutputStream ; 21 import java.io.OutputStreamWriter ; 22 import java.io.SyncFailedException ; 23 import java.io.UnsupportedEncodingException ; 24 import java.lang.reflect.InvocationTargetException ; 25 import java.net.MalformedURLException ; 26 import java.net.URL ; 27 import java.net.URLConnection ; 28 import java.util.ArrayList ; 29 import java.util.Date ; 30 import java.util.HashMap ; 31 import java.util.HashSet ; 32 import java.util.Properties ; 33 import java.util.Set ; 34 35 import javax.xml.parsers.DocumentBuilder ; 36 import javax.xml.parsers.DocumentBuilderFactory ; 37 38 import org.eclipse.core.runtime.CoreException; 39 import org.eclipse.core.runtime.FileLocator; 40 import org.eclipse.osgi.service.datalocation.Location; 41 import org.eclipse.osgi.util.NLS; 42 import org.eclipse.update.configurator.IPlatformConfiguration; 43 import org.w3c.dom.Document ; 44 import org.w3c.dom.Element ; 45 46 58 public class PlatformConfiguration implements IPlatformConfiguration, IConfigurationConstants { 59 60 private static PlatformConfiguration currentPlatformConfiguration = null; 61 private static final String XML_ENCODING = "UTF-8"; 65 private Configuration config; 66 private URL configLocation; 67 private HashMap externalLinkSites; private long changeStamp; 69 private long featuresChangeStamp; 70 private boolean featuresChangeStampIsValid; 71 private long pluginsChangeStamp; 72 private boolean pluginsChangeStampIsValid; 73 private Locker lock = null; 76 private static int defaultPolicy = DEFAULT_POLICY_TYPE; 77 private static boolean checkNio = false; 78 private static boolean useNio; 79 80 private static final String ECLIPSE = "eclipse"; private static final String CONFIG_HISTORY = "history"; private static final String PLATFORM_XML = "platform.xml"; private static final String CONFIG_NAME = ConfigurationActivator.NAME_SPACE + "/" + PLATFORM_XML; private static final String CONFIG_INI = "config.ini"; private static final String CONFIG_FILE_LOCK_SUFFIX = ".lock"; private static final String CONFIG_FILE_TEMP_SUFFIX = ".tmp"; private static final String LINKS = "links"; private static final String [] BOOTSTRAP_PLUGINS = {}; 89 90 private static final String DEFAULT_FEATURE_APPLICATION = "org.eclipse.ui.ide.workbench"; 92 private static final String LINK_PATH = "path"; private static final String LINK_READ = "r"; private static final String LINK_READ_WRITE = "rw"; private static URL installURL; 96 97 private PlatformConfiguration(Location platformConfigLocation) throws CoreException, IOException { 98 99 this.externalLinkSites = new HashMap (); 100 this.config = null; 101 102 initializeCurrent(platformConfigLocation); 104 if(config != null) 105 setDefaultPolicy(); 106 107 if (!isTransient()) 112 configureExternalLinks(); 113 114 validateSites(); 117 118 if (isTransient()) 122 return; 123 124 boolean osgiClean = "true".equals(ConfigurationActivator.getBundleContext().getProperty("osgi.clean")); boolean osgiCheckConfiguration = "true".equals(ConfigurationActivator.getBundleContext().getProperty("osgi.checkConfiguration")); 128 if (osgiClean || osgiCheckConfiguration) { 129 refresh(); 131 reconcile(); 132 } 133 else { 134 changeStamp = computeChangeStamp(); 135 if (changeStamp > config.getDate().getTime()) 136 reconcile(); 137 } 138 } 139 140 PlatformConfiguration(URL url) throws Exception { 141 this.externalLinkSites = new HashMap (); 142 initialize(url); 143 } 144 145 private void setDefaultPolicy() { 146 ISiteEntry[] sentries = getConfiguredSites(); 150 if(sentries != null && sentries.length >0){ 151 int policyType = sentries[0].getSitePolicy().getType(); 152 if(policyType == ISitePolicy.MANAGED_ONLY){ 153 defaultPolicy = policyType; 154 } 155 } 156 } 157 158 public static int getDefaultPolicy(){ 159 return defaultPolicy; 160 } 161 162 165 public ISiteEntry createSiteEntry(URL url, ISitePolicy policy) { 166 return new SiteEntry(url, policy); 167 } 168 169 172 public ISitePolicy createSitePolicy(int type, String [] list) { 173 return new SitePolicy(type, list); 174 } 175 176 179 public IFeatureEntry createFeatureEntry(String id, String version, String pluginVersion, boolean primary, String application, URL [] root) { 180 return new FeatureEntry(id, version, pluginVersion, primary, application, root); 181 } 182 183 187 public IFeatureEntry createFeatureEntry(String id, String version, String pluginIdentifier, String pluginVersion, boolean primary, String application, URL [] root) { 188 return new FeatureEntry(id, version, pluginIdentifier, pluginVersion, primary, application, root); 189 } 190 191 194 public void configureSite(ISiteEntry entry) { 195 configureSite(entry, false); 196 } 197 198 201 public synchronized void configureSite(ISiteEntry entry, boolean replace) { 202 203 if (entry == null) 204 return; 205 206 URL url = entry.getURL(); 207 if (url == null) 208 return; 209 210 String key = url.toExternalForm(); 211 if (config.getSiteEntry(key) != null && !replace) 212 return; 213 214 if (entry instanceof SiteEntry) 215 config.addSiteEntry(key, (SiteEntry)entry); 216 } 217 218 221 public synchronized void unconfigureSite(ISiteEntry entry) { 222 if (entry == null) 223 return; 224 225 URL url = entry.getURL(); 226 if (url == null) 227 return; 228 229 String key = url.toExternalForm(); 230 if (entry instanceof SiteEntry) 231 config.removeSiteEntry(key); 232 } 233 234 237 public ISiteEntry[] getConfiguredSites() { 238 if (config == null) 239 return new ISiteEntry[0]; 240 241 SiteEntry[] sites = config.getSites(); 242 ArrayList enabledSites = new ArrayList (sites.length); 243 for (int i=0; i<sites.length; i++) { 244 if (sites[i].isEnabled()) 245 enabledSites.add(sites[i]); 246 } 247 return (ISiteEntry[])enabledSites.toArray(new ISiteEntry[enabledSites.size()]); 248 } 249 250 253 public ISiteEntry findConfiguredSite(URL url) { 254 return findConfiguredSite(url, true); 255 } 256 257 263 public SiteEntry findConfiguredSite(URL url, boolean checkPlatformURL) { 264 if (url == null) 265 return null; 266 String key = url.toExternalForm(); 267 268 SiteEntry result = config.getSiteEntry(key); 269 if (result == null) { try { 271 key = UpdateURLDecoder.decode(key, "UTF-8"); } catch (UnsupportedEncodingException e) { 275 } 277 result = config.getSiteEntry(key); 278 } 279 280 if (result == null && checkPlatformURL) { 281 try { 282 result = findConfiguredSite(config.asPlatformURL(url), false); 283 } catch (Exception e) { 284 } 286 } 287 return result; 288 } 289 290 293 public synchronized void configureFeatureEntry(IFeatureEntry entry) { 294 if (entry == null) 295 return; 296 297 String key = entry.getFeatureIdentifier(); 298 if (key == null) 299 return; 300 301 if (config == null) 304 config = new Configuration(); 305 306 SiteEntry[] sites = config.getSites(); 307 for (int i=0; i<sites.length; i++) { 308 try { 310 URL url = new URL (sites[i].getURL(), FEATURES + "/" + entry.getFeatureIdentifier()+ "_" + entry.getFeatureVersion() + "/"); if (new File (url.getFile()).exists()) 312 sites[i].addFeatureEntry(entry); 313 else { 314 url = new URL (sites[i].getURL(), FEATURES + "/" + entry.getFeatureIdentifier() + "/"); if (new File (url.getFile()).exists()) 316 sites[i].addFeatureEntry(entry); 317 } 318 } catch (MalformedURLException e) { 319 } 320 } 321 } 322 323 326 public synchronized void unconfigureFeatureEntry(IFeatureEntry entry) { 327 if (entry == null) 328 return; 329 330 String key = entry.getFeatureIdentifier(); 331 if (key == null) 332 return; 333 334 config.unconfigureFeatureEntry(entry); 335 } 336 337 340 public IFeatureEntry[] getConfiguredFeatureEntries() { 341 ArrayList configFeatures = new ArrayList (); 342 SiteEntry[] sites = config.getSites(); 343 for (int i=0; i<sites.length; i++) { 344 FeatureEntry[] features = sites[i].getFeatureEntries(); 345 for (int j=0; j<features.length; j++) 346 configFeatures.add(features[j]); 347 } 348 return (IFeatureEntry[])configFeatures.toArray(new FeatureEntry[configFeatures.size()]); 349 } 350 351 354 public IFeatureEntry findConfiguredFeatureEntry(String id) { 355 if (id == null) 356 return null; 357 358 SiteEntry[] sites = config.getSites(); 359 for (int i=0; i<sites.length; i++) { 360 FeatureEntry f = sites[i].getFeatureEntry(id); 361 if (f != null) 362 return f; 363 } 364 return null; 365 } 366 367 370 public URL getConfigurationLocation() { 371 return configLocation; 372 } 373 374 377 public long getChangeStamp() { 378 if (config.getLinkedConfig() == null) 379 return config.getDate().getTime(); 380 return Math.max(config.getDate().getTime(), config.getLinkedConfig().getDate().getTime()); 381 } 382 383 387 public long getFeaturesChangeStamp() { 388 return 0; 389 } 390 391 395 public long getPluginsChangeStamp() { 396 return 0; 397 } 398 399 400 public String getApplicationIdentifier() { 401 String application = ConfigurationActivator.getBundleContext().getProperty(ECLIPSE_APPLICATION); 403 if (application != null) 404 return application; 405 406 String feature = getPrimaryFeatureIdentifier(); 408 409 if (feature != null) { 411 IFeatureEntry fe = findConfiguredFeatureEntry(feature); 412 if (fe != null) { 413 if (fe.getFeatureApplication() != null) 414 return fe.getFeatureApplication(); 415 } 416 } 417 418 return DEFAULT_FEATURE_APPLICATION; 420 } 421 422 425 public String getPrimaryFeatureIdentifier() { 426 String primaryFeatureId = ConfigurationActivator.getBundleContext().getProperty(ECLIPSE_PRODUCT); 428 if (primaryFeatureId != null) { 429 IFeatureEntry feature = findConfiguredFeatureEntry(primaryFeatureId); 431 if (feature != null && feature.canBePrimary()) 432 return primaryFeatureId; 433 } 434 return null; 435 } 436 437 440 public URL [] getPluginPath() { 441 ArrayList path = new ArrayList (); 442 Utils.debug("computed plug-in path:"); 444 ISiteEntry[] sites = getConfiguredSites(); 445 URL pathURL; 446 for (int i = 0; i < sites.length; i++) { 447 String [] plugins = sites[i].getPlugins(); 448 for (int j = 0; j < plugins.length; j++) { 449 try { 450 pathURL = new URL (((SiteEntry) sites[i]).getResolvedURL(), plugins[j]); 451 path.add(pathURL); 452 Utils.debug(" " + pathURL.toString()); } catch (MalformedURLException e) { 454 Utils.debug(" bad URL: " + e); } 457 } 458 } 459 return (URL []) path.toArray(new URL [0]); 460 } 461 462 public Set getPluginPaths() { 463 464 HashSet paths = new HashSet (); 465 ISiteEntry[] sites = getConfiguredSites(); 466 467 for (int i = 0; i < sites.length; i++) { 468 String [] plugins = sites[i].getPlugins(); 469 for (int j = 0; j < plugins.length; j++) { 470 paths.add(plugins[j]); 471 } 472 } 473 474 return paths; 475 } 476 477 478 481 public PluginEntry[] getPlugins() { 482 ArrayList allPlugins = new ArrayList (); 483 Utils.debug("computed plug-ins:"); 485 ISiteEntry[] sites = getConfiguredSites(); 486 for (int i = 0; i < sites.length; i++) { 487 if (!(sites[i] instanceof SiteEntry)) { 488 Utils.debug("Site " + sites[i].getURL() + " is not a SiteEntry"); continue; 490 } 491 PluginEntry[] plugins = ((SiteEntry)sites[i]).getPluginEntries(); 492 for (int j = 0; j < plugins.length; j++) { 493 allPlugins.add(plugins[j]); 494 Utils.debug(" " + plugins[j].getURL()); } 496 } 497 return (PluginEntry[]) allPlugins.toArray(new PluginEntry[0]); 498 } 499 500 501 504 public String [] getBootstrapPluginIdentifiers() { 505 return BOOTSTRAP_PLUGINS; 506 } 507 508 511 public void setBootstrapPluginLocation(String id, URL location) { 512 } 513 514 517 public boolean isUpdateable() { 518 return true; 519 } 520 521 524 public boolean isTransient() { 525 return (config != null) ? config.isTransient() : false; 526 } 527 528 531 public void isTransient(boolean value) { 532 if (this != getCurrent() && config != null) 533 config.setTransient(value); 534 } 535 536 539 public synchronized void refresh() { 540 ISiteEntry[] sites = getConfiguredSites(); 543 for (int i = 0; i < sites.length; i++) { 544 if (sites[i].isUpdateable()) { 545 ((SiteEntry) sites[i]).refresh(); 547 } 548 } 549 } 550 551 554 public void save() throws IOException { 555 if (isUpdateable()) 556 save(configLocation); 557 } 558 559 562 public synchronized void save(URL url) throws IOException { 563 if (url == null) 564 throw new IOException (Messages.cfig_unableToSave_noURL); 565 566 OutputStream os = null; 567 if (!url.getProtocol().equals("file")) { URLConnection uc = url.openConnection(); 570 uc.setDoOutput(true); 571 os = uc.getOutputStream(); 572 try { 573 saveAsXML(os); 574 config.setDirty(false); 575 } catch (CoreException e) { 576 Utils.log(e.getMessage()); 577 Utils.log(e.getStatus()); 578 throw new IOException (NLS.bind(Messages.cfig_unableToSave, (new String [] { url.toExternalForm() }))); 579 } finally { 580 os.close(); 581 } 582 } else { 583 File cfigFile = new File (url.getFile().replace('/', File.separatorChar)); 585 if (!cfigFile.getName().equals(PLATFORM_XML)) { 586 if (cfigFile.exists() && cfigFile.isFile()) { 587 Utils.log(Messages.PlatformConfiguration_expectingPlatformXMLorDirectory + cfigFile.getName()); 588 cfigFile = cfigFile.getParentFile(); 589 } 590 cfigFile = new File (cfigFile, CONFIG_NAME); 591 } 592 File workingDir = cfigFile.getParentFile(); 593 if (workingDir != null && !workingDir.exists()) 594 workingDir.mkdirs(); 595 596 File cfigFileOriginal = new File (cfigFile.getAbsolutePath()); 601 File cfigTmp = new File (cfigFile.getAbsolutePath() + CONFIG_FILE_TEMP_SUFFIX); 602 603 if (cfigFile.exists()){ 605 File backupDir = new File (workingDir, CONFIG_HISTORY); 606 if (!backupDir.exists()) 607 backupDir.mkdir(); 608 long timestamp = cfigFile.lastModified(); 609 File preservedFile = new File (backupDir, String.valueOf(timestamp)+".xml"); long increment = 1; 612 while (preservedFile.exists() && increment < 100){ 613 preservedFile = new File (backupDir, String.valueOf(timestamp+increment++)+".xml"); } 615 if (!preservedFile.exists()) { 616 if (!cfigFile.renameTo(preservedFile)) 618 Utils.log(Messages.PlatformConfiguration_cannotBackupConfig); 619 } 620 } 621 622 os = new FileOutputStream (cfigTmp); 624 625 try { 626 saveAsXML(os); 627 try { 629 os.flush(); 630 ((FileOutputStream )os).getFD().sync(); 631 } catch (SyncFailedException e2) { 632 Utils.log(e2.getMessage()); 633 } catch (IOException e2) { 634 Utils.log(e2.getMessage()); 635 } 636 try { 637 os.close(); 638 os = null; 639 } catch (IOException e1) { 640 Utils.log(Messages.PlatformConfiguration_cannotCloseStream + cfigTmp); 641 Utils.log(e1.getMessage()); 642 } 643 cfigTmp.setLastModified(config.getDate().getTime()); 645 config.setLastModified(cfigTmp.lastModified()); 647 changeStamp = config.getDate().getTime(); 649 config.setDirty(false); 650 } catch (CoreException e) { 651 throw new IOException (NLS.bind(Messages.cfig_unableToSave, (new String [] { cfigTmp.getAbsolutePath() }))); 652 } finally { 653 if (os != null) 654 try { 655 os.close(); 656 } catch (IOException e1) { 657 Utils.log(Messages.PlatformConfiguration_cannotCloseTempFile + cfigTmp); 658 } 659 } 660 661 boolean ok = cfigTmp.renameTo(cfigFileOriginal); 664 if (!ok) { 665 Utils.log(Messages.PlatformConfiguration_cannotRenameTempFile); 671 672 throw new IOException (NLS.bind(Messages.cfig_unableToSave, (new String [] { cfigTmp.getAbsolutePath() }))); 673 } 674 } 675 } 676 677 678 public static PlatformConfiguration getCurrent() { 679 return currentPlatformConfiguration; 680 } 681 682 685 public static synchronized void startup(URL installURL, Location platformConfigLocation) throws Exception { 686 PlatformConfiguration.installURL = installURL; 687 688 if (currentPlatformConfiguration == null) { 690 currentPlatformConfiguration = new PlatformConfiguration(platformConfigLocation); 691 if (currentPlatformConfiguration.config == null) 692 throw new Exception (Messages.PlatformConfiguration_cannotLoadConfig + platformConfigLocation.getURL()); 693 if (currentPlatformConfiguration.config.isDirty()) 694 if (!currentPlatformConfiguration.isTransient()) 697 currentPlatformConfiguration.save(); 698 } 699 } 700 701 public static synchronized void shutdown() throws IOException { 702 703 PlatformConfiguration config = getCurrent(); 705 if (config != null) { 706 if (config.config.isDirty() && !config.isTransient()) { 708 try { 709 config.save(); 710 } catch (IOException e) { 711 Utils.debug("Unable to save configuration " + e.toString()); } 714 } 715 } 716 } 717 718 719 private synchronized void initializeCurrent(Location platformConfigLocation) throws IOException { 720 721 |