/*******************************************************************************
 * 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.core;
import java.io.*;
import java.net.*;
import java.util.*;

import org.eclipse.core.runtime.*;
import org.eclipse.update.core.*;
import org.eclipse.update.core.model.*;
import org.osgi.framework.*;
import org.osgi.service.packageadmin.*;

/**
 * 
 */
public class UpdateManagerUtils {

	private static boolean OS_UNIX = org.eclipse.osgi.service.environment.Constants.OS_HPUX
			.equals(Platform.getOS())
			|| org.eclipse.osgi.service.environment.Constants.OS_AIX
					.equals(Platform.getOS())
			|| org.eclipse.osgi.service.environment.Constants.OS_LINUX
					.equals(Platform.getOS())
			|| org.eclipse.osgi.service.environment.Constants.OS_SOLARIS
					.equals(Platform.getOS());
	private static FragmentEntry[] noFragments = new FragmentEntry[0];
	private static Map table;

	static {
		table = new HashMap();
		table.put("compatible", new Integer(IImport.RULE_COMPATIBLE)); //$NON-NLS-1$
		table.put("perfect", new Integer(IImport.RULE_PERFECT)); //$NON-NLS-1$
		table.put("equivalent", new Integer(IImport.RULE_EQUIVALENT)); //$NON-NLS-1$
		table.put("greaterOrEqual", new Integer(IImport.RULE_GREATER_OR_EQUAL)); //$NON-NLS-1$
	}

	private static Writer writer;
	// manage URL to File
	private static Map urlFileMap;

	private static Map localFileFragmentMap;
	private static Stack bufferPool;
	private static final int BUFFER_SIZE = 4096; // 4kbytes
	private static final int INCREMENT_SIZE = 10240; // 10kbytes
	/**
	 * return the urlString if it is a absolute URL
	 * otherwise, return the default URL if the urlString is null
	 * The defaultURL may point ot a file, create a file URL then
	 * if the urlString or the default URL are relatives, prepend the rootURL to it
	 */
	public static URL getURL(URL rootURL, String urlString, String defaultURL) throws MalformedURLException {
		URL url = null;

		// if no URL , provide Default
		if (urlString == null || urlString.trim().equals("")) { //$NON-NLS-1$

			// no URL, no default, return right now...
			if (defaultURL == null || defaultURL.trim().equals("")) //$NON-NLS-1$
				return null;
			else
				urlString = defaultURL;
		}

		// URL can be relative or absolute	
		if (urlString.startsWith("/") && urlString.length() > 1) //$NON-NLS-1$
			urlString = urlString.substring(1);
		try {
			url = new URL(urlString);
		} catch (MalformedURLException e) {
			// the url is not an absolute URL
			// try relative
			url = new URL(rootURL, urlString);
		}

		return url;
	}

	/**
	 * return a relative String to rootURL 
	 * if url contains rootURL so
	 * new URL(rootURL, resultString) == url
	 * 
	 */
	public static String getURLAsString(URL rootURL, URL url) {
		String result = null;

		if (rootURL == null) {
			return (url == null) ? null : url.toString();
		}

		// if no URL , return null
		if (url != null) {

			result = url.toExternalForm();

			if (rootURL.getHost() != null && !rootURL.getHost().equals(url.getHost()))
				return result;

			if (rootURL.getProtocol() != null && !rootURL.getProtocol().equals(url.getProtocol()))
				return result;

			if (rootURL.getPort() != url.getPort())
				return result;

			String rootURLFileString = rootURL.getFile();
			rootURLFileString = rootURLFileString.replace(File.separatorChar, '/');
			if (!rootURLFileString.endsWith("/")) {
				int index = rootURLFileString.lastIndexOf('/');
				if (index != -1) {
					rootURLFileString = rootURLFileString.substring(0, index);
				}
			}
			String urlFileString = url.getFile();

			if (urlFileString.startsWith(rootURLFileString)) {
				result = urlFileString.substring(rootURLFileString.length());
				result = result.replace(File.separatorChar, '/');
			} else {
				// we need to check the following
				// file:/C:/ and file:C:/
				if ("file".equalsIgnoreCase(url.getProtocol())) {
					File rootFile = new File(rootURLFileString);
					File urlFile = new File(urlFileString);

					File relativePath = urlFile;
					while (relativePath != null && !rootFile.equals(relativePath.getParentFile())) {
						relativePath = relativePath.getParentFile();
					}

					if (relativePath == null) {
						UpdateCore.warn("Cannot calculate relative path");
						return url.toString();
					} else {
						String relativeRootString = relativePath.getParentFile().getAbsolutePath();
						String fullString = urlFile.getAbsolutePath();
						if (!fullString.startsWith(relativeRootString)) {
							UpdateCore.warn("Full path:" + fullString + " does not start with " + relativeRootString);
							return url.toString();
						} else {
							String returnString = fullString.substring(relativeRootString.length() + 1);
							if (urlFile.isDirectory())
								returnString += File.separator;
							// we lost the last slash when tranforming in File
							returnString = returnString.replace(File.separatorChar, '/');
							return returnString;
						}

					}

				} else {
					result = url.toString();
				}
			}
		}

		return result;
	}

	/**
	 * returns a translated String
	 */
	public static String getResourceString(String infoURL, ResourceBundle bundle) {
		String result = null;
		if (infoURL != null) {
			result = Platform.getResourceString(UpdateCore.getPlugin().getBundle(), infoURL, bundle);
		}
		return result;
	}

	/**
	 * 
	 */
	public static URL copyToLocal(InputStream sourceContentReferenceStream, String localName, InstallMonitor monitor) throws MalformedURLException, IOException, InstallAbortedException {
		URL result = null;
		// create the Dir if they do not exist
		// get the path from the File to resolve File.separator..
		// do not use the String as it may contain URL like separator
		File localFile = new File(localName);
		int index = localFile.getPath().lastIndexOf(File.separator);
		if (index != -1) {
			File dir = new File(localFile.getPath().substring(0, index));
			if (!dir.exists())
				dir.mkdirs();
		}

		// transfer the content of the File
		if (!localFile.isDirectory()) {
			OutputStream localContentReferenceStream = new FileOutputStream(localFile);
			try {
				Utilities.copy(sourceContentReferenceStream, localContentReferenceStream, monitor);
			} finally {
				try {
					localContentReferenceStream.close();
				} catch (IOException e){}
			}
		}
		result = localFile.toURL();
		return result;
	}

	/*
	 * [20305] need to slam permissions for executable libs on some
	 * platforms. This is a temporary fix
	 */
	public static void checkPermissions(ContentReference ref, String filePath) {

		if (ref.getPermission() != 0) {
			UpdateCore.warn("Change permission for " + filePath + " to " + ref.getPermission());
			// FIXME: change the code to use JNI
		}

		if (filePath != null && OS_UNIX && ref.getPermission() != 0) {
			// add execute permission on shared libraries 20305
			// do not remove write permission 20896
			// chmod a+x *.sl
			try {
				Process pr = Runtime.getRuntime().exec(new String[] { "chmod", "a+x", filePath });
				Thread chmodOutput = new StreamConsumer(pr.getInputStream());
				chmodOutput.setName("chmod output reader");
				chmodOutput.start();
				Thread chmodError = new StreamConsumer(pr.getErrorStream());
				chmodError.setName("chmod error reader");
				chmodError.start();
			} catch (IOException ioe) {
			}

		}
	}

	/**
	 * Returns a random file name for the local system
	 * attempt to conserve the extension if there is a '.' in the path
	 * and no File.Seperator after the '.'
	 * 
	 * \a\b\c.txt -> c987659385.txt
	 * c.txt -> c3854763.txt
	 * c	-> c953867549
	 */
	public static String getLocalRandomIdentifier(String remotePath, Date date) {
		int dotIndex = remotePath.lastIndexOf(".");	//$NON-NLS-1$
		int fileIndex = remotePath.lastIndexOf(File.separator);
		// if there is a separator after the dot
		// do not consider it as an extension
		String ext = (dotIndex != -1 && fileIndex < dotIndex) ? remotePath.substring(dotIndex) : ""; //$NON-NLS-1$
		// the name is the string between the separator and the dot
		// if there is no separator, it is the string up to the dot		
		// if there is no dot, go to the end of the string 
		if (fileIndex == -1)
			fileIndex = 0;
		if (dotIndex == -1)
			dotIndex = remotePath.length();
		// if I have a separator and no dot: /a/b/c -> c
		// if my separator is the last /a/b/c/, fileIndex and dotIndex are the same, so it will return the default temp name
		String name = (fileIndex < dotIndex) ? remotePath.substring(fileIndex, dotIndex) : "Eclipse_Update_TMP_"; //$NON-NLS-1$
		String result = name + date.getTime() + ext;
		return result;
	}

	/**
	 * remove a file or directory from the file system.
	 * used to clean up install
	 */
	public static void removeFromFileSystem(File file) {
		if (!file.exists())
			return;

		if (file.isDirectory()) {
			String[] files = file.list();
			if (files != null) // be careful since file.list() can return null
				for (int i = 0; i < files.length; ++i)
					removeFromFileSystem(new File(file, files[i]));
		}

		if (!file.delete()) {
			String msg = Policy.bind("UpdateManagerUtils.UnableToRemoveFile", file.getAbsolutePath());	//$NON-NLS-1$ //$NON-NLS-2$
			UpdateCore.log(msg, new Exception());
		}
	}

	/**
	 * remove all the empty directories recursively
	 * used to clean up install
	 */
	public static void removeEmptyDirectoriesFromFileSystem(File file) {
		if (!file.isDirectory())
			return;

		String[] files = file.list();
		if (files != null) { // be careful since file.list() can return null
			for (int i = 0; i < files.length; ++i) {
				removeEmptyDirectoriesFromFileSystem(new File(file, files[i]));
			}
		}
		if (!file.delete()) {
			String msg = Policy.bind("UpdateManagerUtils.UnableToRemoveFile", file.getAbsolutePath());	//$NON-NLS-1$ //$NON-NLS-2$
			UpdateCore.log(msg, new Exception());
		}
	}

	/**
	 * Returns the plugin entries that are in source array and
	 * not in target array
	 */
	public static IPluginEntry[] diff(IPluginEntry[] sourceArray, IPluginEntry[] targetArray) { // No pluginEntry to Install, return Nothing to instal
		if (sourceArray == null || sourceArray.length == 0) {
			return new IPluginEntry[0];
		} // No pluginEntry installed, Install them all
		if (targetArray == null || targetArray.length == 0) {
			return sourceArray;
		} // if a IPluginEntry from sourceArray is NOT in
		// targetArray, add it to the list
		List list1 = Arrays.asList(targetArray);
		List result = new ArrayList(0);
		for (int i = 0; i < sourceArray.length; i++) {
			if (!list1.contains(sourceArray[i]))
				result.add(sourceArray[i]);
		}

		IPluginEntry[] resultEntry = new IPluginEntry[result.size()];
		if (result.size() > 0)
			result.toArray(resultEntry);
		return resultEntry;
	}

	/**
	 * Returns the parent URL of the given URL, or <code>null</code> if the
	 * given URL is the root.
	 * <table>
	 * <caption>Example</caption>
	 * <tr>
	 *   <th>Given URL</th>
	 *   <th>Parent URL</th>
	 * <tr>
	 *   <td>"http://hostname/"</td>
	 *   <td>null</td>
	 * <tr>
	 *   <td>"http://hostname/folder/file</td>
	 *   <td>"http://hostname/folder/</td>
	 * </table>
	 *
	 * @param url a URL
	 * @return    the parent of the given URL
	 */
	public static URL getParent(URL url) {
		String file = url.getFile();
		int len = file.length();
		if (len == 0 || len == 1 && file.charAt(0) == '/')
			return null;
		int lastSlashIndex = -1;
		for (int i = len - 2; lastSlashIndex == -1 && i >= 0; --i) {
			if (file.charAt(i) == '/')
				lastSlashIndex = i;
		}
		if (lastSlashIndex == -1)
			file = "";
		else
			file = file.substring(0, lastSlashIndex + 1);
		try {
			url = new URL(url.getProtocol(), url.getHost(), url.getPort(), file);
		} catch (MalformedURLException e) {
			Assert.isTrue(false, e.getMessage());
		}
		return url;
	}

	/**
	 * 
	 */
	public static URL asDirectoryURL(URL url) throws MalformedURLException {
		//url = URLEncoder.encode(url);
		String path = url.getFile();
		if (!path.endsWith("/")) {
			int index = path.lastIndexOf('/');
			if (index != -1)
				path = path.substring(0, index + 1);
			// ignore any ref in original URL
			url = new URL(url.getProtocol(), url.getHost(), url.getPort(), path);
		}
		return url;
	}

	/*
	 * Compares two URL for equality
	 * Return false if one of them is null
	 */
	public static boolean sameURL(URL url1, URL url2) {

		if (url1 == null || url2 == null)
			return false;
		if (url1 == url2)
			return true;
		if (url1.equals(url2))
			return true;

		// check if URL are file: URL as we may
		// have 2 URL pointing to the same featureReference
		// but with different representation
		// (i.e. file:/C;/ and file:C:/)
		if (!"file".equalsIgnoreCase(url1.getProtocol()))
			return false;
		if (!"file".equalsIgnoreCase(url2.getProtocol()))
			return false;

		File file1 = getFileFor(url1);//new File(url1.getFile());
		File file2 = getFileFor(url2);

		if (file1 == null)
			return false;

		return (file1.equals(file2));
	}
	
	/*
	 * Method getFileFor.
	 * @param url1
	 * @return File
	 */
	private static File getFileFor(URL url1) {
		if (urlFileMap == null) urlFileMap = new HashMap();
		if (urlFileMap.get(url1)!=null) return (File)urlFileMap.get(url1);
		File newFile = new File(url1.getFile());
		urlFileMap.put(url1,newFile);
		return newFile; 
	}

	/*
	 * returns the list of FeatureReference that are parent of 
	 * the Feature or an empty array if no parent found.
	 * @param onlyOptional if set to <code>true</code> only return parents that consider the feature optional
	 * @param child
	 * @param possiblesParent
	 */
	public static IFeatureReference[] getParentFeatures(IFeature childFeature, IFeatureReference[] possiblesParent, boolean onlyOptional) throws CoreException {

		if (childFeature == null)
			return new IFeatureReference[0];

		List parentList = new ArrayList();
		IIncludedFeatureReference[] children = null;
		IFeature compareFeature = null;
		for (int i = 0; i < possiblesParent.length; i++) {
			try {
				IFeature possibleParentFeature = possiblesParent[i].getFeature(null);
				if (possibleParentFeature != null) {
					children = possibleParentFeature.getIncludedFeatureReferences();
					for (int j = 0; j < children.length; j++) {
						try {
							compareFeature = children[j].getFeature(null);
						} catch (CoreException e) {
							UpdateCore.warn("", e);
						}
						if (childFeature.equals(compareFeature)) {
							if (onlyOptional) {
								if (UpdateManagerUtils.isOptional(children[j])) {
									parentList.add(possiblesParent[i]);
								} else {
									UpdateCore.warn("Feature :" + children[j] + " not optional. Not included in parents list.");
								}
							} else {
								parentList.add(possiblesParent[i]);
							}
						}
					}
				}
			} catch (CoreException e) {
				UpdateCore.warn("", e);
			}
		}

		IFeatureReference[] parents = new IFeatureReference[0];
		if (parentList.size() > 0) {
			parents = new IFeatureReference[parentList.size()];
			parentList.toArray(parents);
		}
		return parents;
	}

	/*
	 * returns the list of Features that are parent of 
	 * the Feature or an empty array if no parent found
	 * @param onlyOptional if set to <code>true</code> only return parents that consider the feature optional
	 * @param child
	 * @param possiblesParent
	 */
	public static IFeatureReference[] getParentFeatures(IFeatureReference child, IFeatureReference[] possiblesParent, boolean onlyOptional) throws CoreException {

		if (child == null)
			return new IFeatureReference[0];

		IFeature childFeature = null;
		try {
			childFeature = child.getFeature(null);
		} catch (CoreException e) {
			UpdateCore.warn(null, e);
		}

		if (childFeature == null)
			return new IFeatureReference[0];

		return getParentFeatures(childFeature, possiblesParent, onlyOptional);
	}

	/*
	 * If the return code of the HTTP connection is not 200 (OK)
	 * thow an IO exception
	 * 
	 */
	public static void checkConnectionResult(Response response,URL url) throws IOException {
		// did the server return an error code ?
			int result = response.getStatusCode();

			if (result != IStatusCodes.HTTP_OK) {
				String serverMsg = response.getStatusMessage();
				throw new IOException(Policy.bind("ContentReference.HttpNok", new Object[] { new Integer(result), serverMsg, url })); //$NON-NLS-1$						
			}
	}

	public static class StreamConsumer extends Thread {
		InputStream is;
		byte[] buf;
		public StreamConsumer(InputStream inputStream) {
			super();
			this.setDaemon(true);
			this.is = inputStream;
			buf = new byte[512];
		}
		public void run() {
			try {
				int n = 0;
				while (n >= 0)
					n = is.read(buf);
			} catch (IOException ioe) {
			}
		}
	}

	/**
	 * Return the optional children to install
	 * The optional features to install may not all be direct children 
	 * of the feature.
	 * Also include non-optional features
	 * 
	 * @param children all the nested features
	 * @param optionalfeatures optional features to install
	 * @return IFeatureReference[]
	 */
	public static IFeatureReference[] optionalChildrenToInstall(IFeatureReference[] children, IFeatureReference[] optionalfeatures) {

		List optionalChildrenToInstall = new ArrayList();
		for (int i = 0; i < children.length; i++) {
			IFeatureReference optionalFeature = children[i];
			if (!UpdateManagerUtils.isOptional(optionalFeature)) {
				optionalChildrenToInstall.add(optionalFeature);
			} else {
				for (int j = 0; j < optionalfeatures.length; j++) {
					if (optionalFeature.equals(optionalfeatures[j])) {
						optionalChildrenToInstall.add(optionalFeature);
						break;
					}
				}
			}
		}

		IFeatureReference[] result = new IFeatureReference[optionalChildrenToInstall.size()];
		if (optionalChildrenToInstall.size() > 0) {
			optionalChildrenToInstall.toArray(result);
		}

		return result;
	}

	/**
	 * returns the mapping of matching rules
	 * the default returns perfect
	 * 
	 * @since 2.0.2
	 */
	public static int getMatchingRule(String rule) {
		if (rule == null)
			return IImport.RULE_PERFECT;
		int ruleInt = ((Integer) table.get(rule)).intValue();
		if (ruleInt == IImport.RULE_NONE)
			return IImport.RULE_PERFECT;
		return ruleInt;
	}
	
	/**
	 * returns the mapping of matching id rules
	 * the default returns perfect
	 * 
	 * @since 2.0.2
	 */
	public static int getMatchingIdRule(String rule) {
		if (rule!=null && rule.equalsIgnoreCase("prefix"))
			return IImport.RULE_PREFIX;
		return IImport.RULE_PERFECT;
	}
	
	/**
	 * Method isOptional.
	 * @param featureReference
	 * @return boolean
	 */
	public static boolean isOptional(IFeatureReference featureReference) {
		if (featureReference==null) return false;
		if (featureReference instanceof IIncludedFeatureReference){
			return ((IIncludedFeatureReference)featureReference).isOptional();
		}
		return false;
	}

	/**
	 * 
	 */
	public static boolean isValidEnvironment(IPlatformEnvironment candidate) {
		if (candidate==null) return false;
		String os = candidate.getOS();
		String ws = candidate.getWS();
		String arch = candidate.getOSArch();
		String nl = candidate.getNL();
		if (os!=null && !isMatching(os, SiteManager.getOS())) return false;
		if (ws!=null && !isMatching(ws, SiteManager.getWS())) return false;
		if (arch!=null && !isMatching(arch, SiteManager.getOSArch())) return false;
		if (nl!=null && !isMatchingLocale(nl, SiteManager.getNL())) return false;
		return true;
	}

	/**
	 * 
	 */	
	private static boolean isMatching(String candidateValues, String siteValues) {
		if (siteValues==null) return false;
		if ("*".equalsIgnoreCase(candidateValues)) return true;
		siteValues = siteValues.toUpperCase();		
		StringTokenizer stok = new StringTokenizer(candidateValues, ",");
		while (stok.hasMoreTokens()) {
			String token = stok.nextToken().toUpperCase();
			if (siteValues.indexOf(token)!=-1) return true;
		}
		return false;
	}
	
	/**
	 * 
	 */	
	private static boolean isMatchingLocale(String candidateValues, String locale) {
		if (locale==null) return false;
		if ("*".equalsIgnoreCase(candidateValues)) return true;
		
		locale = locale.toUpperCase();
		candidateValues = candidateValues.toUpperCase();	
		StringTokenizer stok = new StringTokenizer(candidateValues, ",");
		while (stok.hasMoreTokens()) {
			String candidate = stok.nextToken();
			if (locale.indexOf(candidate) == 0)
				return true;
			if (candidate.indexOf(locale) == 0)
				return true;
		}
		return false;
	}

	
/**
 * write XML file
 */
public static class Writer {

	private PrintWriter w;
	private OutputStream out;
	private OutputStreamWriter outWriter;
	private BufferedWriter buffWriter;
	private String encoding;

	/*
	 * 
	 */
	private Writer() {
		super();
	}
	
	public void init(File file, String encoding) throws FileNotFoundException, UnsupportedEncodingException{
		this.encoding = encoding;
		out = new FileOutputStream(file);
		outWriter = new OutputStreamWriter(out, encoding); //$NON-NLS-1$
		buffWriter = new BufferedWriter(outWriter);
		w = new PrintWriter(buffWriter);
	}

	
	/*
	 * 
	 */
	public void write(IWritable element) {
		w.println("<?xml version=\"1.0\" encoding=\""+encoding+"\"?>"); //$NON-NLS-1$
		w.println(""); //$NON-NLS-1$
		w.println("<!-- File written by Update manager 2.0 -->"); //$NON-NLS-1$
		w.println("<!-- comments in this file are not preserved -->"); //$NON-NLS-1$
		w.println(""); //$NON-NLS-1$
		 ((IWritable) element).write(0, w);
		close();
	}
	
	/*
	 * 
	 */
	 public void close(){
	 		w.close();
	 }

	/*
	 * 
	 */
	private static void appendEscapedChar(StringBuffer buffer, char c) {
		String replacement = getReplacement(c);
		if (replacement != null) {
			buffer.append('&');
			buffer.append(replacement);
			buffer.append(';');
		} else {
			if ((c >= ' ' && c <= 0x7E) || c == '\n' || c == '\r' || c == '\t') {
				buffer.append(c);
			} else {
				buffer.append("&#"); //$NON-NLS-1$
				buffer.append(Integer.toString(c));
				buffer.append(';');
			}
		}
	}

	/*
	 * 
	 */
	public static String xmlSafe(String s) {
		StringBuffer result = new StringBuffer(s.length() + 10);
		for (int i = 0; i < s.length(); ++i)
			appendEscapedChar(result, s.charAt(i));
		return result.toString();
	}
	
	/*
	 * 
	 */
	private static String getReplacement(char c) {
		// Encode special XML characters into the equivalent character references.
		// These five are defined by default for all XML documents.
		switch (c) {
			case '<' :
				return "lt"; //$NON-NLS-1$
			case '>' :
				return "gt"; //$NON-NLS-1$
			case '"' :
				return "quot"; //$NON-NLS-1$
			case '\'' :
				return "apos"; //$NON-NLS-1$
			case '&' :
				return "amp"; //$NON-NLS-1$
		}
		return null;
	}
}
	public static Writer getWriter(File file,String encoding) throws FileNotFoundException, UnsupportedEncodingException {
		if (writer==null) writer = new Writer();
		writer.init(file,encoding);
		return writer;
	}
	
	public static boolean isSameTimestamp(URL url, long timestamp) {	
		try {
			URL resolvedURL = URLEncoder.encode(url);
			Response response = UpdateCore.getPlugin().get(resolvedURL);
			long remoteLastModified = response.getLastModified();
			// 2 seconds tolerance, as some OS's may round up the time stamp
			// to the closest second. For safety, we make it 2 seconds.
			return Math.abs(remoteLastModified - timestamp)/1000 <= 2;
		} catch (MalformedURLException e) {
			return false;
		} catch (IOException e) {
			return false;
		}
	}
	/**
	 * The file is associated with a lookup key.
	 * @param key optional lookup key, or <code>null</code>.
	 * @param temp the local working file
	 */
	public synchronized static void mapLocalFileFragment(String key, FileFragment temp) {
		// create file association 
		if (key != null) {
			if (localFileFragmentMap == null)
				localFileFragmentMap = new HashMap();
			localFileFragmentMap.put(key, temp);
		}
	}

	/**
	 * The file is associated with a lookup key.
	 * @param key optional lookup key, or <code>null</code>.
	 */
	public synchronized static void unMapLocalFileFragment(String key) {
		// remove file association 
		if (key != null && localFileFragmentMap !=null) {
			localFileFragmentMap.remove(key);
		}
	}
	
	/**
	 * Returns a previously cached local file (in temporary area) matching the
	 * specified key. 
	 * 
	 * @param key lookup key
	 * @return cached file, or <code>null</code>.
	 */
	public static synchronized FileFragment lookupLocalFileFragment(String key) {
		if (localFileFragmentMap == null)
			return null;
		return (FileFragment) localFileFragmentMap.get(key);
	}
	
	/**
	 * Copies specified input stream to the output stream. Neither stream
	 * is closed as part of this operation.
	 * 
	 * @param is input stream
	 * @param os output stream
	 * @param monitor progress monitor
     * @param expectedLength - if > 0, the number of bytes from InputStream will be verified
	 * @@return the offset in the input stream where copying stopped. Returns -1 if end of input stream is reached.
	 * @since 2.0
	 */
	public static long copy(InputStream is, OutputStream os, InstallMonitor monitor, long expectedLength) {
		byte[] buf = getBuffer();
		long offset=0;
		try {
			int len = is.read(buf);
			int nextIncrement = 0;
			while (len != -1) {
				os.write(buf, 0, len);
					offset += len;
				if (monitor != null) {
					nextIncrement += len;
					// update monitor periodically
					if (nextIncrement >= INCREMENT_SIZE){ 	
						monitor.incrementCount(nextIncrement);
						nextIncrement = 0;
					}
					if (monitor.isCanceled()) {
						return offset;
					}
				}
				if (expectedLength > 0 && offset == expectedLength) {
					// everything read do not return offset, otherwise trying
					// to read again from this offset will result in HTTP 416
					break;
				}
				
				len = is.read(buf);
			}
			if (nextIncrement > 0 && monitor != null)
				monitor.incrementCount(nextIncrement);
			if(expectedLength>0 && offset!=expectedLength)
				throw new IOException("InputStream ended after "+ offset +" bytes (expected "+expectedLength+").");
			return -1;
		} catch(IOException e){
			// Log the actual error, as this is no longer
			// passed up the calling stack
			UpdateCore.log("UpdateManagerUtils.copy(): " + offset, e);
			return offset;
		} finally {
			freeBuffer(buf);
		}
	}

	public static class CopyException extends Exception {
		Exception rootException;
		int bytesCopied;

		/**
		 * 
		 */
		public CopyException(Exception rootException, int bytesCopied) {
			super();
			this.rootException= rootException;
			this.bytesCopied=bytesCopied;
		}
		/**
		 * Instance of IOException or InstallAbortedException
		 * @return
		 */
		public Exception getRootException(){
			return rootException;
		}
		public int getBytesCopied(){
			return bytesCopied;
		}

	}
	
	private static synchronized byte[] getBuffer() {
		if (bufferPool == null) {
			return new byte[BUFFER_SIZE];
		}

		try {
			return (byte[]) bufferPool.pop();
		} catch (EmptyStackException e) {
			return new byte[BUFFER_SIZE];
		}
	}

	private static synchronized void freeBuffer(byte[] buf) {
		if (bufferPool == null)
			bufferPool = new Stack();
		bufferPool.push(buf);
	}
	
	
	/**
	 * Returns a list of fragments. Zero length if no fragments.
	 * @param bundle the bundle to get fragments for
	 */
	public static FragmentEntry[] getFragments(Bundle bundle) {
		PackageAdmin pkgAdmin = UpdateCore.getPlugin().getPackageAdmin();
		Bundle[] fragmentBundles = pkgAdmin.getFragments(bundle);
		if (fragmentBundles == null) 
			return noFragments;
		
		FragmentEntry[] fragments = new FragmentEntry[fragmentBundles.length];
		for (int i = 0; i < fragments.length; i++) {
			fragments[i] = new FragmentEntry((String) fragmentBundles[i]
					.getHeaders().get(Constants.BUNDLE_SYMBOLICNAME),
					(String) fragmentBundles[i].getHeaders().get(
							Constants.BUNDLE_VERSION), Platform
							.getResourceString(fragmentBundles[i],
									(String) fragmentBundles[i].getHeaders()
											.get(Constants.BUNDLE_VERSION)),
					fragmentBundles[i].getLocation());
		}
		return fragments;	
	}
}
