KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > org > eclipse > pde > internal > core > PlatformConfiguration


1 /*******************************************************************************
2  * Copyright (c) 2000, 2004 IBM Corporation and others.
3  * All rights reserved. This program and the accompanying materials
4  * are made available under the terms of the Eclipse Public License v1.0
5  * which accompanies this distribution, and is available at
6  * http://www.eclipse.org/legal/epl-v10.html
7  *
8  * Contributors:
9  * IBM Corporation - initial API and implementation
10  *******************************************************************************/

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; // used to restore prior link site state
27
private HashMap cfgdFeatures;
28     private HashMap bootPlugins;
29     private String JavaDoc 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 JavaDoc cmdFeature = null;
43     private static String JavaDoc 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 JavaDoc RUNTIME_PLUGIN_ID = "org.eclipse.core.runtime"; //$NON-NLS-1$
52

53     private static final String JavaDoc PLUGINS = "plugins"; //$NON-NLS-1$
54
private static final String JavaDoc FEATURES = "features"; //$NON-NLS-1$
55
private static final String JavaDoc CONFIG_FILE_TEMP_SUFFIX = ".tmp"; //$NON-NLS-1$
56
private static final String JavaDoc CONFIG_FILE_BAK_SUFFIX = ".bak"; //$NON-NLS-1$
57
private static final String JavaDoc PLUGIN_XML = "plugin.xml"; //$NON-NLS-1$
58
private static final String JavaDoc FRAGMENT_XML = "fragment.xml"; //$NON-NLS-1$
59
private static final String JavaDoc FEATURE_XML = "feature.xml"; //$NON-NLS-1$
60

61     private static final String JavaDoc[] BOOTSTRAP_PLUGINS = { "org.eclipse.core.boot" }; //$NON-NLS-1$
62
private static final String JavaDoc CFG_BOOT_PLUGIN = "bootstrap"; //$NON-NLS-1$
63
private static final String JavaDoc CFG_SITE = "site"; //$NON-NLS-1$
64
private static final String JavaDoc CFG_URL = "url"; //$NON-NLS-1$
65
private static final String JavaDoc CFG_POLICY = "policy"; //$NON-NLS-1$
66
private static final String JavaDoc[] CFG_POLICY_TYPE = { "USER-INCLUDE", "USER-EXCLUDE" }; //$NON-NLS-1$ //$NON-NLS-2$
67
private static final String JavaDoc CFG_POLICY_TYPE_UNKNOWN = "UNKNOWN"; //$NON-NLS-1$
68
private static final String JavaDoc CFG_LIST = "list"; //$NON-NLS-1$
69
private static final String JavaDoc CFG_STAMP = "stamp"; //$NON-NLS-1$
70
private static final String JavaDoc CFG_FEATURE_STAMP = "stamp.features"; //$NON-NLS-1$
71
private static final String JavaDoc CFG_PLUGIN_STAMP = "stamp.plugins"; //$NON-NLS-1$
72
private static final String JavaDoc CFG_UPDATEABLE = "updateable"; //$NON-NLS-1$
73
private static final String JavaDoc CFG_LINK_FILE = "linkfile"; //$NON-NLS-1$
74
private static final String JavaDoc CFG_FEATURE_ENTRY = "feature"; //$NON-NLS-1$
75
private static final String JavaDoc CFG_FEATURE_ENTRY_DEFAULT = "feature.default.id"; //$NON-NLS-1$
76
private static final String JavaDoc CFG_FEATURE_ENTRY_ID = "id"; //$NON-NLS-1$
77
private static final String JavaDoc CFG_FEATURE_ENTRY_PRIMARY = "primary"; //$NON-NLS-1$
78
private static final String JavaDoc CFG_FEATURE_ENTRY_VERSION = "version"; //$NON-NLS-1$
79
private static final String JavaDoc CFG_FEATURE_ENTRY_PLUGIN_VERSION = "plugin-version"; //$NON-NLS-1$
80
private static final String JavaDoc CFG_FEATURE_ENTRY_PLUGIN_IDENTIFIER = "plugin-identifier"; //$NON-NLS-1$
81
private static final String JavaDoc CFG_FEATURE_ENTRY_APPLICATION = "application"; //$NON-NLS-1$
82
private static final String JavaDoc CFG_FEATURE_ENTRY_ROOT = "root"; //$NON-NLS-1$
83

84     private static final String JavaDoc DEFAULT_FEATURE_ID = "org.eclipse.platform"; //$NON-NLS-1$
85
private static final String JavaDoc DEFAULT_FEATURE_APPLICATION = "org.eclipse.ui.workbench"; //$NON-NLS-1$
86

87     private static final String JavaDoc CFG_VERSION = "version"; //$NON-NLS-1$
88
private static final String JavaDoc CFG_TRANSIENT = "transient"; //$NON-NLS-1$
89
private static final String JavaDoc VERSION = "2.1"; //$NON-NLS-1$
90
private static final String JavaDoc EOF = "eof"; //$NON-NLS-1$
91
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 JavaDoc[] DEFAULT_POLICY_LIST = new String JavaDoc[0];
95
96
97     protected static final String JavaDoc RECONCILER_APP = "org.eclipse.update.core.reconciler"; //$NON-NLS-1$
98

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; // this is the external URL for the site
106
private URL resolvedURL; // this is the resolved URL used internally
107
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 JavaDoc linkFileName = null;
121
122         private SiteEntry() {
123         }
124         private SiteEntry(URL url, ISitePolicy policy, PlatformConfiguration parent) {
125             if (url == null)
126                 throw new IllegalArgumentException JavaDoc();
127
128             if (policy == null)
129                 throw new IllegalArgumentException JavaDoc();
130
131             if (parent == null)
132                 throw new IllegalArgumentException JavaDoc();
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); // 19536
143
} catch (IOException e) {
144                     // will use the baseline URL ...
145
}
146             }
147         }
148
149         /*
150          * @see ISiteEntry#getURL()
151          */

152         public URL getURL() {
153             return url;
154         }
155
156         /*
157         * @see ISiteEntry#getSitePolicy()
158         */

159         public ISitePolicy getSitePolicy() {
160             return policy;
161         }
162
163         /*
164          * @see ISiteEntry#setSitePolicy(ISitePolicy)
165          */

166         public synchronized void setSitePolicy(ISitePolicy policy) {
167             if (policy == null)
168                 throw new IllegalArgumentException JavaDoc();
169             this.policy = policy;
170         }
171
172         /*
173          * @see ISiteEntry#getFeatures()
174          */

175         public String JavaDoc[] getFeatures() {
176             return getDetectedFeatures();
177         }
178
179         /*
180          * @see ISiteEntry#getPlugins()
181          */

182         public String JavaDoc[] 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 JavaDoc[] 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 JavaDoc[]) detectedPlugins.toArray(new String JavaDoc[0]);
197             }
198
199             // bad policy type
200
return new String JavaDoc[0];
201         }
202
203         /*
204          * @see ISiteEntry#getChangeStamp()
205          */

206         public long getChangeStamp() {
207             if (!changeStampIsValid)
208                 computeChangeStamp();
209             return changeStamp;
210         }
211
212         /*
213          * @see ISiteEntry#getFeaturesChangeStamp()
214          */

215         public long getFeaturesChangeStamp() {
216             if (!featuresChangeStampIsValid)
217                 computeFeaturesChangeStamp();
218             return featuresChangeStamp;
219         }
220
221         /*
222          * @see ISiteEntry#getPluginsChangeStamp()
223          */

224         public long getPluginsChangeStamp() {
225             if (!pluginsChangeStampIsValid)
226                 computePluginsChangeStamp();
227             return pluginsChangeStamp;
228         }
229
230         /*
231          * @see ISiteEntry#isUpdateable()
232          */

233         public boolean isUpdateable() {
234             return updateable;
235         }
236
237         /*
238          * @see ISiteEntry#isNativelyLinked()
239          */

240         public boolean isNativelyLinked() {
241             return isExternallyLinkedSite();
242         }
243
244         private String JavaDoc[] detectFeatures() {
245
246             // invalidate stamps ... we are doing discovery
247
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 JavaDoc[0];
256
257             // locate feature entries on site
258
File siteRoot = new File(resolvedURL.getFile().replace('/', File.separatorChar));
259             File root = new File(siteRoot, FEATURES);
260
261             String JavaDoc[] list = root.list();
262             String JavaDoc 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, '/')); //$NON-NLS-1$
271
}
272             if (DEBUG) {
273                 debug(resolvedURL.toString() + " located " + features.size() + " feature(s)"); //$NON-NLS-1$ //$NON-NLS-2$
274
}
275
276             return (String JavaDoc[]) features.toArray(new String JavaDoc[0]);
277         }
278
279         private String JavaDoc[] detectPlugins() {
280
281             // invalidate stamps ... we are doing discovery
282
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 JavaDoc[0];
291
292             // locate plugin entries on site
293
File root = new File(resolvedURL.getFile().replace('/', File.separatorChar) + PLUGINS);
294             String JavaDoc[] list = root.list();
295             String JavaDoc 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, '/')); //$NON-NLS-1$
307
}
308             if (DEBUG) {
309                 debug(resolvedURL.toString() + " located " + plugins.size() + " plugin(s)"); //$NON-NLS-1$ //$NON-NLS-2$
310
}
311
312             return (String JavaDoc[]) plugins.toArray(new String JavaDoc[0]);
313         }
314
315         private synchronized String JavaDoc[] getDetectedFeatures() {
316             if (features == null)
317                 return detectFeatures();
318             return (String JavaDoc[]) features.toArray(new String JavaDoc[0]);
319         }
320
321         private synchronized String JavaDoc[] getDetectedPlugins() {
322             if (plugins == null)
323                 return detectPlugins();
324             return (String JavaDoc[]) plugins.toArray(new String JavaDoc[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 JavaDoc[] 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"); //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$ //$NON-NLS-4$ //$NON-NLS-5$ //$NON-NLS-6$
351
}
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 JavaDoc[] 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"); //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$ //$NON-NLS-4$ //$NON-NLS-5$ //$NON-NLS-6$
367
}
368         }
369
370         private long computeStamp(String JavaDoc[] targets) {
371
372             long result = 0;
373             if (!supportsDetection(resolvedURL)) {
374                 // NOTE: this path should not be executed until we support running
375
// from an arbitrary URL (in particular from http server). For
376
// now just compute stamp across the list of names. Eventually
377
// when general URLs are supported we need to do better (factor
378
// in at least the existence of the target). However, given this
379
// code executes early on the startup sequence we need to be
380
// extremely mindful of performance issues.
381
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"); //$NON-NLS-1$
385
} else {
386                 // compute stamp across local targets
387
String JavaDoc 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("")); //$NON-NLS-1$
406
}
407
408         private synchronized void refresh() {
409             // reset computed values. Will be updated on next access.
410
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 JavaDoc[] list;
425
426         private SitePolicy() {
427         }
428         private SitePolicy(int type, String JavaDoc[] list) {
429             if (type != ISitePolicy.USER_INCLUDE && type != ISitePolicy.USER_EXCLUDE)
430                 throw new IllegalArgumentException JavaDoc();
431             this.type = type;
432
433             if (list == null)
434                 this.list = new String JavaDoc[0];
435             else
436                 this.list = list;
437         }
438
439         /*
440          * @see ISitePolicy#getType()
441          */

442         public int getType() {
443             return type;
444         }
445
446         /*
447         * @see ISitePolicy#getList()
448         */

449         public String JavaDoc[] getList() {
450             return list;
451         }
452
453         /*
454          * @see ISitePolicy#setList(String[])
455          */

456         public synchronized void setList(String JavaDoc[] list) {
457             if (list == null)
458                 this.list = new String JavaDoc[0];
459             else
460                 this.list = list;
461         }
462
463     }
464
465     public class FeatureEntry implements IPlatformConfiguration.IFeatureEntry {
466         private String JavaDoc id;
467         private String JavaDoc version;
468         private String JavaDoc pluginVersion;
469         private String JavaDoc application;
470         private URL[] root;
471         private boolean primary;
472         private String JavaDoc pluginIdentifier;
473
474         private FeatureEntry(String JavaDoc id, String JavaDoc version, String JavaDoc pluginIdentifier, String JavaDoc pluginVersion, boolean primary, String JavaDoc application, URL[] root) {
475             if (id == null)
476                 throw new IllegalArgumentException JavaDoc();
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 JavaDoc id, String JavaDoc version, String JavaDoc pluginVersion, boolean primary, String JavaDoc application, URL[] root) {
487             this(id, version, id, pluginVersion, primary, application, root);
488         }
489
490         /*
491          * @see IFeatureEntry#getFeatureIdentifier()
492          */

493         public String JavaDoc getFeatureIdentifier() {
494             return id;
495         }
496
497         /*
498          * @see IFeatureEntry#getFeatureVersion()
499          */

500         public String JavaDoc getFeatureVersion() {
501             return version;
502         }
503
504         /*
505          * @see IFeatureEntry#getFeaturePluginVersion()
506          */

507         public String JavaDoc getFeaturePluginVersion() {
508             return pluginVersion;
509         }
510
511         /*
512          * @see IFeatureEntry#getFeatureApplication()
513          */

514         public String JavaDoc getFeatureApplication() {
515             return application;
516         }
517
518         /*
519          * @see IFeatureEntry#getFeatureRootURLs()
520          */

521         public URL[] getFeatureRootURLs() {
522             return root;
523         }
524
525         /*
526          * @see IFeatureEntry#canBePrimary()
527          */

528         public boolean canBePrimary() {
529             return primary;
530         }
531         /*
532          * @see IFeatureEntry#getFeaturePluginIdentifier()
533          */

534         public String JavaDoc getFeaturePluginIdentifier() {
535             return pluginIdentifier;
536         }
537
538     }
539
540
541     /*
542      * Element selector for use with "tiny" parser. Parser callers supply
543      * concrete selectors
544      */

545     public interface Selector {
546
547         /*
548          * Method is called to pre-select a specific xml type. Pre-selected
549          * elements are then fully parsed and result in calls to full
550          * select method.
551          * @return <code>true</code> is the element should be considered,
552          * <code>false</code> otherwise
553          */

554         public boolean select(String JavaDoc entry);
555
556         /*
557          * Method is called with a fully parsed element.
558          * @return <code>true</code> to select this element and terminate the parse,
559          * <code>false</code> otherwise
560          */

561         public boolean select(String JavaDoc element, HashMap attributes);
562     }
563
564     /*
565      * "Tiny" xml parser. Performs a rudimentary parse of a well-formed xml file.
566      * Is specifically geared to parsing plugin.xml files of "bootstrap" plug-ins
567      * during the platform startup sequence before full xml plugin is available.
568      */

569     public static class Parser {
570
571         private ArrayList elements = new ArrayList();
572
573         /*
574          * Construct parser for the specified file
575          */

576         public Parser(File file) {
577             try {
578                 load(new FileInputStream(file));
579             } catch (Exception JavaDoc e) {
580                 // continue ... actual parsing will report errors
581
}
582         }
583
584         /*
585          * Construct parser for the specified URL
586          */

587         public Parser(URL url) {
588             try {
589                 load(url.openStream());
590             } catch (Exception JavaDoc e) {
591                 // continue ... actual parsing will report errors
592
}
593         }
594
595         /*
596          * Return selected elements as an (attribute-name, attribute-value) map.
597          * The name of the selected element is returned as the value of entry with
598          * name "<element>".
599          * @return attribute map for selected element, or <code>null</code>
600          */

601         public HashMap getElement(Selector selector) {
602             if (selector == null)
603                 return null;
604
605             String JavaDoc element;
606             for (int i = 0; i < elements.size(); i++) {
607                 // make pre-parse selector call
608
element = (String JavaDoc) elements.get(i);
609                 if (selector.select(element)) {
610                     // parse selected entry
611
HashMap attributes = new HashMap();
612                     String JavaDoc elementName;
613                     int j;
614                     // parse out element name
615
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                         // parse out attributes
625
StringTokenizer t = new StringTokenizer(element, "=\""); //$NON-NLS-1$
626
boolean isKey = true;
627                         String JavaDoc key = ""; //$NON-NLS-1$
628
while (t.hasMoreTokens()) {
629                             String JavaDoc token = t.nextToken().trim();
630                             if (!token.equals("")) { //$NON-NLS-1$
631
// collect (key, value) pairs
632
if (isKey) {
633                                     key = token;
634                                     isKey = false;
635                                 } else {
636                                     attributes.put(key, token);
637                                     isKey = true;
638                                 }
639                             }
640                         }
641                     }
642                     // make post-parse selector call
643
if (selector.select(elementName, attributes)) {
644                         attributes.put("<element>", elementName); //$NON-NLS-1$
645
return attributes;
646                     }
647                 }
648             }
649             return null;
650         }
651
652         private void load(InputStream is) {
653             if (is == null)
654                 return;
655
656             // read file
657
StringBuffer JavaDoc xml = new StringBuffer JavaDoc(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 JavaDoc e) {
668                 return;
669             } finally {
670                 if (r != null)
671                     try {
672                         r.close();
673                     } catch (IOException e) {
674                         // ignore
675
}
676             }
677
678             // parse out element tokens
679
String JavaDoc xmlString = xml.toString();
680             StringTokenizer t = new StringTokenizer(xmlString, "<>"); //$NON-NLS-1$
681
while (t.hasMoreTokens()) {
682                 String JavaDoc token = t.nextToken().trim();
683                 if (!token.equals("")) //$NON-NLS-1$
684
elements.add(token);
685             }
686         }
687     }
688
689     public static class BootDescriptor {
690         private String JavaDoc id;
691         private String JavaDoc version;
692         private String JavaDoc[] libs;
693         private URL dir;
694
695         public BootDescriptor(String JavaDoc id, String JavaDoc version, String JavaDoc[] libs, URL dir) {
696             this.id = id;
697             this.version = version;
698             this.libs = libs;
699             this.dir = dir;
700         }
701
702         public String JavaDoc getId() {
703             return id;
704         }
705
706         public String JavaDoc getVersion() {
707             return version;
708         }
709
710         public String JavaDoc[] 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     /*
729      * @see IPlatformConfiguration#createSiteEntry(URL, ISitePolicy)
730      */

731     public ISiteEntry createSiteEntry(URL url, ISitePolicy policy) {
732         return new PlatformConfiguration.SiteEntry(url, policy, this);
733     }
734
735     /*
736      * @see IPlatformConfiguration#createSitePolicy(int, String[])
737      */

738     public ISitePolicy createSitePolicy(int type, String JavaDoc[] list) {
739         return new PlatformConfiguration.SitePolicy(type, list);
740     }
741
742     /*
743      * @see IPlatformConfiguration#createFeatureEntry(String, String, String, boolean, String, URL)
744      */

745     public IFeatureEntry createFeatureEntry(String JavaDoc id, String JavaDoc version, String JavaDoc pluginVersion, boolean primary, String JavaDoc application, URL[] root) {
746         return new PlatformConfiguration.FeatureEntry(id, version, pluginVersion, primary, application, root);
747     }
748
749     /*
750      * @see IPlatformConfiguration#createFeatureEntry(String, String, String,
751      * String, boolean, String, URL)
752      */

753     public IFeatureEntry createFeatureEntry(String JavaDoc id, String JavaDoc version, String JavaDoc pluginIdentifier, String JavaDoc pluginVersion, boolean primary, String JavaDoc application, URL[] root) {
754         return new PlatformConfiguration.FeatureEntry(id, version, pluginIdentifier, pluginVersion, primary, application, root);
755     }
756
757     /*
758      * @see IPlatformConfiguration#configureSite(ISiteEntry)
759      */

760     public void configureSite(ISiteEntry entry) {
761         configureSite(entry, false);
762     }
763
764     /*
765      * @see IPlatformConfiguration#configureSite(ISiteEntry, boolean)
766      */

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 JavaDoc key = url.toExternalForm();
776
777         if (sites.containsKey(key) && !replace)
778             return;
779
780         sites.put(key, entry);
781     }
782
783     /*
784      * @see IPlatformConfiguration#unconfigureSite(ISiteEntry)
785      */

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 JavaDoc key = url.toExternalForm();
794
795         sites.remove(key);
796     }
797
798     /*
799      * @see IPlatformConfiguration#getConfiguredSites()
800      */

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     /*
809      * @see IPlatformConfiguration#findConfiguredSite(URL)
810      */

811     public ISiteEntry findConfiguredSite(URL url) {
812         if (url == null)
813             return null;
814         String JavaDoc key = url.toExternalForm();
815
816         ISiteEntry result = (ISiteEntry) sites.get(key);
817         try {
818             if (result == null) // retry with decoded URL string
819
result = (ISiteEntry) sites.get(URLDecoder.decode(key, null));
820         } catch (UnsupportedEncodingException e) {
821         }
822         return result;
823     }
824
825     /*
826      * @see IPlatformConfiguration#configureFeatureEntry(IFeatureEntry)
827      */

828     public synchronized void configureFeatureEntry(IFeatureEntry entry) {
829         if (entry == null)
830             return;
831
832         String JavaDoc key = entry.getFeatureIdentifier();
833         if (key == null)
834             return;
835
836         cfgdFeatures.put(key, entry);
837     }
838
839     /*
840      * @see IPlatformConfiguration#unconfigureFeatureEntry(IFeatureEntry)
841      */

842     public synchronized void unconfigureFeatureEntry(IFeatureEntry entry) {
843         if (entry == null)
844             return;
845
846         String JavaDoc key = entry.getFeatureIdentifier();
847         if (key == null)
848             return;
849
850         cfgdFeatures.remove(key);
851     }
852
853     /*
854      * @see IPlatformConfiguration#getConfiguredFeatureEntries()
855      */

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     /*
864      * @see IPlatformConfiguration#findConfiguredFeatureEntry(String)
865      */

866     public IFeatureEntry findConfiguredFeatureEntry(String JavaDoc id) {
867         if (id == null)
868             return null;
869
870         return (IFeatureEntry) cfgdFeatures.get(id);
871     }
872
873     /*
874      * @see IPlatformConfiguration#getConfigurationLocation()
875      */

876     public URL getConfigurationLocation() {
877         return configLocation;
878     }
879
880     /*
881      * @see IPlatformConfiguration#getChangeStamp()
882      */

883     public long getChangeStamp() {
884         if (!changeStampIsValid)
885             computeChangeStamp();
886         return changeStamp;
887     }
888
889     /*
890      * @see IPlatformConfiguration#getFeaturesChangeStamp()
891      */

892     public long getFeaturesChangeStamp() {
893         if (!featuresChangeStampIsValid)
894             computeFeaturesChangeStamp();
895         return featuresChangeStamp;
896     }
897
898     /*
899      * @see IPlatformConfiguration#getPluginsChangeStamp()
900      */

901     public long getPluginsChangeStamp() {
902         if (!pluginsChangeStampIsValid)
903             computePluginsChangeStamp();
904         return pluginsChangeStamp;
905     }
906
907     /*
908      * @see IPlatformConfiguration#getApplicationIdentifier()
909      */

910     public String JavaDoc getApplicationIdentifier() {
911
912         if (cmdInitialize) {
913             // we are running post-install initialization. Force
914
// running of the reconciler
915
return RECONCILER_APP;
916         }
917
918         if (featuresChangeStamp != lastFeaturesChangeStamp) {
919             // we have detected feature changes ... see if we need to reconcile
920
boolean update = !cmdNoUpdate || cmdUpdate;
921             if (update)
922                 return RECONCILER_APP;
923         }
924
925         // "normal" startup ... run specified application
926
return getApplicationIdentifierInternal();
927     }
928
929     private String JavaDoc getApplicationIdentifierInternal() {
930
931         if (cmdApplication != null) // application was specified
932
return cmdApplication;
933         // if -feature was not specified use the default feature
934
String JavaDoc feature = cmdFeature;
935         if (feature == null)
936             feature = defaultFeature;
937
938         // lookup application for feature (specified or defaulted)
939
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 hardcoded default if we failed
948
return DEFAULT_FEATURE_APPLICATION;
949     }
950
951     /*
952      * @see IPlatformConfiguration#getPrimaryFeatureIdentifier()
953      */

954     public String JavaDoc getPrimaryFeatureIdentifier() {
955
956         if (cmdFeature != null) // -feature was specified on command line
957
return cmdFeature;
958
959         // feature was not specified on command line
960
if (defaultFeature != null)
961             return defaultFeature; // return customized default if set
962
return DEFAULT_FEATURE_ID; // return hardcoded default
963
}
964
965     /*
966      * @see IPlatformConfiguration#getPluginPath()
967      */

968     public URL[] getPluginPath() {
969         ArrayList path = new ArrayList();
970         if (DEBUG)
971             debug("computed plug-in path:"); //$NON-NLS-1$
972

973         ISiteEntry[] sites = getConfiguredSites();
974         URL pathURL;
975         for (int i = 0; i < sites.length; i++) {
976             String JavaDoc[] 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()); //$NON-NLS-1$
983
} catch (MalformedURLException e) {
984                     // skip entry ...
985
if (DEBUG)
986                         debug(" bad URL: " + e); //$NON-NLS-1$
987
}
988             }
989         }
990         return (URL[]) path.toArray(new URL[0]);
991     }
992
993     /*
994      * @see IPlatformConfiguration#getBootstrapPluginIdentifiers()
995      */

996     public String JavaDoc[] getBootstrapPluginIdentifiers() {
997         return BOOTSTRAP_PLUGINS;
998     }
999
1000    /*
1001     * @see IPlatformConfiguration#setBootstrapPluginLocation(String, URL)
1002     */

1003    public void setBootstrapPluginLocation(String JavaDoc id, URL location) {
1004        String JavaDoc[] 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    /*
1014     * @see IPlatformConfiguration#isUpdateable()
1015     */

1016    public boolean isUpdateable() {
1017        return true;
1018    }
1019
1020    /*
1021     * @see IPlatformConfiguration#isTransient()
1022     */

1023    public boolean isTransient() {
1024        return transientConfig;
1025    }
1026
1027    /*
1028     * @see IPlatformConfiguration#isTransient(boolean)
1029     */

1030    public void isTransient(boolean value) {
1031        // if (this != BootLoader.getCurrentPlatformConfiguration())
1032
// transientConfig = value;
1033
}
1034
1035    /*
1036     * @see IPlatformConfiguration#refresh()
1037     */

1038    public synchronized void refresh() {
1039        // Reset computed values. Will be lazily refreshed
1040
// on next access
1041
ISiteEntry[] sites = getConfiguredSites();
1042        for (int i = 0; i < sites.length; i++) {
1043            // reset site entry
1044
((SiteEntry) sites[i]).refresh();
1045        }
1046        // reset configuration entry.
1047
lastFeaturesChangeStamp = featuresChangeStamp;
1048        changeStampIsValid = false;
1049        featuresChangeStampIsValid = false;
1050        pluginsChangeStampIsValid = false;
1051    }
1052
1053    /*
1054     * @see IPlatformConfiguration#save()
1055     */

1056    public void save() throws IOException {
1057        if (isUpdateable())
1058            save(configLocation);
1059    }
1060
1061    /*
1062     * @see IPlatformConfiguration#save(URL)
1063     */

1064    public synchronized void save(URL url) throws IOException {
1065        if (url == null)
1066            throw new IOException("Unable to save. No URL is specified"); //$NON-NLS-1$
1067

1068        PrintWriter w = null;
1069        OutputStream os = null;
1070        if (!url.getProtocol().equals("file")) { //$NON-NLS-1$
1071
// not a file protocol - attempt to save to the URL
1072
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 protocol - do safe i/o
1083
File cfigFile = new File(url.getFile().replace('/', File.separatorChar));
1084            File cfigDir = cfigFile.getParentFile();
1085            if (cfigDir != null)
1086                cfigDir.mkdirs();
1087
1088            // first save the file as temp
1089
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            // make sure we actually succeeded saving the whole configuration.
1099
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()); //$NON-NLS-1$
1105
}
1106            } finally {
1107                is.close();
1108            }
1109
1110            // make the saved config the "active" one
1111
File cfigBak = new File(cfigFile.getAbsolutePath() + CONFIG_FILE_BAK_SUFFIX);
1112            cfigBak.delete(); // may have old .bak due to prior failure
1113

1114            if (cfigFile.exists())
1115                cfigFile.renameTo(cfigBak);
1116
1117            // at this point we have old config (if existed) as "bak" and the
1118
// new config as "tmp".
1119
boolean ok = cfigTmp.renameTo(cfigFile);
1120            if (ok) {
1121                // at this point we have the new config "activated", and the old
1122
// config (if it existed) as "bak"
1123
cfigBak.delete(); // clean up
1124
} else {
1125                // this codepath represents a tiny failure window. The load processing
1126
// on startup will detect missing config and will attempt to start
1127
// with "tmp" (latest), then "bak" (the previous). We can also end up
1128
// here if we failed to rename the current config to "bak". In that
1129
// case we will restart with the previous state.
1130
throw new IOException("Unable to save " + cfigTmp.getAbsolutePath()); //$NON-NLS-1$
1131
}
1132        }
1133    }
1134
1135    public BootDescriptor getPluginBootDescriptor(String JavaDoc id) {
1136        // return the plugin descriptor for the specified plugin. This method
1137
// is used during boot processing to obtain information about "kernel" plugins
1138
// whose class loaders must be created prior to the plugin registry being
1139
// available (ie. loaders needed to create the plugin registry).
1140

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        // save platform configuration
1153
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()); //$NON-NLS-1$
1160
// will recover on next startup
1161
}
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"); //$NON-NLS-1$
1170
return;
1171        }
1172
1173        load(url);
1174        configLocation = url;
1175        if (DEBUG)
1176            debug("Using configuration " + configLocation.toString()); //$NON-NLS-1$
1177
}
1178
1179    private ISiteEntry getRootSite() {
1180        // create default site entry for the root
1181
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" + "/"); //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$ // try using platform-relative URL
1185
} catch (MalformedURLException e) {
1186            siteURL = getInstallURL(); // ensure we come up ... use absolute file URL
1187
}
1188        ISiteEntry defaultSite = createSiteEntry(siteURL, defaultPolicy);
1189        return defaultSite;
1190    }
1191
1192
1193    private void resetInitializationLocation(File dir) {
1194        // [20111]
1195
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            // ignore ...
1214
}
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        /*if (featuresChangeStampIsValid)
1230            return;
1231
1232        long result = 0;
1233        ISiteEntry[] sites = getConfiguredSites();
1234        for (int i = 0; i < sites.length; i++) {
1235            result ^= sites[i].getFeaturesChangeStamp();
1236        }
1237        featuresChangeStamp = result;
1238        featuresChangeStampIsValid = true;*/

1239    }
1240
1241    private void computePluginsChangeStamp() {
1242        /*if (pluginsChangeStampIsValid)
1243            return;
1244
1245        long result = 0;
1246        ISiteEntry[] sites = getConfiguredSites();
1247        for (int i = 0; i < sites.length; i++) {
1248            result ^= sites[i].getPluginsChangeStamp();
1249        }
1250        pluginsChangeStamp = result;
1251        pluginsChangeStampIsValid = true;*/

1252    }
1253    
1254    private void load(URL url) throws IOException {
1255
1256        if (url == null)
1257            throw new IOException("Unable to load URL"); //$NON-NLS-1$
1258

1259        // try to load saved configuration file (watch for failed prior save())
1260
Properties props = null;
1261        IOException originalException = null;
1262        try {
1263            props = loadProperties(url, null); // try to load config file
1264
} catch (IOException e1) {
1265            originalException = e1;
1266            try {
1267                props = loadProperties(url, CONFIG_FILE_TEMP_SUFFIX); // check for failures on save
1268
} catch (IOException e2) {
1269                try {
1270                    props = loadProperties(url, CONFIG_FILE_BAK_SUFFIX); // check for failures on save
1271
} catch (IOException e3) {
1272                    throw originalException; // we tried, but no config here ...
1273
}
1274            }
1275        }
1276
1277        // check version
1278
String JavaDoc v = props.getProperty(CFG_VERSION);
1279        if (!VERSION.equals(v)) {
1280            // the state is invalid, delete any files under the directory
1281
// bug 33493
1282
resetUpdateManagerState(url);
1283            throw new IOException("Bad version:" + v); //$NON-NLS-1$
1284
}
1285
1286        // load simple properties
1287
defaultFeature = loadAttribute(props, CFG_FEATURE_ENTRY_DEFAULT, null);
1288
1289        String JavaDoc flag = loadAttribute(props, CFG_TRANSIENT, null);
1290        if (flag != null) {
1291            if (flag.equals("true")) //$NON-NLS-1$
1292
transientConfig = true;
1293            else
1294                transientConfig = false;
1295        }
1296
1297        String JavaDoc stamp = loadAttribute(props, CFG_FEATURE_STAMP, null);
1298        if (stamp != null) {
1299            try {
1300                lastFeaturesChangeStamp = Long.parseLong(stamp);
1301            } catch (NumberFormatException JavaDoc e) {
1302                // ignore bad attribute ...
1303
}
1304        }
1305
1306        // load bootstrap entries
1307
String JavaDoc[] ids = getBootstrapPluginIdentifiers();
1308        for (int i = 0; i < ids.length; i++) {
1309            bootPlugins.put(ids[i], loadAttribute(props, CFG_BOOT_PLUGIN + "." + ids[i], null)); //$NON-NLS-1$
1310
}
1311
1312        // load feature entries
1313
IFeatureEntry fe = loadFeatureEntry(props, CFG_FEATURE_ENTRY + ".0", null); //$NON-NLS-1$
1314
for (int i = 1; fe != null; i++) {
1315            configureFeatureEntry(fe);
1316            fe = loadFeatureEntry(props, CFG_FEATURE_ENTRY + "." + i, null); //$NON-NLS-1$
1317
}
1318
1319        // load site properties
1320
SiteEntry root = (SiteEntry) getRootSite();
1321        String JavaDoc rootUrlString = root.getURL().toExternalForm();
1322        SiteEntry se = (SiteEntry) loadSite(props, CFG_SITE + ".0", null); //$NON-NLS-1$
1323
for (int i = 1; se != null; i++) {
1324
1325            // check if we are forcing "first use" processing with an existing
1326
// platform.cfg. In this case ignore site entry that represents
1327
// the platform install, and use a root site entry in its place.
1328
// This ensures we do not get messed up by an exclusion list that
1329
// is read from the prior state.
1330
if (cmdFirstUse && rootUrlString.equals(se.getURL().toExternalForm()))
1331                se = root;
1332
1333            if (!se.isExternallyLinkedSite())
1334                configureSite(se);
1335            else
1336                // remember external link site state, but do not configure at this point
1337
externalLinkSites.put(se.getURL(), se);
1338            se = (SiteEntry) loadSite(props, CFG_SITE + "." + i, null); //$NON-NLS-1$
1339
}
1340    }
1341
1342    private Properties loadProperties(URL url, String JavaDoc suffix) throws IOException {
1343
1344        // figure out what we will be loading
1345
if (suffix != null && !suffix.equals("")) //$NON-NLS-1$
1346
url = new URL(url.getProtocol(), url.getHost(), url.getPort(), url.getFile() + suffix);
1347
1348        // try to load saved configuration file
1349
Properties props = new Properties();
1350        InputStream is = null;
1351        try {
1352            is = url.openStream();
1353            props.load(is);
1354            // check to see if we have complete config file
1355
if (!EOF.equals(props.getProperty(EOF))) {
1356                throw new IOException("Unable to load"); //$NON-NLS-1$
1357
}
1358        } finally {
1359            if (is != null) {
1360                try {
1361                    is.close();
1362                } catch (IOException e) {
1363                    // ignore ...
1364
}
1365            }
1366        }
1367        return props;
1368    }
1369
1370    private ISiteEntry loadSite(Properties props, String JavaDoc name, ISiteEntry dflt) {
1371
1372        String JavaDoc urlString = loadAttribute(props, name + "." + CFG_URL, null); //$NON-NLS-1$
1373
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 JavaDoc[] policyList;
1385        String JavaDoc typeString = loadAttribute(props, name + "." + CFG_POLICY, null); //$NON-NLS-1$
1386
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 JavaDoc[0]); //$NON-NLS-1$
1402
}
1403        }
1404
1405        ISitePolicy sp = createSitePolicy(policyType, policyList);
1406        SiteEntry site = (SiteEntry) createSiteEntry(url, sp);
1407
1408        String JavaDoc stamp = loadAttribute(props, name + "." + CFG_FEATURE_STAMP, null); //$NON-NLS-1$
1409
if (stamp != null) {
1410            try {
1411                site.lastFeaturesChangeStamp = Long.parseLong(stamp);
1412            } catch (NumberFormatException JavaDoc e) {
1413                // ignore bad attribute ...
1414
}
1415        }
1416
1417        stamp = loadAttribute(props, name + "." + CFG_PLUGIN_STAMP, null); //$NON-NLS-1$
1418
if (stamp != null) {
1419            try {
1420                site.lastPluginsChangeStamp = Long.parseLong(stamp);
1421            } catch (NumberFormatException JavaDoc e) {
1422                // ignore bad attribute ...
1423
}
1424        }
1425
1426        String JavaDoc flag = loadAttribute(props, name + "." + CFG_UPDATEABLE, null); //$NON-NLS-1$
1427
if (flag != null) {
1428            if (flag.equals("true")) //$NON-NLS-1$
1429
site.updateable = true;
1430            else
1431                site.updateable = false;
1432        }
1433
1434        String JavaDoc linkname = loadAttribute(props, name + "." + CFG_LINK_FILE, null); //$NON-NLS-1$
1435
if (linkname != null && !linkname.equals("")) { //$NON-NLS-1$
1436
site.linkFileName = linkname.replace('/', File.separatorChar);
1437        }
1438
1439        return site;
1440    }
1441
1442    private IFeatureEntry loadFeatureEntry(Properties props, String JavaDoc name, IFeatureEntry dflt) {
1443        String JavaDoc id = loadAttribute(props, name + "." + CFG_FEATURE_ENTRY_ID, null); //$NON-NLS-1$
1444
if (id == null)
1445            return dflt;
1446        String JavaDoc version = loadAttribute(props, name + "." + CFG_FEATURE_ENTRY_VERSION, null); //$NON-NLS-1$
1447
String JavaDoc pluginVersion = loadAttribute(props, name + "." + CFG_FEATURE_ENTRY_PLUGIN_VERSION, null); //$NON-NLS-1$
1448
if (pluginVersion == null)
1449            pluginVersion = version;
1450        String JavaDoc pluginIdentifier = loadAttribute(props, name + "." + CFG_FEATURE_ENTRY_PLUGIN_IDENTIFIER, null); //$NON-NLS-1$
1451
if (pluginIdentifier == null)
1452            pluginIdentifier = id;
1453        String JavaDoc application = loadAttribute(props, name + "." + CFG_FEATURE_ENTRY_APPLICATION, null); //$NON-NLS-1$
1454
ArrayList rootList = new ArrayList();
1455
1456        // get install locations
1457
String JavaDoc rootString = loadAttribute(props, name + "." + CFG_FEATURE_ENTRY_ROOT + ".0", null); //$NON-NLS-1$ //$NON-NLS-2$
1458
for (int i = 1; rootString != null; i++) {
1459            try {
1460                URL rootEntry = new URL(rootString);
1461                rootList.add(rootEntry);
1462            } catch (MalformedURLException e) {
1463                // skip bad entries ...
1464
}
1465            rootString = loadAttribute(props, name + "." + CFG_FEATURE_ENTRY_ROOT + "." + i, null); //$NON-NLS-1$ //$NON-NLS-2$
1466
}
1467        URL[] roots = (URL[]) rootList.toArray(new URL[0]);
1468
1469        // get primary flag
1470
boolean primary = false;
1471        String JavaDoc flag = loadAttribute(props, name + "." + CFG_FEATURE_ENTRY_PRIMARY, null); //$NON-NLS-1$
1472
if (flag != null) {
1473            if (flag.equals("true")) //$NON-NLS-1$
1474
primary = true;
1475        }
1476        return createFeatureEntry(id, version, pluginIdentifier, pluginVersion, primary, application, roots);
1477    }
1478
1479    private String JavaDoc[] loadListAttribute(Properties props, String JavaDoc name, String JavaDoc[] dflt) {
1480        ArrayList list = new ArrayList();
1481        String JavaDoc value = loadAttribute(props, name + ".0", null); //$NON-NLS-1$
1482
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); //$NON-NLS-1$
1488
}
1489        return (String JavaDoc[]) list.toArray(new String JavaDoc[0]);
1490    }
1491
1492    private void loadListAttributeSegment(ArrayList list, String JavaDoc value) {
1493
1494        if (value == null)
1495            return;
1496
1497        StringTokenizer tokens = new StringTokenizer(value, ","); //$NON-NLS-1$
1498
String JavaDoc token;
1499        while (tokens.hasMoreTokens()) {
1500            token = tokens.nextToken().trim();
1501            if (!token.equals("")) //$NON-NLS-1$
1502
list.add(token);
1503        }
1504        return;
1505    }
1506
1507    private String JavaDoc loadAttribute(Properties props, String JavaDoc name, String JavaDoc dflt) {
1508        String JavaDoc 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        // write header
1517
w.println("# " + (new Date()).toString()); //$NON-NLS-1$
1518
writeAttribute(w, CFG_VERSION, VERSION);
1519        if (transientConfig)
1520            writeAttribute(w, CFG_TRANSIENT, "true"); //$NON-NLS-1$
1521
w.println(""); //$NON-NLS-1$
1522

1523        // write global attributes
1524
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        // write out bootstrap entries
1529
String JavaDoc[] ids = getBootstrapPluginIdentifiers();
1530        for (int i = 0; i < ids.length; i++) {
1531            String JavaDoc location = (String JavaDoc) bootPlugins.get(ids[i]);
1532            if (location != null)
1533                writeAttribute(w, CFG_BOOT_PLUGIN + "." + ids[i], location); //$NON-NLS-1$
1534
}
1535
1536        // write out feature entries
1537
w.println(""); //$NON-NLS-1$
1538
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]); //$NON-NLS-1$
1542
}
1543
1544        // write out site entries
1545
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]); //$NON-NLS-1$
1548
}
1549
1550        // write end-of-file marker
1551
writeAttribute(w, EOF, EOF);
1552    }
1553
1554    private void writeSite(PrintWriter w, String JavaDoc id, SiteEntry entry) {
1555
1556        // write site separator
1557
w.println(""); //$NON-NLS-1$
1558

1559        // write out site settings
1560
writeAttribute(w, id + "." + CFG_URL, entry.getURL().toString()); //$NON-NLS-1$
1561
writeAttribute(w, id + "." + CFG_STAMP, Long.toString(entry.getChangeStamp())); //$NON-NLS-1$
1562
writeAttribute(w, id + "." + CFG_FEATURE_STAMP, Long.toString(entry.getFeaturesChangeStamp())); //$NON-NLS-1$
1563
writeAttribute(w, id + "." + CFG_PLUGIN_STAMP, Long.toString(entry.getPluginsChangeStamp())); //$NON-NLS-1$
1564
writeAttribute(w, id + "." + CFG_UPDATEABLE, entry.updateable ? "true" : "false"); //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$
1565
if (entry.linkFileName != null && !entry.linkFileName.trim().equals("")) //$NON-NLS-1$
1566
writeAttribute(w, id + "." + CFG_LINK_FILE, entry.linkFileName.trim().replace(File.separatorChar, '/')); //$NON-NLS-1$
1567

1568        // write out site policy
1569
int type = entry.getSitePolicy().getType();
1570        String JavaDoc typeString = CFG_POLICY_TYPE_UNKNOWN;
1571        try {
1572            typeString = CFG_POLICY_TYPE[type];
1573        } catch (IndexOutOfBoundsException JavaDoc e) {
1574            // ignore bad attribute ...
1575
}
1576        writeAttribute(w, id + "." + CFG_POLICY, typeString); //$NON-NLS-1$
1577
writeListAttribute(w, id + "." + CFG_LIST, entry.getSitePolicy().getList()); //$NON-NLS-1$
1578
}
1579
1580    private void writeFeatureEntry(PrintWriter w, String JavaDoc id, IFeatureEntry entry) {
1581
1582        // write feature entry separator
1583
w.println(""); //$NON-NLS-1$
1584

1585        // write out feature entry settings
1586
writeAttribute(w, id + "." + CFG_FEATURE_ENTRY_ID, entry.getFeatureIdentifier()); //$NON-NLS-1$
1587
if (entry.canBePrimary())
1588            writeAttribute(w, id + "." + CFG_FEATURE_ENTRY_PRIMARY, "true"); //$NON-NLS-1$ //$NON-NLS-2$
1589
writeAttribute(w, id + "." + CFG_FEATURE_ENTRY_VERSION, entry.getFeatureVersion()); //$NON-NLS-1$
1590
if (entry.getFeatureVersion() != null && !entry.getFeatureVersion().equals(entry.getFeaturePluginVersion()))
1591            writeAttribute(w, id + "." + CFG_FEATURE_ENTRY_PLUGIN_VERSION, entry.getFeaturePluginVersion()); //$NON-NLS-1$
1592
if (entry.getFeatureIdentifier() != null && !entry.getFeatureIdentifier().equals(entry.getFeaturePluginIdentifier()))
1593            writeAttribute(w, id + "." + CFG_FEATURE_ENTRY_PLUGIN_IDENTIFIER, entry.getFeaturePluginIdentifier()); //$NON-NLS-1$
1594
writeAttribute(w, id + "." + CFG_FEATURE_ENTRY_APPLICATION, entry.getFeatureApplication()); //$NON-NLS-1$
1595
URL[] roots = entry.getFeatureRootURLs();
1596        for (int i = 0; i < roots.length; i++) {
1597            // write our as individual attributes (is easier for Main.java to read)
1598
writeAttribute(w, id + "." + CFG_FEATURE_ENTRY_ROOT + "." + i, roots[i].toExternalForm()); //$NON-NLS-1$ //$NON-NLS-2$
1599
}
1600    }
1601
1602    private void writeListAttribute(PrintWriter w, String JavaDoc id, String JavaDoc[] list) {
1603        if (list == null || list.length == 0)
1604            return;
1605
1606        String JavaDoc value = ""; //$NON-NLS-1$
1607
int listLen = 0;
1608        int listIndex = 0;
1609        for (int i = 0; i < list.length; i++) {
1610            if (listLen != 0)
1611                value += ","; //$NON-NLS-1$
1612
else
1613                value = ""; //$NON-NLS-1$
1614
value += list[i];
1615
1616            if (++listLen >= CFG_LIST_LENGTH) {
1617                writeAttribute(w, id + "." + Integer.toString(listIndex++), value); //$NON-NLS-1$
1618
listLen = 0;
1619            }
1620        }
1621        if (listLen != 0)
1622            writeAttribute(w, id + "." + Integer.toString(listIndex), value); //$NON-NLS-1$
1623
}
1624
1625    private void writeAttribute(PrintWriter w, String JavaDoc id, String JavaDoc value) {
1626        if (value == null || value.trim().equals("")) //$NON-NLS-1$
1627
return;
1628        w.println(id + "=" + escapedValue(value)); //$NON-NLS-1$
1629
}
1630
1631    private String JavaDoc escapedValue(String JavaDoc value) {
1632        // if required, escape property values as \\uXXXX
1633
StringBuffer JavaDoc buf = new StringBuffer JavaDoc(value.length() * 2); // assume expansion by less than factor of 2
1634
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                // handle characters requiring leading \
1638
buf.append('\\');
1639                buf.append(character);
1640            } else if ((character < 0x0020) || (character > 0x007e)) {
1641                // handle characters outside base range (encoded)
1642
buf.append('\\');
1643                buf.append('u');
1644                buf.append(HEX[(character >> 12) & 0xF]); // first nibble
1645
buf.append(HEX[(character >> 8) & 0xF]); // second nibble
1646
buf.append(HEX[(character >> 4) & 0xF]); // third nibble
1647
buf.append(HEX[character & 0xF]); // fourth nibble
1648
} else {
1649                // handle base characters
1650
buf.append(character);
1651            }
1652        }
1653        return buf.toString();
1654    }
1655
1656
1657
1658
1659    private static boolean supportsDetection(URL url) {
1660        String JavaDoc protocol = url.getProtocol();
1661        if (protocol.equals("file")) //$NON-NLS-1$
1662
return true;
1663        else if (protocol.equals(PlatformURLHandler.PROTOCOL)) {
1664            URL resolved = null;
1665            try {
1666                resolved = resolvePlatformURL(url); // 19536
1667
} catch (IOException e) {
1668                return false; // we tried but failed to resolve the platform URL
1669
}
1670            return resolved.getProtocol().equals("file"); //$NON-NLS-1$
1671
} else
1672            return false;
1673    }
1674
1675    private static URL resolvePlatformURL(URL url) throws IOException {
1676        // 19536
1677
if (url.getProtocol().equals(PlatformURLHandler.PROTOCOL)) {
1678            URLConnection connection = url.openConnection();
1679            if (connection instanceof PlatformURLConnection) {
1680                url = ((PlatformURLConnection) connection).getResolvedURL();
1681            } else {
1682                // connection = new PlatformURLBaseConnection(url);
1683
// url = ((PlatformURLConnection)connection).getResolvedURL();
1684
url = getInstallURL();
1685            }
1686        }
1687        return url;
1688    }
1689
1690    private static void debug(String JavaDoc s) {
1691        System.out.println("PlatformConfig: " + s); //$NON-NLS-1$
1692
}
1693
1694    private void resetUpdateManagerState(URL url) throws IOException {
1695        // [20111]
1696
if (!supportsDetection(url))
1697            return; // can't do ...
1698

1699        // find directory where the platform configuration file is
1700
URL resolved = resolvePlatformURL(url);
1701        File initCfg = new File(resolved.getFile().replace('/', File.separatorChar));
1702        File initDir = initCfg.getParentFile();
1703
1704        // Find the Update Manager State directory
1705
if (initDir == null || !initDir.exists() || !initDir.isDirectory())
1706            return;
1707        String JavaDoc temp = initCfg.getName() + ".metadata"; //$NON-NLS-1$
1708
File UMDir = new File(initDir, temp + '/');
1709
1710        // Attempt to rename it
1711
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