package org.eclipse.update.internal.core;
/*
 * (c) Copyright IBM Corp. 2000, 2002.
 * All Rights Reserved.
 */
import java.io.*;
import java.net.MalformedURLException;
import java.net.URL;

import org.eclipse.core.runtime.*;
import org.eclipse.update.core.*;
import org.eclipse.update.core.model.*;
import org.eclipse.update.internal.model.*;
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 = (SiteModelFactory) 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()) {
				path = siteLocation.getAbsolutePath().replace(File.separatorChar, '/');
				if (!path.endsWith("/"))
					path += "/";
				url = new URL("file:" + path); //$NON-NLS-1$
	
				if (new File(siteLocation, Site.SITE_XML).exists()) {
					siteStream = new FileInputStream(new File(siteLocation, Site.SITE_XML));
					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(Policy.bind("SiteFileFactory.DirectoryDoesNotExist", file.getAbsolutePath()), null);
					//$NON-NLS-1$
	
					if (parentDirectory == null || !parentDirectory.isDirectory())
						throw Utilities.newCoreException(Policy.bind("SiteFileFactory.UnableToObtainParentDirectory", file.getAbsolutePath()), null);
					//$NON-NLS-1$
	
					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(Policy.bind("SiteFileFactory.UnableToCreateURL", url == null ? "" : url.toExternalForm()), e);
			//$NON-NLS-1$
		} catch (IOException e) {
			throw Utilities.newCoreException(Policy.bind("SiteFileFactory.UnableToAccessSite"),ISite.SITE_ACCESS_EXCEPTION, e);//$NON-NLS-1$
		} 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(Policy.bind("SiteFileFactory.FileDoesNotExist", directory.getAbsolutePath()), null);
		//$NON-NLS-1$

		File pluginPath = new File(directory, Site.DEFAULT_PLUGIN_PATH);

		//PACKAGED
		parsePackagedFeature(directory); // in case it contains JAR files

		parsePackagedPlugins(pluginPath);

		// INSTALLED	
		parseInstalledFeature(directory);

		parseInstalledPlugin(pluginPath);

		return (Site) 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();
				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("/") ? "/" : "");
					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);
					} 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(Policy.bind("SiteFileFactory.UnableToCreateURLForFile", newFilePath), e);
				//$NON-NLS-1$
			}
		}
	}

	/**
	* 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);
				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);
					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);
					};
					if (result == null) {
						UpdateCore.warn("Unable to find feature.xml in file:" + currentFeatureFile);
					} 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(Policy.bind("SiteFileFactory.UnableToCreateURLForFile", newFilePath), e);
				//$NON-NLS-1$
			}
		}
	}

	/**
	 * Method parsePlugins.
	 * 
	 * look into each plugin/fragment directory, crack the plugin.xml open (or fragment.xml ???)
	 * get id and version, calculate URL...	
	 * 
	 * @return VersionedIdentifier
	 * @throws CoreException
	 */
	private void parseInstalledPlugin(File dir) throws CoreException {
		File pluginFile = null;

		try {
			if (dir.exists() && dir.isDirectory()) {
				File[] files = dir.listFiles();
				DefaultPluginParser parser = new DefaultPluginParser();
				for (int i = 0; i < files.length; i++) {
					if (files[i].isDirectory()) {

						if (!(pluginFile = new File(files[i], "plugin.xml")).exists()) { //$NON-NLS-1$
							pluginFile = new File(files[i], "fragment.xml"); //$NON-NLS-1$
						}

						if (pluginFile != null && pluginFile.exists() && !pluginFile.isDirectory()) {
							PluginEntry entry = parser.parse(new FileInputStream(pluginFile));
							addParsedPlugin(entry,files[i]);
						}
					} // files[i] is a directory
				}
			} // path is a directory
		} catch (IOException e) {
			String pluginFileString = (pluginFile == null) ? null : pluginFile.getAbsolutePath();
			throw Utilities.newCoreException(Policy.bind("SiteFileFactory.ErrorAccessing", pluginFileString), e);
			//$NON-NLS-1$
		} catch (SAXException e) {
			String pluginFileString = (pluginFile == null) ? null : pluginFile.getAbsolutePath();
			throw Utilities.newCoreException(Policy.bind("SiteFileFactory.ErrorParsingFile", pluginFileString), e);
			//$NON-NLS-1$
		}

	}

	/**
	 * 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);
				}
			}
		} catch (MalformedURLException e) {
			throw Utilities.newCoreException(Policy.bind("SiteFileFactory.UnableToCreateURLForFile", location), e);
			//$NON-NLS-1$
		}
	}

	/**
	 * 
	 */
	private void parsePackagedPlugins(File pluginDir) throws CoreException {

		File file = null;
		String[] dir;

		ContentReference ref = null;
		String refString = null;

		try {
			if (pluginDir.exists()) {
				dir = pluginDir.list(FeaturePackagedContentProvider.filter);
				for (int i = 0; i < dir.length; i++) {
					file = new File(pluginDir, dir[i]);
					JarContentReference jarReference = new JarContentReference(null, file);
					ref = jarReference.peek("plugin.xml", null, null); //$NON-NLS-1$
					if (ref == null)
						jarReference.peek("fragment.xml", null, null); //$NON-NLS-1$

					refString = (ref == null) ? null : ref.asURL().toExternalForm();

					if (ref != null) {
						PluginEntry entry = new DefaultPluginParser().parse(ref.getInputStream());
						addParsedPlugin(entry,file);
					} //ref!=null
				} //for
			}

		} catch (IOException e) {
			throw Utilities.newCoreException(Policy.bind("SiteFileFactory.ErrorAccessing", refString), e);
			//$NON-NLS-1$
		} catch (SAXException e) {
			throw Utilities.newCoreException(Policy.bind("SiteFileFactory.ErrorParsingFile", refString), e);
			//$NON-NLS-1$
		}
	}

	/*
	 * @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));
	}

}