/*******************************************************************************
 * Copyright (c) 2005, 2006 IBM Corporation and others.
 * All rights reserved. This program and the accompanying materials
 * are made available under the terms of the Eclipse Public License v1.0
 * which accompanies this distribution, and is available at
 * http://www.eclipse.org/legal/epl-v10.html
 * 
 * Contributors:
 *     IBM Corporation - initial API and implementation
 *     Chris Aniszczyk (IBM Corp.) - Fixed NPE
 *******************************************************************************/
package org.eclipse.update.internal.core;

import java.io.BufferedWriter;
import java.io.File;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.io.OutputStreamWriter;
import java.io.PrintWriter;
import java.io.UnsupportedEncodingException;
import java.net.MalformedURLException;
import java.net.URL;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Date;
import java.util.EmptyStackException;
import java.util.HashMap;
import java.util.List;
import java.util.Locale;
import java.util.Map;
import java.util.ResourceBundle;
import java.util.Stack;
import java.util.StringTokenizer;

import org.eclipse.core.runtime.Assert;
import org.eclipse.core.runtime.CoreException;
import org.eclipse.core.runtime.Platform;
import org.eclipse.osgi.util.NLS;
import org.eclipse.update.core.ContentReference;
import org.eclipse.update.core.IFeature;
import org.eclipse.update.core.IFeatureReference;
import org.eclipse.update.core.IImport;
import org.eclipse.update.core.IIncludedFeatureReference;
import org.eclipse.update.core.IPlatformEnvironment;
import org.eclipse.update.core.IPluginEntry;
import org.eclipse.update.core.InstallMonitor;
import org.eclipse.update.core.Site;
import org.eclipse.update.core.SiteManager;
import org.eclipse.update.core.Utilities;
import org.eclipse.update.core.model.InstallAbortedException;
import org.eclipse.update.internal.core.connection.ConnectionFactory;
import org.eclipse.update.internal.core.connection.IResponse;
import org.osgi.framework.Bundle;
import org.osgi.framework.Constants;
import org.osgi.service.packageadmin.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() || !file.canWrite())
			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 = NLS.bind(Messages.UpdateManagerUtils_UnableToRemoveFile, (new String[] { file.getAbsolutePath() }));
			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 = NLS.bind(Messages.UpdateManagerUtils_UnableToRemoveFile, (new String[] { file.getAbsolutePath() }));
			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(IResponse 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 FatalIOException(NLS.bind(Messages.ContentReference_HttpNok, (new Object[] { new Integer(result), serverMsg, url })));						
		}
	}

	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_COMPATIBLE;
		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)
			return IImport.RULE_COMPATIBLE;
		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;
	}

	/* Original code - commented out to provide a replacement as per bug 98387
	
	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;
	}
	*/
	
	/*
	 * Fixed bug 98387
	 */
	
	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$
		StringTokenizer siteTokens = new StringTokenizer(siteValues, ",");  //$NON-NLS-1$
		//$NON-NLS-1$	
		while(siteTokens.hasMoreTokens()) {
		    StringTokenizer candidateTokens = new StringTokenizer
	                                       (candidateValues, ","); //$NON-NLS-1$
			String siteValue = siteTokens.nextToken();
			while (candidateTokens.hasMoreTokens()) {
				if (siteValue.equalsIgnoreCase
	                             (candidateTokens.nextToken())) 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); 
		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$
		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 {
			if (UpdateCore.getPlugin().getUpdateSession().isVisited(url)) {
				return true;
			}
			URL resolvedURL = URLEncoder.encode(url);
			IResponse response = ConnectionFactory.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(NLS.bind(Messages.UpdateManagerUtils_inputStreamEnded, (new String[] { String.valueOf(offset), String.valueOf(expectedLength) })));
			return -1;
		} catch(IOException e){
			// Log the actual error, as this is no longer
			// passed up the calling stack
			UpdateCore.log(Messages.UpdateManagerUtils_copy + offset, e); 
			return offset;
		} finally {
			freeBuffer(buf);
		}
	}

	public static class CopyException extends Exception {
        
        private static final long serialVersionUID = 1L;
        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;	
	}
	
	public static String getWritableXMLString(String value) {
		StringBuffer buf = new StringBuffer();
		if(value == null)
			return buf.toString();
		for (int i = 0; i < value.length(); i++) {
			char c = value.charAt(i);
			switch (c) {
				case '&' :
					buf.append("&amp;"); //$NON-NLS-1$
					break;
				case '<' :
					buf.append("&lt;"); //$NON-NLS-1$
					break;
				case '>' :
					buf.append("&gt;"); //$NON-NLS-1$
					break;
				case '\'' :
					buf.append("&apos;"); //$NON-NLS-1$
					break;
				case '\"' :
					buf.append("&quot;"); //$NON-NLS-1$
					break;
				default :
					buf.append(c);
					break;
			}
		}
		return buf.toString();
	}
	
	public static LiteFeature[] getLightFeatures(ExtendedSite site) {
		
		URL fullDigestURL;
		try {
			fullDigestURL = getFullDigestURL( site, Locale.getDefault().getCountry(), Locale.getDefault().getLanguage());
		} catch (MalformedURLException e) {
			UpdateCore.log("Could not access digest on the site: " + e.getMessage(), null); //$NON-NLS-1$
			return null;
		}
		
		Digest digest = new Digest( fullDigestURL);
		try {
			LiteFeature[] features =  (LiteFeature[])digest.parseDigest();
			for(int i = 0; i < features.length; i++) {
				features[i].setSite(site);
			}
			return features;
		} catch(Exception e){ 
			UpdateCore.log("Digest could not be parsed:" + e.getMessage(), null); //$NON-NLS-1$
			return null;
		}
	}
	
	private static URL getFullDigestURL(ExtendedSite site, String country, String language) throws MalformedURLException {
		
		String digestURL = (site.getDigestURL().endsWith("/")? site.getDigestURL(): site.getDigestURL() + "/"); //$NON-NLS-1$ //$NON-NLS-2$ 
		
		if (digestURL.indexOf("://") == -1) { //$NON-NLS-1$
			String siteURL = site.getLocationURL().toExternalForm();
			if (siteURL.endsWith(Site.SITE_XML)) {
				siteURL = siteURL.substring(0, siteURL.length() - Site.SITE_XML.length());
			} 
			if (digestURL.equals("/")) { //$NON-NLS-1$
				digestURL = siteURL;
			} else {
				if (digestURL.startsWith("/")) { //$NON-NLS-1$
					digestURL = digestURL.substring(1, digestURL.length());
				}
				digestURL = siteURL + digestURL;
			}
		}
		
		digestURL += "digest";  //$NON-NLS-1$
		
		if ( isLocalSupported(site, country, language)) {
			return new URL(digestURL + "_" + language + "_" + country + ".zip"); //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$
		}
		if ( isLangaugeSupported(site, language)) {
			return new URL(digestURL + "_" + language + ".zip"); //$NON-NLS-1$ //$NON-NLS-2$
		}
		return new URL(digestURL + ".zip"); //$NON-NLS-1$
	}

	private static boolean isLangaugeSupported(ExtendedSite site, String language) {
		String[] availableLanguages =  site.getAvailableLocals();
		if ((availableLanguages == null) || (availableLanguages.length == 0)) {
			return false;
		}
		for(int i = 0; i < availableLanguages.length; i++) {
			if (availableLanguages[i].equals(language)) {
				return true;
			}
		}
		return false;
	}

	private static boolean isLocalSupported(ExtendedSite site, String country, String language) {
		String localeCode = language + "_" + country; //$NON-NLS-1$
		String[] availableLocals =  site.getAvailableLocals();
		if ((availableLocals == null) || (availableLocals.length == 0)) {
			return false;
		}
		for(int i = 0; i < availableLocals.length; i++) {
			if (availableLocals[i].equals(localeCode)) {
				return true;
			}
		}
		return false;
	}
}
