| /******************************************************************************* |
| * Copyright (c) 2000, 2003 IBM Corporation and others. |
| * All rights reserved. This program and the accompanying materials |
| * are made available under the terms of the Common Public License v1.0 |
| * which accompanies this distribution, and is available at |
| * http://www.eclipse.org/legal/cpl-v10.html |
| * |
| * Contributors: |
| * IBM Corporation - initial API and implementation |
| *******************************************************************************/ |
| package org.eclipse.update.internal.configurator; |
| |
| import java.io.*; |
| import java.net.*; |
| import java.util.*; |
| |
| import javax.xml.parsers.*; |
| import javax.xml.transform.*; |
| import javax.xml.transform.dom.*; |
| import javax.xml.transform.stream.*; |
| |
| import org.eclipse.core.internal.boot.*; |
| import org.eclipse.update.configurator.*; |
| import org.w3c.dom.*; |
| |
| public class PlatformConfiguration implements IPlatformConfiguration { |
| |
| private static PlatformConfiguration currentPlatformConfiguration = null; |
| private static final DocumentBuilderFactory documentBuilderFactory = DocumentBuilderFactory.newInstance(); |
| private static final TransformerFactory transformerFactory = TransformerFactory.newInstance(); |
| |
| private URL configLocation; |
| private HashMap sites; |
| private HashMap externalLinkSites; // used to restore prior link site state |
| private HashMap cfgdFeatures; |
| private HashMap bootPlugins; |
| private String defaultFeature; |
| private long changeStamp; |
| private boolean changeStampIsValid = false; |
| private long lastFeaturesChangeStamp; |
| private long featuresChangeStamp; |
| private boolean featuresChangeStampIsValid = false; |
| private long lastPluginsChangeStamp; |
| private long pluginsChangeStamp; |
| private boolean pluginsChangeStampIsValid = false; |
| private boolean transientConfig = false; |
| private File cfgLockFile; |
| private RandomAccessFile cfgLockFileRAF; |
| |
| private static String cmdFeature = null; |
| private static String cmdApplication = null; |
| private static boolean cmdInitialize = false; |
| private static boolean cmdFirstUse = false; |
| private static boolean cmdUpdate = false; |
| private static boolean cmdNoUpdate = false; |
| private static boolean cmdDev = false; |
| private static boolean cmdNoLinkedConfig = true; |
| |
| private static final String ECLIPSE = "eclipse"; //$NON-NLS-1$ |
| private static final String CONFIG_DIR = ".config"; //$NON-NLS-1$ |
| private static final String CONFIG_NAME = "platform.cfg"; //$NON-NLS-1$ |
| private static final String CONFIG_FILE = CONFIG_DIR + "/" + CONFIG_NAME; //$NON-NLS-1$ |
| private static final String CONFIG_FILE_INIT = "install.ini"; //$NON-NLS-1$ |
| private static final String CONFIG_INI = "config.ini"; //NON-NLS-1$ |
| private static final String CONFIG_FILE_LOCK_SUFFIX = ".lock"; //$NON-NLS-1$ |
| private static final String CONFIG_FILE_TEMP_SUFFIX = ".tmp"; //$NON-NLS-1$ |
| private static final String CONFIG_FILE_BAK_SUFFIX = ".bak"; //$NON-NLS-1$ |
| private static final String CHANGES_MARKER = ".newupdates"; //$NON-NLS-1$ |
| private static final String LINKS = "links"; //$NON-NLS-1$ |
| private static final String[] BOOTSTRAP_PLUGINS = { "org.eclipse.core.boot" }; //$NON-NLS-1$ |
| private static final String CFG = "config"; //$NON-NLS-1$ |
| private static final String CFG_BOOT_PLUGIN = "bootstrap"; //$NON-NLS-1$ |
| private static final String CFG_SITE = "site"; //$NON-NLS-1$ |
| private static final String CFG_URL = "url"; //$NON-NLS-1$ |
| private static final String CFG_POLICY = "policy"; //$NON-NLS-1$ |
| private static final String[] CFG_POLICY_TYPE = { "USER-INCLUDE", "USER-EXCLUDE" }; //$NON-NLS-1$ //$NON-NLS-2$ |
| private static final String CFG_POLICY_TYPE_UNKNOWN = "UNKNOWN"; //$NON-NLS-1$ |
| private static final String CFG_LIST = "list"; //$NON-NLS-1$ |
| private static final String CFG_STAMP = "stamp"; //$NON-NLS-1$ |
| private static final String CFG_FEATURE_STAMP = "stamp.features"; //$NON-NLS-1$ |
| private static final String CFG_PLUGIN_STAMP = "stamp.plugins"; //$NON-NLS-1$ |
| private static final String CFG_UPDATEABLE = "updateable"; //$NON-NLS-1$ |
| private static final String CFG_LINK_FILE = "linkfile"; //$NON-NLS-1$ |
| private static final String CFG_FEATURE_ENTRY = "feature"; //$NON-NLS-1$ |
| private static final String CFG_FEATURE_ENTRY_DEFAULT = "feature.default.id"; //$NON-NLS-1$ |
| private static final String CFG_FEATURE_ENTRY_ID = "id"; //$NON-NLS-1$ |
| private static final String CFG_FEATURE_ENTRY_PRIMARY = "primary"; //$NON-NLS-1$ |
| private static final String CFG_FEATURE_ENTRY_VERSION = "version"; //$NON-NLS-1$ |
| private static final String CFG_FEATURE_ENTRY_PLUGIN_VERSION = "plugin-version"; //$NON-NLS-1$ |
| private static final String CFG_FEATURE_ENTRY_PLUGIN_IDENTIFIER = "plugin-identifier"; //$NON-NLS-1$ |
| private static final String CFG_FEATURE_ENTRY_APPLICATION = "application"; //$NON-NLS-1$ |
| private static final String CFG_FEATURE_ENTRY_ROOT = "root"; //$NON-NLS-1$ |
| |
| private static final String INIT_DEFAULT_FEATURE_ID = "feature.default.id"; //$NON-NLS-1$ |
| private static final String INIT_DEFAULT_PLUGIN_ID = "feature.default.plugin.id"; //$NON-NLS-1$ |
| private static final String INIT_DEFAULT_FEATURE_APPLICATION = "feature.default.application"; //$NON-NLS-1$ |
| private static final String DEFAULT_FEATURE_ID = "org.eclipse.platform"; //$NON-NLS-1$ |
| private static final String DEFAULT_FEATURE_APPLICATION = "org.eclipse.ui.ide.workbench"; //$NON-NLS-1$ |
| |
| private static final String CFG_VERSION = "version"; //$NON-NLS-1$ |
| private static final String CFG_TRANSIENT = "transient"; //$NON-NLS-1$ |
| private static final String VERSION = "2.1"; //$NON-NLS-1$ |
| private static final String EOF = "eof"; //$NON-NLS-1$ |
| private static final int CFG_LIST_LENGTH = 10; |
| |
| private static final int DEFAULT_POLICY_TYPE = ISitePolicy.USER_EXCLUDE; |
| private static final String[] DEFAULT_POLICY_LIST = new String[0]; |
| |
| private static final String LINK_PATH = "path"; //$NON-NLS-1$ |
| private static final String LINK_READ = "r"; //$NON-NLS-1$ |
| private static final String LINK_READ_WRITE = "rw"; //$NON-NLS-1$ |
| |
| private static final String CMD_FEATURE = "-feature"; //$NON-NLS-1$ |
| private static final String CMD_APPLICATION = "-application"; //$NON-NLS-1$ |
| private static final String CMD_UPDATE = "-update"; //$NON-NLS-1$ |
| private static final String CMD_INITIALIZE = "-initialize"; //$NON-NLS-1$ |
| private static final String CMD_FIRSTUSE = "-firstuse"; //$NON-NLS-1$ |
| private static final String CMD_NO_UPDATE = "-noupdate"; //$NON-NLS-1$ |
| private static final String CMD_NEW_UPDATES = "-newUpdates"; //$NON-NLS-1$ |
| private static final String CMD_DEV = "-dev"; // triggers -noupdate //$NON-NLS-1$ |
| private static final String CMD_NO_LINKED_CONFIG = "-no_linked_config"; |
| |
| public static final String RECONCILER_APP = "org.eclipse.update.core.reconciler"; //$NON-NLS-1$ |
| |
| private static final char[] HEX = { '0', '1', '2', '3', '4', '5', '6', '7', '8', '9', 'A', 'B', 'C', 'D', 'E', 'F' }; |
| |
| private static URL installURL; |
| |
| |
| private PlatformConfiguration(String configPath) throws IOException { |
| this.sites = new HashMap(); |
| this.externalLinkSites = new HashMap(); |
| this.cfgdFeatures = new HashMap(); |
| this.bootPlugins = new HashMap(); |
| |
| // initialize configuration |
| initializeCurrent(configPath); |
| |
| // pick up any first-time default settings (relative to install location) |
| loadInitializationAttributes(); |
| |
| // Detect external links. These are "soft link" to additional sites. The link |
| // files are usually provided by external installation programs. They are located |
| // relative to this configuration URL. |
| configureExternalLinks(); |
| |
| // Validate sites in the configuration. Causes any sites that do not exist to |
| // be removed from the configuration |
| validateSites(); |
| |
| // compute differences between configuration and actual content of the sites |
| // (base sites and link sites) |
| computeChangeStamp(); |
| |
| // determine which plugins we will use to start the rest of the "kernel" |
| // (need to get core.runtime matching the executing core.boot and |
| // xerces matching the selected core.runtime) |
| // locateDefaultPlugins(); |
| } |
| |
| PlatformConfiguration(URL url) throws IOException { |
| this.sites = new HashMap(); |
| this.externalLinkSites = new HashMap(); |
| this.cfgdFeatures = new HashMap(); |
| this.bootPlugins = new HashMap(); |
| initialize(url); |
| } |
| |
| /* |
| * @see IPlatformConfiguration#createSiteEntry(URL, ISitePolicy) |
| */ |
| public ISiteEntry createSiteEntry(URL url, ISitePolicy policy) { |
| return new SiteEntry(url, policy, this); |
| } |
| |
| /* |
| * @see IPlatformConfiguration#createSitePolicy(int, String[]) |
| */ |
| public ISitePolicy createSitePolicy(int type, String[] list) { |
| return new SitePolicy(type, list); |
| } |
| |
| /* |
| * @see IPlatformConfiguration#createFeatureEntry(String, String, String, boolean, String, URL) |
| */ |
| public IFeatureEntry createFeatureEntry(String id, String version, String pluginVersion, boolean primary, String application, URL[] root) { |
| return new FeatureEntry(id, version, pluginVersion, primary, application, root); |
| } |
| |
| /* |
| * @see IPlatformConfiguration#createFeatureEntry(String, String, String, |
| * String, boolean, String, URL) |
| */ |
| public IFeatureEntry createFeatureEntry(String id, String version, String pluginIdentifier, String pluginVersion, boolean primary, String application, URL[] root) { |
| return new FeatureEntry(id, version, pluginIdentifier, pluginVersion, primary, application, root); |
| } |
| |
| /* |
| * @see IPlatformConfiguration#configureSite(ISiteEntry) |
| */ |
| public void configureSite(ISiteEntry entry) { |
| configureSite(entry, false); |
| } |
| |
| /* |
| * @see IPlatformConfiguration#configureSite(ISiteEntry, boolean) |
| */ |
| public synchronized void configureSite(ISiteEntry entry, boolean replace) { |
| |
| if (entry == null) |
| return; |
| |
| URL url = entry.getURL(); |
| if (url == null) |
| return; |
| String key = url.toExternalForm(); |
| |
| if (sites.containsKey(key) && !replace) |
| return; |
| |
| sites.put(key, entry); |
| } |
| |
| /* |
| * @see IPlatformConfiguration#unconfigureSite(ISiteEntry) |
| */ |
| public synchronized void unconfigureSite(ISiteEntry entry) { |
| if (entry == null) |
| return; |
| |
| URL url = entry.getURL(); |
| if (url == null) |
| return; |
| String key = url.toExternalForm(); |
| |
| sites.remove(key); |
| } |
| |
| /* |
| * @see IPlatformConfiguration#getConfiguredSites() |
| */ |
| public ISiteEntry[] getConfiguredSites() { |
| if (sites.size() == 0) |
| return new ISiteEntry[0]; |
| |
| return (ISiteEntry[]) sites.values().toArray(new ISiteEntry[0]); |
| } |
| |
| /* |
| * @see IPlatformConfiguration#findConfiguredSite(URL) |
| */ |
| public ISiteEntry findConfiguredSite(URL url) { |
| if (url == null) |
| return null; |
| String key = url.toExternalForm(); |
| |
| ISiteEntry result = (ISiteEntry) sites.get(key); |
| try { |
| key = URLDecoder.decode(key, "UTF-8"); |
| } catch (UnsupportedEncodingException e) { |
| // ignore |
| } |
| |
| if (result == null) // retry with decoded URL string |
| result = (ISiteEntry) sites.get(key); |
| |
| return result; |
| } |
| |
| /* |
| * @see IPlatformConfiguration#configureFeatureEntry(IFeatureEntry) |
| */ |
| public synchronized void configureFeatureEntry(IFeatureEntry entry) { |
| if (entry == null) |
| return; |
| |
| String key = entry.getFeatureIdentifier(); |
| if (key == null) |
| return; |
| |
| cfgdFeatures.put(key, entry); |
| } |
| |
| /* |
| * @see IPlatformConfiguration#unconfigureFeatureEntry(IFeatureEntry) |
| */ |
| public synchronized void unconfigureFeatureEntry(IFeatureEntry entry) { |
| if (entry == null) |
| return; |
| |
| String key = entry.getFeatureIdentifier(); |
| if (key == null) |
| return; |
| |
| cfgdFeatures.remove(key); |
| } |
| |
| /* |
| * @see IPlatformConfiguration#getConfiguredFeatureEntries() |
| */ |
| public IFeatureEntry[] getConfiguredFeatureEntries() { |
| if (cfgdFeatures.size() == 0) |
| return new IFeatureEntry[0]; |
| |
| return (IFeatureEntry[]) cfgdFeatures.values().toArray(new IFeatureEntry[0]); |
| } |
| |
| /* |
| * @see IPlatformConfiguration#findConfiguredFeatureEntry(String) |
| */ |
| public IFeatureEntry findConfiguredFeatureEntry(String id) { |
| if (id == null) |
| return null; |
| |
| return (IFeatureEntry) cfgdFeatures.get(id); |
| } |
| |
| /* |
| * @see IPlatformConfiguration#getConfigurationLocation() |
| */ |
| public URL getConfigurationLocation() { |
| return configLocation; |
| } |
| |
| /* |
| * @see IPlatformConfiguration#getChangeStamp() |
| */ |
| public long getChangeStamp() { |
| if (!changeStampIsValid) |
| computeChangeStamp(); |
| return changeStamp; |
| } |
| |
| /* |
| * @see IPlatformConfiguration#getFeaturesChangeStamp() |
| */ |
| public long getFeaturesChangeStamp() { |
| if (!featuresChangeStampIsValid) |
| computeFeaturesChangeStamp(); |
| return featuresChangeStamp; |
| } |
| |
| /* |
| * @see IPlatformConfiguration#getPluginsChangeStamp() |
| */ |
| public long getPluginsChangeStamp() { |
| if (!pluginsChangeStampIsValid) |
| computePluginsChangeStamp(); |
| return pluginsChangeStamp; |
| } |
| |
| /* |
| * @see IPlatformConfiguration#getApplicationIdentifier() |
| */ |
| public String getApplicationIdentifier() { |
| |
| if (cmdInitialize) { |
| // we are running post-install initialization. Force |
| // running of the reconciler |
| return RECONCILER_APP; |
| } |
| |
| if (featuresChangeStamp != lastFeaturesChangeStamp) { |
| // we have detected feature changes ... see if we need to reconcile |
| boolean update = !cmdNoUpdate || cmdUpdate; |
| if (update) |
| return RECONCILER_APP; |
| } |
| |
| // "normal" startup ... run specified application |
| return getApplicationIdentifierInternal(); |
| } |
| |
| private String getApplicationIdentifierInternal() { |
| |
| if (cmdApplication != null) // application was specified |
| return cmdApplication; |
| else { |
| // if -feature was not specified use the default feature |
| String feature = cmdFeature; |
| if (feature == null) |
| feature = defaultFeature; |
| |
| // lookup application for feature (specified or defaulted) |
| if (feature != null) { |
| IFeatureEntry fe = findConfiguredFeatureEntry(feature); |
| if (fe != null) { |
| if (fe.getFeatureApplication() != null) |
| return fe.getFeatureApplication(); |
| } |
| } |
| } |
| |
| // return hardcoded default if we failed |
| return DEFAULT_FEATURE_APPLICATION; |
| } |
| |
| /* |
| * @see IPlatformConfiguration#getPrimaryFeatureIdentifier() |
| */ |
| public String getPrimaryFeatureIdentifier() { |
| String primaryFeatureId = null; |
| if (cmdFeature != null) // -feature was specified on command line |
| primaryFeatureId = cmdFeature; |
| else if (defaultFeature != null) |
| primaryFeatureId = defaultFeature; // return customized default if set |
| else |
| primaryFeatureId = DEFAULT_FEATURE_ID; // return hardcoded default |
| |
| // check if feature exists |
| if (findConfiguredFeatureEntry(primaryFeatureId) == null) |
| return null; |
| else |
| return primaryFeatureId; |
| } |
| |
| /* |
| * @see IPlatformConfiguration#getPluginPath() |
| */ |
| public URL[] getPluginPath() { |
| ArrayList path = new ArrayList(); |
| Utils.debug("computed plug-in path:"); //$NON-NLS-1$ |
| |
| ISiteEntry[] sites = getConfiguredSites(); |
| URL pathURL; |
| for (int i = 0; i < sites.length; i++) { |
| String[] plugins = sites[i].getPlugins(); |
| for (int j = 0; j < plugins.length; j++) { |
| try { |
| pathURL = new URL(((SiteEntry) sites[i]).getResolvedURL(), plugins[j]); |
| path.add(pathURL); |
| Utils.debug(" " + pathURL.toString()); //$NON-NLS-1$ |
| } catch (MalformedURLException e) { |
| // skip entry ... |
| Utils.debug(" bad URL: " + e); //$NON-NLS-1$ |
| } |
| } |
| } |
| return (URL[]) path.toArray(new URL[0]); |
| } |
| |
| /* |
| * @see IPlatformConfiguration#getBootstrapPluginIdentifiers() |
| */ |
| public String[] getBootstrapPluginIdentifiers() { |
| return BOOTSTRAP_PLUGINS; |
| } |
| |
| /* |
| * @see IPlatformConfiguration#setBootstrapPluginLocation(String, URL) |
| */ |
| public void setBootstrapPluginLocation(String id, URL location) { |
| String[] ids = getBootstrapPluginIdentifiers(); |
| for (int i = 0; i < ids.length; i++) { |
| if (ids[i].equals(id)) { |
| bootPlugins.put(id, location.toExternalForm()); |
| break; |
| } |
| } |
| } |
| |
| /* |
| * @see IPlatformConfiguration#isUpdateable() |
| */ |
| public boolean isUpdateable() { |
| return true; |
| } |
| |
| /* |
| * @see IPlatformConfiguration#isTransient() |
| */ |
| public boolean isTransient() { |
| return transientConfig; |
| } |
| |
| /* |
| * @see IPlatformConfiguration#isTransient(boolean) |
| */ |
| public void isTransient(boolean value) { |
| // if (this != BootLoader.getCurrentPlatformConfiguration()) |
| // transientConfig = value; |
| } |
| |
| /* |
| * @see IPlatformConfiguration#refresh() |
| */ |
| public synchronized void refresh() { |
| // Reset computed values. Will be lazily refreshed |
| // on next access |
| ISiteEntry[] sites = getConfiguredSites(); |
| for (int i = 0; i < sites.length; i++) { |
| // reset site entry |
| ((SiteEntry) sites[i]).refresh(); |
| } |
| // reset configuration entry. |
| lastFeaturesChangeStamp = featuresChangeStamp; |
| lastPluginsChangeStamp = pluginsChangeStamp; |
| changeStampIsValid = false; |
| featuresChangeStampIsValid = false; |
| pluginsChangeStampIsValid = false; |
| } |
| |
| /* |
| * @see IPlatformConfiguration#save() |
| */ |
| public void save() throws IOException { |
| if (isUpdateable()) |
| save(configLocation); |
| } |
| |
| /* |
| * @see IPlatformConfiguration#save(URL) |
| */ |
| public synchronized void save(URL url) throws IOException { |
| if (url == null) |
| throw new IOException(Messages.getString("cfig.unableToSave.noURL")); //$NON-NLS-1$ |
| |
| PrintWriter w = null; |
| OutputStream os = null; |
| if (!url.getProtocol().equals("file")) { //$NON-NLS-1$ |
| // not a file protocol - attempt to save to the URL |
| URLConnection uc = url.openConnection(); |
| uc.setDoOutput(true); |
| os = uc.getOutputStream(); |
| w = new PrintWriter(os); |
| try { |
| write(w); |
| } finally { |
| w.close(); |
| } |
| } else { |
| // file protocol - do safe i/o |
| File cfigFile = new File(url.getFile().replace('/', File.separatorChar)); |
| if (!cfigFile.getName().equals(CONFIG_NAME)) |
| cfigFile = new File(cfigFile, CONFIG_NAME); |
| File cfigDir = cfigFile.getParentFile(); |
| if (cfigDir != null) |
| cfigDir.mkdirs(); |
| |
| // If config.ini does not exist, generate it |
| writeConfigIni(cfigDir); |
| |
| // first save the file as temp |
| File cfigTmp = new File(cfigFile.getAbsolutePath() + CONFIG_FILE_TEMP_SUFFIX); |
| os = new FileOutputStream(cfigTmp); |
| w = new PrintWriter(os); |
| try { |
| write(w); |
| //saveAsXML(new File(cfigDir, "platform.xml")); |
| } finally { |
| w.close(); |
| } |
| |
| // make sure we actually succeeded saving the whole configuration. |
| InputStream is = new FileInputStream(cfigTmp); |
| Properties tmpProps = new Properties(); |
| try { |
| tmpProps.load(is); |
| if (!EOF.equals(tmpProps.getProperty(EOF))) { |
| throw new IOException(Messages.getString("cfig.unableToSave", cfigTmp.getAbsolutePath())); //$NON-NLS-1$ |
| } |
| } finally { |
| is.close(); |
| } |
| |
| // make the saved config the "active" one |
| File cfigBak = new File(cfigFile.getAbsolutePath() + CONFIG_FILE_BAK_SUFFIX); |
| cfigBak.delete(); // may have old .bak due to prior failure |
| |
| if (cfigFile.exists()) |
| cfigFile.renameTo(cfigBak); |
| |
| // at this point we have old config (if existed) as "bak" and the |
| // new config as "tmp". |
| boolean ok = cfigTmp.renameTo(cfigFile); |
| if (ok) { |
| // at this point we have the new config "activated", and the old |
| // config (if it existed) as "bak" |
| cfigBak.delete(); // clean up |
| } else { |
| // this codepath represents a tiny failure window. The load processing |
| // on startup will detect missing config and will attempt to start |
| // with "tmp" (latest), then "bak" (the previous). We can also end up |
| // here if we failed to rename the current config to "bak". In that |
| // case we will restart with the previous state. |
| throw new IOException(Messages.getString("cfig.unableToSave", cfigTmp.getAbsolutePath())); //$NON-NLS-1$ |
| } |
| } |
| } |
| |
| private void writeConfigIni(File configDir) { |
| try { |
| File configIni = new File(configDir, CONFIG_INI); |
| if (!configIni.exists()) { |
| URL configIniURL = ConfigurationActivator.getBundleContext().getBundle().getEntry(CONFIG_INI); |
| copy(configIniURL, configIni); |
| } |
| } catch (Exception e) { |
| System.out.println(Messages.getString("cfg.unableToCreateConfig.ini")); |
| } |
| } |
| |
| public static PlatformConfiguration getCurrent() { |
| return currentPlatformConfiguration; |
| } |
| |
| /** |
| * Create and initialize the current platform configuration |
| * @param cmdArgs command line arguments (startup and boot arguments are |
| * already consumed) |
| * @param r10apps application identifies as passed on the BootLoader.run(...) |
| * method. Supported for R1.0 compatibility. |
| */ |
| public static synchronized String[] startup(String[] cmdArgs, String r10app, URL installURL, String configPath) throws Exception { |
| PlatformConfiguration.installURL = installURL; |
| |
| cmdApplication = r10app; // R1.0 compatibility |
| |
| // process command line arguments |
| String[] passthruArgs = processCommandLine(cmdArgs); |
| if (cmdDev) |
| cmdNoUpdate = true; // force -noupdate when in dev mode (eg. PDE) |
| |
| // create current configuration |
| if (currentPlatformConfiguration == null) |
| currentPlatformConfiguration = new PlatformConfiguration(configPath); |
| |
| // check if we will be forcing reconciliation |
| passthruArgs = checkForFeatureChanges(passthruArgs, currentPlatformConfiguration); |
| |
| // check if we should indicate new changes |
| passthruArgs = checkForNewUpdates(currentPlatformConfiguration, passthruArgs); |
| |
| return passthruArgs; |
| } |
| |
| public static synchronized void shutdown() throws IOException { |
| |
| // save platform configuration |
| PlatformConfiguration config = getCurrent(); |
| if (config != null) { |
| try { |
| config.save(); |
| } catch (IOException e) { |
| Utils.debug("Unable to save configuration " + e.toString()); //$NON-NLS-1$ |
| // will recover on next startup |
| } |
| config.clearConfigurationLock(); |
| } |
| } |
| |
| private synchronized void initializeCurrent(String configPath) throws IOException { |
| // FIXME: commented out for now. Remove if not needed. |
| //boolean concurrentUse = false; |
| |
| if (cmdInitialize) { |
| // we are running post-install initialization (-install command |
| // line argument). Ignore any configuration URL passed in. |
| // Force the configuration to be saved in the install location. |
| // Allow an existing configuration to be re-initialized. |
| URL url = new URL(getInstallURL(), CONFIG_FILE); // if we fail here, return exception |
| // FIXME: commented out for now. Remove if not needed. |
| // I left the call to #getConfigurationLock in just in case |
| // calling it has useful side effect. If not, then it can be removed too. |
| //concurrentUse = getConfigurationLock(url); |
| getConfigurationLock(url); |
| |
| resetInitializationConfiguration(url); // [20111] |
| |
| configureSite(getRootSite()); |
| Utils.debug("Initializing configuration " + url.toString()); //$NON-NLS-1$ |
| configLocation = url; |
| verifyPath(configLocation); |
| return; |
| } |
| |
| // Configuration URL was is specified by the OSGi layer. |
| // Default behavior is to look |
| // for configuration in the specified meta area. If not found, look |
| // for pre-initialized configuration in the installation location. |
| // If it is found it is used as the initial configuration. Otherwise |
| // a new configuration is created. In either case the resulting |
| // configuration is written into the specified configuration area. |
| |
| URL configDirURL = new URL("file", "", configPath); |
| URL configFileURL = new URL("file", "", configPath + "/" + CONFIG_NAME); |
| try { |
| // check concurrent use lock |
| // FIXME: might not need this method call. |
| getConfigurationLock(configFileURL); |
| |
| // try loading the configuration |
| try { |
| load(configFileURL); |
| Utils.debug("Using configuration " + configFileURL.toString()); //$NON-NLS-1$ |
| } catch (IOException e) { |
| // failed to load, see if we can find pre-initialized configuration. |
| // Don't attempt this initialization when self-hosting (is unpredictable) |
| try { |
| URL sharedConfigDirURL = new URL(getInstallURL(), CONFIG_DIR); |
| URL sharedConfigFileURL = new URL(getInstallURL(), CONFIG_FILE); |
| |
| load(sharedConfigFileURL); |
| |
| // pre-initialized config loaded OK ... copy any remaining update metadata |
| // Only copy if the default config location is not the install location |
| if (!sharedConfigDirURL.equals(configDirURL)) { |
| // if (cmdNoLinkedConfig) |
| // // need to link config info instead of using a copy |
| // linkInitializedState(sharedConfigDirURL, configPath); |
| // else |
| // copy config info |
| copyInitializedState(sharedConfigDirURL, configPath); |
| |
| Utils.debug("Configuration initialized from " + sharedConfigDirURL.toString()); //$NON-NLS-1$ |
| } |
| return; |
| } catch (IOException ioe) { |
| cmdFirstUse = true; |
| // we are creating new configuration |
| configureSite(getRootSite()); |
| } |
| } |
| } finally { |
| configLocation = configFileURL; |
| verifyPath(configLocation); |
| Utils.debug("Creating configuration " + configFileURL.toString()); //$NON-NLS-1$ |
| } |
| } |
| |
| private synchronized void initialize(URL url) throws IOException { |
| if (url == null) { |
| Utils.debug("Creating empty configuration object"); //$NON-NLS-1$ |
| return; |
| } |
| |
| load(url); |
| configLocation = url; |
| Utils.debug("Using configuration " + configLocation.toString()); //$NON-NLS-1$ |
| } |
| |
| private ISiteEntry getRootSite() { |
| // create default site entry for the root |
| ISitePolicy defaultPolicy = createSitePolicy(DEFAULT_POLICY_TYPE, DEFAULT_POLICY_LIST); |
| URL siteURL = null; |
| try { |
| siteURL = new URL(PlatformURLHandler.PROTOCOL + PlatformURLHandler.PROTOCOL_SEPARATOR + "/" + "base" + "/"); //$NON-NLS-1$ //$NON-NLS-2$ // try using platform-relative URL |
| } catch (MalformedURLException e) { |
| siteURL = getInstallURL(); // ensure we come up ... use absolute file URL |
| } |
| ISiteEntry defaultSite = createSiteEntry(siteURL, defaultPolicy); |
| return defaultSite; |
| } |
| |
| private void resetInitializationConfiguration(URL url) throws IOException { |
| // [20111] |
| if (!supportsDetection(url)) |
| return; // can't do ... |
| |
| URL resolved = resolvePlatformURL(url); |
| File initCfg = new File(resolved.getFile().replace('/', File.separatorChar)); |
| File initDir = initCfg.getParentFile(); |
| resetInitializationLocation(initDir); |
| } |
| |
| private void resetInitializationLocation(File dir) { |
| // [20111] |
| if (dir == null || !dir.exists() || !dir.isDirectory()) |
| return; |
| File[] list = dir.listFiles(); |
| for (int i = 0; i < list.length; i++) { |
| if (list[i].isDirectory()) |
| resetInitializationLocation(list[i]); |
| list[i].delete(); |
| } |
| } |
| |
| private boolean getConfigurationLock(URL url) { |
| |
| // if (!url.getProtocol().equals("file")) //$NON-NLS-1$ |
| // return false; |
| // |
| // verifyPath(url); |
| // String cfgName = url.getFile().replace('/', File.separatorChar); |
| // String lockName = cfgName + CONFIG_FILE_LOCK_SUFFIX; |
| // cfgLockFile = new File(lockName); |
| // |
| // //if the lock file already exists, try to delete, |
| // //assume failure means another eclipse has it open |
| // if (cfgLockFile.exists()) |
| // cfgLockFile.delete(); |
| // if (cfgLockFile.exists()) { |
| // throw new RuntimeException(Policy.bind("cfig.inUse", cfgName, lockName)); //$NON-NLS-1$ |
| // } |
| // |
| // // OK so far ... open the lock file so other instances will fail |
| // try { |
| // cfgLockFileRAF = new RandomAccessFile(cfgLockFile, "rw"); //$NON-NLS-1$ |
| // cfgLockFileRAF.writeByte(0); |
| // } catch (IOException e) { |
| // throw new RuntimeException(Policy.bind("cfig.failCreateLock", cfgName)); //$NON-NLS-1$ |
| // } |
| |
| return false; |
| } |
| |
| private void clearConfigurationLock() { |
| try { |
| if (cfgLockFileRAF != null) { |
| cfgLockFileRAF.close(); |
| cfgLockFileRAF = null; |
| } |
| } catch (IOException e) { |
| // ignore ... |
| } |
| if (cfgLockFile != null) { |
| cfgLockFile.delete(); |
| cfgLockFile = null; |
| } |
| } |
| |
| private void computeChangeStamp() { |
| computeFeaturesChangeStamp(); |
| computePluginsChangeStamp(); |
| changeStamp = featuresChangeStamp ^ pluginsChangeStamp; |
| changeStampIsValid = true; |
| } |
| |
| private void computeFeaturesChangeStamp() { |
| if (featuresChangeStampIsValid) |
| return; |
| |
| long result = 0; |
| ISiteEntry[] sites = getConfiguredSites(); |
| for (int i = 0; i < sites.length; i++) { |
| result ^= sites[i].getFeaturesChangeStamp(); |
| } |
| featuresChangeStamp = result; |
| featuresChangeStampIsValid = true; |
| } |
| |
| private void computePluginsChangeStamp() { |
| if (pluginsChangeStampIsValid) |
| return; |
| |
| long result = 0; |
| ISiteEntry[] sites = getConfiguredSites(); |
| for (int i = 0; i < sites.length; i++) { |
| result ^= sites[i].getPluginsChangeStamp(); |
| } |
| pluginsChangeStamp = result; |
| pluginsChangeStampIsValid = true; |
| } |
| |
| private void configureExternalLinks() { |
| URL linkURL = getInstallURL(); |
| if (!supportsDetection(linkURL)) |
| return; |
| |
| try { |
| linkURL = new URL(linkURL, LINKS + "/"); //$NON-NLS-1$ |
| } catch (MalformedURLException e) { |
| // skip bad links ... |
| Utils.debug("Unable to obtain link URL"); //$NON-NLS-1$ |
| return; |
| } |
| |
| File linkDir = new File(linkURL.getFile()); |
| File[] links = linkDir.listFiles(); |
| if (links == null || links.length == 0) { |
| Utils.debug("No links detected in " + linkURL.toExternalForm()); //$NON-NLS-1$ |
| return; |
| } |
| |
| for (int i = 0; i < links.length; i++) { |
| if (links[i].isDirectory()) |
| continue; |
| Utils.debug("Link file " + links[i].getAbsolutePath()); //$NON-NLS-1$ |
| Properties props = new Properties(); |
| FileInputStream is = null; |
| try { |
| is = new FileInputStream(links[i]); |
| props.load(is); |
| configureExternalLinkSites(links[i], props); |
| } catch (IOException e) { |
| // skip bad links ... |
| Utils.debug(" unable to load link file " + e); //$NON-NLS-1$ |
| continue; |
| } finally { |
| if (is != null) { |
| try { |
| is.close(); |
| } catch (IOException e) { |
| // ignore ... |
| } |
| } |
| } |
| } |
| } |
| |
| private void configureExternalLinkSites(File linkFile, Properties props) { |
| String path = props.getProperty(LINK_PATH); |
| if (path == null) { |
| Utils.debug(" no path definition"); //$NON-NLS-1$ |
| return; |
| } |
| |
| String link; |
| boolean updateable = true; |
| URL siteURL; |
| SiteEntry linkSite; |
| ISitePolicy linkSitePolicy = createSitePolicy(DEFAULT_POLICY_TYPE, DEFAULT_POLICY_LIST); |
| |
| // parse out link information |
| if (path.startsWith(LINK_READ + " ")) { //$NON-NLS-1$ |
| updateable = false; |
| link = path.substring(2).trim(); |
| } else if (path.startsWith(LINK_READ_WRITE + " ")) { //$NON-NLS-1$ |
| link = path.substring(3).trim(); |
| } else { |
| link = path; |
| } |
| |
| // make sure we have a valid link specification |
| try { |
| if (!link.endsWith(File.separator)) |
| link += File.separator; |
| File target = new File(link + ECLIPSE); |
| link = "file:" + target.getAbsolutePath().replace(File.separatorChar, '/'); //$NON-NLS-1$ |
| if (!link.endsWith("/")) //$NON-NLS-1$ |
| link += "/"; // sites must be directories //$NON-NLS-1$ |
| siteURL = new URL(link); |
| } catch (MalformedURLException e) { |
| // ignore bad links ... |
| Utils.debug(" bad URL " + e); //$NON-NLS-1$ |
| return; |
| } |
| |
| // process the link |
| linkSite = (SiteEntry) externalLinkSites.get(siteURL); |
| if (linkSite == null) { |
| // this is a link to a new target so create site for it |
| linkSite = (SiteEntry) createSiteEntry(siteURL, linkSitePolicy); |
| } |
| // update site entry if needed |
| linkSite.setUpdateable(updateable); |
| linkSite.setLinkFileName(linkFile.getAbsolutePath()); |
| |
| // configure the new site |
| // NOTE: duplicates are not replaced (first one in wins) |
| configureSite(linkSite); |
| Utils.debug(" " + (updateable ? "R/W -> " : "R/O -> ") + siteURL.toString()); //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$ |
| } |
| |
| private void validateSites() { |
| |
| // check to see if all sites are valid. Remove any sites that do not exist. |
| SiteEntry[] list = (SiteEntry[]) sites.values().toArray(new SiteEntry[0]); |
| for (int i = 0; i < list.length; i++) { |
| URL siteURL = list[i].getResolvedURL(); |
| if (!supportsDetection(siteURL)) |
| continue; |
| |
| File siteRoot = new File(siteURL.getFile().replace('/', File.separatorChar)); |
| if (!siteRoot.exists()) { |
| unconfigureSite(list[i]); |
| Utils.debug("Site " + siteURL + " does not exist ... removing from configuration"); //$NON-NLS-1$ //$NON-NLS-2$ |
| } |
| } |
| } |
| |
| private void linkInitializedState(URL source, String target) { |
| try { |
| if (!source.getProtocol().equals("file")) //$NON-NLS-1$ |
| return; // need to be able to do "dir" |
| |
| copy(new File(source.getFile()), new File(target)); |
| // modify config.ini and platform.cfg to only link original files |
| File configIni = new File(target, CONFIG_INI); |
| Properties props = new Properties(); |
| props.put("link", new URL(source, CONFIG_DIR+"/"+CONFIG_INI)); |
| props.store(new FileOutputStream(configIni), "Linked configuration"); |
| |
| File platformCfg = new File(target, CONFIG_NAME); |
| props = new Properties(); |
| props.put(CFG_VERSION, VERSION); |
| props.put("link", new URL(source, CONFIG_DIR+"/"+CONFIG_NAME)); |
| props.store(new FileOutputStream(platformCfg), "Linked configuration"); |
| |
| } catch (IOException e) { |
| // this is an optimistic copy. If we fail, the state will be reconciled |
| // when the update manager is triggered. |
| System.out.println(e); |
| } |
| } |
| |
| private void copyInitializedState(URL source, String target) { |
| try { |
| if (!source.getProtocol().equals("file")) //$NON-NLS-1$ |
| return; // need to be able to do "dir" |
| |
| copy(new File(source.getFile()), new File(target)); |
| |
| } catch (IOException e) { |
| // this is an optimistic copy. If we fail, the state will be reconciled |
| // when the update manager is triggered. |
| } |
| } |
| |
| private void copy(File src, File tgt) throws IOException { |
| if (src.isDirectory()) { |
| // copy content of directories |
| tgt.mkdir(); |
| FilenameFilter filter = new FilenameFilter() { |
| public boolean accept(File dir, String name) { |
| return !name.equals(ConfigurationActivator.LAST_CONFIG_STAMP); |
| } |
| }; |
| File[] list = src.listFiles(filter); |
| if (list == null) |
| return; |
| for (int i = 0; i < list.length; i++) { |
| copy(list[i], new File(tgt, list[i].getName())); |
| } |
| } else { |
| // copy individual files |
| FileInputStream is = null; |
| FileOutputStream os = null; |
| try { |
| is = new FileInputStream(src); |
| os = new FileOutputStream(tgt); |
| byte[] buff = new byte[1024]; |
| int count = is.read(buff); |
| while (count != -1) { |
| os.write(buff, 0, count); |
| count = is.read(buff); |
| } |
| } catch (IOException e) { |
| // continue ... update reconciler will have to reconstruct state |
| } finally { |
| if (is != null) |
| try { |
| is.close(); |
| } catch (IOException e) { |
| // ignore ... |
| } |
| if (os != null) |
| try { |
| os.close(); |
| } catch (IOException e) { |
| // ignore ... |
| } |
| } |
| } |
| } |
| |
| private void copy(URL src, File tgt) throws IOException { |
| InputStream is = null; |
| OutputStream os = null; |
| try { |
| is = src.openStream(); |
| os = new FileOutputStream(tgt); |
| byte[] buff = new byte[1024]; |
| int count = is.read(buff); |
| while (count != -1) { |
| os.write(buff, 0, count); |
| count = is.read(buff); |
| } |
| } finally { |
| if (is != null) |
| try { |
| is.close(); |
| } catch (IOException e) { |
| // ignore ... |
| } |
| if (os != null) |
| try { |
| os.close(); |
| } catch (IOException e) { |
| // ignore ... |
| } |
| } |
| } |
| |
| private void load(URL url) throws IOException { |
| |
| if (url == null) |
| throw new IOException(Messages.getString("cfig.unableToLoad.noURL")); //$NON-NLS-1$ |
| |
| // try to load saved configuration file (watch for failed prior save()) |
| Properties props = null; |
| IOException originalException = null; |
| try { |
| props = loadProperties(url, null); // try to load config file |
| } catch (IOException e1) { |
| originalException = e1; |
| try { |
| props = loadProperties(url, CONFIG_FILE_TEMP_SUFFIX); // check for failures on save |
| } catch (IOException e2) { |
| try { |
| props = loadProperties(url, CONFIG_FILE_BAK_SUFFIX); // check for failures on save |
| } catch (IOException e3) { |
| throw originalException; // we tried, but no config here ... |
| } |
| } |
| } |
| |
| // check version |
| String v = props.getProperty(CFG_VERSION); |
| if (!VERSION.equals(v)) { |
| // the state is invalid, delete any files under the directory |
| // bug 33493 |
| resetUpdateManagerState(url); |
| throw new IOException(Messages.getString("cfig.badVersion", v)); //$NON-NLS-1$ |
| } |
| |
| // load simple properties |
| defaultFeature = loadAttribute(props, CFG_FEATURE_ENTRY_DEFAULT, null); |
| |
| String flag = loadAttribute(props, CFG_TRANSIENT, null); |
| if (flag != null) { |
| if (flag.equals("true")) //$NON-NLS-1$ |
| transientConfig = true; |
| else |
| transientConfig = false; |
| } |
| |
| String stamp = loadAttribute(props, CFG_FEATURE_STAMP, null); |
| if (stamp != null) { |
| try { |
| lastFeaturesChangeStamp = Long.parseLong(stamp); |
| } catch (NumberFormatException e) { |
| // ignore bad attribute ... |
| } |
| } |
| |
| stamp = loadAttribute(props, CFG_PLUGIN_STAMP, null); |
| if (stamp != null) { |
| try { |
| lastPluginsChangeStamp = Long.parseLong(stamp); |
| } catch (NumberFormatException e) { |
| // ignore bad attribute ... |
| } |
| } |
| |
| // load bootstrap entries |
| String[] ids = getBootstrapPluginIdentifiers(); |
| for (int i = 0; i < ids.length; i++) { |
| bootPlugins.put(ids[i], loadAttribute(props, CFG_BOOT_PLUGIN + "." + ids[i], null)); //$NON-NLS-1$ |
| } |
| |
| // load feature entries |
| IFeatureEntry fe = loadFeatureEntry(props, CFG_FEATURE_ENTRY + ".0", null); //$NON-NLS-1$ |
| for (int i = 1; fe != null; i++) { |
| configureFeatureEntry(fe); |
| fe = loadFeatureEntry(props, CFG_FEATURE_ENTRY + "." + i, null); //$NON-NLS-1$ |
| } |
| |
| // load site properties |
| SiteEntry root = (SiteEntry) getRootSite(); |
| String rootUrlString = root.getURL().toExternalForm(); |
| SiteEntry se = (SiteEntry) loadSite(props, CFG_SITE + ".0", null); //$NON-NLS-1$ |
| |
| for (int i = 1; se != null; i++) { |
| |
| // check if we are forcing "first use" processing with an existing |
| // platform.cfg. In this case ignore site entry that represents |
| // the platform install, and use a root site entry in its place. |
| // This ensures we do not get messed up by an exclusion list that |
| // is read from the prior state. |
| if (cmdFirstUse && rootUrlString.equals(se.getURL().toExternalForm())) |
| se = root; |
| |
| if (!se.isExternallyLinkedSite()) |
| configureSite(se); |
| else |
| // remember external link site state, but do not configure at this point |
| externalLinkSites.put(se.getURL(), se); |
| se = (SiteEntry) loadSite(props, CFG_SITE + "." + i, null); //$NON-NLS-1$ |
| } |
| } |
| |
| private Properties loadProperties(URL url, String suffix) throws IOException { |
| |
| // figure out what we will be loading |
| if (suffix != null && !suffix.equals("")) //$NON-NLS-1$ |
| url = new URL(url.getProtocol(), url.getHost(), url.getPort(), url.getFile() + suffix); |
| |
| // try to load saved configuration file |
| Properties props = new Properties(); |
| InputStream is = null; |
| try { |
| is = url.openStream(); |
| if (is == null) |
| throw new IOException(); |
| props.load(is); |
| // check to see if we have complete config file |
| if (!EOF.equals(props.getProperty(EOF))) { |
| throw new IOException(Messages.getString("cfig.unableToLoad.incomplete", url.toString())); //$NON-NLS-1$ |
| } |
| } finally { |
| if (is != null) { |
| try { |
| is.close(); |
| } catch (IOException e) { |
| // ignore ... |
| } |
| } |
| } |
| return props; |
| } |
| |
| private ISiteEntry loadSite(Properties props, String name, ISiteEntry dflt) { |
| |
| String urlString = loadAttribute(props, name + "." + CFG_URL, null); //$NON-NLS-1$ |
| if (urlString == null) |
| return dflt; |
| |
| URL url = null; |
| try { |
| url = new URL(urlString); |
| } catch (MalformedURLException e) { |
| return dflt; |
| } |
| |
| int policyType; |
| String[] policyList; |
| String typeString = loadAttribute(props, name + "." + CFG_POLICY, null); //$NON-NLS-1$ |
| if (typeString == null) { |
| policyType = DEFAULT_POLICY_TYPE; |
| policyList = DEFAULT_POLICY_LIST; |
| } else { |
| int i; |
| for (i = 0; i < CFG_POLICY_TYPE.length; i++) { |
| if (typeString.equals(CFG_POLICY_TYPE[i])) { |
| break; |
| } |
| } |
| if (i >= CFG_POLICY_TYPE.length) { |
| policyType = DEFAULT_POLICY_TYPE; |
| policyList = DEFAULT_POLICY_LIST; |
| } else { |
| policyType = i; |
| policyList = loadListAttribute(props, name + "." + CFG_LIST, new String[0]); //$NON-NLS-1$ |
| } |
| } |
| |
| ISitePolicy sp = createSitePolicy(policyType, policyList); |
| SiteEntry site = (SiteEntry) createSiteEntry(url, sp); |
| |
| String stamp = loadAttribute(props, name + "." + CFG_FEATURE_STAMP, null); //$NON-NLS-1$ |
| if (stamp != null) { |
| try { |
| site.setLastFeaturesChangeStamp(Long.parseLong(stamp)); |
| } catch (NumberFormatException e) { |
| // ignore bad attribute ... |
| } |
| } |
| |
| stamp = loadAttribute(props, name + "." + CFG_PLUGIN_STAMP, null); //$NON-NLS-1$ |
| if (stamp != null) { |
| try { |
| site.setLastPluginsChangeStamp(Long.parseLong(stamp)); |
| } catch (NumberFormatException e) { |
| // ignore bad attribute ... |
| } |
| } |
| |
| String flag = loadAttribute(props, name + "." + CFG_UPDATEABLE, null); //$NON-NLS-1$ |
| if (flag != null) { |
| if (flag.equals("true")) //$NON-NLS-1$ |
| site.setUpdateable(true); |
| else |
| site.setUpdateable(false); |
| } |
| |
| String linkname = loadAttribute(props, name + "." + CFG_LINK_FILE, null); //$NON-NLS-1$ |
| if (linkname != null && !linkname.equals("")) { //$NON-NLS-1$ |
| site.setLinkFileName(linkname.replace('/', File.separatorChar)); |
| } |
| |
| return site; |
| } |
| |
| private IFeatureEntry loadFeatureEntry(Properties props, String name, IFeatureEntry dflt) { |
| String id = loadAttribute(props, name + "." + CFG_FEATURE_ENTRY_ID, null); //$NON-NLS-1$ |
| if (id == null) |
| return dflt; |
| String version = loadAttribute(props, name + "." + CFG_FEATURE_ENTRY_VERSION, null); //$NON-NLS-1$ |
| String pluginVersion = loadAttribute(props, name + "." + CFG_FEATURE_ENTRY_PLUGIN_VERSION, null); //$NON-NLS-1$ |
| if (pluginVersion == null) |
| pluginVersion = version; |
| String pluginIdentifier = loadAttribute(props, name + "." + CFG_FEATURE_ENTRY_PLUGIN_IDENTIFIER, null); //$NON-NLS-1$ |
| if (pluginIdentifier == null) |
| pluginIdentifier = id; |
| String application = loadAttribute(props, name + "." + CFG_FEATURE_ENTRY_APPLICATION, null); //$NON-NLS-1$ |
| ArrayList rootList = new ArrayList(); |
| |
| // get install locations |
| String rootString = loadAttribute(props, name + "." + CFG_FEATURE_ENTRY_ROOT + ".0", null); //$NON-NLS-1$ //$NON-NLS-2$ |
| for (int i = 1; rootString != null; i++) { |
| try { |
| URL rootEntry = new URL(rootString); |
| rootList.add(rootEntry); |
| } catch (MalformedURLException e) { |
| // skip bad entries ... |
| } |
| rootString = loadAttribute(props, name + "." + CFG_FEATURE_ENTRY_ROOT + "." + i, null); //$NON-NLS-1$ //$NON-NLS-2$ |
| } |
| URL[] roots = (URL[]) rootList.toArray(new URL[0]); |
| |
| // get primary flag |
| boolean primary = false; |
| String flag = loadAttribute(props, name + "." + CFG_FEATURE_ENTRY_PRIMARY, null); //$NON-NLS-1$ |
| if (flag != null) { |
| if (flag.equals("true")) //$NON-NLS-1$ |
| primary = true; |
| } |
| return createFeatureEntry(id, version, pluginIdentifier, pluginVersion, primary, application, roots); |
| } |
| |
| private String[] loadListAttribute(Properties props, String name, String[] dflt) { |
| ArrayList list = new ArrayList(); |
| String value = loadAttribute(props, name + ".0", null); //$NON-NLS-1$ |
| if (value == null) |
| return dflt; |
| |
| for (int i = 1; value != null; i++) { |
| loadListAttributeSegment(list, value); |
| value = loadAttribute(props, name + "." + i, null); //$NON-NLS-1$ |
| } |
| return (String[]) list.toArray(new String[0]); |
| } |
| |
| private void loadListAttributeSegment(ArrayList list, String value) { |
| |
| if (value == null) |
| return; |
| |
| StringTokenizer tokens = new StringTokenizer(value, ","); //$NON-NLS-1$ |
| String token; |
| while (tokens.hasMoreTokens()) { |
| token = tokens.nextToken().trim(); |
| if (!token.equals("")) //$NON-NLS-1$ |
| list.add(token); |
| } |
| return; |
| } |
| |
| private String loadAttribute(Properties props, String name, String dflt) { |
| String prop = props.getProperty(name); |
| if (prop == null) |
| return dflt; |
| else |
| return prop.trim(); |
| } |
| |
| private void loadInitializationAttributes() { |
| |
| // look for the product initialization file relative to the install location |
| URL url = getInstallURL(); |
| |
| // load any initialization attributes. These are the default settings for |
| // key attributes (eg. default primary feature) supplied by the packaging team. |
| // They are always reloaded on startup to pick up any changes due to |
| // "native" updates. |
| Properties initProps = new Properties(); |
| InputStream is = null; |
| try { |
| URL initURL = new URL(url, CONFIG_FILE_INIT); |
| is = initURL.openStream(); |
| initProps.load(is); |
| Utils.debug("Defaults from " + initURL.toExternalForm()); //$NON-NLS-1$ |
| } catch (IOException e) { |
| return; // could not load default settings |
| } finally { |
| if (is != null) { |
| try { |
| is.close(); |
| } catch (IOException e) { |
| // ignore ... |
| } |
| } |
| } |
| |
| // use default settings if supplied |
| String initId = loadAttribute(initProps, INIT_DEFAULT_FEATURE_ID, null); |
| if (initId != null) { |
| String application = loadAttribute(initProps, INIT_DEFAULT_FEATURE_APPLICATION, null); |
| String initPluginId = loadAttribute(initProps, INIT_DEFAULT_PLUGIN_ID, null); |
| if (initPluginId == null) |
| initPluginId = initId; |
| IFeatureEntry fe = findConfiguredFeatureEntry(initId); |
| |
| if (fe == null) { |
| // bug 26896 : setup optimistic reconciliation if the primary feature has changed or is new |
| cmdFirstUse = true; |
| // create entry if not exists |
| fe = createFeatureEntry(initId, null, initPluginId, null, true, application, null); |
| } else |
| // update existing entry with new info |
| fe = createFeatureEntry(initId, fe.getFeatureVersion(), fe.getFeaturePluginIdentifier(), fe.getFeaturePluginVersion(), fe.canBePrimary(), application, fe.getFeatureRootURLs()); |
| configureFeatureEntry(fe); |
| defaultFeature = initId; |
| if (ConfigurationActivator.DEBUG) { |
| Utils.debug(" Default primary feature: " + defaultFeature); //$NON-NLS-1$ |
| if (application != null) |
| Utils.debug(" Default application : " + application); //$NON-NLS-1$ |
| } |
| } |
| } |
| |
| private void write(PrintWriter w) { |
| // write header |
| w.println("# " + (new Date()).toString()); //$NON-NLS-1$ |
| writeAttribute(w, CFG_VERSION, VERSION); |
| if (transientConfig) |
| writeAttribute(w, CFG_TRANSIENT, "true"); //$NON-NLS-1$ |
| w.println(""); //$NON-NLS-1$ |
| |
| // write global attributes |
| writeAttribute(w, CFG_STAMP, Long.toString(getChangeStamp())); |
| writeAttribute(w, CFG_FEATURE_STAMP, Long.toString(getFeaturesChangeStamp())); |
| writeAttribute(w, CFG_PLUGIN_STAMP, Long.toString(getPluginsChangeStamp())); |
| |
| // write out bootstrap entries |
| String[] ids = getBootstrapPluginIdentifiers(); |
| for (int i = 0; i < ids.length; i++) { |
| String location = (String) bootPlugins.get(ids[i]); |
| if (location != null) |
| writeAttribute(w, CFG_BOOT_PLUGIN + "." + ids[i], location); //$NON-NLS-1$ |
| } |
| |
| // write out feature entries |
| w.println(""); //$NON-NLS-1$ |
| writeAttribute(w, CFG_FEATURE_ENTRY_DEFAULT, defaultFeature); |
| IFeatureEntry[] feats = getConfiguredFeatureEntries(); |
| for (int i = 0; i < feats.length; i++) { |
| writeFeatureEntry(w, CFG_FEATURE_ENTRY + "." + Integer.toString(i), feats[i]); //$NON-NLS-1$ |
| } |
| |
| // write out site entries |
| SiteEntry[] list = (SiteEntry[]) sites.values().toArray(new SiteEntry[0]); |
| for (int i = 0; i < list.length; i++) { |
| writeSite(w, CFG_SITE + "." + Integer.toString(i), list[i]); //$NON-NLS-1$ |
| } |
| |
| // write end-of-file marker |
| writeAttribute(w, EOF, EOF); |
| } |
| |
| private void writeSite(PrintWriter w, String id, SiteEntry entry) { |
| |
| // write site separator |
| w.println(""); //$NON-NLS-1$ |
| |
| // write out site settings |
| writeAttribute(w, id + "." + CFG_URL, entry.getURL().toString()); //$NON-NLS-1$ |
| writeAttribute(w, id + "." + CFG_STAMP, Long.toString(entry.getChangeStamp())); //$NON-NLS-1$ |
| writeAttribute(w, id + "." + CFG_FEATURE_STAMP, Long.toString(entry.getFeaturesChangeStamp())); //$NON-NLS-1$ |
| writeAttribute(w, id + "." + CFG_PLUGIN_STAMP, Long.toString(entry.getPluginsChangeStamp())); //$NON-NLS-1$ |
| writeAttribute(w, id + "." + CFG_UPDATEABLE, entry.isUpdateable() ? "true" : "false"); //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$ |
| if (entry.isExternallyLinkedSite()) //$NON-NLS-1$ |
| writeAttribute(w, id + "." + CFG_LINK_FILE, entry.getLinkFileName().trim().replace(File.separatorChar, '/')); //$NON-NLS-1$ |
| |
| // write out site policy |
| int type = entry.getSitePolicy().getType(); |
| String typeString = CFG_POLICY_TYPE_UNKNOWN; |
| try { |
| typeString = CFG_POLICY_TYPE[type]; |
| } catch (IndexOutOfBoundsException e) { |
| // ignore bad attribute ... |
| } |
| writeAttribute(w, id + "." + CFG_POLICY, typeString); //$NON-NLS-1$ |
| writeListAttribute(w, id + "." + CFG_LIST, entry.getSitePolicy().getList()); //$NON-NLS-1$ |
| } |
| |
| private void writeFeatureEntry(PrintWriter w, String id, IFeatureEntry entry) { |
| |
| // write feature entry separator |
| w.println(""); //$NON-NLS-1$ |
| |
| // write out feature entry settings |
| writeAttribute(w, id + "." + CFG_FEATURE_ENTRY_ID, entry.getFeatureIdentifier()); //$NON-NLS-1$ |
| if (entry.canBePrimary()) |
| writeAttribute(w, id + "." + CFG_FEATURE_ENTRY_PRIMARY, "true"); //$NON-NLS-1$ //$NON-NLS-2$ |
| writeAttribute(w, id + "." + CFG_FEATURE_ENTRY_VERSION, entry.getFeatureVersion()); //$NON-NLS-1$ |
| if (entry.getFeatureVersion() != null && !entry.getFeatureVersion().equals(entry.getFeaturePluginVersion())) |
| writeAttribute(w, id + "." + CFG_FEATURE_ENTRY_PLUGIN_VERSION, entry.getFeaturePluginVersion()); //$NON-NLS-1$ |
| if (entry.getFeatureIdentifier() != null && !entry.getFeatureIdentifier().equals(entry.getFeaturePluginIdentifier())) |
| writeAttribute(w, id + "." + CFG_FEATURE_ENTRY_PLUGIN_IDENTIFIER, entry.getFeaturePluginIdentifier()); //$NON-NLS-1$ |
| writeAttribute(w, id + "." + CFG_FEATURE_ENTRY_APPLICATION, entry.getFeatureApplication()); //$NON-NLS-1$ |
| URL[] roots = entry.getFeatureRootURLs(); |
| for (int i = 0; i < roots.length; i++) { |
| // write our as individual attributes (is easier for Main.java to read) |
| writeAttribute(w, id + "." + CFG_FEATURE_ENTRY_ROOT + "." + i, roots[i].toExternalForm()); //$NON-NLS-1$ //$NON-NLS-2$ |
| } |
| } |
| |
| private void writeListAttribute(PrintWriter w, String id, String[] list) { |
| if (list == null || list.length == 0) |
| return; |
| |
| String value = ""; //$NON-NLS-1$ |
| int listLen = 0; |
| int listIndex = 0; |
| for (int i = 0; i < list.length; i++) { |
| if (listLen != 0) |
| value += ","; //$NON-NLS-1$ |
| else |
| value = ""; //$NON-NLS-1$ |
| value += list[i]; |
| |
| if (++listLen >= CFG_LIST_LENGTH) { |
| writeAttribute(w, id + "." + Integer.toString(listIndex++), value); //$NON-NLS-1$ |
| listLen = 0; |
| } |
| } |
| if (listLen != 0) |
| writeAttribute(w, id + "." + Integer.toString(listIndex), value); //$NON-NLS-1$ |
| } |
| |
| private void writeAttribute(PrintWriter w, String id, String value) { |
| if (value == null || value.trim().equals("")) //$NON-NLS-1$ |
| return; |
| w.println(id + "=" + escapedValue(value)); //$NON-NLS-1$ |
| } |
| |
| private String escapedValue(String value) { |
| // if required, escape property values as \\uXXXX |
| StringBuffer buf = new StringBuffer(value.length() * 2); // assume expansion by less than factor of 2 |
| for (int i = 0; i < value.length(); i++) { |
| char character = value.charAt(i); |
| if (character == '\\' || character == '\t' || character == '\r' || character == '\n' || character == '\f') { |
| // handle characters requiring leading \ |
| buf.append('\\'); |
| buf.append(character); |
| } else if ((character < 0x0020) || (character > 0x007e)) { |
| // handle characters outside base range (encoded) |
| buf.append('\\'); |
| buf.append('u'); |
| buf.append(HEX[(character >> 12) & 0xF]); // first nibble |
| buf.append(HEX[(character >> 8) & 0xF]); // second nibble |
| buf.append(HEX[(character >> 4) & 0xF]); // third nibble |
| buf.append(HEX[character & 0xF]); // fourth nibble |
| } else { |
| // handle base characters |
| buf.append(character); |
| } |
| } |
| return buf.toString(); |
| } |
| |
| private static String[] checkForFeatureChanges(String[] args, PlatformConfiguration cfg) { |
| String original = cfg.getApplicationIdentifierInternal(); |
| String actual = cfg.getApplicationIdentifier(); |
| |
| if (original.equals(actual)) |
| // base startup of specified application |
| return args; |
| else { |
| // Will run reconciler. |
| // Re-insert -application argument with original app and optionally |
| // force "first use" processing |
| int newArgCnt = cmdFirstUse ? 3 : 2; |
| String[] newArgs = new String[args.length + newArgCnt]; |
| newArgs[0] = CMD_APPLICATION; |
| newArgs[1] = original; |
| if (cmdFirstUse) |
| newArgs[2] = CMD_FIRSTUSE; |
| System.arraycopy(args, 0, newArgs, newArgCnt, args.length); |
| Utils.debug("triggering reconciliation ..."); //$NON-NLS-1$ |
| return newArgs; |
| } |
| } |
| |
| private static String[] checkForNewUpdates(IPlatformConfiguration cfg, String[] args) { |
| try { |
| URL markerURL = new URL(cfg.getConfigurationLocation(), CHANGES_MARKER); |
| File marker = new File(markerURL.getFile()); |
| if (!marker.exists()) |
| return args; |
| |
| // indicate -newUpdates |
| marker.delete(); |
| String[] newArgs = new String[args.length + 1]; |
| newArgs[0] = CMD_NEW_UPDATES; |
| System.arraycopy(args, 0, newArgs, 1, args.length); |
| return newArgs; |
| } catch (MalformedURLException e) { |
| return args; |
| } |
| } |
| |
| private static String[] processCommandLine(String[] args) throws Exception { |
| int[] configArgs = new int[100]; |
| configArgs[0] = -1; // need to initialize the first element to something that could not be an index. |
| int configArgIndex = 0; |
| for (int i = 0; i < args.length; i++) { |
| boolean found = false; |
| |
| // check for args without parameters (i.e., a flag arg) |
| |
| // look for forced "first use" processing (triggered by stale |
| // bootstrap information) |
| if (args[i].equalsIgnoreCase(CMD_FIRSTUSE)) { |
| cmdFirstUse = true; |
| found = true; |
| } |
| |
| // look for the update flag |
| if (args[i].equalsIgnoreCase(CMD_UPDATE)) { |
| cmdUpdate = true; |
| found = true; |
| } |
| |
| // look for the no-update flag |
| if (args[i].equalsIgnoreCase(CMD_NO_UPDATE)) { |
| cmdNoUpdate = true; |
| found = true; |
| } |
| |
| // look for the no-linked-config flag |
| if (args[i].equalsIgnoreCase(CMD_NO_LINKED_CONFIG)) { |
| cmdNoLinkedConfig = true; |
| found = true; |
| } |
| |
| // look for the initialization flag |
| if (args[i].equalsIgnoreCase(CMD_INITIALIZE)) { |
| cmdInitialize = true; |
| continue; // do not remove from command line |
| } |
| |
| // look for the development mode flag ... triggers no-update |
| if (args[i].equalsIgnoreCase(CMD_DEV)) { |
| cmdDev = true; |
| continue; // do not remove from command line |
| } |
| |
| if (found) { |
| configArgs[configArgIndex++] = i; |
| continue; |
| } |
| |
| // check for args with parameters. If we are at the last argument or if the next one |
| // has a '-' as the first character, then we can't have an arg with a parm so continue. |
| |
| if (i == args.length - 1 || args[i + 1].startsWith("-")) { //$NON-NLS-1$ |
| continue; |
| } |
| |
| String arg = args[++i]; |
| |
| // look for the feature to use for customization. |
| if (args[i - 1].equalsIgnoreCase(CMD_FEATURE)) { |
| found = true; |
| cmdFeature = arg; |
| } |
| |
| // look for the application to run. Only use the value from the |
| // command line if the application identifier was not explicitly |
| // passed on BootLoader.run(...) invocation. |
| if (args[i - 1].equalsIgnoreCase(CMD_APPLICATION)) { |
| found = true; |
| if (cmdApplication == null) |
| cmdApplication = arg; |
| } |
| |
| // done checking for args. Remember where an arg was found |
| if (found) { |
| configArgs[configArgIndex++] = i - 1; |
| configArgs[configArgIndex++] = i; |
| } |
| } |
| |
| // remove all the arguments consumed by this argument parsing |
| if (configArgIndex == 0) |
| return args; |
| String[] passThruArgs = new String[args.length - configArgIndex]; |
| configArgIndex = 0; |
| int j = 0; |
| for (int i = 0; i < args.length; i++) { |
| if (i == configArgs[configArgIndex]) |
| configArgIndex++; |
| else |
| passThruArgs[j++] = args[i]; |
| } |
| return passThruArgs; |
| } |
| |
| public static boolean supportsDetection(URL url) { |
| String protocol = url.getProtocol(); |
| if (protocol.equals("file")) //$NON-NLS-1$ |
| return true; |
| else if (protocol.equals(PlatformURLHandler.PROTOCOL)) { |
| URL resolved = null; |
| try { |
| resolved = resolvePlatformURL(url); // 19536 |
| } catch (IOException e) { |
| return false; // we tried but failed to resolve the platform URL |
| } |
| return resolved.getProtocol().equals("file"); //$NON-NLS-1$ |
| } else |
| return false; |
| } |
| |
| private static void verifyPath(URL url) { |
| String protocol = url.getProtocol(); |
| String path = null; |
| if (protocol.equals("file")) //$NON-NLS-1$ |
| path = url.getFile(); |
| else if (protocol.equals(PlatformURLHandler.PROTOCOL)) { |
| URL resolved = null; |
| try { |
| resolved = resolvePlatformURL(url); // 19536 |
| if (resolved.getProtocol().equals("file")) //$NON-NLS-1$ |
| path = resolved.getFile(); |
| } catch (IOException e) { |
| // continue ... |
| } |
| } |
| |
| if (path != null) { |
| File dir = new File(path).getParentFile(); |
| if (dir != null) |
| dir.mkdirs(); |
| } |
| } |
| |
| public static URL resolvePlatformURL(URL url) throws IOException { |
| // 19536 |
| if (url.getProtocol().equals(PlatformURLHandler.PROTOCOL)) { |
| URLConnection connection = url.openConnection(); |
| if (connection instanceof PlatformURLConnection) { |
| url = ((PlatformURLConnection) connection).getResolvedURL(); |
| } else { |
| // connection = new PlatformURLBaseConnection(url); |
| // url = ((PlatformURLConnection)connection).getResolvedURL(); |
| url = getInstallURL(); |
| } |
| } |
| return url; |
| } |
| |
| private void resetUpdateManagerState(URL url) throws IOException { |
| // [20111] |
| if (!supportsDetection(url)) |
| return; // can't do ... |
| |
| // find directory where the platform configuration file is |
| URL resolved = resolvePlatformURL(url); |
| File initCfg = new File(resolved.getFile().replace('/', File.separatorChar)); |
| File initDir = initCfg.getParentFile(); |
| |
| // Find the Update Manager State directory |
| if (initDir == null || !initDir.exists() || !initDir.isDirectory()) |
| return; |
| String temp = initCfg.getName() + ".metadata"; //$NON-NLS-1$ |
| File UMDir = new File(initDir, temp + '/'); |
| |
| // Attempt to rename it |
| if (UMDir == null || !UMDir.exists() || !UMDir.isDirectory()) |
| return; |
| Date now = new Date(); |
| boolean renamed = UMDir.renameTo(new File(initDir, temp + now.getTime() + '/')); |
| |
| if (!renamed) |
| resetInitializationLocation(UMDir); |
| } |
| |
| private static URL getInstallURL() { |
| return installURL; |
| } |
| |
| public void invalidateFeaturesChangeStamp() { |
| changeStampIsValid = false; |
| featuresChangeStampIsValid = false; |
| } |
| |
| public void invalidatePluginsChangeStamp() { |
| changeStampIsValid = false; |
| pluginsChangeStampIsValid = false; |
| } |
| |
| private void saveAsXML(File platformXML) { |
| try { |
| DocumentBuilder docBuilder = documentBuilderFactory.newDocumentBuilder(); |
| Document doc = docBuilder.newDocument(); |
| |
| doc.appendChild(doc.createProcessingInstruction("date", "\""+(new Date()).toString()+"\"")); |
| |
| Element configElement = doc.createElement(CFG); |
| doc.appendChild(configElement); |
| configElement.setAttribute(CFG_VERSION, VERSION); |
| if (transientConfig) |
| configElement.setAttribute(CFG_TRANSIENT, "true"); //$NON-NLS-1$ |
| |
| // collect global attributes |
| configElement.setAttribute(CFG_STAMP, Long.toString(getChangeStamp())); |
| configElement.setAttribute(CFG_FEATURE_STAMP, Long.toString(getFeaturesChangeStamp())); |
| configElement.setAttribute(CFG_PLUGIN_STAMP, Long.toString(getPluginsChangeStamp())); |
| |
| // collect bootstrap entries |
| String[] ids = getBootstrapPluginIdentifiers(); |
| for (int i = 0; i < ids.length; i++) { |
| String location = (String) bootPlugins.get(ids[i]); |
| if (location != null) { |
| Element bootPlugin = doc.createElement(CFG_BOOT_PLUGIN); |
| bootPlugin.setNodeValue(location); |
| configElement.appendChild(bootPlugin); |
| } |
| } |
| |
| // collect feature entries |
| configElement.setAttribute(CFG_FEATURE_ENTRY_DEFAULT, defaultFeature); |
| IFeatureEntry[] feats = getConfiguredFeatureEntries(); |
| for (int i = 0; i < feats.length; i++) { |
| saveFeatureAsXML(feats[i], configElement); |
| } |
| |
| // collect site entries |
| SiteEntry[] list = (SiteEntry[]) sites.values().toArray(new SiteEntry[0]); |
| for (int i = 0; i < list.length; i++) { |
| saveSiteAsXML(list[i], configElement); |
| } |
| |
| // Write out to a file |
| FileOutputStream stream = new FileOutputStream(platformXML); |
| |
| Transformer transformer=transformerFactory.newTransformer(); |
| transformer.setOutputProperty(OutputKeys.METHOD, "xml"); |
| transformer.setOutputProperty(OutputKeys.ENCODING, "UTF-8"); |
| transformer.setOutputProperty(OutputKeys.INDENT, "yes"); |
| DOMSource source = new DOMSource(doc); |
| StreamResult result = new StreamResult(stream); |
| |
| transformer.transform(source,result); |
| stream.close(); |
| } catch (DOMException e) { |
| // TODO Auto-generated catch block |
| e.printStackTrace(); |
| } catch (FileNotFoundException e) { |
| // TODO Auto-generated catch block |
| e.printStackTrace(); |
| } catch (TransformerConfigurationException e) { |
| // TODO Auto-generated catch block |
| e.printStackTrace(); |
| } catch (IllegalArgumentException e) { |
| // TODO Auto-generated catch block |
| e.printStackTrace(); |
| } catch (ParserConfigurationException e) { |
| // TODO Auto-generated catch block |
| e.printStackTrace(); |
| } catch (TransformerException e) { |
| // TODO Auto-generated catch block |
| e.printStackTrace(); |
| } catch (IOException e) { |
| // TODO Auto-generated catch block |
| e.printStackTrace(); |
| } catch (Exception e) { |
| e.printStackTrace(); |
| } |
| } |
| |
| |
| /** |
| * Saves state as xml content in a given parent element |
| * @param parent |
| */ |
| private void saveSiteAsXML(SiteEntry site, Element parent) { |
| Document doc = parent.getOwnerDocument(); |
| Element siteElement = doc.createElement(CFG_SITE); |
| parent.appendChild(siteElement); |
| |
| if (site.getURL().toString() != null) |
| siteElement.setAttribute(CFG_URL, site.getURL().toString()); |
| siteElement.setAttribute(CFG_STAMP, Long.toString(site.getChangeStamp())); |
| siteElement.setAttribute(CFG_FEATURE_STAMP, Long.toString(site.getFeaturesChangeStamp())); |
| siteElement.setAttribute(CFG_PLUGIN_STAMP, Long.toString(site.getPluginsChangeStamp())); |
| siteElement.setAttribute(CFG_UPDATEABLE, site.isUpdateable() ? "true" : "false"); |
| if (site.isExternallyLinkedSite()) |
| siteElement.setAttribute(CFG_LINK_FILE, site.getLinkFileName().trim().replace(File.separatorChar, '/')); |
| |
| int type = site.getSitePolicy().getType(); |
| String typeString = CFG_POLICY_TYPE_UNKNOWN; |
| try { |
| typeString = CFG_POLICY_TYPE[type]; |
| } catch (IndexOutOfBoundsException e) { |
| // ignore bad attribute ... |
| } |
| siteElement.setAttribute(CFG_POLICY, typeString); |
| String[] list = site.getSitePolicy().getList(); |
| for (int i=0; i<list.length; i++) { |
| Element listElement = doc.createElement(CFG_LIST); |
| listElement.setNodeValue(list[i]); |
| siteElement.appendChild(listElement); |
| } |
| // note: we don't save features inside the site element. |
| } |
| |
| /** |
| * Saves state as xml content in a given parent element |
| * @param parent |
| */ |
| private void saveFeatureAsXML(IFeatureEntry feature, Element parent) { |
| Document doc = parent.getOwnerDocument(); |
| Element featureElement = doc.createElement(CFG_FEATURE_ENTRY); |
| parent.appendChild(featureElement); |
| |
| // write out feature entry settings |
| if (feature.getFeatureIdentifier() != null) |
| featureElement.setAttribute(CFG_FEATURE_ENTRY_ID, feature.getFeatureIdentifier()); |
| if (feature.canBePrimary()) |
| featureElement.setAttribute(CFG_FEATURE_ENTRY_PRIMARY, "true"); |
| if (feature.getFeatureVersion() != null) |
| featureElement.setAttribute(CFG_FEATURE_ENTRY_VERSION, feature.getFeatureVersion()); |
| if (feature.getFeaturePluginVersion() != null && !feature.getFeaturePluginVersion().equals(feature.getFeatureVersion())) |
| featureElement.setAttribute(CFG_FEATURE_ENTRY_PLUGIN_VERSION, feature.getFeaturePluginVersion()); |
| if (feature.getFeaturePluginIdentifier() != null && !feature.getFeaturePluginIdentifier().equals(feature.getFeatureIdentifier())) |
| featureElement.setAttribute(CFG_FEATURE_ENTRY_PLUGIN_IDENTIFIER, feature.getFeaturePluginIdentifier()); |
| if (feature.getFeatureApplication() != null) |
| featureElement.setAttribute(CFG_FEATURE_ENTRY_APPLICATION, feature.getFeatureApplication()); |
| URL[] roots = feature.getFeatureRootURLs(); |
| for (int i=0; i<roots.length; i++) { |
| String root = roots[i].toExternalForm(); |
| if (root != null && root.trim().length() > 0){ |
| Element rootElement = doc.createElement(CFG_FEATURE_ENTRY_ROOT); |
| rootElement.appendChild(doc.createTextNode(root)); |
| featureElement.appendChild(rootElement); |
| } |
| } |
| } |
| } |