KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > org > eclipse > update > internal > configurator > PlatformConfiguration


1 /*******************************************************************************
2  * Copyright (c) 2000, 2007 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  * James D Miles (IBM Corp.) - bug 176250, Configurator needs to handle more platform urls
11  *******************************************************************************/

12 package org.eclipse.update.internal.configurator;
13
14 import java.io.BufferedWriter JavaDoc;
15 import java.io.File JavaDoc;
16 import java.io.FileFilter JavaDoc;
17 import java.io.FileInputStream JavaDoc;
18 import java.io.FileOutputStream JavaDoc;
19 import java.io.IOException JavaDoc;
20 import java.io.OutputStream JavaDoc;
21 import java.io.OutputStreamWriter JavaDoc;
22 import java.io.SyncFailedException JavaDoc;
23 import java.io.UnsupportedEncodingException JavaDoc;
24 import java.lang.reflect.InvocationTargetException JavaDoc;
25 import java.net.MalformedURLException JavaDoc;
26 import java.net.URL JavaDoc;
27 import java.net.URLConnection JavaDoc;
28 import java.util.ArrayList JavaDoc;
29 import java.util.Date JavaDoc;
30 import java.util.HashMap JavaDoc;
31 import java.util.HashSet JavaDoc;
32 import java.util.Properties JavaDoc;
33 import java.util.Set JavaDoc;
34
35 import javax.xml.parsers.DocumentBuilder JavaDoc;
36 import javax.xml.parsers.DocumentBuilderFactory JavaDoc;
37
38 import org.eclipse.core.runtime.CoreException;
39 import org.eclipse.core.runtime.FileLocator;
40 import org.eclipse.osgi.service.datalocation.Location;
41 import org.eclipse.osgi.util.NLS;
42 import org.eclipse.update.configurator.IPlatformConfiguration;
43 import org.w3c.dom.Document JavaDoc;
44 import org.w3c.dom.Element JavaDoc;
45
46 /**
47  * This class is responsible for providing the features and plugins (bundles) to
48  * the runtime. Configuration data is stored in the configuration/org.eclipse.update/platform.xml file.
49  * When eclipse starts, it tries to load the config info from platform.xml.
50  * If the file does not exist, then it also tries to read it from a temp or backup file.
51  * If this does not succeed, a platform.xml is created by inspecting the eclipse
52  * installation directory (its features and plugin folders).
53  * If platform.xml already exists, a check is made to see when it was last modified
54  * and whether there are any file system changes that are newer (users may manually unzip
55  * features and plugins). In this case, the newly added features and plugins are picked up.
56  * A check for existence of features and plugins is also performed, to detect deletions.
57  */

58 public class PlatformConfiguration implements IPlatformConfiguration, IConfigurationConstants {
59
60     private static PlatformConfiguration currentPlatformConfiguration = null;
61     //private static final DocumentBuilderFactory documentBuilderFactory = DocumentBuilderFactory.newInstance();
62
// private static final TransformerFactory transformerFactory = TransformerFactory.newInstance();
63
private static final String JavaDoc XML_ENCODING = "UTF-8"; //$NON-NLS-1$
64

65     private Configuration config;
66     private URL JavaDoc configLocation;
67     private HashMap JavaDoc externalLinkSites; // used to restore prior link site state
68
private long changeStamp;
69     private long featuresChangeStamp;
70     private boolean featuresChangeStampIsValid;
71     private long pluginsChangeStamp;
72     private boolean pluginsChangeStampIsValid;
73     //PAL nio optional
74
//private FileLock lock;
75
private Locker lock = null;
76     private static int defaultPolicy = DEFAULT_POLICY_TYPE;
77     private static boolean checkNio = false;
78     private static boolean useNio;
79
80     private static final String JavaDoc ECLIPSE = "eclipse"; //$NON-NLS-1$
81
private static final String JavaDoc CONFIG_HISTORY = "history"; //$NON-NLS-1$
82
private static final String JavaDoc PLATFORM_XML = "platform.xml"; //$NON-NLS-1$
83
private static final String JavaDoc CONFIG_NAME = ConfigurationActivator.NAME_SPACE + "/" + PLATFORM_XML; //$NON-NLS-1$
84
private static final String JavaDoc CONFIG_INI = "config.ini"; //NON-NLS-1$ //$NON-NLS-1$
85
private static final String JavaDoc CONFIG_FILE_LOCK_SUFFIX = ".lock"; //$NON-NLS-1$
86
private static final String JavaDoc CONFIG_FILE_TEMP_SUFFIX = ".tmp"; //$NON-NLS-1$
87
private static final String JavaDoc LINKS = "links"; //$NON-NLS-1$
88
private static final String JavaDoc[] BOOTSTRAP_PLUGINS = {};
89
90     private static final String JavaDoc DEFAULT_FEATURE_APPLICATION = "org.eclipse.ui.ide.workbench"; //$NON-NLS-1$
91

92     private static final String JavaDoc LINK_PATH = "path"; //$NON-NLS-1$
93
private static final String JavaDoc LINK_READ = "r"; //$NON-NLS-1$
94
private static final String JavaDoc LINK_READ_WRITE = "rw"; //$NON-NLS-1$
95
private static URL JavaDoc installURL;
96     
97     private PlatformConfiguration(Location platformConfigLocation) throws CoreException, IOException JavaDoc {
98
99         this.externalLinkSites = new HashMap JavaDoc();
100         this.config = null;
101         
102         // initialize configuration
103
initializeCurrent(platformConfigLocation);
104         if(config != null)
105             setDefaultPolicy();
106
107         // Detect external links. These are "soft link" to additional sites. The link
108
// files are usually provided by external installation programs. They are located
109
// relative to this configuration URL.
110
// Note: don't do it for self hosting
111
if (!isTransient())
112             configureExternalLinks();
113
114         // Validate sites in the configuration. Causes any sites that do not exist to
115
// be removed from the configuration
116
validateSites();
117
118         // compute differences between configuration and actual content of the sites
119
// (base sites and link sites)
120
// Note: when the config is transient (generated by PDE, etc.) we don't reconcile
121
if (isTransient())
122             return;
123         
124         // for 'osgi.clean' or osgi.checkConfiguration', force a refresh
125
boolean osgiClean = "true".equals(ConfigurationActivator.getBundleContext().getProperty("osgi.clean")); //$NON-NLS-1$ //$NON-NLS-2$
126
boolean osgiCheckConfiguration = "true".equals(ConfigurationActivator.getBundleContext().getProperty("osgi.checkConfiguration")); //$NON-NLS-1$ //$NON-NLS-2$
127

128         if (osgiClean || osgiCheckConfiguration) {
129             // We have to call refresh() for features to be rescanned correctly
130
refresh();
131             reconcile();
132         }
133         else {
134             changeStamp = computeChangeStamp();
135             if (changeStamp > config.getDate().getTime())
136                 reconcile();
137         }
138     }
139
140     PlatformConfiguration(URL JavaDoc url) throws Exception JavaDoc {
141         this.externalLinkSites = new HashMap JavaDoc();
142         initialize(url);
143     }
144
145     private void setDefaultPolicy() {
146         // Assumption: If the configuration that we initialize with
147
// has a MANAGED_ONLY policy, then all sites should have default policy
148
// of MANAGED_ONLY.
149
ISiteEntry[] sentries = getConfiguredSites();
150         if(sentries != null && sentries.length >0){
151             int policyType = sentries[0].getSitePolicy().getType();
152             if(policyType == ISitePolicy.MANAGED_ONLY){
153                 defaultPolicy = policyType;
154             }
155         }
156     }
157
158     public static int getDefaultPolicy(){
159         return defaultPolicy;
160     }
161
162     /*
163      * @see IPlatformConfiguration#createSiteEntry(URL, ISitePolicy)
164      */

165     public ISiteEntry createSiteEntry(URL JavaDoc url, ISitePolicy policy) {
166         return new SiteEntry(url, policy);
167     }
168
169     /*
170      * @see IPlatformConfiguration#createSitePolicy(int, String[])
171      */

172     public ISitePolicy createSitePolicy(int type, String JavaDoc[] list) {
173         return new SitePolicy(type, list);
174     }
175
176     /*
177      * @see IPlatformConfiguration#createFeatureEntry(String, String, String, boolean, String, URL)
178      */

179     public IFeatureEntry createFeatureEntry(String JavaDoc id, String JavaDoc version, String JavaDoc pluginVersion, boolean primary, String JavaDoc application, URL JavaDoc[] root) {
180         return new FeatureEntry(id, version, pluginVersion, primary, application, root);
181     }
182
183     /*
184      * @see IPlatformConfiguration#createFeatureEntry(String, String, String,
185      * String, boolean, String, URL)
186      */

187     public IFeatureEntry createFeatureEntry(String JavaDoc id, String JavaDoc version, String JavaDoc pluginIdentifier, String JavaDoc pluginVersion, boolean primary, String JavaDoc application, URL JavaDoc[] root) {
188         return new FeatureEntry(id, version, pluginIdentifier, pluginVersion, primary, application, root);
189     }
190
191     /*
192      * @see IPlatformConfiguration#configureSite(ISiteEntry)
193      */

194     public void configureSite(ISiteEntry entry) {
195         configureSite(entry, false);
196     }
197
198     /*
199      * @see IPlatformConfiguration#configureSite(ISiteEntry, boolean)
200      */

201     public synchronized void configureSite(ISiteEntry entry, boolean replace) {
202
203         if (entry == null)
204             return;
205     
206         URL JavaDoc url = entry.getURL();
207         if (url == null)
208             return;
209
210         String JavaDoc key = url.toExternalForm();
211         if (config.getSiteEntry(key) != null && !replace)
212             return;
213     
214         if (entry instanceof SiteEntry)
215             config.addSiteEntry(key, (SiteEntry)entry);
216     }
217
218     /*
219      * @see IPlatformConfiguration#unconfigureSite(ISiteEntry)
220      */

221     public synchronized void unconfigureSite(ISiteEntry entry) {
222         if (entry == null)
223             return;
224
225         URL JavaDoc url = entry.getURL();
226         if (url == null)
227             return;
228         
229         String JavaDoc key = url.toExternalForm();
230         if (entry instanceof SiteEntry)
231             config.removeSiteEntry(key);
232     }
233
234     /*
235      * @see IPlatformConfiguration#getConfiguredSites()
236      */

237     public ISiteEntry[] getConfiguredSites() {
238         if (config == null)
239             return new ISiteEntry[0];
240         
241         SiteEntry[] sites = config.getSites();
242         ArrayList JavaDoc enabledSites = new ArrayList JavaDoc(sites.length);
243         for (int i=0; i<sites.length; i++) {
244             if (sites[i].isEnabled())
245                 enabledSites.add(sites[i]);
246         }
247         return (ISiteEntry[])enabledSites.toArray(new ISiteEntry[enabledSites.size()]);
248     }
249
250     /*
251      * @see IPlatformConfiguration#findConfiguredSite(URL)
252      */

253     public ISiteEntry findConfiguredSite(URL JavaDoc url) {
254         return findConfiguredSite(url, true);
255     }
256     
257     /**
258      *
259      * @param url site url
260      * @param checkPlatformURL if true, check for url format that is platform:/...
261      * @return
262      */

263     public SiteEntry findConfiguredSite(URL JavaDoc url, boolean checkPlatformURL) {
264         if (url == null)
265             return null;
266         String JavaDoc key = url.toExternalForm();
267
268         SiteEntry result = config.getSiteEntry(key);
269         if (result == null) { // retry with decoded URL string
270
try {
271                 //PAL foundation
272
//key = URLDecoder.decode(key, "UTF-8"); //$NON-NLS-1$
273
key = UpdateURLDecoder.decode(key, "UTF-8"); //$NON-NLS-1$
274
} catch (UnsupportedEncodingException JavaDoc e) {
275                 // ignore
276
}
277             result = config.getSiteEntry(key);
278         }
279             
280         if (result == null && checkPlatformURL) {
281             try {
282                 result = findConfiguredSite(config.asPlatformURL(url), false);
283             } catch (Exception JavaDoc e) {
284                 //ignore
285
}
286         }
287         return result;
288     }
289
290     /*
291      * @see IPlatformConfiguration#configureFeatureEntry(IFeatureEntry)
292      */

293     public synchronized void configureFeatureEntry(IFeatureEntry entry) {
294         if (entry == null)
295             return;
296
297         String JavaDoc key = entry.getFeatureIdentifier();
298         if (key == null)
299             return;
300
301         // we should check each site and find where the feature is
302
// located and then configure it
303
if (config == null)
304             config = new Configuration();
305
306         SiteEntry[] sites = config.getSites();
307         for (int i=0; i<sites.length; i++) {
308             // find out what site contains the feature and configure it
309
try {
310                 URL JavaDoc url = new URL JavaDoc(sites[i].getURL(), FEATURES + "/" + entry.getFeatureIdentifier()+ "_" + entry.getFeatureVersion() + "/"); //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$
311
if (new File JavaDoc(url.getFile()).exists())
312                     sites[i].addFeatureEntry(entry);
313                 else {
314                     url = new URL JavaDoc(sites[i].getURL(), FEATURES + "/" + entry.getFeatureIdentifier() + "/"); //$NON-NLS-1$ //$NON-NLS-2$
315
if (new File JavaDoc(url.getFile()).exists())
316                         sites[i].addFeatureEntry(entry);
317                 }
318             } catch (MalformedURLException JavaDoc e) {
319             }
320         }
321     }
322
323     /*
324      * @see IPlatformConfiguration#unconfigureFeatureEntry(IFeatureEntry)
325      */

326     public synchronized void unconfigureFeatureEntry(IFeatureEntry entry) {
327         if (entry == null)
328             return;
329
330         String JavaDoc key = entry.getFeatureIdentifier();
331         if (key == null)
332             return;
333
334         config.unconfigureFeatureEntry(entry);
335     }
336
337     /*
338      * @see IPlatformConfiguration#getConfiguredFeatureEntries()
339      */

340     public IFeatureEntry[] getConfiguredFeatureEntries() {
341         ArrayList JavaDoc configFeatures = new ArrayList JavaDoc();
342         SiteEntry[] sites = config.getSites();
343         for (int i=0; i<sites.length; i++) {
344             FeatureEntry[] features = sites[i].getFeatureEntries();
345             for (int j=0; j<features.length; j++)
346                 configFeatures.add(features[j]);
347         }
348         return (IFeatureEntry[])configFeatures.toArray(new FeatureEntry[configFeatures.size()]);
349     }
350
351     /*
352      * @see IPlatformConfiguration#findConfiguredFeatureEntry(String)
353      */

354     public IFeatureEntry findConfiguredFeatureEntry(String JavaDoc id) {
355         if (id == null)
356             return null;
357
358         SiteEntry[] sites = config.getSites();
359         for (int i=0; i<sites.length; i++) {
360             FeatureEntry f = sites[i].getFeatureEntry(id);
361             if (f != null)
362                 return f;
363         }
364         return null;
365     }
366
367     /*
368      * @see IPlatformConfiguration#getConfigurationLocation()
369      */

370     public URL JavaDoc getConfigurationLocation() {
371         return configLocation;
372     }
373
374     /*
375      * @see IPlatformConfiguration#getChangeStamp()
376      */

377     public long getChangeStamp() {
378         if (config.getLinkedConfig() == null)
379             return config.getDate().getTime();
380         return Math.max(config.getDate().getTime(), config.getLinkedConfig().getDate().getTime());
381     }
382
383     /*
384      * @see IPlatformConfiguration#getFeaturesChangeStamp()
385      * @deprecated Don't use this method
386      */

387     public long getFeaturesChangeStamp() {
388         return 0;
389     }
390
391     /*
392      * @see IPlatformConfiguration#getPluginsChangeStamp()
393      * @deprecated Don't use this method
394      */

395     public long getPluginsChangeStamp() {
396         return 0;
397     }
398
399
400     public String JavaDoc getApplicationIdentifier() {
401         // Return the app if defined in system properties
402
String JavaDoc application = ConfigurationActivator.getBundleContext().getProperty(ECLIPSE_APPLICATION);
403         if (application != null)
404             return application;
405
406         // Otherwise, try to get it from the primary feature (aka product)
407
String JavaDoc feature = getPrimaryFeatureIdentifier();
408
409         // lookup application for feature (specified or defaulted)
410
if (feature != null) {
411             IFeatureEntry fe = findConfiguredFeatureEntry(feature);
412             if (fe != null) {
413                 if (fe.getFeatureApplication() != null)
414                     return fe.getFeatureApplication();
415             }
416         }
417
418         // return hardcoded default if we failed
419
return DEFAULT_FEATURE_APPLICATION;
420     }
421
422     /*
423      * @see IPlatformConfiguration#getPrimaryFeatureIdentifier()
424      */

425     public String JavaDoc getPrimaryFeatureIdentifier() {
426         // Return the product if defined in system properties
427
String JavaDoc primaryFeatureId = ConfigurationActivator.getBundleContext().getProperty(ECLIPSE_PRODUCT);
428         if (primaryFeatureId != null) {
429             // check if feature exists
430
IFeatureEntry feature = findConfiguredFeatureEntry(primaryFeatureId);
431             if (feature != null && feature.canBePrimary())
432                 return primaryFeatureId;
433         }
434         return null;
435     }
436
437     /*
438      * @see IPlatformConfiguration#getPluginPath()
439      */

440     public URL JavaDoc[] getPluginPath() {
441         ArrayList JavaDoc path = new ArrayList JavaDoc();
442         Utils.debug("computed plug-in path:"); //$NON-NLS-1$
443

444         ISiteEntry[] sites = getConfiguredSites();
445         URL JavaDoc pathURL;
446         for (int i = 0; i < sites.length; i++) {
447             String JavaDoc[] plugins = sites[i].getPlugins();
448             for (int j = 0; j < plugins.length; j++) {
449                 try {
450                     pathURL = new URL JavaDoc(((SiteEntry) sites[i]).getResolvedURL(), plugins[j]);
451                     path.add(pathURL);
452                     Utils.debug(" " + pathURL.toString()); //$NON-NLS-1$
453
} catch (MalformedURLException JavaDoc e) {
454                     // skip entry ...
455
Utils.debug(" bad URL: " + e); //$NON-NLS-1$
456
}
457             }
458         }
459         return (URL JavaDoc[]) path.toArray(new URL JavaDoc[0]);
460     }
461     
462     public Set JavaDoc getPluginPaths() {
463         
464         HashSet JavaDoc paths = new HashSet JavaDoc();
465         ISiteEntry[] sites = getConfiguredSites();
466
467         for (int i = 0; i < sites.length; i++) {
468             String JavaDoc[] plugins = sites[i].getPlugins();
469             for (int j = 0; j < plugins.length; j++) {
470                     paths.add(plugins[j]);
471             }
472         }
473         
474         return paths;
475     }
476     
477
478     /*
479      * A variation of the getPluginPath, but it returns the actual plugin entries
480      */

481     public PluginEntry[] getPlugins() {
482         ArrayList JavaDoc allPlugins = new ArrayList JavaDoc();
483         Utils.debug("computed plug-ins:"); //$NON-NLS-1$
484

485         ISiteEntry[] sites = getConfiguredSites();
486         for (int i = 0; i < sites.length; i++) {
487             if (!(sites[i] instanceof SiteEntry)) {
488                 Utils.debug("Site " + sites[i].getURL() + " is not a SiteEntry"); //$NON-NLS-1$ //$NON-NLS-2$
489
continue;
490             }
491             PluginEntry[] plugins = ((SiteEntry)sites[i]).getPluginEntries();
492             for (int j = 0; j < plugins.length; j++) {
493                 allPlugins.add(plugins[j]);
494                 Utils.debug(" " + plugins[j].getURL()); //$NON-NLS-1$
495
}
496         }
497         return (PluginEntry[]) allPlugins.toArray(new PluginEntry[0]);
498     }
499     
500
501     /*
502      * @see IPlatformConfiguration#getBootstrapPluginIdentifiers()
503      */

504     public String JavaDoc[] getBootstrapPluginIdentifiers() {
505         return BOOTSTRAP_PLUGINS;
506     }
507
508     /*
509      * @see IPlatformConfiguration#setBootstrapPluginLocation(String, URL)
510      */

511     public void setBootstrapPluginLocation(String JavaDoc id, URL JavaDoc location) {
512     }
513
514     /*
515      * @see IPlatformConfiguration#isUpdateable()
516      */

517     public boolean isUpdateable() {
518         return true;
519     }
520
521     /*
522      * @see IPlatformConfiguration#isTransient()
523      */

524     public boolean isTransient() {
525         return (config != null) ? config.isTransient() : false;
526     }
527
528     /*
529      * @see IPlatformConfiguration#isTransient(boolean)
530      */

531     public void isTransient(boolean value) {
532         if (this != getCurrent() && config != null)
533             config.setTransient(value);
534     }
535
536     /*
537      * @see IPlatformConfiguration#refresh()
538      */

539     public synchronized void refresh() {
540         // Reset computed values. Will be lazily refreshed
541
// on next access
542
ISiteEntry[] sites = getConfiguredSites();
543         for (int i = 0; i < sites.length; i++) {
544             if (sites[i].isUpdateable()) {
545                 // reset site entry
546
((SiteEntry) sites[i]).refresh();
547             }
548         }
549     }
550
551     /*
552      * @see IPlatformConfiguration#save()
553      */

554     public void save() throws IOException JavaDoc {
555         if (isUpdateable())
556             save(configLocation);
557     }
558
559     /*
560      * @see IPlatformConfiguration#save(URL)
561      */

562     public synchronized void save(URL JavaDoc url) throws IOException JavaDoc {
563         if (url == null)
564             throw new IOException JavaDoc(Messages.cfig_unableToSave_noURL);
565
566         OutputStream JavaDoc os = null;
567         if (!url.getProtocol().equals("file")) { //$NON-NLS-1$
568
// not a file protocol - attempt to save to the URL
569
URLConnection JavaDoc uc = url.openConnection();
570             uc.setDoOutput(true);
571             os = uc.getOutputStream();
572             try {
573                 saveAsXML(os);
574                 config.setDirty(false);
575             } catch (CoreException e) {
576                 Utils.log(e.getMessage());
577                 Utils.log(e.getStatus());
578                 throw new IOException JavaDoc(NLS.bind(Messages.cfig_unableToSave, (new String JavaDoc[] { url.toExternalForm() })));
579             } finally {
580                 os.close();
581             }
582         } else {
583             // file protocol - do safe i/o
584
File JavaDoc cfigFile = new File JavaDoc(url.getFile().replace('/', File.separatorChar));
585             if (!cfigFile.getName().equals(PLATFORM_XML)) {
586                 if (cfigFile.exists() && cfigFile.isFile()) {
587                     Utils.log(Messages.PlatformConfiguration_expectingPlatformXMLorDirectory + cfigFile.getName());
588                     cfigFile = cfigFile.getParentFile();
589                 }
590                 cfigFile = new File JavaDoc(cfigFile, CONFIG_NAME);
591             }
592             File JavaDoc workingDir = cfigFile.getParentFile();
593             if (workingDir != null && !workingDir.exists())
594                 workingDir.mkdirs();
595
596             // Do safe i/o:
597
// - backup current config, by moving it to the history folder
598
// - write new config to platform.xml.tmp file
599
// - rename the temp file to platform.xml
600
File JavaDoc cfigFileOriginal = new File JavaDoc(cfigFile.getAbsolutePath());
601             File JavaDoc cfigTmp = new File JavaDoc(cfigFile.getAbsolutePath() + CONFIG_FILE_TEMP_SUFFIX);
602             
603             // Backup old file
604
if (cfigFile.exists()){
605                 File JavaDoc backupDir = new File JavaDoc(workingDir, CONFIG_HISTORY);
606                 if (!backupDir.exists())
607                     backupDir.mkdir();
608                 long timestamp = cfigFile.lastModified();
609                 File JavaDoc preservedFile = new File JavaDoc(backupDir, String.valueOf(timestamp)+".xml"); //$NON-NLS-1$
610
// If the target file exists, increment the timestamp. Try at most 100 times.
611
long increment = 1;
612                 while (preservedFile.exists() && increment < 100){
613                     preservedFile = new File JavaDoc(backupDir, String.valueOf(timestamp+increment++)+".xml"); //$NON-NLS-1$
614
}
615                 if (!preservedFile.exists()) {
616                     // try renaming current config to backup copy
617
if (!cfigFile.renameTo(preservedFile))
618                         Utils.log(Messages.PlatformConfiguration_cannotBackupConfig);
619                 }
620             }
621
622             // first save the file as temp
623
os = new FileOutputStream JavaDoc(cfigTmp);
624             
625             try {
626                 saveAsXML(os);
627                 // Try flushing any internal buffers, and synchronize with the disk
628
try {
629                     os.flush();
630                     ((FileOutputStream JavaDoc)os).getFD().sync();
631                 } catch (SyncFailedException JavaDoc e2) {
632                     Utils.log(e2.getMessage());
633                 } catch (IOException JavaDoc e2) {
634                     Utils.log(e2.getMessage());
635                 }
636                 try {
637                     os.close();
638                     os = null;
639                 } catch (IOException JavaDoc e1) {
640                     Utils.log(Messages.PlatformConfiguration_cannotCloseStream + cfigTmp);
641                     Utils.log(e1.getMessage());
642                 }
643                 // set file time stamp to match that of the config element
644
cfigTmp.setLastModified(config.getDate().getTime());
645                 // set this on config, in case the value was rounded off
646
config.setLastModified(cfigTmp.lastModified());
647                 // make the change stamp to be the same as the config file
648
changeStamp = config.getDate().getTime();
649                 config.setDirty(false);
650             } catch (CoreException e) {
651                 throw new IOException JavaDoc(NLS.bind(Messages.cfig_unableToSave, (new String JavaDoc[] { cfigTmp.getAbsolutePath() })));
652             } finally {
653                 if (os != null)
654                     try {
655                         os.close();
656                     } catch (IOException JavaDoc e1) {
657                         Utils.log(Messages.PlatformConfiguration_cannotCloseTempFile + cfigTmp);
658                     }
659             }
660
661             // at this point we have old config (if existed) as "bak" and the
662
// new config as "tmp".
663
boolean ok = cfigTmp.renameTo(cfigFileOriginal);
664             if (!ok) {
665                 // this codepath represents a tiny failure window. The load processing
666
// on startup will detect missing config and will attempt to start
667
// with "tmp" (latest), then "bak" (the previous). We can also end up
668
// here if we failed to rename the current config to "bak". In that
669
// case we will restart with the previous state.
670
Utils.log(Messages.PlatformConfiguration_cannotRenameTempFile);
671                 
672                 throw new IOException JavaDoc(NLS.bind(Messages.cfig_unableToSave, (new String JavaDoc[] { cfigTmp.getAbsolutePath() })));
673             }
674         }
675     }
676
677
678     public static PlatformConfiguration getCurrent() {
679         return currentPlatformConfiguration;
680     }
681
682     /**
683      * Starts a platform installed at specified installURL using configuration located at platformConfigLocation.
684      */

685     public static synchronized void startup(URL JavaDoc installURL, Location platformConfigLocation) throws Exception JavaDoc {
686         PlatformConfiguration.installURL = installURL;
687     
688         // create current configuration
689
if (currentPlatformConfiguration == null) {
690             currentPlatformConfiguration = new PlatformConfiguration(platformConfigLocation);
691             if (currentPlatformConfiguration.config == null)
692                 throw new Exception JavaDoc(Messages.PlatformConfiguration_cannotLoadConfig + platformConfigLocation.getURL());
693             if (currentPlatformConfiguration.config.isDirty())
694                 // If this is a transient config (generated by PDE),do nothing
695
// otherwise, save the configuration with proper date
696
if (!currentPlatformConfiguration.isTransient())
697                     currentPlatformConfiguration.save();
698         }
699     }
700
701     public static synchronized void shutdown() throws IOException JavaDoc {
702
703         // save platform configuration
704
PlatformConfiguration config = getCurrent();
705         if (config != null) {
706             // only save if there are changes in the config
707
if (config.config.isDirty() && !config.isTransient()) {
708                 try {
709                     config.save();
710                 } catch (IOException JavaDoc e) {
711                     Utils.debug("Unable to save configuration " + e.toString()); //$NON-NLS-1$
712
// will recover on next startup
713
}
714             }
715         }
716     }
717
718
719     private synchronized void initializeCurrent(Location platformConfigLocation) throws IOException JavaDoc {
720
721         // Configuration URL was is specified by the OSGi layer.
722
// Default behavior is to look
723
// for configuration in the specified meta area. If not found, look
724
// for pre-initialized configuration in the installation location.
725
// If it is found it is used as the initial configuration. Otherwise
726
// a new configuration is created. In either case the resulting
727
// configuration is written into the specified configuration area.
728

729         URL JavaDoc configFileURL = new URL JavaDoc(platformConfigLocation.getURL(), CONFIG_NAME);
730         try {
731             // check concurrent use lock
732
getConfigurationLock(platformConfigLocation.getURL());
733
734             // try loading the configuration
735
try {
736                 config = loadConfig(configFileURL);
737                 Utils.debug("Using configuration " + configFileURL.toString()); //$NON-NLS-1$
738
} catch (Exception JavaDoc e) {
739                 // failed to load, see if we can find pre-initialized configuration.
740
try {
741                     Location parentLocation = platformConfigLocation.getParentLocation();
742                     if (parentLocation == null)
743                         throw new IOException JavaDoc(); // no platform.xml found, need to create default site
744

745                     URL JavaDoc sharedConfigFileURL = new URL JavaDoc(parentLocation.getURL(), CONFIG_NAME);
746                     config = loadConfig(sharedConfigFileURL);
747                     
748                     // pre-initialized config loaded OK ... copy any remaining update metadata
749
// Only copy if the default config location is not the install location
750
if (!sharedConfigFileURL.equals(configFileURL)) {
751                         // need to link config info instead of using a copy
752
linkInitializedState(config, parentLocation, platformConfigLocation);
753                         Utils.debug("Configuration initialized from " + sharedConfigFileURL.toString()); //$NON-NLS-1$
754
}
755                     return;
756                 } catch (Exception JavaDoc ioe) {
757                     Utils.debug("Creating default configuration from " + configFileURL.toExternalForm()); //$NON-NLS-1$
758
createDefaultConfiguration(configFileURL);
759                 }
760             } finally {
761                 // if config == null an unhandled exception has been thrown and we allow it to propagate
762
if (config != null) {
763                     configLocation = configFileURL;
764                      if (config.getURL() == null)
765                         config.setURL(configFileURL);
766                     verifyPath(configLocation);
767                     Utils.debug("Creating configuration " + configFileURL.toString()); //$NON-NLS-1$
768
}
769             }
770         } finally {
771             // releaes concurrent use lock
772
clearConfigurationLock();
773         }
774     }
775
776     
777     private synchronized void initialize(URL JavaDoc url) throws Exception JavaDoc {
778         if (url != null) {
779             config = loadConfig(url);
780             Utils.debug("Using configuration " + url.toString()); //$NON-NLS-1$
781
}
782         if (config == null) {
783             config = new Configuration();
784             Utils.debug("Creating empty configuration object"); //$NON-NLS-1$
785
}
786         config.setURL(url);
787         configLocation = url;
788     }
789
790     private void createDefaultConfiguration(URL JavaDoc url)throws IOException JavaDoc{
791         // we are creating new configuration
792
config = new Configuration();
793         config.setURL(url);
794         SiteEntry defaultSite = (SiteEntry)getRootSite();
795         configureSite(defaultSite);
796         try {
797             // parse the site directory to discover features
798
defaultSite.loadFromDisk(0);
799         } catch (CoreException e1) {
800             Utils.log(Messages.PlatformConfiguration_cannotLoadDefaultSite + defaultSite.getResolvedURL());
801             return;
802         }
803     }
804     private ISiteEntry getRootSite() {
805         // create default site entry for the root
806
ISitePolicy defaultPolicy = createSitePolicy(getDefaultPolicy(), DEFAULT_POLICY_LIST);
807         URL JavaDoc siteURL = null;
808         try {
809             siteURL = new URL JavaDoc("platform:/base/"); //$NON-NLS-1$ // try using platform-relative URL
810
} catch (MalformedURLException JavaDoc e) {
811             siteURL = getInstallURL(); // ensure we come up ... use absolute file URL
812
}
813         ISiteEntry defaultSite = createSiteEntry(siteURL, defaultPolicy);
814         return defaultSite;
815     }
816     
817     /**
818      * Gets the configuration lock
819      * @param url configuration directory
820      */

821     private void getConfigurationLock(URL JavaDoc url) {
822         if (!url.getProtocol().equals("file")) //$NON-NLS-1$
823
return;
824
825         File JavaDoc lockFile = new File JavaDoc(url.getFile(), ConfigurationActivator.NAME_SPACE+ File.separator+CONFIG_FILE_LOCK_SUFFIX);
826         verifyPath(url);
827         // PAL nio optional
828
lock = createLocker(lockFile);
829         try {
830             lock.lock();
831         } catch (IOException JavaDoc ioe) {
832             lock = null;
833         }
834     }
835     
836     private void clearConfigurationLock() {
837         // PAL nio optional
838
if (lock != null) {
839             lock.release();
840         }
841     }
842     
843     /**
844      * Create a locker using java new I/O or regular I/O
845      * depending whether we run in J2SE or cdcFoundation
846      * PAL nio optional
847      */

848     private static Locker createLocker(File JavaDoc lock) {
849         if (!checkNio) {
850             useNio = true;
851             try {
852                  Class.forName("java.nio.channels.FileLock"); //$NON-NLS-1$
853
} catch (ClassNotFoundException JavaDoc e) {
854                 useNio = false;
855             }
856         }
857         if (useNio)
858             return new Locker_JavaNio(lock);
859         
860         return new Locker_JavaIo(lock);
861     }
862     
863     private long computeChangeStamp() {
864         featuresChangeStamp = computeFeaturesChangeStamp();
865         pluginsChangeStamp = computePluginsChangeStamp();
866         changeStamp = Math.max(featuresChangeStamp, pluginsChangeStamp);
867         // round off to seconds
868
changeStamp = (changeStamp/1000)*1000;
869         return changeStamp;
870     }
871
872     private long computeFeaturesChangeStamp() {
873         if (featuresChangeStampIsValid)
874             return featuresChangeStamp;
875
876         long result = 0;
877         ISiteEntry[] sites = config.getSites();
878         for (int i = 0; i < sites.length; i++) {
879             result = Math.max(result, sites[i].getFeaturesChangeStamp());
880         }
881         featuresChangeStamp = result;
882         featuresChangeStampIsValid = true;
883         return featuresChangeStamp;
884     }
885
886     private long computePluginsChangeStamp() {
887         if (pluginsChangeStampIsValid)
888             return pluginsChangeStamp;
889
890         long result = 0;
891         ISiteEntry[] sites = config.getSites();
892         for (int i = 0; i < sites.length; i++) {
893             result = Math.max(result, sites[i].getPluginsChangeStamp());
894         }
895         pluginsChangeStamp = result;
896         pluginsChangeStampIsValid = true;
897         return pluginsChangeStamp;
898     }
899
900     private void configureExternalLinks() {
901         URL JavaDoc linkURL = getInstallURL();
902         if (!supportsDetection(linkURL))
903             return;
904
905         try {
906             linkURL = new URL JavaDoc(linkURL, LINKS + "/"); //$NON-NLS-1$
907
} catch (MalformedURLException JavaDoc e) {
908             // skip bad links ...
909
Utils.debug("Unable to obtain link URL"); //$NON-NLS-1$
910
return;
911         }
912
913         File JavaDoc linkDir = new File JavaDoc(linkURL.getFile());
914         File JavaDoc[] links = linkDir.listFiles();
915         if (links == null || links.length == 0) {
916             Utils.debug("No links detected in " + linkURL.toExternalForm()); //$NON-NLS-1$
917
return;
918         }
919
920         for (int i = 0; i < links.length; i++) {
921             if (links[i].isDirectory())
922                 continue;
923             Utils.debug("Link file " + links[i].getAbsolutePath()); //$NON-NLS-1$
924
Properties JavaDoc props = new Properties JavaDoc();
925             FileInputStream JavaDoc is = null;
926             try {
927                 is = new FileInputStream JavaDoc(links[i]);
928                 props.load(is);
929                 configureExternalLinkSite(links[i], props);
930             } catch (IOException JavaDoc e) {
931                 // skip bad links ...
932
Utils.debug(" unable to load link file " + e); //$NON-NLS-1$
933
continue;
934             } finally {
935                 if (is != null) {
936                     try {
937                         is.close();
938                     } catch (IOException JavaDoc e) {
939                         // ignore ...
940
}
941                 }
942             }
943         }
944     }
945
946     private void configureExternalLinkSite(File JavaDoc linkFile, Properties JavaDoc props) {
947         String JavaDoc path = props.getProperty(LINK_PATH);
948         if (path == null) {
949             Utils.debug(" no path definition"); //$NON-NLS-1$
950
return;
951         }
952
953         String JavaDoc link;
954         boolean updateable = true;
955         URL JavaDoc siteURL;
956
957         // parse out link information
958
if (path.startsWith(LINK_READ + " ")) { //$NON-NLS-1$
959
updateable = false;
960             link = path.substring(2).trim();
961         } else if (path.startsWith(LINK_READ_WRITE + " ")) { //$NON-NLS-1$
962
link = path.substring(3).trim();
963         } else {
964             link = path.trim();
965         }
966
967         // make sure we have a valid link specification
968
try {
969             File JavaDoc siteFile = new File JavaDoc(link);
970             siteFile = new File JavaDoc(siteFile, ECLIPSE);
971             siteURL = siteFile.toURL();
972             if (findConfiguredSite(siteURL, true) != null)
973                 // linked site is already known
974
return;
975         } catch (MalformedURLException JavaDoc e) {
976             // ignore bad links ...
977
Utils.debug(" bad URL " + e); //$NON-NLS-1$
978
return;
979         }
980         
981         // process the link
982
SiteEntry linkSite = (SiteEntry) externalLinkSites.get(siteURL);
983         if (linkSite == null) {
984             // this is a link to a new target so create site for it
985
ISitePolicy linkSitePolicy = createSitePolicy(getDefaultPolicy(), DEFAULT_POLICY_LIST);
986             linkSite = (SiteEntry) createSiteEntry(siteURL, linkSitePolicy);
987         }
988         // update site entry if needed
989
linkSite.setUpdateable(updateable);
990         linkSite.setLinkFileName(linkFile.getAbsolutePath());
991
992         // configure the new site
993
// NOTE: duplicates are not replaced (first one in wins)
994
configureSite(linkSite);
995         // there are changes in the config
996
config.setDirty(true);
997         Utils.debug(" " + (updateable ? "R/W -> " : "R/O -> ") + siteURL.toString()); //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$
998
}
999
1000    private void validateSites() {
1001
1002        // check to see if all sites are valid. Remove any sites that do not exist.
1003
SiteEntry[] list = config.getSites();
1004        for (int i = 0; i < list.length; i++) {
1005            URL JavaDoc siteURL = list[i].getResolvedURL();
1006            if (!supportsDetection(siteURL))
1007                continue;
1008
1009            File JavaDoc siteRoot = new File JavaDoc(siteURL.getFile().replace('/', File.separatorChar));
1010            if (!siteRoot.exists()) {
1011                unconfigureSite(list[i]);
1012                Utils.debug("Site " + siteURL + " does not exist ... removing from configuration"); //$NON-NLS-1$ //$NON-NLS-2$
1013
}
1014            
1015            // If multiple paths are defined in the same link file
1016
// or if the path changes, the old site will still be kept.
1017
// A better algorithm could be implemented by keeping track
1018
// of the previous content of the link file.
1019
// TODO do the above
1020
String JavaDoc linkName = list[i].getLinkFileName();
1021            if (linkName != null) {
1022                File JavaDoc linkFile = new File JavaDoc(linkName);
1023                if (!linkFile.exists()) {
1024                    unconfigureSite(list[i]);
1025                    config.setDirty(true);
1026                    Utils.debug("Site " + siteURL + " is no longer linked ... removing from configuration"); //$NON-NLS-1$ //$NON-NLS-2$
1027
}
1028            }
1029        }
1030    }
1031    
1032    private void linkInitializedState(Configuration sharedConfig, Location sharedConfigLocation, Location newConfigLocation) {
1033        try {
1034            URL JavaDoc newConfigIniURL = new URL JavaDoc(newConfigLocation.getURL(), CONFIG_INI);
1035            if (!newConfigIniURL.getProtocol().equals("file")) //$NON-NLS-1$
1036
return; // need to be able to do write
1037

1038            // modify config.ini and platform.xml to only link original files
1039
File JavaDoc configIni = new File JavaDoc(newConfigIniURL.getFile());
1040            Properties JavaDoc props = new Properties JavaDoc();
1041            String JavaDoc externalForm = Utils.makeRelative(Utils.getInstallURL(), sharedConfigLocation.getURL()).toExternalForm();
1042            props.put("osgi.sharedConfiguration.area", externalForm); //$NON-NLS-1$
1043
props.store(new FileOutputStream JavaDoc(configIni), "Linked configuration"); //$NON-NLS-1$
1044

1045            config = new Configuration(new Date JavaDoc());
1046            config.setURL(new URL JavaDoc(newConfigLocation.getURL(), CONFIG_NAME));
1047            config.setLinkedConfig(sharedConfig);
1048            config.setDirty(true);
1049        } catch (IOException JavaDoc e) {
1050            // this is an optimistic copy. If we fail, the state will be reconciled
1051
// when the update manager is triggered.
1052
System.out.println(e);
1053        }
1054    }
1055    
1056    private Configuration loadConfig(URL JavaDoc url) throws Exception JavaDoc {
1057        if (url == null)
1058            throw new IOException JavaDoc(Messages.cfig_unableToLoad_noURL);
1059
1060        // try to load saved configuration file (watch for failed prior save())
1061
ConfigurationParser parser = null;
1062        try {
1063            parser = new ConfigurationParser();
1064        } catch (InvocationTargetException JavaDoc e) {
1065            throw (Exception JavaDoc)e.getTargetException();
1066        }
1067        
1068        config = null;
1069        Exception JavaDoc originalException = null;
1070        try {
1071            config = parser.parse(url);
1072            if (config == null)
1073                throw new Exception JavaDoc(Messages.PlatformConfiguration_cannotFindConfigFile);
1074        } catch (Exception JavaDoc e1) {
1075            // check for save failures, so open temp and backup configurations
1076
originalException = e1;
1077            try {
1078                URL JavaDoc tempURL = new URL JavaDoc(url.toExternalForm()+CONFIG_FILE_TEMP_SUFFIX);
1079                config = parser.parse(tempURL);
1080                if (config == null)
1081                    throw new Exception JavaDoc();
1082                config.setDirty(true); // force saving to platform.xml
1083
} catch (Exception JavaDoc e2) {
1084                try {
1085                    // check the backup
1086
if ("file".equals(url.getProtocol())) { //$NON-NLS-1$
1087
File JavaDoc cfigFile = new File JavaDoc(url.getFile().replace('/', File.separatorChar));
1088                        File JavaDoc workingDir = cfigFile.getParentFile();
1089                        if (workingDir != null && workingDir.exists()) {
1090                            File JavaDoc[] backups = workingDir.listFiles(new FileFilter JavaDoc(){
1091                                public boolean accept(File JavaDoc pathname) {
1092                                    return pathname.isFile() && pathname.getName().endsWith(".xml"); //$NON-NLS-1$
1093
}});
1094                            if (backups != null && backups.length > 0) {
1095                                URL JavaDoc backupUrl = backups[backups.length-1].toURL();
1096                                config = parser.parse(backupUrl);
1097                            }
1098                        }
1099                    }
1100                    if (config == null)
1101                        throw originalException; // we tried, but no config here ...
1102
config.setDirty(true); // force saving to platform.xml
1103
} catch (IOException JavaDoc e3) {
1104                    throw originalException; // we tried, but no config here ...
1105
}
1106            }
1107        }
1108
1109        return config;
1110    }
1111
1112    public static boolean supportsDetection(URL JavaDoc url) {
1113        String JavaDoc protocol = url.getProtocol();
1114        if (protocol.equals("file")) //$NON-NLS-1$
1115
return true;
1116        else if (protocol.equals("platform")) { //$NON-NLS-1$
1117
URL JavaDoc resolved = null;
1118            try {
1119                resolved = resolvePlatformURL(url); // 19536
1120
} catch (IOException JavaDoc e) {
1121                return false; // we tried but failed to resolve the platform URL
1122
}
1123            return resolved.getProtocol().equals("file"); //$NON-NLS-1$
1124
} else
1125            return false;
1126    }
1127
1128    private static void verifyPath(URL JavaDoc url) {
1129        String JavaDoc protocol = url.getProtocol();
1130        String JavaDoc path = null;
1131        if (protocol.equals("file")) //$NON-NLS-1$
1132
path = url.getFile();
1133        else if (protocol.equals("platform")) { //$NON-NLS-1$
1134
URL JavaDoc resolved = null;
1135            try {
1136                resolved = resolvePlatformURL(url); // 19536
1137
if (resolved.getProtocol().equals("file")) //$NON-NLS-1$
1138
path = resolved.getFile();
1139            } catch (IOException JavaDoc e) {
1140                // continue ...
1141
}
1142        }
1143
1144        if (path != null) {
1145            File JavaDoc dir = new File JavaDoc(path).getParentFile();
1146            if (dir != null)
1147                dir.mkdirs();
1148        }
1149    }
1150
1151    public static URL JavaDoc resolvePlatformURL(URL JavaDoc url) throws IOException JavaDoc {
1152        if (url.getProtocol().equals("platform")) { //$NON-NLS-1$
1153
url = FileLocator.toFileURL(url);
1154            File JavaDoc f = new File JavaDoc(url.getFile());
1155            url = f.toURL();
1156        }
1157        return url;
1158    }
1159    
1160    public static URL JavaDoc getInstallURL() {
1161        return installURL;
1162    }
1163    
1164    // Patch from Phil to support cdc/foundation: will use the method below instead of this one.
1165
// private void saveAsXML(OutputStream stream) throws CoreException {
1166
// StreamResult result = null;
1167
// try {
1168
// DocumentBuilder docBuilder = documentBuilderFactory.newDocumentBuilder();
1169
// Document doc = docBuilder.newDocument();
1170
//
1171
// if (config == null)
1172
// throw Utils.newCoreException(Messages.getString("PlatformConfiguration.cannotSaveNonExistingConfig"),null); //$NON-NLS-1$
1173
//
1174
// config.setDate(new Date());
1175
// doc.appendChild(doc.createComment("Created on " + config.getDate().toString())); //$NON-NLS-1$
1176
// Element configElement = config.toXML(doc);
1177
// doc.appendChild(configElement);
1178
//
1179
// // Write out to a file
1180
//
1181
// Transformer transformer=transformerFactory.newTransformer();
1182
// transformer.setOutputProperty(OutputKeys.METHOD, "xml"); //$NON-NLS-1$
1183
// transformer.setOutputProperty(OutputKeys.ENCODING, "UTF-8"); //$NON-NLS-1$
1184
// transformer.setOutputProperty(OutputKeys.INDENT, "yes"); //$NON-NLS-1$
1185
// DOMSource source = new DOMSource(doc);
1186
// result = new StreamResult(stream);
1187
//
1188
// transformer.transform(source,result);
1189
// //will close the stream in the caller
1190
// //stream.close();
1191
// } catch (Exception e) {
1192
// throw Utils.newCoreException("", e); //$NON-NLS-1$
1193
// } finally {
1194
// result.setOutputStream(null);
1195
// result = null;
1196
// }
1197
// }
1198

1199    private void saveAsXML(OutputStream JavaDoc stream) throws CoreException,IOException JavaDoc {
1200        BufferedWriter JavaDoc xmlWriter = new BufferedWriter JavaDoc(new OutputStreamWriter JavaDoc(stream,XML_ENCODING));
1201        try {
1202            DocumentBuilderFactory JavaDoc factory = DocumentBuilderFactory.newInstance();
1203            factory.setExpandEntityReferences(false);
1204            factory.setValidating(false);
1205            factory.setIgnoringComments(true);
1206            DocumentBuilder JavaDoc docBuilder = factory.newDocumentBuilder();
1207            Document JavaDoc doc = docBuilder.newDocument();
1208            
1209            if (config == null)
1210                throw Utils.newCoreException(Messages.PlatformConfiguration_cannotSaveNonExistingConfig,null);
1211            
1212            config.setDate(new Date JavaDoc());
1213            Element JavaDoc configElement = config.toXML(doc);
1214            doc.appendChild(configElement);
1215            
1216            // This is not DBCS friendly... PAL
1217
//XMLPrintHandler.printComment(xmlWriter,"Created on " + config.getDate().toString());
1218
XMLPrintHandler.printNode(xmlWriter,doc,XML_ENCODING);
1219            
1220        } catch (Exception JavaDoc e) {
1221            throw Utils.newCoreException("", e); //$NON-NLS-1$
1222
} finally {
1223            xmlWriter.flush();
1224            // will close the stream in the caller
1225
//xmlWriter.close();
1226
}
1227    }
1228    
1229    private void reconcile() throws CoreException {
1230        long lastChange = config.getDate().getTime();
1231        SiteEntry[] sites = config.getSites();
1232        for (int s = 0; s < sites.length; s++) {
1233            if (sites[s].isUpdateable()) {
1234                long siteTimestamp = sites[s].getChangeStamp();
1235                if (siteTimestamp > lastChange)
1236                    sites[s].loadFromDisk(lastChange);
1237            }
1238        }
1239        config.setDirty(true);
1240    }
1241    
1242    public Configuration getConfiguration() {
1243        return config;
1244    }
1245}
1246
Popular Tags