/*******************************************************************************
 * Copyright (c) 2000, 2011 IBM Corporation and others.
 *
 * This program and the accompanying materials
 * are made available under the terms of the Eclipse Public License 2.0
 * which accompanies this distribution, and is available at
 * https://www.eclipse.org/legal/epl-2.0/
 *
 * SPDX-License-Identifier: EPL-2.0
 *
 * Contributors:
 *     IBM Corporation - initial API and implementation
 *     Ferenc Hechler, ferenc_hechler@users.sourceforge.net -  83258 [jar exporter] Deploy java application as executable jar
 *     Ferenc Hechler, ferenc_hechler@users.sourceforge.net - 262768 [jar exporter] Jardesc for normal Jar contains <fatjar builder="...
 *******************************************************************************/
package org.eclipse.jdt.internal.ui.jarpackager;

import java.io.BufferedInputStream;
import java.io.ByteArrayInputStream;
import java.io.IOException;
import java.io.InputStream;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.HashSet;
import java.util.List;
import java.util.Set;

import javax.xml.parsers.DocumentBuilder;
import javax.xml.parsers.DocumentBuilderFactory;
import javax.xml.parsers.ParserConfigurationException;

import org.xml.sax.InputSource;
import org.xml.sax.SAXException;
import org.xml.sax.helpers.DefaultHandler;

import org.w3c.dom.Element;
import org.w3c.dom.Node;
import org.w3c.dom.NodeList;

import org.eclipse.core.runtime.Assert;
import org.eclipse.core.runtime.CoreException;
import org.eclipse.core.runtime.IAdaptable;
import org.eclipse.core.runtime.IPath;
import org.eclipse.core.runtime.IStatus;
import org.eclipse.core.runtime.MultiStatus;
import org.eclipse.core.runtime.Path;
import org.eclipse.core.runtime.Status;

import org.eclipse.core.resources.IFile;
import org.eclipse.core.resources.IFolder;
import org.eclipse.core.resources.IProject;
import org.eclipse.core.resources.ResourcesPlugin;

import org.eclipse.ltk.core.refactoring.RefactoringCore;
import org.eclipse.ltk.core.refactoring.RefactoringDescriptor;
import org.eclipse.ltk.core.refactoring.RefactoringDescriptorProxy;
import org.eclipse.ltk.core.refactoring.history.IRefactoringHistoryService;
import org.eclipse.ltk.core.refactoring.history.RefactoringHistory;

import org.eclipse.jdt.core.IJavaElement;
import org.eclipse.jdt.core.IPackageFragment;
import org.eclipse.jdt.core.IType;
import org.eclipse.jdt.core.JavaCore;

import org.eclipse.jdt.internal.corext.util.Messages;

import org.eclipse.jdt.ui.jarpackager.IJarDescriptionReader;
import org.eclipse.jdt.ui.jarpackager.JarPackageData;

import org.eclipse.jdt.internal.ui.IJavaStatusConstants;
import org.eclipse.jdt.internal.ui.JavaPlugin;

/**
 * Reads data from an InputStream and returns a JarPackage
 */
public class JarPackageReader extends Object implements IJarDescriptionReader {

	protected InputStream fInputStream;

	private MultiStatus fWarnings;

	/**
	 * Reads a Jar Package from the underlying stream.
	 * It is the client's responsibility to close the stream.
	 * 
	 * @param inputStream the input stream
	 */
	public JarPackageReader(InputStream inputStream) {
		Assert.isNotNull(inputStream);
		fInputStream= new BufferedInputStream(inputStream);
		fWarnings= new MultiStatus(JavaPlugin.getPluginId(), 0, JarPackagerMessages.JarPackageReader_jarPackageReaderWarnings, null);
	}

	@Override
	public void read(JarPackageData jarPackage) throws CoreException {
		try {
			readXML(jarPackage);
		} catch (IOException ex) {
			String message= (ex.getLocalizedMessage() != null ? ex.getLocalizedMessage() : ""); //$NON-NLS-1$
			throw new CoreException(new Status(IStatus.ERROR, JavaPlugin.getPluginId(), IJavaStatusConstants.INTERNAL_ERROR, message, ex));
		} catch (SAXException ex) {
			String message= (ex.getLocalizedMessage() != null ? ex.getLocalizedMessage() : ""); //$NON-NLS-1$
			throw new CoreException(new Status(IStatus.ERROR, JavaPlugin.getPluginId(), IJavaStatusConstants.INTERNAL_ERROR, message, ex));
		}
	}


	/**
     * Closes this stream.
	 * It is the clients responsibility to close the stream.
	 *
	 * @exception CoreException if closing the stream fails
     */
    @Override
	public void close() throws CoreException {
    	if (fInputStream != null)
    		try {
				fInputStream.close();
    		} catch (IOException ex) {
    			String message= (ex.getLocalizedMessage() != null ? ex.getLocalizedMessage() : ""); //$NON-NLS-1$
				throw new CoreException(new Status(IStatus.ERROR, JavaPlugin.getPluginId(), IJavaStatusConstants.INTERNAL_ERROR, message, ex));
			}
	}

	public JarPackageData readXML(JarPackageData jarPackage) throws IOException, SAXException {
	  	DocumentBuilderFactory factory= DocumentBuilderFactory.newInstance();
    	factory.setValidating(false);
		DocumentBuilder parser= null;

		try {
			parser= factory.newDocumentBuilder();
		} catch (ParserConfigurationException ex) {
			throw new IOException(ex.getLocalizedMessage());
		} finally {
			// Note: Above code is OK since clients are responsible to close the stream
		}
		parser.setErrorHandler(new DefaultHandler());
		Element xmlJarDesc= parser.parse(new InputSource(fInputStream)).getDocumentElement();
		if (!xmlJarDesc.getNodeName().equals(JarPackagerUtil.DESCRIPTION_EXTENSION)) {
			throw new IOException(JarPackagerMessages.JarPackageReader_error_badFormat);
		}
		NodeList topLevelElements= xmlJarDesc.getChildNodes();
		for (int i= 0; i < topLevelElements.getLength(); i++) {
			Node node= topLevelElements.item(i);
			if (node.getNodeType() != Node.ELEMENT_NODE)
				continue;
			Element element= (Element)node;
			xmlReadJarLocation(jarPackage, element);
			xmlReadOptions(jarPackage, element);
			xmlReadRefactoring(jarPackage, element);
			xmlReadSelectedProjects(jarPackage, element);
			if (jarPackage.areGeneratedFilesExported())
				xmlReadManifest(jarPackage, element);
			xmlReadSelectedElements(jarPackage, element);
		}
		return jarPackage;
	}

	private void xmlReadJarLocation(JarPackageData jarPackage, Element element) {
		if (element.getNodeName().equals(JarPackagerUtil.JAR_EXTENSION))
			jarPackage.setJarLocation(Path.fromPortableString(element.getAttribute("path"))); //$NON-NLS-1$
	}

	private void xmlReadOptions(JarPackageData jarPackage, Element element) throws java.io.IOException {
		if (element.getNodeName().equals("options")) { //$NON-NLS-1$
			jarPackage.setOverwrite(getBooleanAttribute(element, "overwrite")); //$NON-NLS-1$
			jarPackage.setCompress(getBooleanAttribute(element, "compress")); //$NON-NLS-1$
			jarPackage.setExportErrors(getBooleanAttribute(element, "exportErrors")); //$NON-NLS-1$
			jarPackage.setExportWarnings(getBooleanAttribute(element, "exportWarnings")); //$NON-NLS-1$
			jarPackage.setSaveDescription(getBooleanAttribute(element, "saveDescription")); //$NON-NLS-1$
			jarPackage.setUseSourceFolderHierarchy(getBooleanAttribute(element, "useSourceFolders", false)); //$NON-NLS-1$
			jarPackage.setDescriptionLocation(Path.fromPortableString(element.getAttribute("descriptionLocation"))); //$NON-NLS-1$
			jarPackage.setBuildIfNeeded(getBooleanAttribute(element, "buildIfNeeded", jarPackage.isBuildingIfNeeded())); //$NON-NLS-1$
			jarPackage.setIncludeDirectoryEntries(getBooleanAttribute(element, "includeDirectoryEntries", false)); //$NON-NLS-1$
			jarPackage.setRefactoringAware(getBooleanAttribute(element, "storeRefactorings", false)); //$NON-NLS-1$
		}
	}

	private void xmlReadRefactoring(JarPackageData jarPackage, Element element) throws java.io.IOException {
		if (element.getNodeName().equals("storedRefactorings")) { //$NON-NLS-1$
			jarPackage.setExportStructuralOnly(getBooleanAttribute(element, "structuralOnly", jarPackage.isExportStructuralOnly())); //$NON-NLS-1$
			jarPackage.setDeprecationAware(getBooleanAttribute(element, "deprecationInfo", jarPackage.isDeprecationAware())); //$NON-NLS-1$
			List<IAdaptable> elements= new ArrayList<>();
			int count= 1;
			String value= element.getAttribute("project" + count); //$NON-NLS-1$
			while (value != null && !"".equals(value)) { //$NON-NLS-1$
				final IProject project= ResourcesPlugin.getWorkspace().getRoot().getProject(value);
				if (project.exists())
					elements.add(project);
				count++;
				value= element.getAttribute("project" + count); //$NON-NLS-1$
			}
			jarPackage.setRefactoringProjects(elements.toArray(new IProject[elements.size()]));
			elements.clear();
			count= 1;
			IRefactoringHistoryService service= RefactoringCore.getHistoryService();
			try {
				service.connect();
				value= element.getAttribute("refactoring" + count); //$NON-NLS-1$
				while (value != null && !"".equals(value)) { //$NON-NLS-1$
					final ByteArrayInputStream stream= new ByteArrayInputStream(value.getBytes("UTF-8")); //$NON-NLS-1$
					try {
						final RefactoringHistory history= service.readRefactoringHistory(stream, RefactoringDescriptor.NONE);
						if (history != null) {
							final RefactoringDescriptorProxy[] descriptors= history.getDescriptors();
							if (descriptors.length > 0) {
								elements.addAll(Arrays.asList(descriptors));
							}
						}
					} catch (CoreException exception) {
						JavaPlugin.log(exception);
					}
					count++;
					value= element.getAttribute("refactoring" + count); //$NON-NLS-1$
				}
			} finally {
				service.disconnect();
			}
			jarPackage.setRefactoringDescriptors(elements.toArray(new RefactoringDescriptorProxy[elements.size()]));
		}
	}

	private void xmlReadManifest(JarPackageData jarPackage, Element element) throws java.io.IOException {
		if (element.getNodeName().equals("manifest")) { //$NON-NLS-1$
			jarPackage.setManifestVersion(element.getAttribute("manifestVersion")); //$NON-NLS-1$
			jarPackage.setUsesManifest(getBooleanAttribute(element, "usesManifest")); //$NON-NLS-1$
			jarPackage.setReuseManifest(getBooleanAttribute(element, "reuseManifest")); //$NON-NLS-1$
			jarPackage.setSaveManifest(getBooleanAttribute(element,"saveManifest")); //$NON-NLS-1$
			jarPackage.setGenerateManifest(getBooleanAttribute(element, "generateManifest")); //$NON-NLS-1$
			jarPackage.setManifestLocation(Path.fromPortableString(element.getAttribute("manifestLocation"))); //$NON-NLS-1$
			jarPackage.setManifestMainClass(getMainClass(element));
			xmlReadSealingInfo(jarPackage, element);
		}
	}

	private void xmlReadSealingInfo(JarPackageData jarPackage, Element element) throws java.io.IOException {
		/*
		 * Try to find sealing info. Could ask for single child node
		 * but this would stop others from adding more child nodes to
		 * the manifest node.
		 */
		NodeList sealingElementContainer= element.getChildNodes();
		for (int j= 0; j < sealingElementContainer.getLength(); j++) {
			Node sealingNode= sealingElementContainer.item(j);
			if (sealingNode.getNodeType() == Node.ELEMENT_NODE
				&& sealingNode.getNodeName().equals("sealing")) { //$NON-NLS-1$
				// Sealing
				Element sealingElement= (Element)sealingNode;
				jarPackage.setSealJar(getBooleanAttribute(sealingElement, "sealJar")); //$NON-NLS-1$
				jarPackage.setPackagesToSeal(getPackages(sealingElement.getElementsByTagName("packagesToSeal"))); //$NON-NLS-1$
				jarPackage.setPackagesToUnseal(getPackages(sealingElement.getElementsByTagName("packagesToUnSeal"))); //$NON-NLS-1$
			}
		}
	}

	private void xmlReadSelectedElements(JarPackageData jarPackage, Element element) throws java.io.IOException {
		if (element.getNodeName().equals("selectedElements")) { //$NON-NLS-1$
			jarPackage.setExportClassFiles(getBooleanAttribute(element, "exportClassFiles")); //$NON-NLS-1$
			jarPackage.setExportOutputFolders(getBooleanAttribute(element, "exportOutputFolder", false)); //$NON-NLS-1$
			jarPackage.setExportJavaFiles(getBooleanAttribute(element, "exportJavaFiles")); //$NON-NLS-1$
			NodeList selectedElements= element.getChildNodes();
			Set<IAdaptable> elementsToExport= new HashSet<>(selectedElements.getLength());
			for (int j= 0; j < selectedElements.getLength(); j++) {
				Node selectedNode= selectedElements.item(j);
				if (selectedNode.getNodeType() != Node.ELEMENT_NODE)
					continue;
				Element selectedElement= (Element)selectedNode;
				if (selectedElement.getNodeName().equals("file")) //$NON-NLS-1$
					addFile(elementsToExport, selectedElement);
				else if (selectedElement.getNodeName().equals("folder")) //$NON-NLS-1$
					addFolder(elementsToExport,selectedElement);
				else if (selectedElement.getNodeName().equals("project")) //$NON-NLS-1$
					addProject(elementsToExport ,selectedElement);
				else if (selectedElement.getNodeName().equals("javaElement")) //$NON-NLS-1$
					addJavaElement(elementsToExport, selectedElement);
				// Note: Other file types are not handled by this writer
			}
			jarPackage.setElements(elementsToExport.toArray());
		}
	}

	private void xmlReadSelectedProjects(JarPackageData jarPackage, Element element) throws java.io.IOException {
		if (element.getNodeName().equals("selectedProjects")) { //$NON-NLS-1$
			NodeList selectedElements= element.getChildNodes();
			Set<IAdaptable> selectedProjects= new HashSet<>(selectedElements.getLength());
			for (int index= 0; index < selectedElements.getLength(); index++) {
				Node node= selectedElements.item(index);
				if (node.getNodeType() != Node.ELEMENT_NODE)
					continue;
				Element selectedElement= (Element)node;
				if (selectedElement.getNodeName().equals("project")) //$NON-NLS-1$
					addProject(selectedProjects ,selectedElement);
			}
			jarPackage.setRefactoringProjects(selectedProjects.toArray(new IProject[selectedProjects.size()]));
		}
	}

	protected boolean getBooleanAttribute(Element element, String name, boolean defaultValue) throws IOException {
		if (element.hasAttribute(name))
			return getBooleanAttribute(element, name);
		else
			return defaultValue;
	}

	protected boolean getBooleanAttribute(Element element, String name) throws IOException {
		String value= element.getAttribute(name);
		if (value != null && value.equalsIgnoreCase("true")) //$NON-NLS-1$
			return true;
		if (value != null && value.equalsIgnoreCase("false")) //$NON-NLS-1$
			return false;
		throw new IOException(JarPackagerMessages.JarPackageReader_error_illegalValueForBooleanAttribute);
	}

	private void addFile(Set<IAdaptable> selectedElements, Element element) throws IOException {
		IPath path= getPath(element);
		if (path != null) {
			IFile file= JavaPlugin.getWorkspace().getRoot().getFile(path);
			if (file != null)
				selectedElements.add(file);
		}
	}

	private void addFolder(Set<IAdaptable> selectedElements, Element element) throws IOException {
		IPath path= getPath(element);
		if (path != null) {
			IFolder folder= JavaPlugin.getWorkspace().getRoot().getFolder(path);
			if (folder != null)
				selectedElements.add(folder);
		}
	}

	private void addProject(Set<IAdaptable> selectedElements, Element element) throws IOException {
		String name= element.getAttribute("name"); //$NON-NLS-1$
		if (name.length() == 0)
			throw new IOException(JarPackagerMessages.JarPackageReader_error_tagNameNotFound);
		IProject project= JavaPlugin.getWorkspace().getRoot().getProject(name);
		if (project != null)
			selectedElements.add(project);
	}

	private IPath getPath(Element element) throws IOException {
		String pathString= element.getAttribute("path"); //$NON-NLS-1$
		if (pathString.length() == 0)
			throw new IOException(JarPackagerMessages.JarPackageReader_error_tagPathNotFound);
		return Path.fromPortableString(element.getAttribute("path")); //$NON-NLS-1$
	}

	private void addJavaElement(Set<IAdaptable> selectedElements, Element element) throws IOException {
		String handleId= element.getAttribute("handleIdentifier"); //$NON-NLS-1$
		if (handleId.length() == 0)
			throw new IOException(JarPackagerMessages.JarPackageReader_error_tagHandleIdentifierNotFoundOrEmpty);
		IJavaElement je= JavaCore.create(handleId);
		if (je == null)
			addWarning(JarPackagerMessages.JarPackageReader_warning_javaElementDoesNotExist, null);
		else
			selectedElements.add(je);
	}

	private IPackageFragment[] getPackages(NodeList list) throws IOException {
		if (list.getLength() > 1)
			throw new IOException(Messages.format(JarPackagerMessages.JarPackageReader_error_duplicateTag, list.item(0).getNodeName()));
		if (list.getLength() == 0)
			return null; // optional entry is not present
		NodeList packageNodes= list.item(0).getChildNodes();
		List<IJavaElement> packages= new ArrayList<>(packageNodes.getLength());
		for (int i= 0; i < packageNodes.getLength(); i++) {
			Node packageNode= packageNodes.item(i);
			if (packageNode.getNodeType() == Node.ELEMENT_NODE && packageNode.getNodeName().equals("package")) { //$NON-NLS-1$
				String handleId= ((Element)packageNode).getAttribute("handleIdentifier"); //$NON-NLS-1$
				if (handleId.isEmpty())
					throw new IOException(JarPackagerMessages.JarPackageReader_error_tagHandleIdentifierNotFoundOrEmpty);
				IJavaElement je= JavaCore.create(handleId);
				if (je != null && je.getElementType() == IJavaElement.PACKAGE_FRAGMENT)
					packages.add(je);
				else
					addWarning(JarPackagerMessages.JarPackageReader_warning_javaElementDoesNotExist, null);
			}
		}
		return packages.toArray(new IPackageFragment[packages.size()]);
	}

	private IType getMainClass(Element element) {
		String handleId= element.getAttribute("mainClassHandleIdentifier"); //$NON-NLS-1$
		if (handleId.isEmpty())
			return null;	// Main-Class entry is optional or can be empty
		IJavaElement je= JavaCore.create(handleId);
		if (je != null && je.getElementType() == IJavaElement.TYPE)
			return (IType)je;
		addWarning(JarPackagerMessages.JarPackageReader_warning_mainClassDoesNotExist, null);
		return null;
	}

	/**
	 * Returns the status of the reader.
	 * If there were any errors, the result is a status object containing
	 * individual status objects for each error.
	 * If there were no errors, the result is a status object with error code <code>OK</code>.
	 *
	 * @return the status of this operation
	 */
	@Override
	public IStatus getStatus() {
		if (fWarnings.getChildren().length == 0)
			return Status.OK_STATUS;
		else
			return fWarnings;
	}

	/**
	 * Adds a new warning to the list with the passed information.
	 * Normally the export operation continues after a warning.
	 * @param	message		the message
	 * @param	error	      the throwable that caused the warning, or <code>null</code>
	 */
	protected void addWarning(String message, Throwable error) {
		fWarnings.add(new Status(IStatus.WARNING, JavaPlugin.getPluginId(), 0, message, error));
	}

}
