/*******************************************************************************
 * Copyright (c) 2000, 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
 *******************************************************************************/
package org.eclipse.update.core;

import java.io.BufferedOutputStream;
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.net.URL;
import java.util.Date;
import java.util.HashMap;
import java.util.Iterator;
import java.util.Map;
import java.util.Properties;
import java.util.Set;
import java.util.StringTokenizer;

import org.eclipse.core.runtime.CoreException;
import org.eclipse.core.runtime.IPath;
import org.eclipse.core.runtime.Path;
import org.eclipse.osgi.util.NLS;
import org.eclipse.update.core.model.ContentEntryModel;
import org.eclipse.update.core.model.InstallAbortedException;
import org.eclipse.update.core.model.NonPluginEntryModel;
import org.eclipse.update.core.model.PluginEntryModel;
import org.eclipse.update.internal.core.FatalIOException;
import org.eclipse.update.internal.core.FeatureDownloadException;
import org.eclipse.update.internal.core.FileFragment;
import org.eclipse.update.internal.core.InternalSiteManager;
import org.eclipse.update.internal.core.LockManager;
import org.eclipse.update.internal.core.Messages;
import org.eclipse.update.internal.core.UpdateCore;
import org.eclipse.update.internal.core.UpdateManagerUtils;

/**
 * Base implementation of a feature content provider. This class provides a set
 * of helper methods useful for implementing feature content providers. In
 * particular, methods dealing with downloading and caching of feature files.
 * <p>
 * This class must be subclassed by clients.
 * </p>
 * <p>
 * <b>Note:</b> This class/interface is part of an interim API that is still under development and expected to
 * change significantly before reaching stability. It is being made available at this early stage to solicit feedback
 * from pioneering adopters on the understanding that any code that uses this API will almost certainly be broken
 * (repeatedly) as the API evolves.
 * </p>
 * @see org.eclipse.update.core.IFeatureContentProvider
 * @since 2.0
 */
public abstract class FeatureContentProvider
	implements IFeatureContentProvider {

	private static final boolean SWITCH_COPY_LOCAL = true;
	//public static long timer = 0; 
	
	//public static long first = 0; 
	
	/**
	 *  
	 */
	public class FileFilter {

		private IPath filterPath = null;

		/**
		 * Constructor for FileFilter.
		 */
		public FileFilter(String filter) {
			super();
			this.filterPath = new Path(filter);
		}

		/**
		 * returns true if the name matches the rule
		 */
		public boolean accept(String name) {

			if (name == null)
				return false;

			// no '*' pattern matching
			// must be equals
			IPath namePath = new Path(name);
			if (filterPath.lastSegment().indexOf('*') == -1) {
				return filterPath.equals(namePath);
			}

			// check same file extension if extension exists (a.txt/*.txt)
			// or same file name (a.txt,a.*)
			String extension = filterPath.getFileExtension();
			if (extension != null && !extension.equals("*")) { //$NON-NLS-1$
				if (!extension.equalsIgnoreCase(namePath.getFileExtension()))
					return false;
			} else {
				IPath noExtension = filterPath.removeFileExtension();
				String fileName = noExtension.lastSegment();
				if (!fileName.equals("*")) { //$NON-NLS-1$
					if (!namePath.lastSegment().startsWith(fileName))
						return false;
				}
			}

			// check same path
			IPath p1 = namePath.removeLastSegments(1);
			IPath p2 = filterPath.removeLastSegments(1);
			return p1.equals(p2);
		}

	}

	private URL base;
	private IFeature feature;
	private File tmpDir; // local work area for each provider
	public static final String JAR_EXTENSION = ".jar"; //$NON-NLS-1$	

	private static final String DOT_PERMISSIONS = "permissions.properties"; //$NON-NLS-1$
	private static final String EXECUTABLES = "permissions.executable"; //$NON-NLS-1$

	/**
	 * Feature content provider constructor
	 * 
	 * @param base
	 *            feature URL. The interpretation of this URL is specific to
	 *            each content provider.
	 * @since 2.0
	 */
	public FeatureContentProvider(URL base) {
		this.base = base;
		this.feature = null;
	}

	/**
	 * Returns the feature url.
	 * 
	 * @see IFeatureContentProvider#getURL()
	 */
	public URL getURL() {
		return base;
	}

	/**
	 * Returns the feature associated with this content provider.
	 * 
	 * @see IFeatureContentProvider#getFeature()
	 */
	public IFeature getFeature() {
		return feature;
	}

	/**
	 * Sets the feature associated with this content provider.
	 * 
	 * @see IFeatureContentProvider#setFeature(IFeature)
	 */
	public void setFeature(IFeature feature) {
		this.feature = feature;
	}

	/**
	 * Returns the specified reference as a local file system reference. If
	 * required, the file represented by the specified content reference is
	 * first downloaded to the local system
	 * 
	 * @param ref
	 *            content reference
	 * @param monitor
	 *            progress monitor, can be <code>null</code>
	 * @exception IOException
	 * @exception CoreException
	 * @since 2.0
	 */
	public ContentReference asLocalReference(ContentReference ref, InstallMonitor monitor) throws IOException, CoreException {

		// check to see if this is already a local reference
		if (ref.isLocalReference())
			return ref;

		// check to see if we already have a local file for this reference
		String key = ref.toString();

		// need to synch as another thread my have created the file but
		// is still copying into it
		File localFile = null;
		FileFragment localFileFragment = null;
		Object keyLock = LockManager.getLock(key);
		synchronized (keyLock) {
			localFile = Utilities.lookupLocalFile(key);
			if (localFile != null) {
				// check if the cached file is still valid (no newer version on
				// server)
				try {
				if (UpdateManagerUtils.isSameTimestamp(ref.asURL(), localFile.lastModified()))
					return ref.createContentReference(ref.getIdentifier(), localFile);
				} catch(FatalIOException e) {
					throw e;
				} catch(IOException e) {
					throw new FeatureDownloadException(NLS.bind(Messages.FeatureContentProvider_ExceptionDownloading, (new Object[] {getURL().toExternalForm()})), e);
				}
			}

			if (localFile == null) {
				localFileFragment = UpdateManagerUtils.lookupLocalFileFragment(key);
			}
			// 
			// download the referenced file into local temporary area
			InputStream is = null;
			OutputStream os = null;
			long bytesCopied = 0;
			long inputLength = 0;
			boolean success = false;
			if (monitor != null) {
				monitor.saveState();
				monitor.setTaskName(Messages.FeatureContentProvider_Downloading);
				monitor.subTask(ref.getIdentifier() + " "); //$NON-NLS-1$
				try {
					monitor.setTotalCount(ref.getInputSize());
				} catch (FatalIOException e) {
					throw e;
				} catch (IOException e) {
					throw new FeatureDownloadException(NLS.bind(Messages.FeatureContentProvider_ExceptionDownloading, (new Object[] {getURL().toExternalForm()})), e);
				}
				monitor.showCopyDetails(true);
			}

			try {
				//long startTime = System.nanoTime();
				if (localFileFragment != null && "http".equals(ref.asURL().getProtocol())) { //$NON-NLS-1$
					localFile = localFileFragment.getFile();
					try {
						// get partial input stream
						is = ref.getPartialInputStream(localFileFragment.getSize());
						inputLength = ref.getInputSize() - localFileFragment.getSize();
						// get output stream to append to file fragment
						os = new BufferedOutputStream(
						// PAL foundation
								//new FileOutputStream(localFile, true));
								new FileOutputStream(localFile.getPath(), true));
					} catch (FatalIOException e) {
						throw e;
					} catch (IOException e) {
						try {
							if (is != null)
								is.close();
						} catch (IOException ioe) {
						}
						is = null;
						os = null;
						localFileFragment = null;
						throw new FeatureDownloadException(NLS.bind(Messages.FeatureContentProvider_ExceptionDownloading, (new Object[] {getURL().toExternalForm()})), e);
					}
				}
				if (is == null) {
					// must download from scratch
					localFile = Utilities.createLocalFile(getWorkingDirectory(), null);
					try {
						is = ref.getInputStream();
						inputLength = ref.getInputSize();
					} catch (FatalIOException e) {
						throw Utilities.newCoreException(NLS.bind(Messages.FeatureContentProvider_UnableToRetrieve, (new Object[] {ref})), e);
					} catch (IOException e) {
						throw new FeatureDownloadException(NLS.bind(Messages.FeatureContentProvider_ExceptionDownloading, (new Object[] {getURL().toExternalForm()})), e);
					}

					try {
						os = new BufferedOutputStream(new FileOutputStream(localFile));
					} catch (FileNotFoundException e) {
						throw Utilities.newCoreException(NLS.bind(Messages.FeatureContentProvider_UnableToCreate, (new Object[] {localFile})), e);
					}
				}

				Date start = new Date();
				if (localFileFragment != null) {
					bytesCopied = localFileFragment.getSize();
					if (monitor != null) {
						monitor.setCopyCount(bytesCopied);
					}
				}

				// Transfer as many bytes as possible from input to output stream
				long offset = UpdateManagerUtils.copy(is, os, monitor, inputLength);
				if (offset != -1) {
					bytesCopied += offset;
					if (bytesCopied > 0) {
						// preserve partially downloaded file
						UpdateManagerUtils.mapLocalFileFragment(key, new FileFragment(localFile, bytesCopied));
					}
					if (monitor.isCanceled()) {
						String msg = Messages.Feature_InstallationCancelled;
						throw new InstallAbortedException(msg, null);
					} else {
						throw new FeatureDownloadException(NLS.bind(Messages.FeatureContentProvider_ExceptionDownloading, (new Object[] {getURL().toExternalForm()})), new IOException());
					}
				} else {
					UpdateManagerUtils.unMapLocalFileFragment(key);
				}

				Date stop = new Date();
				long timeInseconds = (stop.getTime() - start.getTime()) / 1000;
				// time in milliseconds /1000 = time in seconds
				InternalSiteManager.downloaded(
					ref.getInputSize(),
					(timeInseconds),
					ref.asURL());

				success = true;
				//long endTime = System.nanoTime();
				// file is downloaded succesfully, map it
				Utilities.mapLocalFile(key, localFile);
				
				/*if (ref.asURL().toExternalForm().endsWith("jar")) {
					synchronized(this.getClass()) {
						timer += (endTime - startTime);
						if (first == 0) {
							first = endTime - startTime;
						}
					}
				}*/
			} catch (ClassCastException e) {
				throw Utilities.newCoreException(
					NLS.bind(Messages.FeatureContentProvider_UnableToCreate, (new Object[] { localFile })),
					e);
			} finally {
				//Do not close IS if user cancel,
				//closing IS will read the entire Stream until the end
				if (success && is != null)
					try {
						is.close();
					} catch (IOException e) {
					}
				if (os != null)
					try {
						os.close(); // should flush buffer stream
					} catch (IOException e) {
					}

				if (success || bytesCopied > 0) {
					// set the timestamp on the temp file to match the remote
					// timestamp
					localFile.setLastModified(ref.getLastModified());
				}
				if (monitor != null)
					monitor.restoreState();
			}
			LockManager.returnLock(key);
		} // end lock
		ContentReference reference =
			ref.createContentReference(ref.getIdentifier(), localFile);
		
		UpdateCore.getPlugin().getUpdateSession().markVisited(ref.asURL());
		
		return reference;
	}

	/**
	 * Returns the specified reference as a local file. If required, the file
	 * represented by the specified content reference is first downloaded to
	 * the local system
	 * 
	 * @param ref
	 *            content reference
	 * @param monitor
	 *            progress monitor, can be <code>null</code>
	 * @exception IOException
	 * @exception CoreException
	 * @since 2.0
	 */
	public File asLocalFile(ContentReference ref, InstallMonitor monitor) throws IOException, CoreException {
		File file = ref.asFile();
		if (file != null && !SWITCH_COPY_LOCAL)
			return file;
		ContentReference localRef = asLocalReference(ref, monitor);
		file = localRef.asFile();
		return file;
	}

	/**
	 * Returns working directory for this content provider
	 * 
	 * @return working directory
	 * @exception IOException
	 * @since 2.0
	 */
	protected File getWorkingDirectory() throws IOException {
		if (tmpDir == null)
			tmpDir = Utilities.createWorkingDirectory();
		return tmpDir;
	}

	/**
	 * Returns the total size of all archives required for the specified
	 * plug-in and non-plug-in entries (the "packaging" view).
	 * 
	 * @see IFeatureContentProvider#getDownloadSizeFor(IPluginEntry[],
	 *      INonPluginEntry[])
	 */
	public long getDownloadSizeFor(IPluginEntry[] pluginEntries, INonPluginEntry[] nonPluginEntries) {
		long result = 0;

		// if both are null or empty, return UNKNOWN size
		if ((pluginEntries == null || pluginEntries.length == 0) && (nonPluginEntries == null || nonPluginEntries.length == 0)) {
			return ContentEntryModel.UNKNOWN_SIZE;
		}

		// loop on plugin entries
		long size = 0;
		if (pluginEntries != null)
			for (int i = 0; i < pluginEntries.length; i++) {
				size = ((PluginEntryModel) pluginEntries[i]).getDownloadSize();
				if (size == ContentEntryModel.UNKNOWN_SIZE) {
					return ContentEntryModel.UNKNOWN_SIZE;
				}
				result += size;
			}

		// loop on non plugin entries
		if (nonPluginEntries != null)
			for (int i = 0; i < nonPluginEntries.length; i++) {
				size = ((NonPluginEntryModel) nonPluginEntries[i]).getDownloadSize();
				if (size == ContentEntryModel.UNKNOWN_SIZE) {
					return ContentEntryModel.UNKNOWN_SIZE;
				}
				result += size;
			}

		return result;
	}

	/**
	 * Returns the total size of all files required for the specified plug-in
	 * and non-plug-in entries (the "logical" view).
	 * 
	 * @see IFeatureContentProvider#getInstallSizeFor(IPluginEntry[],
	 *      INonPluginEntry[])
	 */
	public long getInstallSizeFor(IPluginEntry[] pluginEntries, INonPluginEntry[] nonPluginEntries) {
		long result = 0;

		// if both are null or empty, return UNKNOWN size
		if ((pluginEntries == null || pluginEntries.length == 0) && (nonPluginEntries == null || nonPluginEntries.length == 0)) {
			return ContentEntryModel.UNKNOWN_SIZE;
		}

		// loop on plugin entries
		long size = 0;
		if (pluginEntries != null)
			for (int i = 0; i < pluginEntries.length; i++) {
				size = ((PluginEntryModel) pluginEntries[i]).getInstallSize();
				if (size == ContentEntryModel.UNKNOWN_SIZE) {
					return ContentEntryModel.UNKNOWN_SIZE;
				}
				result += size;
			}

		// loop on non plugin entries
		if (nonPluginEntries != null)
			for (int i = 0; i < nonPluginEntries.length; i++) {
				size = ((NonPluginEntryModel) nonPluginEntries[i]).getInstallSize();
				if (size == ContentEntryModel.UNKNOWN_SIZE) {
					return ContentEntryModel.UNKNOWN_SIZE;
				}
				result += size;
			}

		return result;
	}

	/**
	 * Returns the path identifier for a plugin entry. <code>plugins/&lt;pluginId>_&lt;pluginVersion>.jar</code>
	 * 
	 * @return the path identifier
	 */
	protected String getPathID(IPluginEntry entry) {
		return Site.DEFAULT_PLUGIN_PATH + entry.getVersionedIdentifier().toString() + JAR_EXTENSION;
	}

	/**
	 * Returns the path identifer for a non plugin entry. <code>features/&lt;featureId>_&lt;featureVersion>/&lt;dataId></code>
	 * 
	 * @return the path identifier
	 */
	protected String getPathID(INonPluginEntry entry) {
		String nonPluginBaseID = Site.DEFAULT_FEATURE_PATH + feature.getVersionedIdentifier().toString() + "/"; //$NON-NLS-1$
		return nonPluginBaseID + entry.getIdentifier();
	}

	/**
	 * Sets the permission of all the ContentReferences Check for the
	 * .permissions contentReference and use it to set the permissions of other
	 * ContentReference
	 */
	protected void validatePermissions(ContentReference[] references) {

		if (references == null || references.length == 0)
			return;

		Map permissions = getPermissions(references);
		if (permissions.isEmpty())
			return;

		for (int i = 0; i < references.length; i++) {
			ContentReference contentReference = references[i];
			String id = contentReference.getIdentifier();
			Object value = null;
			if ((value = matchesOneRule(id, permissions)) != null) {
				Integer permission = (Integer) value;
				contentReference.setPermission(permission.intValue());
			}
		}
	}

	/**
	 * Returns the value of the matching rule or <code>null</code> if none
	 * found. A rule is matched if the id is equals to a key, or if the id is
	 * resolved by a key. if the id is <code>/path/file.txt</code> it is
	 * resolved by <code>/path/*</code> or <code>/path/*.txt</code>
	 * 
	 * @param id
	 *            the identifier
	 * @param permissions
	 *            list of rules
	 * @return Object the value of the matcing rule or <code>null</code>
	 */
	private Object matchesOneRule(String id, Map permissions) {

		Set keySet = permissions.keySet();
		Iterator iter = keySet.iterator();
		while (iter.hasNext()) {
			FileFilter rule = (FileFilter) iter.next();
			if (rule.accept(id)) {
				return permissions.get(rule);
			}
		}

		return null;
	}

	/*
	 * returns the permission MAP
	 */
	private Map getPermissions(ContentReference[] references) {

		Map result = new HashMap();
		// search for .permissions
		boolean notfound = true;
		ContentReference permissionReference = null;
		for (int i = 0; i < references.length && notfound; i++) {
			ContentReference contentReference = references[i];
			if (DOT_PERMISSIONS.equals(contentReference.getIdentifier())) {
				notfound = false;
				permissionReference = contentReference;
			}
		}
		if (notfound)
			return result;

		Properties prop = new Properties();
		InputStream propertyStream = null;
		try {
			try {
				propertyStream = permissionReference.getInputStream();
				prop.load(propertyStream);
			} finally {
				if (propertyStream != null)
					propertyStream.close();
			}
		} catch (IOException e) {
			UpdateCore.warn("", e); //$NON-NLS-1$
		}

		String executables = prop.getProperty(EXECUTABLES);
		if (executables == null)
			return result;

		StringTokenizer tokenizer = new StringTokenizer(executables, ","); //$NON-NLS-1$
		Integer defaultExecutablePermission = new Integer(ContentReference.DEFAULT_EXECUTABLE_PERMISSION);
		while (tokenizer.hasMoreTokens()) {
			FileFilter filter = new FileFilter(tokenizer.nextToken());
			result.put(filter, defaultExecutablePermission);
		}

		return result;
	}
}
