/*******************************************************************************
 * 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("/")) { //$NON-NLS-1$
				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())) { //$NON-NLS-1$
					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"); //$NON-NLS-1$
						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); //$NON-NLS-1$ //$NON-NLS-2$
							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()); //$NON-NLS-1$ //$NON-NLS-2$
			// 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 }); //$NON-NLS-1$ //$NON-NLS-2$
				Thread chmodOutput = new StreamConsumer(pr.getInputStream());
				chmodOutput.setName("chmod output reader"); //$NON-NLS-1$
				chmodOutput.start();
				Thread chmodError = new StreamConsumer(pr.getErrorStream());
				chmodError.setName("chmod error reader"); //$NON-NLS-1$
				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 = ""; //$NON-NLS-1$
		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("/")) { //$NON-NLS-1$
			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())) //$NON-NLS-1$
			return false;
		if (!"file".equalsIgnoreCase(url2.getProtocol())) //$NON-NLS-1$
			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); //$NON-NLS-1$
						}
						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."); //$NON-NLS-1$ //$NON-NLS-2$
								}
							} else {
								parentList.add(possiblesParent[i]);
							}
						}
					}
				}
			} catch (CoreException e) {
				UpdateCore.warn("", e); //$NON-NLS-1$
			}
		}

		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")) //$NON-NLS-1$
			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 ("*".equals(candidateValues)) return true; //$NON-NLS-1$
		if ("".equals(candidateValues)) return true; //$NON-NLS-1$
		siteValues = siteValues.toUpperCase();		
		StringTokenizer stok = new StringTokenizer(candidateValues, ","); //$NON-NLS-1$
		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 ("*".equals(candidateValues)) return true; //$NON-NLS-1$
		if ("".equals(candidateValues)) return true; //$NON-NLS-1$
		
		locale = locale.toUpperCase();
		candidateValues = candidateValues.toUpperCase();	
		StringTokenizer stok = new StringTokenizer(candidateValues, ","); //$NON-NLS-1$
		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$ //$NON-NLS-2$
		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(Policy.bind("UpdateManagerUtils.inputStreamEnded", String.valueOf(offset), String.valueOf(expectedLength))); //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$
			return -1;
		} catch(IOException e){
			// Log the actual error, as this is no longer
			// passed up the calling stack
			UpdateCore.log(Policy.bind("UpdateManagerUtils.copy") + offset, e); //$NON-NLS-1$
			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;	
	}
}
