		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());
}

*****************************************
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
	
