1 11 package org.eclipse.pde.internal.core; 12 13 import java.io.*; 14 import java.net.*; 15 import java.util.*; 16 17 import org.eclipse.core.internal.boot.*; 18 import org.eclipse.update.configurator.*; 19 20 public class PlatformConfiguration implements IPlatformConfiguration { 21 22 private static PlatformConfiguration currentPlatformConfiguration = null; 23 24 private URL configLocation; 25 private HashMap sites; 26 private HashMap externalLinkSites; private HashMap cfgdFeatures; 28 private HashMap bootPlugins; 29 private String defaultFeature; 30 private long changeStamp; 31 private boolean changeStampIsValid = false; 32 private long lastFeaturesChangeStamp; 33 private long featuresChangeStamp; 34 private boolean featuresChangeStampIsValid = false; 35 private long pluginsChangeStamp; 36 private boolean pluginsChangeStampIsValid = false; 37 private boolean transientConfig = false; 38 private File cfgLockFile; 39 private RandomAccessFile cfgLockFileRAF; 40 private BootDescriptor runtimeDescriptor; 41 42 private static String cmdFeature = null; 43 private static String cmdApplication = null; 44 private static boolean cmdInitialize = false; 45 private static boolean cmdFirstUse = false; 46 private static boolean cmdUpdate = false; 47 private static boolean cmdNoUpdate = false; 48 49 static boolean DEBUG = false; 50 51 private static final String RUNTIME_PLUGIN_ID = "org.eclipse.core.runtime"; 53 private static final String PLUGINS = "plugins"; private static final String FEATURES = "features"; private static final String CONFIG_FILE_TEMP_SUFFIX = ".tmp"; private static final String CONFIG_FILE_BAK_SUFFIX = ".bak"; private static final String PLUGIN_XML = "plugin.xml"; private static final String FRAGMENT_XML = "fragment.xml"; private static final String FEATURE_XML = "feature.xml"; 61 private static final String [] BOOTSTRAP_PLUGINS = { "org.eclipse.core.boot" }; private static final String CFG_BOOT_PLUGIN = "bootstrap"; private static final String CFG_SITE = "site"; private static final String CFG_URL = "url"; private static final String CFG_POLICY = "policy"; private static final String [] CFG_POLICY_TYPE = { "USER-INCLUDE", "USER-EXCLUDE" }; private static final String CFG_POLICY_TYPE_UNKNOWN = "UNKNOWN"; private static final String CFG_LIST = "list"; private static final String CFG_STAMP = "stamp"; private static final String CFG_FEATURE_STAMP = "stamp.features"; private static final String CFG_PLUGIN_STAMP = "stamp.plugins"; private static final String CFG_UPDATEABLE = "updateable"; private static final String CFG_LINK_FILE = "linkfile"; private static final String CFG_FEATURE_ENTRY = "feature"; private static final String CFG_FEATURE_ENTRY_DEFAULT = "feature.default.id"; private static final String CFG_FEATURE_ENTRY_ID = "id"; private static final String CFG_FEATURE_ENTRY_PRIMARY = "primary"; private static final String CFG_FEATURE_ENTRY_VERSION = "version"; private static final String CFG_FEATURE_ENTRY_PLUGIN_VERSION = "plugin-version"; private static final String CFG_FEATURE_ENTRY_PLUGIN_IDENTIFIER = "plugin-identifier"; private static final String CFG_FEATURE_ENTRY_APPLICATION = "application"; private static final String CFG_FEATURE_ENTRY_ROOT = "root"; 84 private static final String DEFAULT_FEATURE_ID = "org.eclipse.platform"; private static final String DEFAULT_FEATURE_APPLICATION = "org.eclipse.ui.workbench"; 87 private static final String CFG_VERSION = "version"; private static final String CFG_TRANSIENT = "transient"; private static final String VERSION = "2.1"; private static final String EOF = "eof"; private static final int CFG_LIST_LENGTH = 10; 92 93 private static final int DEFAULT_POLICY_TYPE = ISitePolicy.USER_EXCLUDE; 94 private static final String [] DEFAULT_POLICY_LIST = new String [0]; 95 96 97 protected static final String RECONCILER_APP = "org.eclipse.update.core.reconciler"; 99 private static final char[] HEX = { '0', '1', '2', '3', '4', '5', '6', '7', '8', '9', 'A', 'B', 'C', 'D', 'E', 'F' }; 100 101 private static URL installURL; 102 103 public class SiteEntry implements IPlatformConfiguration.ISiteEntry { 104 105 private URL url; private URL resolvedURL; private ISitePolicy policy; 108 private boolean updateable = true; 109 private ArrayList features; 110 private ArrayList plugins; 111 private PlatformConfiguration parent; 112 private long changeStamp; 113 private boolean changeStampIsValid = false; 114 private long lastFeaturesChangeStamp; 115 private long featuresChangeStamp; 116 private boolean featuresChangeStampIsValid = false; 117 private long lastPluginsChangeStamp; 118 private long pluginsChangeStamp; 119 private boolean pluginsChangeStampIsValid = false; 120 private String linkFileName = null; 121 122 private SiteEntry() { 123 } 124 private SiteEntry(URL url, ISitePolicy policy, PlatformConfiguration parent) { 125 if (url == null) 126 throw new IllegalArgumentException (); 127 128 if (policy == null) 129 throw new IllegalArgumentException (); 130 131 if (parent == null) 132 throw new IllegalArgumentException (); 133 134 this.url = url; 135 this.policy = policy; 136 this.parent = parent; 137 this.features = null; 138 this.plugins = null; 139 this.resolvedURL = this.url; 140 if (url.getProtocol().equals(PlatformURLHandler.PROTOCOL)) { 141 try { 142 resolvedURL = resolvePlatformURL(url); } catch (IOException e) { 144 } 146 } 147 } 148 149 152 public URL getURL() { 153 return url; 154 } 155 156 159 public ISitePolicy getSitePolicy() { 160 return policy; 161 } 162 163 166 public synchronized void setSitePolicy(ISitePolicy policy) { 167 if (policy == null) 168 throw new IllegalArgumentException (); 169 this.policy = policy; 170 } 171 172 175 public String [] getFeatures() { 176 return getDetectedFeatures(); 177 } 178 179 182 public String [] getPlugins() { 183 184 ISitePolicy policy = getSitePolicy(); 185 186 if (policy.getType() == ISitePolicy.USER_INCLUDE) 187 return policy.getList(); 188 189 if (policy.getType() == ISitePolicy.USER_EXCLUDE) { 190 ArrayList detectedPlugins = new ArrayList(Arrays.asList(getDetectedPlugins())); 191 String [] excludedPlugins = policy.getList(); 192 for (int i = 0; i < excludedPlugins.length; i++) { 193 if (detectedPlugins.contains(excludedPlugins[i])) 194 detectedPlugins.remove(excludedPlugins[i]); 195 } 196 return (String []) detectedPlugins.toArray(new String [0]); 197 } 198 199 return new String [0]; 201 } 202 203 206 public long getChangeStamp() { 207 if (!changeStampIsValid) 208 computeChangeStamp(); 209 return changeStamp; 210 } 211 212 215 public long getFeaturesChangeStamp() { 216 if (!featuresChangeStampIsValid) 217 computeFeaturesChangeStamp(); 218 return featuresChangeStamp; 219 } 220 221 224 public long getPluginsChangeStamp() { 225 if (!pluginsChangeStampIsValid) 226 computePluginsChangeStamp(); 227 return pluginsChangeStamp; 228 } 229 230 233 public boolean isUpdateable() { 234 return updateable; 235 } 236 237 240 public boolean isNativelyLinked() { 241 return isExternallyLinkedSite(); 242 } 243 244 private String [] detectFeatures() { 245 246 changeStampIsValid = false; 248 featuresChangeStampIsValid = false; 249 parent.changeStampIsValid = false; 250 parent.featuresChangeStampIsValid = false; 251 252 features = new ArrayList(); 253 254 if (!supportsDetection(resolvedURL)) 255 return new String [0]; 256 257 File siteRoot = new File(resolvedURL.getFile().replace('/', File.separatorChar)); 259 File root = new File(siteRoot, FEATURES); 260 261 String [] list = root.list(); 262 String path; 263 File plugin; 264 for (int i = 0; list != null && i < list.length; i++) { 265 path = list[i] + File.separator + FEATURE_XML; 266 plugin = new File(root, path); 267 if (!plugin.exists()) { 268 continue; 269 } 270 features.add(FEATURES + "/" + path.replace(File.separatorChar, '/')); } 272 if (DEBUG) { 273 debug(resolvedURL.toString() + " located " + features.size() + " feature(s)"); } 275 276 return (String []) features.toArray(new String [0]); 277 } 278 279 private String [] detectPlugins() { 280 281 changeStampIsValid = false; 283 pluginsChangeStampIsValid = false; 284 parent.changeStampIsValid = false; 285 parent.pluginsChangeStampIsValid = false; 286 287 plugins = new ArrayList(); 288 289 if (!supportsDetection(resolvedURL)) 290 return new String [0]; 291 292 File root = new File(resolvedURL.getFile().replace('/', File.separatorChar) + PLUGINS); 294 String [] list = root.list(); 295 String path; 296 File plugin; 297 for (int i = 0; list != null && i < list.length; i++) { 298 path = list[i] + File.separator + PLUGIN_XML; 299 plugin = new File(root, path); 300 if (!plugin.exists()) { 301 path = list[i] + File.separator + FRAGMENT_XML; 302 plugin = new File(root, path); 303 if (!plugin.exists()) 304 continue; 305 } 306 plugins.add(PLUGINS + "/" + path.replace(File.separatorChar, '/')); } 308 if (DEBUG) { 309 debug(resolvedURL.toString() + " located " + plugins.size() + " plugin(s)"); } 311 312 return (String []) plugins.toArray(new String [0]); 313 } 314 315 private synchronized String [] getDetectedFeatures() { 316 if (features == null) 317 return detectFeatures(); 318 return (String []) features.toArray(new String [0]); 319 } 320 321 private synchronized String [] getDetectedPlugins() { 322 if (plugins == null) 323 return detectPlugins(); 324 return (String []) plugins.toArray(new String [0]); 325 } 326 327 private URL getResolvedURL() { 328 return resolvedURL; 329 } 330 331 private void computeChangeStamp() { 332 computeFeaturesChangeStamp(); 333 computePluginsChangeStamp(); 334 changeStamp = resolvedURL.hashCode() ^ featuresChangeStamp ^ pluginsChangeStamp; 335 changeStampIsValid = true; 336 } 337 338 private synchronized void computeFeaturesChangeStamp() { 339 if (featuresChangeStampIsValid) 340 return; 341 342 long start = 0; 343 if (DEBUG) 344 start = (new Date()).getTime(); 345 String [] features = getFeatures(); 346 featuresChangeStamp = computeStamp(features); 347 featuresChangeStampIsValid = true; 348 if (DEBUG) { 349 long end = (new Date()).getTime(); 350 debug(resolvedURL.toString() + " feature stamp: " + featuresChangeStamp + ((featuresChangeStamp == lastFeaturesChangeStamp) ? " [no changes]" : " [was " + lastFeaturesChangeStamp + "]") + " in " + (end - start) + "ms"); } 352 } 353 354 private synchronized void computePluginsChangeStamp() { 355 if (pluginsChangeStampIsValid) 356 return; 357 358 long start = 0; 359 if (DEBUG) 360 start = (new Date()).getTime(); 361 String [] plugins = getPlugins(); 362 pluginsChangeStamp = computeStamp(plugins); 363 pluginsChangeStampIsValid = true; 364 if (DEBUG) { 365 long end = (new Date()).getTime(); 366 debug(resolvedURL.toString() + " plugin stamp: " + pluginsChangeStamp + ((pluginsChangeStamp == lastPluginsChangeStamp) ? " [no changes]" : " [was " + lastPluginsChangeStamp + "]") + " in " + (end - start) + "ms"); } 368 } 369 370 private long computeStamp(String [] targets) { 371 372 long result = 0; 373 if (!supportsDetection(resolvedURL)) { 374 for (int i = 0; i < targets.length; i++) 382 result ^= targets[i].hashCode(); 383 if (DEBUG) 384 debug("*WARNING* computing stamp using URL hashcodes only"); } else { 386 String rootPath = resolvedURL.getFile().replace('/', File.separatorChar); 388 if (!rootPath.endsWith(File.separator)) 389 rootPath += File.separator; 390 File rootFile = new File(rootPath); 391 if (rootFile.exists()) { 392 File f = null; 393 for (int i = 0; i < targets.length; i++) { 394 f = new File(rootFile, targets[i]); 395 if (f.exists()) 396 result ^= f.getAbsolutePath().hashCode() ^ f.lastModified() ^ f.length(); 397 } 398 } 399 } 400 401 return result; 402 } 403 404 private boolean isExternallyLinkedSite() { 405 return (linkFileName != null && !linkFileName.trim().equals("")); } 407 408 private synchronized void refresh() { 409 lastFeaturesChangeStamp = featuresChangeStamp; 411 lastPluginsChangeStamp = pluginsChangeStamp; 412 changeStampIsValid = false; 413 featuresChangeStampIsValid = false; 414 pluginsChangeStampIsValid = false; 415 features = null; 416 plugins = null; 417 } 418 419 } 420 421 public class SitePolicy implements IPlatformConfiguration.ISitePolicy { 422 423 private int type; 424 private String [] list; 425 426 private SitePolicy() { 427 } 428 private SitePolicy(int type, String [] list) { 429 if (type != ISitePolicy.USER_INCLUDE && type != ISitePolicy.USER_EXCLUDE) 430 throw new IllegalArgumentException (); 431 this.type = type; 432 433 if (list == null) 434 this.list = new String [0]; 435 else 436 this.list = list; 437 } 438 439 442 public int getType() { 443 return type; 444 } 445 446 449 public String [] getList() { 450 return list; 451 } 452 453 456 public synchronized void setList(String [] list) { 457 if (list == null) 458 this.list = new String [0]; 459 else 460 this.list = list; 461 } 462 463 } 464 465 public class FeatureEntry implements IPlatformConfiguration.IFeatureEntry { 466 private String id; 467 private String version; 468 private String pluginVersion; 469 private String application; 470 private URL[] root; 471 private boolean primary; 472 private String pluginIdentifier; 473 474 private FeatureEntry(String id, String version, String pluginIdentifier, String pluginVersion, boolean primary, String application, URL[] root) { 475 if (id == null) 476 throw new IllegalArgumentException (); 477 this.id = id; 478 this.version = version; 479 this.pluginVersion = pluginVersion; 480 this.pluginIdentifier = pluginIdentifier; 481 this.primary = primary; 482 this.application = application; 483 this.root = (root == null ? new URL[0] : root); 484 } 485 486 private FeatureEntry(String id, String version, String pluginVersion, boolean primary, String application, URL[] root) { 487 this(id, version, id, pluginVersion, primary, application, root); 488 } 489 490 493 public String getFeatureIdentifier() { 494 return id; 495 } 496 497 500 public String getFeatureVersion() { 501 return version; 502 } 503 504 507 public String getFeaturePluginVersion() { 508 return pluginVersion; 509 } 510 511 514 public String getFeatureApplication() { 515 return application; 516 } 517 518 521 public URL[] getFeatureRootURLs() { 522 return root; 523 } 524 525 528 public boolean canBePrimary() { 529 return primary; 530 } 531 534 public String getFeaturePluginIdentifier() { 535 return pluginIdentifier; 536 } 537 538 } 539 540 541 545 public interface Selector { 546 547 554 public boolean select(String entry); 555 556 561 public boolean select(String element, HashMap attributes); 562 } 563 564 569 public static class Parser { 570 571 private ArrayList elements = new ArrayList(); 572 573 576 public Parser(File file) { 577 try { 578 load(new FileInputStream(file)); 579 } catch (Exception e) { 580 } 582 } 583 584 587 public Parser(URL url) { 588 try { 589 load(url.openStream()); 590 } catch (Exception e) { 591 } 593 } 594 595 601 public HashMap getElement(Selector selector) { 602 if (selector == null) 603 return null; 604 605 String element; 606 for (int i = 0; i < elements.size(); i++) { 607 element = (String ) elements.get(i); 609 if (selector.select(element)) { 610 HashMap attributes = new HashMap(); 612 String elementName; 613 int j; 614 for (j = 0; j < element.length(); j++) { 616 if (Character.isWhitespace(element.charAt(j))) 617 break; 618 } 619 if (j >= element.length()) { 620 elementName = element; 621 } else { 622 elementName = element.substring(0, j); 623 element = element.substring(j); 624 StringTokenizer t = new StringTokenizer(element, "=\""); boolean isKey = true; 627 String key = ""; while (t.hasMoreTokens()) { 629 String token = t.nextToken().trim(); 630 if (!token.equals("")) { if (isKey) { 633 key = token; 634 isKey = false; 635 } else { 636 attributes.put(key, token); 637 isKey = true; 638 } 639 } 640 } 641 } 642 if (selector.select(elementName, attributes)) { 644 attributes.put("<element>", elementName); return attributes; 646 } 647 } 648 } 649 return null; 650 } 651 652 private void load(InputStream is) { 653 if (is == null) 654 return; 655 656 StringBuffer xml = new StringBuffer (4096); 658 char[] iobuf = new char[4096]; 659 InputStreamReader r = null; 660 try { 661 r = new InputStreamReader(is); 662 int len = r.read(iobuf, 0, iobuf.length); 663 while (len != -1) { 664 xml.append(iobuf, 0, len); 665 len = r.read(iobuf, 0, iobuf.length); 666 } 667 } catch (Exception e) { 668 return; 669 } finally { 670 if (r != null) 671 try { 672 r.close(); 673 } catch (IOException e) { 674 } 676 } 677 678 String xmlString = xml.toString(); 680 StringTokenizer t = new StringTokenizer(xmlString, "<>"); while (t.hasMoreTokens()) { 682 String token = t.nextToken().trim(); 683 if (!token.equals("")) elements.add(token); 685 } 686 } 687 } 688 689 public static class BootDescriptor { 690 private String id; 691 private String version; 692 private String [] libs; 693 private URL dir; 694 695 public BootDescriptor(String id, String version, String [] libs, URL dir) { 696 this.id = id; 697 this.version = version; 698 this.libs = libs; 699 this.dir = dir; 700 } 701 702 public String getId() { 703 return id; 704 } 705 706 public String getVersion() { 707 return version; 708 } 709 710 public String [] getLibraries() { 711 return libs; 712 } 713 714 public URL getPluginDirectoryURL() { 715 return dir; 716 } 717 } 718 719 720 PlatformConfiguration(URL url) throws IOException { 721 this.sites = new HashMap(); 722 this.externalLinkSites = new HashMap(); 723 this.cfgdFeatures = new HashMap(); 724 this.bootPlugins = new HashMap(); 725 initialize(url); 726 } 727 728 731 public ISiteEntry createSiteEntry(URL url, ISitePolicy policy) { 732 return new PlatformConfiguration.SiteEntry(url, policy, this); 733 } 734 735 738 public ISitePolicy createSitePolicy(int type, String [] list) { 739 return new PlatformConfiguration.SitePolicy(type, list); 740 } 741 742 745 public IFeatureEntry createFeatureEntry(String id, String version, String pluginVersion, boolean primary, String application, URL[] root) { 746 return new PlatformConfiguration.FeatureEntry(id, version, pluginVersion, primary, application, root); 747 } 748 749 753 public IFeatureEntry createFeatureEntry(String id, String version, String pluginIdentifier, String pluginVersion, boolean primary, String application, URL[] root) { 754 return new PlatformConfiguration.FeatureEntry(id, version, pluginIdentifier, pluginVersion, primary, application, root); 755 } 756 757 760 public void configureSite(ISiteEntry entry) { 761 configureSite(entry, false); 762 } 763 764 767 public synchronized void configureSite(ISiteEntry entry, boolean replace) { 768 769 if (entry == null) 770 return; 771 772 URL url = entry.getURL(); 773 if (url == null) 774 return; 775 String key = url.toExternalForm(); 776 777 if (sites.containsKey(key) && !replace) 778 return; 779 780 sites.put(key, entry); 781 } 782 783 786 public synchronized void unconfigureSite(ISiteEntry entry) { 787 if (entry == null) 788 return; 789 790 URL url = entry.getURL(); 791 if (url == null) 792 return; 793 String key = url.toExternalForm(); 794 795 sites.remove(key); 796 } 797 798 801 public ISiteEntry[] getConfiguredSites() { 802 if (sites.size() == 0) 803 return new ISiteEntry[0]; 804 805 return (ISiteEntry[]) sites.values().toArray(new ISiteEntry[0]); 806 } 807 808 811 public ISiteEntry findConfiguredSite(URL url) { 812 if (url == null) 813 return null; 814 String key = url.toExternalForm(); 815 816 ISiteEntry result = (ISiteEntry) sites.get(key); 817 try { 818 if (result == null) result = (ISiteEntry) sites.get(URLDecoder.decode(key, null)); 820 } catch (UnsupportedEncodingException e) { 821 } 822 return result; 823 } 824 825 828 public synchronized void configureFeatureEntry(IFeatureEntry entry) { 829 if (entry == null) 830 return; 831 832 String key = entry.getFeatureIdentifier(); 833 if (key == null) 834 return; 835 836 cfgdFeatures.put(key, entry); 837 } 838 839 842 public synchronized void unconfigureFeatureEntry(IFeatureEntry entry) { 843 if (entry == null) 844 return; 845 846 String key = entry.getFeatureIdentifier(); 847 if (key == null) 848 return; 849 850 cfgdFeatures.remove(key); 851 } 852 853 856 public IFeatureEntry[] getConfiguredFeatureEntries() { 857 if (cfgdFeatures.size() == 0) 858 return new IFeatureEntry[0]; 859 860 return (IFeatureEntry[]) cfgdFeatures.values().toArray(new IFeatureEntry[0]); 861 } 862 863 866 public IFeatureEntry findConfiguredFeatureEntry(String id) { 867 if (id == null) 868 return null; 869 870 return (IFeatureEntry) cfgdFeatures.get(id); 871 } 872 873 876 public URL getConfigurationLocation() { 877 return configLocation; 878 } 879 880 883 public long getChangeStamp() { 884 if (!changeStampIsValid) 885 computeChangeStamp(); 886 return changeStamp; 887 } 888 889 892 public long getFeaturesChangeStamp() { 893 if (!featuresChangeStampIsValid) 894 computeFeaturesChangeStamp(); 895 return featuresChangeStamp; 896 } 897 898 901 public long getPluginsChangeStamp() { 902 if (!pluginsChangeStampIsValid) 903 computePluginsChangeStamp(); 904 return pluginsChangeStamp; 905 } 906 907 910 public String getApplicationIdentifier() { 911 912 if (cmdInitialize) { 913 return RECONCILER_APP; 916 } 917 918 if (featuresChangeStamp != lastFeaturesChangeStamp) { 919 boolean update = !cmdNoUpdate || cmdUpdate; 921 if (update) 922 return RECONCILER_APP; 923 } 924 925 return getApplicationIdentifierInternal(); 927 } 928 929 private String getApplicationIdentifierInternal() { 930 931 if (cmdApplication != null) return cmdApplication; 933 String feature = cmdFeature; 935 if (feature == null) 936 feature = defaultFeature; 937 938 if (feature != null) { 940 IFeatureEntry fe = findConfiguredFeatureEntry(feature); 941 if (fe != null) { 942 if (fe.getFeatureApplication() != null) 943 return fe.getFeatureApplication(); 944 } 945 } 946 947 return DEFAULT_FEATURE_APPLICATION; 949 } 950 951 954 public String getPrimaryFeatureIdentifier() { 955 956 if (cmdFeature != null) return cmdFeature; 958 959 if (defaultFeature != null) 961 return defaultFeature; return DEFAULT_FEATURE_ID; } 964 965 968 public URL[] getPluginPath() { 969 ArrayList path = new ArrayList(); 970 if (DEBUG) 971 debug("computed plug-in path:"); 973 ISiteEntry[] sites = getConfiguredSites(); 974 URL pathURL; 975 for (int i = 0; i < sites.length; i++) { 976 String [] plugins = sites[i].getPlugins(); 977 for (int j = 0; j < plugins.length; j++) { 978 try { 979 pathURL = new URL(((SiteEntry) sites[i]).getResolvedURL(), plugins[j]); 980 path.add(pathURL); 981 if (DEBUG) 982 debug(" " + pathURL.toString()); } catch (MalformedURLException e) { 984 if (DEBUG) 986 debug(" bad URL: " + e); } 988 } 989 } 990 return (URL[]) path.toArray(new URL[0]); 991 } 992 993 996 public String [] getBootstrapPluginIdentifiers() { 997 return BOOTSTRAP_PLUGINS; 998 } 999 1000 1003 public void setBootstrapPluginLocation(String id, URL location) { 1004 String [] ids = getBootstrapPluginIdentifiers(); 1005 for (int i = 0; i < ids.length; i++) { 1006 if (ids[i].equals(id)) { 1007 bootPlugins.put(id, location.toExternalForm()); 1008 break; 1009 } 1010 } 1011 } 1012 1013 1016 public boolean isUpdateable() { 1017 return true; 1018 } 1019 1020 1023 public boolean isTransient() { 1024 return transientConfig; 1025 } 1026 1027 1030 public void isTransient(boolean value) { 1031 } 1034 1035 1038 public synchronized void refresh() { 1039 ISiteEntry[] sites = getConfiguredSites(); 1042 for (int i = 0; i < sites.length; i++) { 1043 ((SiteEntry) sites[i]).refresh(); 1045 } 1046 lastFeaturesChangeStamp = featuresChangeStamp; 1048 changeStampIsValid = false; 1049 featuresChangeStampIsValid = false; 1050 pluginsChangeStampIsValid = false; 1051 } 1052 1053 1056 public void save() throws IOException { 1057 if (isUpdateable()) 1058 save(configLocation); 1059 } 1060 1061 1064 public synchronized void save(URL url) throws IOException { 1065 if (url == null) 1066 throw new IOException("Unable to save. No URL is specified"); 1068 PrintWriter w = null; 1069 OutputStream os = null; 1070 if (!url.getProtocol().equals("file")) { URLConnection uc = url.openConnection(); 1073 uc.setDoOutput(true); 1074 os = uc.getOutputStream(); 1075 w = new PrintWriter(os); 1076 try { 1077 write(w); 1078 } finally { 1079 w.close(); 1080 } 1081 } else { 1082 File cfigFile = new File(url.getFile().replace('/', File.separatorChar)); 1084 File cfigDir = cfigFile.getParentFile(); 1085 if (cfigDir != null) 1086 cfigDir.mkdirs(); 1087 1088 File cfigTmp = new File(cfigFile.getAbsolutePath() + CONFIG_FILE_TEMP_SUFFIX); 1090 os = new FileOutputStream(cfigTmp); 1091 w = new PrintWriter(os); 1092 try { 1093 write(w); 1094 } finally { 1095 w.close(); 1096 } 1097 1098 InputStream is = new FileInputStream(cfigTmp); 1100 Properties tmpProps = new Properties(); 1101 try { 1102 tmpProps.load(is); 1103 if (!EOF.equals(tmpProps.getProperty(EOF))) { 1104 throw new IOException("Unable to save " + cfigTmp.getAbsolutePath()); } 1106 } finally { 1107 is.close(); 1108 } 1109 1110 File cfigBak = new File(cfigFile.getAbsolutePath() + CONFIG_FILE_BAK_SUFFIX); 1112 cfigBak.delete(); 1114 if (cfigFile.exists()) 1115 cfigFile.renameTo(cfigBak); 1116 1117 boolean ok = cfigTmp.renameTo(cfigFile); 1120 if (ok) { 1121 cfigBak.delete(); } else { 1125 throw new IOException("Unable to save " + cfigTmp.getAbsolutePath()); } 1132 } 1133 } 1134 1135 public BootDescriptor getPluginBootDescriptor(String id) { 1136 1141 if (RUNTIME_PLUGIN_ID.equals(id)) 1142 return runtimeDescriptor; 1143 return null; 1144 } 1145 1146 static PlatformConfiguration getCurrent() { 1147 return currentPlatformConfiguration; 1148 } 1149 1150 static synchronized void shutdown() throws IOException { 1151 1152 PlatformConfiguration config = getCurrent(); 1154 if (config != null) { 1155 try { 1156 config.save(); 1157 } catch (IOException e) { 1158 if (DEBUG) 1159 debug("Unable to save configuration " + e.toString()); } 1162 config.clearConfigurationLock(); 1163 } 1164 } 1165 1166 private synchronized void initialize(URL url) throws IOException { 1167 if (url == null) { 1168 if (DEBUG) 1169 debug("Creating empty configuration object"); return; 1171 } 1172 1173 load(url); 1174 configLocation = url; 1175 if (DEBUG) 1176 debug("Using configuration " + configLocation.toString()); } 1178 1179 private ISiteEntry getRootSite() { 1180 ISitePolicy defaultPolicy = createSitePolicy(DEFAULT_POLICY_TYPE, DEFAULT_POLICY_LIST); 1182 URL siteURL = null; 1183 try { 1184 siteURL = new URL(PlatformURLHandler.PROTOCOL + PlatformURLHandler.PROTOCOL_SEPARATOR + "/" + "base" + "/"); } catch (MalformedURLException e) { 1186 siteURL = getInstallURL(); } 1188 ISiteEntry defaultSite = createSiteEntry(siteURL, defaultPolicy); 1189 return defaultSite; 1190 } 1191 1192 1193 private void resetInitializationLocation(File dir) { 1194 if (dir == null || !dir.exists() || !dir.isDirectory()) 1196 return; 1197 File[] list = dir.listFiles(); 1198 for (int i = 0; i < list.length; i++) { 1199 if (list[i].isDirectory()) 1200 resetInitializationLocation(list[i]); 1201 list[i].delete(); 1202 } 1203 } 1204 1205 1206 private void clearConfigurationLock() { 1207 try { 1208 if (cfgLockFileRAF != null) { 1209 cfgLockFileRAF.close(); 1210 cfgLockFileRAF = null; 1211 } 1212 } catch (IOException e) { 1213 } 1215 if (cfgLockFile != null) { 1216 cfgLockFile.delete(); 1217 cfgLockFile = null; 1218 } 1219 } 1220 1221 private void computeChangeStamp() { 1222 computeFeaturesChangeStamp(); 1223 computePluginsChangeStamp(); 1224 changeStamp = featuresChangeStamp ^ pluginsChangeStamp; 1225 changeStampIsValid = true; 1226 } 1227 1228 private void computeFeaturesChangeStamp() { 1229 1239 } 1240 1241 private void computePluginsChangeStamp() { 1242 1252 } 1253 1254 private void load(URL url) throws IOException { 1255 1256 if (url == null) 1257 throw new IOException("Unable to load URL"); 1259 Properties props = null; 1261 IOException originalException = null; 1262 try { 1263 props = loadProperties(url, null); } catch (IOException e1) { 1265 originalException = e1; 1266 try { 1267 props = loadProperties(url, CONFIG_FILE_TEMP_SUFFIX); } catch (IOException e2) { 1269 try { 1270 props = loadProperties(url, CONFIG_FILE_BAK_SUFFIX); } catch (IOException e3) { 1272 throw originalException; } 1274 } 1275 } 1276 1277 String v = props.getProperty(CFG_VERSION); 1279 if (!VERSION.equals(v)) { 1280 resetUpdateManagerState(url); 1283 throw new IOException("Bad version:" + v); } 1285 1286 defaultFeature = loadAttribute(props, CFG_FEATURE_ENTRY_DEFAULT, null); 1288 1289 String flag = loadAttribute(props, CFG_TRANSIENT, null); 1290 if (flag != null) { 1291 if (flag.equals("true")) transientConfig = true; 1293 else 1294 transientConfig = false; 1295 } 1296 1297 String stamp = loadAttribute(props, CFG_FEATURE_STAMP, null); 1298 if (stamp != null) { 1299 try { 1300 lastFeaturesChangeStamp = Long.parseLong(stamp); 1301 } catch (NumberFormatException e) { 1302 } 1304 } 1305 1306 String [] ids = getBootstrapPluginIdentifiers(); 1308 for (int i = 0; i < ids.length; i++) { 1309 bootPlugins.put(ids[i], loadAttribute(props, CFG_BOOT_PLUGIN + "." + ids[i], null)); } 1311 1312 IFeatureEntry fe = loadFeatureEntry(props, CFG_FEATURE_ENTRY + ".0", null); for (int i = 1; fe != null; i++) { 1315 configureFeatureEntry(fe); 1316 fe = loadFeatureEntry(props, CFG_FEATURE_ENTRY + "." + i, null); } 1318 1319 SiteEntry root = (SiteEntry) getRootSite(); 1321 String rootUrlString = root.getURL().toExternalForm(); 1322 SiteEntry se = (SiteEntry) loadSite(props, CFG_SITE + ".0", null); for (int i = 1; se != null; i++) { 1324 1325 if (cmdFirstUse && rootUrlString.equals(se.getURL().toExternalForm())) 1331 se = root; 1332 1333 if (!se.isExternallyLinkedSite()) 1334 configureSite(se); 1335 else 1336 externalLinkSites.put(se.getURL(), se); 1338 se = (SiteEntry) loadSite(props, CFG_SITE + "." + i, null); } 1340 } 1341 1342 private Properties loadProperties(URL url, String suffix) throws IOException { 1343 1344 if (suffix != null && !suffix.equals("")) url = new URL(url.getProtocol(), url.getHost(), url.getPort(), url.getFile() + suffix); 1347 1348 Properties props = new Properties(); 1350 InputStream is = null; 1351 try { 1352 is = url.openStream(); 1353 props.load(is); 1354 if (!EOF.equals(props.getProperty(EOF))) { 1356 throw new IOException("Unable to load"); } 1358 } finally { 1359 if (is != null) { 1360 try { 1361 is.close(); 1362 } catch (IOException e) { 1363 } 1365 } 1366 } 1367 return props; 1368 } 1369 1370 private ISiteEntry loadSite(Properties props, String name, ISiteEntry dflt) { 1371 1372 String urlString = loadAttribute(props, name + "." + CFG_URL, null); if (urlString == null) 1374 return dflt; 1375 1376 URL url = null; 1377 try { 1378 url = new URL(urlString); 1379 } catch (MalformedURLException e) { 1380 return dflt; 1381 } 1382 1383 int policyType; 1384 String [] policyList; 1385 String typeString = loadAttribute(props, name + "." + CFG_POLICY, null); if (typeString == null) { 1387 policyType = DEFAULT_POLICY_TYPE; 1388 policyList = DEFAULT_POLICY_LIST; 1389 } else { 1390 int i; 1391 for (i = 0; i < CFG_POLICY_TYPE.length; i++) { 1392 if (typeString.equals(CFG_POLICY_TYPE[i])) { 1393 break; 1394 } 1395 } 1396 if (i >= CFG_POLICY_TYPE.length) { 1397 policyType = DEFAULT_POLICY_TYPE; 1398 policyList = DEFAULT_POLICY_LIST; 1399 } else { 1400 policyType = i; 1401 policyList = loadListAttribute(props, name + "." + CFG_LIST, new String [0]); } 1403 } 1404 1405 ISitePolicy sp = createSitePolicy(policyType, policyList); 1406 SiteEntry site = (SiteEntry) createSiteEntry(url, sp); 1407 1408 String stamp = loadAttribute(props, name + "." + CFG_FEATURE_STAMP, null); if (stamp != null) { 1410 try { 1411 site.lastFeaturesChangeStamp = Long.parseLong(stamp); 1412 } catch (NumberFormatException e) { 1413 } 1415 } 1416 1417 stamp = loadAttribute(props, name + "." + CFG_PLUGIN_STAMP, null); if (stamp != null) { 1419 try { 1420 site.lastPluginsChangeStamp = Long.parseLong(stamp); 1421 } catch (NumberFormatException e) { 1422 } 1424 } 1425 1426 String flag = loadAttribute(props, name + "." + CFG_UPDATEABLE, null); if (flag != null) { 1428 if (flag.equals("true")) site.updateable = true; 1430 else 1431 site.updateable = false; 1432 } 1433 1434 String linkname = loadAttribute(props, name + "." + CFG_LINK_FILE, null); if (linkname != null && !linkname.equals("")) { site.linkFileName = linkname.replace('/', File.separatorChar); 1437 } 1438 1439 return site; 1440 } 1441 1442 private IFeatureEntry loadFeatureEntry(Properties props, String name, IFeatureEntry dflt) { 1443 String id = loadAttribute(props, name + "." + CFG_FEATURE_ENTRY_ID, null); if (id == null) 1445 return dflt; 1446 String version = loadAttribute(props, name + "." + CFG_FEATURE_ENTRY_VERSION, null); String pluginVersion = loadAttribute(props, name + "." + CFG_FEATURE_ENTRY_PLUGIN_VERSION, null); if (pluginVersion == null) 1449 pluginVersion = version; 1450 String pluginIdentifier = loadAttribute(props, name + "." + CFG_FEATURE_ENTRY_PLUGIN_IDENTIFIER, null); if (pluginIdentifier == null) 1452 pluginIdentifier = id; 1453 String application = loadAttribute(props, name + "." + CFG_FEATURE_ENTRY_APPLICATION, null); ArrayList rootList = new ArrayList(); 1455 1456 String rootString = loadAttribute(props, name + "." + CFG_FEATURE_ENTRY_ROOT + ".0", null); for (int i = 1; rootString != null; i++) { 1459 try { 1460 URL rootEntry = new URL(rootString); 1461 rootList.add(rootEntry); 1462 } catch (MalformedURLException e) { 1463 } 1465 rootString = loadAttribute(props, name + "." + CFG_FEATURE_ENTRY_ROOT + "." + i, null); } 1467 URL[] roots = (URL[]) rootList.toArray(new URL[0]); 1468 1469 boolean primary = false; 1471 String flag = loadAttribute(props, name + "." + CFG_FEATURE_ENTRY_PRIMARY, null); if (flag != null) { 1473 if (flag.equals("true")) primary = true; 1475 } 1476 return createFeatureEntry(id, version, pluginIdentifier, pluginVersion, primary, application, roots); 1477 } 1478 1479 private String [] loadListAttribute(Properties props, String name, String [] dflt) { 1480 ArrayList list = new ArrayList(); 1481 String value = loadAttribute(props, name + ".0", null); if (value == null) 1483 return dflt; 1484 1485 for (int i = 1; value != null; i++) { 1486 loadListAttributeSegment(list, value); 1487 value = loadAttribute(props, name + "." + i, null); } 1489 return (String []) list.toArray(new String [0]); 1490 } 1491 1492 private void loadListAttributeSegment(ArrayList list, String value) { 1493 1494 if (value == null) 1495 return; 1496 1497 StringTokenizer tokens = new StringTokenizer(value, ","); String token; 1499 while (tokens.hasMoreTokens()) { 1500 token = tokens.nextToken().trim(); 1501 if (!token.equals("")) list.add(token); 1503 } 1504 return; 1505 } 1506 1507 private String loadAttribute(Properties props, String name, String dflt) { 1508 String prop = props.getProperty(name); 1509 if (prop == null) 1510 return dflt; 1511 return prop.trim(); 1512 } 1513 1514 1515 private void write(PrintWriter w) { 1516 w.println("# " + (new Date()).toString()); writeAttribute(w, CFG_VERSION, VERSION); 1519 if (transientConfig) 1520 writeAttribute(w, CFG_TRANSIENT, "true"); w.println(""); 1523 writeAttribute(w, CFG_STAMP, Long.toString(getChangeStamp())); 1525 writeAttribute(w, CFG_FEATURE_STAMP, Long.toString(getFeaturesChangeStamp())); 1526 writeAttribute(w, CFG_PLUGIN_STAMP, Long.toString(getPluginsChangeStamp())); 1527 1528 String [] ids = getBootstrapPluginIdentifiers(); 1530 for (int i = 0; i < ids.length; i++) { 1531 String location = (String ) bootPlugins.get(ids[i]); 1532 if (location != null) 1533 writeAttribute(w, CFG_BOOT_PLUGIN + "." + ids[i], location); } 1535 1536 w.println(""); writeAttribute(w, CFG_FEATURE_ENTRY_DEFAULT, defaultFeature); 1539 IFeatureEntry[] feats = getConfiguredFeatureEntries(); 1540 for (int i = 0; i < feats.length; i++) { 1541 writeFeatureEntry(w, CFG_FEATURE_ENTRY + "." + Integer.toString(i), feats[i]); } 1543 1544 SiteEntry[] list = (SiteEntry[]) sites.values().toArray(new SiteEntry[0]); 1546 for (int i = 0; i < list.length; i++) { 1547 writeSite(w, CFG_SITE + "." + Integer.toString(i), list[i]); } 1549 1550 writeAttribute(w, EOF, EOF); 1552 } 1553 1554 private void writeSite(PrintWriter w, String id, SiteEntry entry) { 1555 1556 w.println(""); 1559 writeAttribute(w, id + "." + CFG_URL, entry.getURL().toString()); writeAttribute(w, id + "." + CFG_STAMP, Long.toString(entry.getChangeStamp())); writeAttribute(w, id + "." + CFG_FEATURE_STAMP, Long.toString(entry.getFeaturesChangeStamp())); writeAttribute(w, id + "." + CFG_PLUGIN_STAMP, Long.toString(entry.getPluginsChangeStamp())); writeAttribute(w, id + "." + CFG_UPDATEABLE, entry.updateable ? "true" : "false"); if (entry.linkFileName != null && !entry.linkFileName.trim().equals("")) writeAttribute(w, id + "." + CFG_LINK_FILE, entry.linkFileName.trim().replace(File.separatorChar, '/')); 1568 int type = entry.getSitePolicy().getType(); 1570 String typeString = CFG_POLICY_TYPE_UNKNOWN; 1571 try { 1572 typeString = CFG_POLICY_TYPE[type]; 1573 } catch (IndexOutOfBoundsException e) { 1574 } 1576 writeAttribute(w, id + "." + CFG_POLICY, typeString); writeListAttribute(w, id + "." + CFG_LIST, entry.getSitePolicy().getList()); } 1579 1580 private void writeFeatureEntry(PrintWriter w, String id, IFeatureEntry entry) { 1581 1582 w.println(""); 1585 writeAttribute(w, id + "." + CFG_FEATURE_ENTRY_ID, entry.getFeatureIdentifier()); if (entry.canBePrimary()) 1588 writeAttribute(w, id + "." + CFG_FEATURE_ENTRY_PRIMARY, "true"); writeAttribute(w, id + "." + CFG_FEATURE_ENTRY_VERSION, entry.getFeatureVersion()); if (entry.getFeatureVersion() != null && !entry.getFeatureVersion().equals(entry.getFeaturePluginVersion())) 1591 writeAttribute(w, id + "." + CFG_FEATURE_ENTRY_PLUGIN_VERSION, entry.getFeaturePluginVersion()); if (entry.getFeatureIdentifier() != null && !entry.getFeatureIdentifier().equals(entry.getFeaturePluginIdentifier())) 1593 writeAttribute(w, id + "." + CFG_FEATURE_ENTRY_PLUGIN_IDENTIFIER, entry.getFeaturePluginIdentifier()); writeAttribute(w, id + "." + CFG_FEATURE_ENTRY_APPLICATION, entry.getFeatureApplication()); URL[] roots = entry.getFeatureRootURLs(); 1596 for (int i = 0; i < roots.length; i++) { 1597 writeAttribute(w, id + "." + CFG_FEATURE_ENTRY_ROOT + "." + i, roots[i].toExternalForm()); } 1600 } 1601 1602 private void writeListAttribute(PrintWriter w, String id, String [] list) { 1603 if (list == null || list.length == 0) 1604 return; 1605 1606 String value = ""; int listLen = 0; 1608 int listIndex = 0; 1609 for (int i = 0; i < list.length; i++) { 1610 if (listLen != 0) 1611 value += ","; else 1613 value = ""; value += list[i]; 1615 1616 if (++listLen >= CFG_LIST_LENGTH) { 1617 writeAttribute(w, id + "." + Integer.toString(listIndex++), value); listLen = 0; 1619 } 1620 } 1621 if (listLen != 0) 1622 writeAttribute(w, id + "." + Integer.toString(listIndex), value); } 1624 1625 private void writeAttribute(PrintWriter w, String id, String value) { 1626 if (value == null || value.trim().equals("")) return; 1628 w.println(id + "=" + escapedValue(value)); } 1630 1631 private String escapedValue(String value) { 1632 StringBuffer buf = new StringBuffer (value.length() * 2); for (int i = 0; i < value.length(); i++) { 1635 char character = value.charAt(i); 1636 if (character == '\\' || character == '\t' || character == '\r' || character == '\n' || character == '\f') { 1637 buf.append('\\'); 1639 buf.append(character); 1640 } else if ((character < 0x0020) || (character > 0x007e)) { 1641 buf.append('\\'); 1643 buf.append('u'); 1644 buf.append(HEX[(character >> 12) & 0xF]); buf.append(HEX[(character >> 8) & 0xF]); buf.append(HEX[(character >> 4) & 0xF]); buf.append(HEX[character & 0xF]); } else { 1649 buf.append(character); 1651 } 1652 } 1653 return buf.toString(); 1654 } 1655 1656 1657 1658 1659 private static boolean supportsDetection(URL url) { 1660 String protocol = url.getProtocol(); 1661 if (protocol.equals("file")) return true; 1663 else if (protocol.equals(PlatformURLHandler.PROTOCOL)) { 1664 URL resolved = null; 1665 try { 1666 resolved = resolvePlatformURL(url); } catch (IOException e) { 1668 return false; } 1670 return resolved.getProtocol().equals("file"); } else 1672 return false; 1673 } 1674 1675 private static URL resolvePlatformURL(URL url) throws IOException { 1676 if (url.getProtocol().equals(PlatformURLHandler.PROTOCOL)) { 1678 URLConnection connection = url.openConnection(); 1679 if (connection instanceof PlatformURLConnection) { 1680 url = ((PlatformURLConnection) connection).getResolvedURL(); 1681 } else { 1682 url = getInstallURL(); 1685 } 1686 } 1687 return url; 1688 } 1689 1690 private static void debug(String s) { 1691 System.out.println("PlatformConfig: " + s); } 1693 1694 private void resetUpdateManagerState(URL url) throws IOException { 1695 if (!supportsDetection(url)) 1697 return; 1699 URL resolved = resolvePlatformURL(url); 1701 File initCfg = new File(resolved.getFile().replace('/', File.separatorChar)); 1702 File initDir = initCfg.getParentFile(); 1703 1704 if (initDir == null || !initDir.exists() || !initDir.isDirectory()) 1706 return; 1707 String temp = initCfg.getName() + ".metadata"; File UMDir = new File(initDir, temp + '/'); 1709 1710 if (UMDir == null || !UMDir.exists() || !UMDir.isDirectory()) 1712 return; 1713 Date now = new Date(); 1714 boolean renamed = UMDir.renameTo(new File(initDir, temp + now.getTime() + '/')); 1715 1716 if (!renamed) 1717 resetInitializationLocation(UMDir); 1718 } 1719 1720 private static URL getInstallURL() { 1721 return installURL; 1722 } 1723 1724 1725} 1726 | Popular Tags |