blob: c19bcc9600fcfb3b6bd88bddf68d89e8335f8fe1 [file] [log] [blame]
/*******************************************************************************
* 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 org.eclipse.core.internal.boot.*;
import org.eclipse.update.configurator.*;
import org.eclipse.update.configurator.IPlatformConfiguration.*;
public class SiteEntry implements IPlatformConfiguration.ISiteEntry {
private static final String PLUGINS = "plugins"; //$NON-NLS-1$
private static final String FEATURES = "features"; //$NON-NLS-1$
private static final String PLUGIN_XML = "plugin.xml"; //$NON-NLS-1$
private static final String FRAGMENT_XML = "fragment.xml"; //$NON-NLS-1$
private static final String FEATURE_XML = "feature.xml"; //$NON-NLS-1$
private URL url; // this is the external URL for the site
private URL resolvedURL; // this is the resolved URL used internally
private ISitePolicy policy;
private boolean updateable = true;
private ArrayList featureEntries = new ArrayList();
private ArrayList pluginEntries = new ArrayList();
private ArrayList features;
private ArrayList plugins;
private PlatformConfiguration parent;
private long changeStamp;
private boolean changeStampIsValid;
private long lastFeaturesChangeStamp;
private long featuresChangeStamp;
private boolean featuresChangeStampIsValid;
private long lastPluginsChangeStamp;
private long pluginsChangeStamp;
private boolean pluginsChangeStampIsValid;
private String linkFileName;
public SiteEntry() {
}
public SiteEntry(URL url, ISitePolicy policy, PlatformConfiguration parent) {
if (url == null)
throw new IllegalArgumentException();
if (policy == null)
throw new IllegalArgumentException();
if (parent == null)
throw new IllegalArgumentException();
this.url = url;
this.policy = policy;
this.parent = parent;
this.features = null;
this.plugins = null;
this.resolvedURL = this.url;
if (url.getProtocol().equals(PlatformURLHandler.PROTOCOL)) {
try {
resolvedURL = PlatformConfiguration.resolvePlatformURL(url); // 19536
} catch (IOException e) {
// will use the baseline URL ...
}
}
}
/*
* @see ISiteEntry#getURL()
*/
public URL getURL() {
return url;
}
/*
* @see ISiteEntry#getSitePolicy()
*/
public ISitePolicy getSitePolicy() {
return policy;
}
/*
* @see ISiteEntry#setSitePolicy(ISitePolicy)
*/
public synchronized void setSitePolicy(ISitePolicy policy) {
if (policy == null)
throw new IllegalArgumentException();
this.policy = policy;
}
/*
* @see ISiteEntry#getFeatures()
*/
public String[] getFeatures() {
return getDetectedFeatures();
}
/*
* @see ISiteEntry#getPlugins()
*/
public String[] getPlugins() {
ISitePolicy policy = getSitePolicy();
if (policy.getType() == ISitePolicy.USER_INCLUDE)
return policy.getList();
if (policy.getType() == ISitePolicy.USER_EXCLUDE) {
ArrayList detectedPlugins = new ArrayList(Arrays.asList(getDetectedPlugins()));
String[] excludedPlugins = policy.getList();
for (int i = 0; i < excludedPlugins.length; i++) {
if (detectedPlugins.contains(excludedPlugins[i]))
detectedPlugins.remove(excludedPlugins[i]);
}
return (String[]) detectedPlugins.toArray(new String[0]);
}
// bad policy type
return new String[0];
}
/*
* @see ISiteEntry#getChangeStamp()
*/
public long getChangeStamp() {
if (!changeStampIsValid)
computeChangeStamp();
return changeStamp;
}
/*
* @see ISiteEntry#getFeaturesChangeStamp()
*/
public long getFeaturesChangeStamp() {
if (!featuresChangeStampIsValid)
computeFeaturesChangeStamp();
return featuresChangeStamp;
}
/*
* @see ISiteEntry#getPluginsChangeStamp()
*/
public long getPluginsChangeStamp() {
if (!pluginsChangeStampIsValid)
computePluginsChangeStamp();
return pluginsChangeStamp;
}
/*
* @see ISiteEntry#isUpdateable()
*/
public boolean isUpdateable() {
return updateable;
}
public void setUpdateable(boolean updateable) {
this.updateable = updateable;
}
/*
* @see ISiteEntry#isNativelyLinked()
*/
public boolean isNativelyLinked() {
return isExternallyLinkedSite();
}
public URL getResolvedURL() {
return resolvedURL;
}
private String[] detectFeatures() {
// invalidate stamps ... we are doing discovery
invalidateFeaturesChangeStamp();
features = new ArrayList();
if (!PlatformConfiguration.supportsDetection(resolvedURL))
return new String[0];
// locate feature entries on site
File siteRoot = new File(resolvedURL.getFile().replace('/', File.separatorChar));
File root = new File(siteRoot, FEATURES);
String[] list = root.list();
String path;
File plugin;
for (int i = 0; list != null && i < list.length; i++) {
path = list[i] + File.separator + FEATURE_XML;
plugin = new File(root, path);
if (!plugin.exists()) {
continue;
}
features.add(FEATURES + "/" + path.replace(File.separatorChar, '/')); //$NON-NLS-1$
}
Utils.debug(resolvedURL.toString() + " located " + features.size() + " feature(s)"); //$NON-NLS-1$ //$NON-NLS-2$
return (String[]) features.toArray(new String[0]);
}
private String[] detectPlugins() {
// invalidate stamps ... we are doing discovery
invalidatePluginsChangeStamp();
plugins = new ArrayList();
if (!PlatformConfiguration.supportsDetection(resolvedURL))
return new String[0];
// locate plugin entries on site
File root = new File(resolvedURL.getFile().replace('/', File.separatorChar) + PLUGINS);
String[] list = root.list();
String path;
File plugin;
for (int i = 0; list != null && i < list.length; i++) {
path = list[i] + File.separator + PLUGIN_XML;
plugin = new File(root, path);
if (!plugin.exists()) {
path = list[i] + File.separator + FRAGMENT_XML;
plugin = new File(root, path);
if (!plugin.exists())
continue;
}
plugins.add(PLUGINS + "/" + path.replace(File.separatorChar, '/')); //$NON-NLS-1$
}
Utils.debug(resolvedURL.toString() + " located " + plugins.size() + " plugin(s)"); //$NON-NLS-1$ //$NON-NLS-2$
return (String[]) plugins.toArray(new String[0]);
}
private synchronized String[] getDetectedFeatures() {
if (features == null)
return detectFeatures();
else
return (String[]) features.toArray(new String[0]);
}
private synchronized String[] getDetectedPlugins() {
if (plugins == null)
return detectPlugins();
else
return (String[]) plugins.toArray(new String[0]);
}
private void computeChangeStamp() {
computeFeaturesChangeStamp();
computePluginsChangeStamp();
changeStamp = resolvedURL.hashCode() ^ featuresChangeStamp ^ pluginsChangeStamp;
changeStampIsValid = true;
}
private synchronized void computeFeaturesChangeStamp() {
if (featuresChangeStampIsValid)
return;
long start = 0;
if (ConfigurationActivator.DEBUG)
start = (new Date()).getTime();
String[] features = getFeatures();
featuresChangeStamp = computeStamp(features);
featuresChangeStampIsValid = true;
if (ConfigurationActivator.DEBUG) {
long end = (new Date()).getTime();
Utils.debug(resolvedURL.toString() + " feature stamp: " + featuresChangeStamp + ((featuresChangeStamp == lastFeaturesChangeStamp) ? " [no changes]" : " [was " + lastFeaturesChangeStamp + "]") + " in " + (end - start) + "ms"); //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$ //$NON-NLS-4$ //$NON-NLS-5$ //$NON-NLS-6$
}
}
private synchronized void computePluginsChangeStamp() {
if (pluginsChangeStampIsValid)
return;
long start = 0;
if (ConfigurationActivator.DEBUG)
start = (new Date()).getTime();
String[] plugins = getPlugins();
pluginsChangeStamp = computeStamp(plugins);
pluginsChangeStampIsValid = true;
if (ConfigurationActivator.DEBUG) {
long end = (new Date()).getTime();
Utils.debug(resolvedURL.toString() + " plugin stamp: " + pluginsChangeStamp + ((pluginsChangeStamp == lastPluginsChangeStamp) ? " [no changes]" : " [was " + lastPluginsChangeStamp + "]") + " in " + (end - start) + "ms"); //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$ //$NON-NLS-4$ //$NON-NLS-5$ //$NON-NLS-6$
}
}
private long computeStamp(String[] targets) {
long result = 0;
if (!PlatformConfiguration.supportsDetection(resolvedURL)) {
// NOTE: this path should not be executed until we support running
// from an arbitrary URL (in particular from http server). For
// now just compute stamp across the list of names. Eventually
// when general URLs are supported we need to do better (factor
// in at least the existence of the target). However, given this
// code executes early on the startup sequence we need to be
// extremely mindful of performance issues.
for (int i = 0; i < targets.length; i++)
result ^= targets[i].hashCode();
Utils.debug("*WARNING* computing stamp using URL hashcodes only"); //$NON-NLS-1$
} else {
// compute stamp across local targets
String rootPath = resolvedURL.getFile().replace('/', File.separatorChar);
if (!rootPath.endsWith(File.separator))
rootPath += File.separator;
File rootFile = new File(rootPath);
if (rootFile.exists()) {
File f = null;
for (int i = 0; i < targets.length; i++) {
f = new File(rootFile, targets[i]);
if (f.exists())
result ^= f.getAbsolutePath().hashCode() ^ f.lastModified() ^ f.length();
}
}
}
return result;
}
public void setLinkFileName(String linkFileName) {
this.linkFileName = linkFileName;
}
public String getLinkFileName() {
return linkFileName;
}
public boolean isExternallyLinkedSite() {
return (linkFileName != null && !linkFileName.trim().equals("")); //$NON-NLS-1$
}
public synchronized void refresh() {
// reset computed values. Will be updated on next access.
lastFeaturesChangeStamp = featuresChangeStamp;
lastPluginsChangeStamp = pluginsChangeStamp;
changeStampIsValid = false;
featuresChangeStampIsValid = false;
pluginsChangeStampIsValid = false;
features = null;
plugins = null;
}
public void setLastFeaturesChangeStamp(long stamp) {
this.lastFeaturesChangeStamp = stamp;
}
public void setLastPluginsChangeStamp(long stamp) {
this.lastPluginsChangeStamp = stamp;
}
public void invalidateFeaturesChangeStamp() {
changeStampIsValid = false;
featuresChangeStampIsValid = false;
parent.invalidateFeaturesChangeStamp();
}
public void invalidatePluginsChangeStamp() {
changeStampIsValid = false;
pluginsChangeStampIsValid = false;
parent.invalidatePluginsChangeStamp();
}
public void addFeatureEntry(IFeatureEntry feature) {
featureEntries.add(feature);
}
public IFeatureEntry[] getFeatureEntries() {
return (IFeatureEntry[])featureEntries.toArray(new IFeatureEntry[featureEntries.size()]);
}
public void addPluginEntry(PluginEntry plugin) {
pluginEntries.add(plugin);
}
public PluginEntry[] getPluginEntries() {
return (PluginEntry[])pluginEntries.toArray(new PluginEntry[pluginEntries.size()]);
}
}