		java.util.Enumeration enum =  System.getProperties().keys();
		String key = null;
		while (enum.hasMoreElements()){
			key = (String)enum.nextElement();
			System.out.print(key);
			for (int i =0;i<(30-key.length());i++)System.out.print(" ");
			System.out.println("->"+System.getProperty(key));
		}


new java.net.URL("file://C:/temp/org.eclipse.update.core.feature1_1.0.0/org.eclipse.update.core.feature1.plugin1_1.1.1.jar").openStream()

(new java.io.File("C:\\chris chris\hello\\")).mkdirs();

java.net.URL a =  new java.net.URL("http","www.oti.com","/feature/blah.jar");
java.net.URL b =  new java.net.URL("jar",null,a.toExternalForm()+"!/hello.txt");
b

new java.net.URL("file",null,System.getProperty("java.io.tmpdir"));
new java.net.URL("file",null,System.getProperty("user.home"));

String tempDir = "c:\\TEMP\\features2.jar";
java.net.URL TEMP_SITE = new java.net.URL("file",null,tempDir);
java.net.URL file = new java.net.URL("jar",null,TEMP_SITE.toExternalForm()+"!/feature.xml");
file.openStream();
file

java.io.File f =  new java.io.File("c:\\temp\\xtf\\file.jar");
f.mkdirs()

java.util.Locale.getDefault()
java.util.ResourceBundle

java.net.URL url = new java.net.URL("file",null,"C:\\path"+java.io.File.separator);
url.getPath().endsWith("/");
url

java.net.URL url = new java.net.URL("http://machine:8080/path space/file.abc#hello");
java.net.URL url2 = new java.net.URL(url,"/ ");
url2.getPath()

java.lang.ClassLoader l = new java.net.URLClassLoader(new java.net.URL[] {new java.net.URL("file",null,"c:\\oti\\wsw205\\eclipse\\install\\features\\org.eclipse.help.feature_1.0.4/") }, null);
java.util.ResourceBundle bundle = java.util.ResourceBundle.getBundle("feature", java.util.Locale.getDefault(), l);
bundle

String[] ss = {"a", "b"}; 
java.util.List list = new java.util.ArrayList(0);
list.addAll(java.util.Arrays.asList(ss)); 
list.add("c");
list.size();

java.util.List list = new java.util.ArrayList(0);
list.add("1");
list.add("2");
list.add("3");
list.add("4");
list.add("5");
list.add("6");
list.add("7");
while (list.size()>5){
	list.remove(0);
}
list.get(0)


org.eclipse.update.internal.security.KeyStores k = new org.eclipse.update.internal.security.KeyStores();
while (k.hasNext()){
	org.eclipse.update.internal.security.KeystoreHandle handle = (org.eclipse.update.internal.security.KeystoreHandle) k.next();
	System.out.println("KeyStore:"+handle.getLocation()+":"+handle.getType());
}

int i = (13/3);
i

*****************************************
OLD Feature Code


	/**
	 */
	private void downloadArchivesLocally(ISite tempSite, String[] archiveIDToInstall, IProgressMonitor monitor) throws CoreException, IOException {

		URL sourceURL;
		String newFile;
		URL newURL;

		if (monitor != null) {
			monitor.beginTask("Download archives bundles to Temporary Space", archiveIDToInstall.length);
		}
		for (int i = 0; i < archiveIDToInstall.length; i++) {

			// transform the id by asking the site to map them to real URL inside the SITE
			if (getSite() != null) {
				sourceURL = getSite().getSiteContentProvider().getArchivesReferences(archiveIDToInstall[i]);
				if (monitor != null) {
					monitor.subTask("..." + archiveIDToInstall[i]);
				}
				// the name of the file in the temp directory
				// should be the regular plugins/pluginID_ver as the Temp site is OUR site
				newFile = Site.DEFAULT_PLUGIN_PATH + archiveIDToInstall[i];
				newURL = UpdateManagerUtils.resolveAsLocal(sourceURL, newFile, monitor);

				// transfer the possible mapping to the temp site						
				 ((Site) tempSite).addArchive(new URLEntry(archiveIDToInstall[i], newURL));
				if (monitor != null) {
					monitor.worked(1);
					if (monitor.isCanceled()) {
						throw CANCEL_EXCEPTION;
					}
				}
			}
		}

		// the site of this feature now becomes the TEMP directory
		// FIXME: make sure there is no other issue
		// like asking for stuff that hasn't been copied
		// or reusing this feature
		// of having an un-manageable temp site

		this.setSite(tempSite);

	}

	/**
	 */
	private void downloadDataLocally(IFeature targetFeature, INonPluginEntry[] dataToInstall, IProgressMonitor monitor) throws CoreException, IOException {

		URL sourceURL;
		// any other data
		INonPluginEntry[] entries = getNonPluginEntries();
		if (entries != null) {
			if (monitor != null) {
				monitor.beginTask("Installing Other Data information", dataToInstall.length);
				if (monitor.isCanceled()) {
					throw CANCEL_EXCEPTION;
				}
			}

			for (int j = 0; j < entries.length; j++) {
				String name = dataToInstall[j].getIdentifier();
				if (monitor != null) {
					monitor.subTask("..." + name);
				}

				// the id is URL format with "/"
				String dataEntryId = Site.DEFAULT_FEATURE_PATH + getIdentifier().toString() + "/" + name;
				// transform the id by asking the site to map them to real URL inside the SITE
				if (getSite() != null) {
					sourceURL = getSite().getSiteContentProvider().getArchivesReferences(dataEntryId);
					((Site) targetFeature.getSite()).storeFeatureInfo(getIdentifier(), name, sourceURL.openStream());
					if (monitor != null) {
						monitor.worked(1);
						if (monitor.isCanceled()) {
							throw CANCEL_EXCEPTION;
						}
					}
				}// getSite==null
			}
		}
	}
	
	
		/**
		 * Method install.
		 * @param targetFeature
		 * @param monitor
		 * @throws CoreException
		 */
	public void old_install(IFeature targetFeature, IProgressMonitor monitor) throws CoreException {

		IPluginEntry[] sourceFeaturePluginEntries = getPluginEntries();
		IPluginEntry[] targetSitePluginEntries = targetFeature.getSite().getPluginEntries();
		Site tempSite = (Site) SiteManager.getTempSite();

		// determine list of plugins to install
		// find the intersection between the two arrays of IPluginEntry...
		// The one teh site contains and teh one the feature contains
		IPluginEntry[] pluginsToInstall = intersection(sourceFeaturePluginEntries, targetSitePluginEntries);

		// private abstract - Determine list of content references id /archives id /bundles id that 
		// map the list of plugins to install
		String[] archiveIDToInstall = getContentReferenceToInstall(pluginsToInstall);

		try {
			// download and install data bundles
			// before we set the site of teh feature to the TEMP site
			INonPluginEntry[] dataEntries = getNonPluginEntries();
			if (dataEntries.length > 0) {
				downloadDataLocally(targetFeature, dataEntries, monitor);
			}

			// optmization, may be private to implementation
			// copy *blobs/content references/archives/bundles* in TEMP space
			if (((Site) getSite()).optimize()) {
				if (archiveIDToInstall != null) {
					downloadArchivesLocally(tempSite, archiveIDToInstall, monitor);
				}
			}

			// obtain the list of *Streamable Storage Unit*
			// from the archive
			if (monitor != null) {
				int total = pluginsToInstall == null ? 1 : pluginsToInstall.length + 1;
				monitor.beginTask("Install feature " + getLabel(), total);
			}
			if (pluginsToInstall != null) {
				InputStream inStream = null;
				for (int i = 0; i < pluginsToInstall.length; i++) {
					if (monitor != null) {
						monitor.subTask("Installing plug-in: " + pluginsToInstall[i]);
						if (monitor.isCanceled()) {
							throw CANCEL_EXCEPTION;
						}
					}

					open(pluginsToInstall[i]);
					String[] names = getStorageUnitNames(pluginsToInstall[i]);
					if (names != null) {
						for (int j = 0; j < names.length; j++) {
							if ((inStream = getInputStreamFor(pluginsToInstall[i], names[j])) != null)
								targetFeature.store(pluginsToInstall[i], names[j], inStream);
						}
					}
					close(pluginsToInstall[i]);
					if (monitor != null) {
						monitor.worked(1);
						if (monitor.isCanceled()) {
							throw CANCEL_EXCEPTION;
						}
					}

				}
			}

			// install the Feature info
			InputStream inStream = null;
			String[] names = getStorageUnitNames(this);
			if (names != null) {
				openFeature();
				if (monitor != null) {
					monitor.subTask("Installing Feature information");
					if (monitor.isCanceled()) {
						throw CANCEL_EXCEPTION;
					}
				}

				for (int j = 0; j < names.length; j++) {
					if ((inStream = getInputStreamFor(this, names[j])) != null)
						 ((Site) targetFeature.getSite()).storeFeatureInfo(getIdentifier(), names[j], inStream);
				}
				closeFeature();
				if (monitor != null) {
					monitor.worked(1);
					if (monitor.isCanceled()) {
						throw CANCEL_EXCEPTION;
					}
				}

			}

		} catch (IOException e) {
			String id = UpdateManagerPlugin.getPlugin().getDescriptor().getUniqueIdentifier();
			IStatus status = new Status(IStatus.ERROR, id, IStatus.OK, "Error during Install", e);
			throw new CoreException(status);
		} finally {
			//do not clean up TEMP drive
			// as other feature may be there... clean up when exiting the plugin
		}
	}
	
	
		/**
	 * @see IPluginContainer#store(IPluginEntry, String, InputStream)
	 */
	public void store(IPluginEntry pluginEntry, String contentKey, InputStream inStream) throws CoreException {
		// check if pluginEntry already exists before passing to the site
		// anything else ?
		boolean found = false;
		int i = 0;
		IPluginEntry[] entries = getPluginEntries();
		while (i < entries.length && !found) {
			if (entries[i].equals(pluginEntry)) {
				found = true;
			}
			i++;
		}
		if (!found) {
			String id = UpdateManagerPlugin.getPlugin().getDescriptor().getUniqueIdentifier();
			IStatus status = new Status(IStatus.ERROR, id, IStatus.OK, "The plugin:" + pluginEntry.getIdentifier().toString() + " is not part of the plugins of the feature:" + this.getIdentifier().toString(), null);
			throw new CoreException(status);
		}
		getSite().store(pluginEntry, contentKey, inStream);
	}
	
		/**
	 * perform pre processing before opening a plugin archive
	 * @param entry the plugin about to be opened
	 */
	protected void open(IPluginEntry entry) {
	};

	/**
	 * perform post processing to close a plugin archive
	 * @param entry the plugin about to be closed
	 */
	protected void close(IPluginEntry entry) throws IOException {
	};

	/**
	 * perform pre processing before opening the feature archive
	 */
	protected void openFeature() {
	};

	/**
	 * perform post processing to close a feature archive
	 */
	public void closeFeature() throws IOException {
	};
	
	
		/**
	 * return the list of FILE to be transfered for a Plugin
	 */
	protected abstract String[] getStorageUnitNames(IPluginEntry pluginEntry) throws CoreException;

	/**
	 * return the list of FILE to be transfered from within the Feature
	 */
	protected abstract String[] getStorageUnitNames(IFeature feature) throws CoreException;

	/**
	 * return the Stream of the FILE to be transfered for a Plugin
	 */
	protected abstract InputStream getInputStreamFor(IPluginEntry pluginEntry, String name) throws CoreException;

	/**
	 * return the Stream of FILE to be transfered from within the Feature
	 */
	protected abstract InputStream getInputStreamFor(IFeature feature, String name) throws IOException, CoreException;

	/**
	 * returns the list of archive to transfer/install
	 * in order to install the list of plugins
	 * 
	 * @param pluginsToInstall list of plugin to install 
	 */
	protected abstract String[] getContentReferenceToInstall(IPluginEntry[] pluginsToInstall);
	
	
		/**
	 * remove myself...
	 */
	public void old_remove(IProgressMonitor monitor) throws CoreException {

		// remove the feature and the plugins if they are not used and not activated

		// get the plugins from the feature
		IPluginEntry[] pluginsToRemove = ((SiteLocal) SiteManager.getLocalSite()).getDeltaPluginEntries(this);

		try {

			// obtain the list of *Streamable Storage Unit*
			// from the archive
			if (monitor != null) {
				int total = pluginsToRemove == null ? 1 : pluginsToRemove.length + 1;
				monitor.beginTask("Uninstall feature " + getLabel(), total);
			}
			if (pluginsToRemove != null) {
				for (int i = 0; i < pluginsToRemove.length; i++) {
					if (monitor != null) {
						monitor.subTask("Removing plug-in: " + pluginsToRemove[i]);
						if (monitor.isCanceled()) {
							throw CANCEL_EXCEPTION;
						}
					}

					remove(pluginsToRemove[i]);

					if (monitor != null) {
						monitor.worked(1);
						if (monitor.isCanceled()) {
							throw CANCEL_EXCEPTION;
						}
					}

				}
			}

			// remove the Feature info
			String[] names = getStorageUnitNames(this);
			if (names != null) {
				if (monitor != null) {
					monitor.subTask("Removing Feature information");
					if (monitor.isCanceled()) {
						throw CANCEL_EXCEPTION;
					}
				}

				((Site) this.getSite()).removeFeatureInfo(getIdentifier());

				closeFeature();
				if (monitor != null) {
					monitor.worked(1);
					if (monitor.isCanceled()) {
						throw CANCEL_EXCEPTION;
					}
				}

			}

		} catch (IOException e) {
			String id = UpdateManagerPlugin.getPlugin().getDescriptor().getUniqueIdentifier();
			IStatus status = new Status(IStatus.ERROR, id, IStatus.OK, "Error during Uninstall", e);
			throw new CoreException(status);
		}
	}
	
	System.getProperty("java.io.tmpdir")(java.lang.String) /tmp
	
	true^false
	true^true

	
org.eclipse.core.runtime.IPath p1= (new org.eclipse.core.runtime.Path("/path1/path2/*.txt"));
org.eclipse.core.runtime.IPath p2= (new org.eclipse.core.runtime.Path("/path1/path2/a.txt"));
p1.equals(p2);


org.eclipse.update.internal.core.URLEncoder.encode(new java.net.URL("http://www.ourwebsite.com/servlet/update?jar=somefeaturejarfile"));(java.net.URL) http://www.ourwebsite.com/servlet/update?jar=somefeaturejarfile

