/*******************************************************************************
 * Copyright (c) 2000, 2004 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.internal.core;


import java.io.File;
import java.io.FileFilter;
import java.io.FileInputStream;
import java.io.IOException;
import java.io.InputStream;
import java.net.MalformedURLException;
import java.net.URL;

import org.eclipse.core.runtime.CoreException;
import org.eclipse.core.runtime.IStatus;
import org.eclipse.core.runtime.Status;
import org.eclipse.osgi.util.NLS;
import org.eclipse.update.core.BaseSiteFactory;
import org.eclipse.update.core.ContentReference;
import org.eclipse.update.core.Feature;
import org.eclipse.update.core.ISite;
import org.eclipse.update.core.JarContentReference;
import org.eclipse.update.core.PluginEntry;
import org.eclipse.update.core.Site;
import org.eclipse.update.core.SiteContentProvider;
import org.eclipse.update.core.SiteFeatureReferenceModel;
import org.eclipse.update.core.Utilities;
import org.eclipse.update.core.model.ArchiveReferenceModel;
import org.eclipse.update.core.model.InvalidSiteTypeException;
import org.eclipse.update.core.model.SiteModel;
import org.eclipse.update.core.model.SiteModelFactory;
import org.eclipse.update.internal.model.BundleManifest;
import org.eclipse.update.internal.model.DefaultPluginParser;
import org.xml.sax.SAXException;

public class SiteFileFactory extends BaseSiteFactory {

	// private when parsing file system
	private SiteFile site;


	/*
	 * @see ISiteFactory#createSite(URL,boolean)
	 */
	public ISite createSite(URL url) throws CoreException, InvalidSiteTypeException {
	
		Site site = null;
		InputStream siteStream = null;
		SiteModelFactory factory = this;
	
		try {
			// if url points to a directory
			// attempt to parse site.xml
			String path = url.getFile();
			File siteLocation = new File(path);
			if (siteLocation.isDirectory()) {
				url = siteLocation.toURL();
				File siteXMLFile = new File(siteLocation, Site.SITE_XML);
				if (siteXMLFile.exists()) {
					siteStream = new FileInputStream(siteXMLFile);
					site = (Site) factory.parseSite(siteStream);
				} else {
					// parse siteLocation
					site = parseSite(siteLocation);
				}
			} else {
				// we are not pointing to a directory
				// attempt to parse the file
				try {
					URL resolvedURL = URLEncoder.encode(url);
					siteStream = openStream(resolvedURL);
					site = (Site) factory.parseSite(siteStream);
				} catch (IOException e) {
	
					// attempt to parse parent directory
					File file = new File(url.getFile());
					File parentDirectory = file.getParentFile();
	
					// do not create directory if it doesn't exist	[18318]
					// instead hrow error					
					if (parentDirectory != null && !parentDirectory.exists())
						throw Utilities.newCoreException(NLS.bind(Messages.SiteFileFactory_DirectoryDoesNotExist, (new String[] { file.getAbsolutePath() })), null);
	
					if (parentDirectory == null || !parentDirectory.isDirectory())
						throw Utilities.newCoreException(NLS.bind(Messages.SiteFileFactory_UnableToObtainParentDirectory, (new String[] { file.getAbsolutePath() })), null);
	
					site = parseSite(parentDirectory);
	
				}
			}
	
			SiteContentProvider contentProvider = new SiteFileContentProvider(url);
			site.setSiteContentProvider(contentProvider);
			contentProvider.setSite(site);
			site.resolve(url, url);
	
			// Do not set read only as may install in it
			//site.markReadOnly();
		} catch (MalformedURLException e) {
			throw Utilities.newCoreException(NLS.bind(Messages.SiteFileFactory_UnableToCreateURL, (new String[] { url == null ? "" : url.toExternalForm() })), e);	//$NON-NLS-1$
		} catch (IOException e) {
			throw Utilities.newCoreException(Messages.SiteFileFactory_UnableToAccessSite,ISite.SITE_ACCESS_EXCEPTION, e);
		} finally {
			try {
				if (siteStream != null)
					siteStream.close();
			} catch (IOException e) {
			}
		}
		return site;
	}
	/**
	 * Method parseSite.
	 */
	private Site parseSite(File directory) throws CoreException {

		this.site = (SiteFile) createSiteMapModel();

		if (!directory.exists())
			throw Utilities.newCoreException(NLS.bind(Messages.SiteFileFactory_FileDoesNotExist, (new String[] { directory.getAbsolutePath() })), null);

		File pluginPath = new File(directory, Site.DEFAULT_PLUGIN_PATH);

		//PACKAGED
		try {
			parsePackagedFeature(directory); // in case it contains JAR files
		} catch (EmptyDirectoryException ede) {
			UpdateCore.log(ede.getStatus());
		}

		try {
			parsePackagedPlugins(pluginPath);
		} catch (EmptyDirectoryException ede) {
			UpdateCore.log(ede.getStatus());
		}

		// INSTALLED
		try {
			parseInstalledFeature(directory);
		} catch (EmptyDirectoryException ede) {
			UpdateCore.log(ede.getStatus());
		}

		try {
			parseInstalledPlugins(pluginPath);
		} catch (EmptyDirectoryException ede) {
			UpdateCore.log(ede.getStatus());
		}

		return site;

	}

	/**
	 * Method parseFeature.
	 * @throws CoreException
	 */
	private void parseInstalledFeature(File directory) throws CoreException {

		File featureDir = new File(directory, Site.DEFAULT_INSTALLED_FEATURE_PATH);
		if (featureDir.exists()) {
			String[] dir;
			SiteFeatureReferenceModel featureRef;
			URL featureURL;
			File currentFeatureDir;
			String newFilePath = null;

			try {
				// handle the installed featuresConfigured under featuresConfigured subdirectory
				dir = featureDir.list();				
				if (dir == null) {
					throw new EmptyDirectoryException( new Status(IStatus.WARNING, UpdateCore.getPlugin().getBundle().getSymbolicName(), IStatus.OK, directory.getName() + File.separator + directory.getName() + "directory is empty", null)); //$NON-NLS-1$
				}
				for (int index = 0; index < dir.length; index++) {

					// the URL must ends with '/' for the bundle to be resolved
					newFilePath = dir[index] + (dir[index].endsWith("/") ? "/" : ""); //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$
					currentFeatureDir = new File(featureDir, newFilePath);
					// check if feature.xml exists
					File featureXMLFile = new File(currentFeatureDir, Feature.FEATURE_XML);
					if (!featureXMLFile.exists()) {
						UpdateCore.warn("Unable to find feature.xml in directory:" + currentFeatureDir); //$NON-NLS-1$
					} else {
						// PERF: remove code
						//SiteFileFactory archiveFactory = new SiteFileFactory();
						featureURL = currentFeatureDir.toURL();
						featureRef = createFeatureReferenceModel();
						featureRef.setSiteModel(site);
						featureRef.setURLString(featureURL.toExternalForm());
						featureRef.setType(ISite.DEFAULT_INSTALLED_FEATURE_TYPE);
						((Site) site).addFeatureReferenceModel(featureRef);
					}
				}
			} catch (MalformedURLException e) {
				throw Utilities.newCoreException(NLS.bind(Messages.SiteFileFactory_UnableToCreateURLForFile, (new String[] { newFilePath })), e);
			}
		}
	}

	/**
	* Method parseFeature.
	* @throws CoreException
	*/
	private void parsePackagedFeature(File directory) throws CoreException {

		// FEATURES
		File featureDir = new File(directory, Site.DEFAULT_FEATURE_PATH);
		if (featureDir.exists()) {
			String[] dir;
			SiteFeatureReferenceModel featureRef;
			URL featureURL;
			File currentFeatureFile;
			String newFilePath = null;

			try {
				// only list JAR files
				dir = featureDir.list(FeaturePackagedContentProvider.filter);
				if (dir == null) {
					throw new EmptyDirectoryException( new Status(IStatus.WARNING, UpdateCore.getPlugin().getBundle().getSymbolicName(), IStatus.OK, directory.getName() + File.separator + directory.getName() + "directory is empty", null)); //$NON-NLS-1$
				}
				
				for (int index = 0; index < dir.length; index++) {

					// check if the JAR file contains a feature.xml
					currentFeatureFile = new File(featureDir, dir[index]);
					JarContentReference ref = new JarContentReference("", currentFeatureFile); //$NON-NLS-1$
					ContentReference result = null;
					try {
						result = ref.peek(Feature.FEATURE_XML, null, null);
					} catch (IOException e) {
						UpdateCore.warn("Exception retrieving feature.xml in file:" + currentFeatureFile, e); //$NON-NLS-1$
					}
					if (result == null) {
						UpdateCore.warn("Unable to find feature.xml in file:" + currentFeatureFile); //$NON-NLS-1$
					} else {
						featureURL = currentFeatureFile.toURL();
						// PERF: remove code
						//SiteFileFactory archiveFactory = new SiteFileFactory();
						featureRef = createFeatureReferenceModel();
						featureRef.setSiteModel(site);
						featureRef.setURLString(featureURL.toExternalForm());
						featureRef.setType(ISite.DEFAULT_PACKAGED_FEATURE_TYPE);
						site.addFeatureReferenceModel(featureRef);
					}
				}
			} catch (MalformedURLException e) {
				throw Utilities.newCoreException(NLS.bind(Messages.SiteFileFactory_UnableToCreateURLForFile, (new String[] { newFilePath })), e);
			}
		}
	}

	/**
	 * Method parsePlugins.
	 * 
	 * look into each plugin/fragment directory, crack the plugin.xml open (or
	 * fragment.xml ???) get id and version, calculate URL...
	 * 
	 * @throws CoreException
	 */
	private void parseInstalledPlugins(File pluginsDir) throws CoreException {
		if (!pluginsDir.exists() || !pluginsDir.isDirectory()) {
			return;
		}
		File[] dirs = pluginsDir.listFiles(new FileFilter() {
			public boolean accept(File f) {
				return f.isDirectory();
			}
		});
		DefaultPluginParser parser = new DefaultPluginParser();
		
		if (dirs == null) {
			throw new EmptyDirectoryException( new Status(IStatus.WARNING, UpdateCore.getPlugin().getBundle().getSymbolicName(), IStatus.OK, pluginsDir.getName() + File.separator + pluginsDir.getName() + "directory is empty", null)); //$NON-NLS-1$
		}
		for (int i = 0; i < dirs.length; i++) {
			File pluginFile = new File(dirs[i], "META-INF/MANIFEST.MF"); //$NON-NLS-1$
			InputStream in = null;
			try {
				BundleManifest bundleManifest = new BundleManifest(pluginFile);
				if (bundleManifest.exists()) {
					PluginEntry entry = bundleManifest.getPluginEntry();
					addParsedPlugin(entry, dirs[i]);
				} else {
					if (!(pluginFile = new File(dirs[i], "plugin.xml")) //$NON-NLS-1$
							.exists()) { 
						pluginFile = new File(dirs[i], "fragment.xml"); //$NON-NLS-1$
					}
					if (pluginFile != null && pluginFile.exists()
							&& !pluginFile.isDirectory()) {
						in = new FileInputStream(pluginFile);
						PluginEntry entry = parser.parse(in);
						addParsedPlugin(entry, dirs[i]);
					}
				}
			} catch (IOException e) {
				String pluginFileString = (pluginFile == null)
						? null
						: pluginFile.getAbsolutePath();
				throw Utilities.newCoreException(NLS.bind(Messages.SiteFileFactory_ErrorAccessing, (new String[] { pluginFileString })), e);
			} catch (SAXException e) {
				String pluginFileString = (pluginFile == null)
						? null
						: pluginFile.getAbsolutePath();
				throw Utilities.newCoreException(NLS.bind(Messages.SiteFileFactory_ErrorParsingFile, (new String[] { pluginFileString })),
						e);
			} finally {
				if (in != null){
					try{
						in.close();
					} catch(IOException e){
					}
				}
			}
		}
	}

	/**
	 * tranform each Plugin and Fragment into an ArchiveReferenceModel
	 * and a PluginEntry for the Site	 
	 */
	// PERF: removed intermediate Plugin object
	private void addParsedPlugin(PluginEntry entry,File file) throws CoreException {

		String location = null;
		try {
			if (entry != null) {

				// create the plugin Entry
				((Site) site).addPluginEntry(entry);

				// Create the Site mapping ArchiveRef->PluginEntry
				// the id of the archiveRef is plugins\<pluginid>_<ver>.jar as per the specs
				// PERF: remove code
				//SiteFileFactory archiveFactory = new SiteFileFactory();				
				ArchiveReferenceModel archive = createArchiveReferenceModel();
				String id = (entry.getVersionedIdentifier().toString());
				String pluginID = Site.DEFAULT_PLUGIN_PATH + id + FeaturePackagedContentProvider.JAR_EXTENSION;
				archive.setPath(pluginID);
				location = file.toURL().toExternalForm();
				archive.setURLString(location);
				((Site) site).addArchiveReferenceModel(archive);

				// TRACE				
				if (UpdateCore.DEBUG && UpdateCore.DEBUG_SHOW_PARSING) {
					UpdateCore.debug("Added archive to site:" + pluginID + " pointing to: " + location); //$NON-NLS-1$ //$NON-NLS-2$
				}
			}
		} catch (MalformedURLException e) {
			throw Utilities.newCoreException(NLS.bind(Messages.SiteFileFactory_UnableToCreateURLForFile, (new String[] { location })), e);
		}
	}

	/**
	 *  
	 */
	private void parsePackagedPlugins(File pluginDir) throws CoreException {
		if (!pluginDir.exists()) {
			return;
		}
		String[] dir = pluginDir.list(FeaturePackagedContentProvider.filter);
		
		if (dir == null) {
			throw new EmptyDirectoryException( new Status(IStatus.WARNING, UpdateCore.getPlugin().getBundle().getSymbolicName(), IStatus.OK, pluginDir.getName() + File.separator + pluginDir.getName() + "directory is empty", null)); //$NON-NLS-1$
		}
		for (int i = 0; i < dir.length; i++) {
			ContentReference ref = null;
			String refString = null;
			InputStream in = null;
			JarContentReference jarReference = null;
			try {
				File file = new File(pluginDir, dir[i]);
				jarReference = new JarContentReference(
						null, file);
				ref = jarReference.peek("META-INF/MANIFEST.MF", null, null); //$NON-NLS-1$
				if (ref != null) {
					in = ref.getInputStream();
					BundleManifest manifest = new BundleManifest(in);
					if (manifest.exists()) {
						addParsedPlugin(manifest.getPluginEntry(), file);
						continue;
					}
				}
				ref = jarReference.peek("plugin.xml", null, null); //$NON-NLS-1$
				if (ref == null) {
					ref = jarReference.peek("fragment.xml", null, null); //$NON-NLS-1$
				}
				if (ref != null) {
					in = ref.getInputStream();
					PluginEntry entry = new DefaultPluginParser().parse(in);
					addParsedPlugin(entry, file);
				}
			} catch (IOException e) {
				try {
					refString = (ref == null) ? null : ref.asURL()
							.toExternalForm();
				} catch (IOException ioe) {
				}
				throw Utilities.newCoreException(NLS.bind(Messages.SiteFileFactory_ErrorAccessing, (new String[] { refString })), e);
			} catch (SAXException e) {
				try {
					refString = (ref == null) ? null : ref.asURL()
							.toExternalForm();
				} catch (IOException ioe) {
				}
				throw Utilities.newCoreException(NLS.bind(Messages.SiteFileFactory_ErrorParsingFile, (new String[] { refString })), e);
			} finally {
				if(in != null){
					try{
						in.close();
					}catch(IOException ce){
					}
				}
				if (jarReference != null) {
					try {
						jarReference.closeArchive();
					} catch (IOException e) {
						// TODO Auto-generated catch block
						e.printStackTrace();
					}
				}
			}
		}
	}

	/*
	 * @see SiteModelFactory#createSiteMapModel()
	 */
	public SiteModel createSiteMapModel() {
		return new SiteFile();
	}

	/*
	 * @see SiteModelFactory#canParseSiteType(String)
	 */
	public boolean canParseSiteType(String type) {
		return (super.canParseSiteType(type) || SiteFileContentProvider.SITE_TYPE.equalsIgnoreCase(type));
	}

}
