/*******************************************************************************
 * Copyright (c) 2003, 2016 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
 *******************************************************************************/

package org.eclipse.osgi.util;

import java.io.BufferedInputStream;
import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.util.ArrayList;
import java.util.Enumeration;
import java.util.HashMap;
import java.util.Hashtable;
import java.util.List;
import java.util.Map;
import java.util.StringTokenizer;
import org.eclipse.osgi.internal.messages.Msg;
import org.eclipse.osgi.internal.util.SupplementDebug;
import org.eclipse.osgi.internal.util.Tokenizer;
import org.osgi.framework.BundleException;

/**
 * This class represents a single manifest element.  A manifest element must consist of a single
 * {@link String} value.  The {@link String} value may be split up into component values each
 * separated by a semi-colon (';').  A manifest element may optionally have a set of 
 * attribute and directive values associated with it. The general syntax of a manifest element is as follows:
 * <pre>
 * ManifestElement ::= component (';' component)* (';' parameter)*
 * component ::= ([^;,:="\#x0D#x0A#x00])+ | quoted-string
 * quoted-string::= '"' ( [^"\#x0D#x0A#x00] | '\"'| '\\')* '"'
 * parameter ::= directive | attribute 
 * directive ::= token ':=' argument
 * attribute ::= token '=' argument
 * argument ::= extended  | quoted-string
 * token ::= ( alphanum | '_' | '-' )+ 
 * extended ::= ( alphanum | '_' | '-' | '.' )+ 
 * </pre>
 * <p>
 * For example, the following is an example of a manifest element to the <code>Export-Package</code> header:
 * </p>
 * <pre>
 * org.osgi.framework; specification-version="1.2"; another-attr="examplevalue"
 * </pre>
 * <p>
 * This manifest element has a value of <code>org.osgi.framework</code> and it has two attributes, 
 * <code>specification-version</code> and <code>another-attr</code>. 
 * </p>
 * <p>
 * The following manifest element is an example of a manifest element that has multiple
 * components to its value: 
 * </p>
 * <pre>
 * code1.jar;code2.jar;code3.jar;attr1=value1;attr2=value2;attr3=value3
 * </pre>
 * <p>
 * This manifest element has a value of <code>code1.jar;code2.jar;code3.jar</code>.  
 * This is an example of a multiple component value.  This value has three
 * components: <code>code1.jar</code>, <code>code2.jar</code>, and <code>code3.jar</code>.
 * </p>
 * <p>
 * If components contain delimiter characters (e.g ';', ',' ':' "=") then it must be
 * a quoted string.  For example, the following is an example of a manifest element 
 * that has multiple components containing delimiter characters:
 * </p>
 * <pre>
 * "component ; 1"; "component , 2"; "component : 3"; attr1=value1; attr2=value2; attr3=value3
 * </pre>
 * <p>
 * This manifest element has a value of <code>"component ; 1"; "component , 2"; "component : 3"</code>.  
 * This value has three components: <code>"component ; 1"</code>, <code>"component , 2"</code>, <code>"component : 3"</code>.
 * </p>
 * <p>
 * This class is not intended to be subclassed by clients.
 * </p>
 * 
 * @since 3.0
 * @noextend This class is not intended to be subclassed by clients.
 */
public class ManifestElement {

	/**
	 * The value of the manifest element.
	 */
	private final String mainValue;

	/**
	 * The value components of the manifest element.
	 */
	private final String[] valueComponents;

	/**
	 * The table of attributes for the manifest element.
	 */
	private Hashtable<String, Object> attributes;

	/**
	 * The table of directives for the manifest element.
	 */
	private Hashtable<String, Object> directives;

	/**
	 * Constructs an empty manifest element with no value or attributes.
	 */
	private ManifestElement(String value, String[] valueComponents) {
		this.mainValue = value;
		this.valueComponents = valueComponents;
	}

	/**
	 * Returns the value of the manifest element.  The value returned is the
	 * complete value up to the first attribute or directive.  For example, the 
	 * following manifest element: 
	 * <pre>
	 * test1.jar;test2.jar;test3.jar;selection-filter="(os.name=Windows XP)"
	 * </pre>
	 * <p>
	 * This manifest element has a value of <code>test1.jar;test2.jar;test3.jar</code>
	 * </p>
	 * 
	 * @return the value of the manifest element.
	 */
	public String getValue() {
		return mainValue;
	}

	/**
	 * Returns the value components of the manifest element. The value
	 * components returned are the complete list of value components up to 
	 * the first attribute or directive.  
	 * For example, the following manifest element: 
	 * <pre>
	 * test1.jar;test2.jar;test3.jar;selection-filter="(os.name=Windows XP)"
	 * </pre>
	 * <p>
	 * This manifest element has the value components array 
	 * <code>{ "test1.jar", "test2.jar", "test3.jar" }</code>
	 * Each value component is delemited by a semi-colon (<code>';'</code>).
	 * </p>
	 * 
	 * @return the String[] of value components
	 */
	public String[] getValueComponents() {
		return valueComponents;
	}

	/**
	 * Returns the value for the specified attribute or <code>null</code> if it does 
	 * not exist.  If the attribute has multiple values specified then the last value 
	 * specified is returned. For example the following manifest element: 
	 * <pre>
	 * elementvalue; myattr="value1"; myattr="value2"
	 * </pre>
	 * <p>
	 * specifies two values for the attribute key <code>myattr</code>.  In this case <code>value2</code>
	 * will be returned because it is the last value specified for the attribute
	 * <code>myattr</code>.
	 * </p>
	 * 
	 * @param key the attribute key to return the value for
	 * @return the attribute value or <code>null</code>
	 */
	public String getAttribute(String key) {
		return getTableValue(attributes, key);
	}

	/**
	 * Returns an array of values for the specified attribute or 
	 * <code>null</code> if the attribute does not exist.
	 * 
	 * @param key the attribute key to return the values for
	 * @return the array of attribute values or <code>null</code> 
	 * @see #getAttribute(String)
	 */
	public String[] getAttributes(String key) {
		return getTableValues(attributes, key);
	}

	/**
	 * Returns an enumeration of attribute keys for this manifest element or
	 * <code>null</code> if none exist.
	 * 
	 * @return the enumeration of attribute keys or null if none exist.
	 */
	public Enumeration<String> getKeys() {
		return getTableKeys(attributes);
	}

	/**
	 * Add an attribute to this manifest element.
	 * 
	 * @param key the key of the attribute
	 * @param value the value of the attribute
	 */
	private void addAttribute(String key, String value) {
		attributes = addTableValue(attributes, key, value);
	}

	/**
	 * Returns the value for the specified directive or <code>null</code> if it 
	 * does not exist.  If the directive has multiple values specified then the 
	 * last value specified is returned. For example the following manifest element: 
	 * <pre>
	 * elementvalue; mydir:="value1"; mydir:="value2"
	 * </pre>
	 * <p>
	 * specifies two values for the directive key <code>mydir</code>.  In this case <code>value2</code>
	 * will be returned because it is the last value specified for the directive <code>mydir</code>.
	 * </p>
	 * 
	 * @param key the directive key to return the value for
	 * @return the directive value or <code>null</code>
	 */
	public String getDirective(String key) {
		return getTableValue(directives, key);
	}

	/**
	 * Returns an array of string values for the specified directives or 
	 * <code>null</code> if it does not exist.
	 * 
	 * @param key the directive key to return the values for
	 * @return the array of directive values or <code>null</code>
	 * @see #getDirective(String)
	 */
	public String[] getDirectives(String key) {
		return getTableValues(directives, key);
	}

	/**
	 * Return an enumeration of directive keys for this manifest element or
	 * <code>null</code> if there are none.
	 * 
	 * @return the enumeration of directive keys or <code>null</code>
	 */
	public Enumeration<String> getDirectiveKeys() {
		return getTableKeys(directives);
	}

	/**
	 * Add a directive to this manifest element.
	 * 
	 * @param key the key of the attribute
	 * @param value the value of the attribute
	 */
	private void addDirective(String key, String value) {
		directives = addTableValue(directives, key, value);
	}

	/*
	 * Return the last value associated with the given key in the specified table.
	 */
	private String getTableValue(Hashtable<String, Object> table, String key) {
		if (table == null)
			return null;
		Object result = table.get(key);
		if (result == null)
			return null;
		if (result instanceof String)
			return (String) result;

		@SuppressWarnings("unchecked")
		List<String> valueList = (List<String>) result;
		//return the last value
		return valueList.get(valueList.size() - 1);
	}

	/*
	 * Return the values associated with the given key in the specified table.
	 */
	private String[] getTableValues(Hashtable<String, Object> table, String key) {
		if (table == null)
			return null;
		Object result = table.get(key);
		if (result == null)
			return null;
		if (result instanceof String)
			return new String[] {(String) result};
		@SuppressWarnings("unchecked")
		List<String> valueList = (List<String>) result;
		return valueList.toArray(new String[valueList.size()]);
	}

	/*
	 * Return an enumeration of table keys for the specified table. 
	 */
	private Enumeration<String> getTableKeys(Hashtable<String, Object> table) {
		if (table == null)
			return null;
		return table.keys();
	}

	/*
	 * Add the given key/value association to the specified table. If an entry already exists
	 * for this key, then create an array list from the current value (if necessary) and
	 * append the new value to the end of the list.
	 */
	@SuppressWarnings("unchecked")
	private Hashtable<String, Object> addTableValue(Hashtable<String, Object> table, String key, String value) {
		if (table == null) {
			table = new Hashtable<>(7);
		}
		Object curValue = table.get(key);
		if (curValue != null) {
			List<String> newList;
			// create a list to contain multiple values
			if (curValue instanceof List) {
				newList = (List<String>) curValue;
			} else {
				newList = new ArrayList<>(5);
				newList.add((String) curValue);
			}
			newList.add(value);
			table.put(key, newList);
		} else {
			table.put(key, value);
		}
		return table;
	}

	/**
	 * Parses a manifest header value into an array of ManifestElements.  Each
	 * ManifestElement returned will have a non-null value returned by getValue().
	 * 
	 * @param header the header name to parse.  This is only specified to provide error messages
	 * 	when the header value is invalid.
	 * @param value the header value to parse.
	 * @return the array of ManifestElements that are represented by the header value; null will be
	 * 	returned if the value specified is null or if the value does not parse into
	 * 	one or more ManifestElements.
	 * @throws BundleException if the header value is invalid
	 */
	public static ManifestElement[] parseHeader(String header, String value) throws BundleException {
		if (value == null)
			return (null);
		List<ManifestElement> headerElements = new ArrayList<>(10);
		Tokenizer tokenizer = new Tokenizer(value);
		parseloop: while (true) {
			String next = tokenizer.getString(";,"); //$NON-NLS-1$
			if (next == null)
				throw new BundleException(NLS.bind(Msg.MANIFEST_INVALID_HEADER_EXCEPTION, header, value), BundleException.MANIFEST_ERROR);
			List<String> headerValues = new ArrayList<>();
			StringBuffer headerValue = new StringBuffer(next);
			headerValues.add(next);

			if (SupplementDebug.STATIC_DEBUG_MANIFEST)
				System.out.print("parseHeader: " + next); //$NON-NLS-1$
			boolean directive = false;
			char c = tokenizer.getChar();
			// Header values may be a list of ';' separated values.  Just append them all into one value until the first '=' or ','
			while (c == ';') {
				next = tokenizer.getString(";,=:"); //$NON-NLS-1$
				if (next == null)
					throw new BundleException(NLS.bind(Msg.MANIFEST_INVALID_HEADER_EXCEPTION, header, value), BundleException.MANIFEST_ERROR);
				c = tokenizer.getChar();
				while (c == ':') { // may not really be a :=
					c = tokenizer.getChar();
					if (c != '=') {
						String restOfNext = tokenizer.getToken(";,=:"); //$NON-NLS-1$
						if (restOfNext == null)
							throw new BundleException(NLS.bind(Msg.MANIFEST_INVALID_HEADER_EXCEPTION, header, value), BundleException.MANIFEST_ERROR);
						next += ":" + c + restOfNext; //$NON-NLS-1$
						c = tokenizer.getChar();
					} else
						directive = true;
				}
				if (c == ';' || c == ',' || c == '\0') /* more */ {
					headerValues.add(next);
					headerValue.append(";").append(next); //$NON-NLS-1$
					if (SupplementDebug.STATIC_DEBUG_MANIFEST)
						System.out.print(";" + next); //$NON-NLS-1$
				}
			}
			// found the header value create a manifestElement for it.
			ManifestElement manifestElement = new ManifestElement(headerValue.toString(), headerValues.toArray(new String[headerValues.size()]));

			// now add any attributes/directives for the manifestElement.
			while (c == '=' || c == ':') {
				while (c == ':') { // may not really be a :=
					c = tokenizer.getChar();
					if (c != '=') {
						String restOfNext = tokenizer.getToken("=:"); //$NON-NLS-1$
						if (restOfNext == null)
							throw new BundleException(NLS.bind(Msg.MANIFEST_INVALID_HEADER_EXCEPTION, header, value), BundleException.MANIFEST_ERROR);
						next += ":" + c + restOfNext; //$NON-NLS-1$
						c = tokenizer.getChar();
					} else
						directive = true;
				}
				// determine if the attribute is the form attr:List<type>
				String preserveEscapes = null;
				if (!directive && next.indexOf("List") > 0) { //$NON-NLS-1$
					Tokenizer listTokenizer = new Tokenizer(next);
					String attrKey = listTokenizer.getToken(":"); //$NON-NLS-1$
					if (attrKey != null && listTokenizer.getChar() == ':' && "List".equals(listTokenizer.getToken("<"))) { //$NON-NLS-1$//$NON-NLS-2$
						// we assume we must preserve escapes for , and "
						preserveEscapes = "\\,"; //$NON-NLS-1$
					}
				}
				String val = tokenizer.getString(";,", preserveEscapes); //$NON-NLS-1$
				if (val == null)
					throw new BundleException(NLS.bind(Msg.MANIFEST_INVALID_HEADER_EXCEPTION, header, value), BundleException.MANIFEST_ERROR);

				if (SupplementDebug.STATIC_DEBUG_MANIFEST)
					System.out.print(";" + next + "=" + val); //$NON-NLS-1$ //$NON-NLS-2$
				try {
					if (directive)
						manifestElement.addDirective(next, val);
					else
						manifestElement.addAttribute(next, val);
					directive = false;
				} catch (Exception e) {
					throw new BundleException(NLS.bind(Msg.MANIFEST_INVALID_HEADER_EXCEPTION, header, value), BundleException.MANIFEST_ERROR, e);
				}
				c = tokenizer.getChar();
				if (c == ';') /* more */ {
					next = tokenizer.getToken("=:"); //$NON-NLS-1$
					if (next == null)
						throw new BundleException(NLS.bind(Msg.MANIFEST_INVALID_HEADER_EXCEPTION, header, value), BundleException.MANIFEST_ERROR);
					c = tokenizer.getChar();
				}
			}
			headerElements.add(manifestElement);
			if (SupplementDebug.STATIC_DEBUG_MANIFEST)
				System.out.println(""); //$NON-NLS-1$
			if (c == ',') /* another manifest element */
				continue parseloop;
			if (c == '\0') /* end of value */
				break parseloop;
			throw new BundleException(NLS.bind(Msg.MANIFEST_INVALID_HEADER_EXCEPTION, header, value), BundleException.MANIFEST_ERROR);
		}
		int size = headerElements.size();
		if (size == 0)
			return (null);

		ManifestElement[] result = headerElements.toArray(new ManifestElement[size]);
		return (result);
	}

	/**
	 * Returns the result of converting a list of comma-separated tokens into an array.
	 * 
	 * @return the array of string tokens or <code>null</code> if there are none
	 * @param stringList the initial comma-separated string
	 */
	public static String[] getArrayFromList(String stringList) {
		String[] result = getArrayFromList(stringList, ","); //$NON-NLS-1$
		return result.length == 0 ? null : result;
	}

	/**
	 * Returns the result of converting a list of tokens into an array.  The tokens
	 * are split using the specified separator.
	 * 
	 * @return the array of string tokens.  If there are none then an empty array
	 * is returned.
	 * @param stringList the initial string list
	 * @param separator the separator to use to split the list into tokens.
	 * @since 3.2
	 */
	public static String[] getArrayFromList(String stringList, String separator) {
		if (stringList == null || stringList.trim().length() == 0)
			return new String[0];
		List<String> list = new ArrayList<>();
		StringTokenizer tokens = new StringTokenizer(stringList, separator);
		while (tokens.hasMoreTokens()) {
			String token = tokens.nextToken().trim();
			if (token.length() != 0)
				list.add(token);
		}
		return list.toArray(new String[list.size()]);
	}

	/**
	 * Parses a bundle manifest and puts the header/value pairs into the supplied Map.
	 * Only the main section of the manifest is parsed (up to the first blank line).  All
	 * other sections are ignored.  If a header is duplicated then only the last  
	 * value is stored in the map.
	 * <p>
	 * The supplied input stream is consumed by this method and will be closed.
	 * If the supplied Map is null then a Map is created to put the header/value pairs into.
	 * </p>
	 * @param manifest an input stream for a bundle manifest.
	 * @param headers a map used to put the header/value pairs from the bundle manifest.  This value may be null.
	 * @throws BundleException if the manifest has an invalid syntax
	 * @throws IOException if an error occurs while reading the manifest
	 * @return the map with the header/value pairs from the bundle manifest
	 */
	public static Map<String, String> parseBundleManifest(InputStream manifest, Map<String, String> headers) throws IOException, BundleException {
		if (headers == null)
			headers = new HashMap<>();

		manifest = new BufferedInputStream(manifest);
		try {

			ByteArrayOutputStream buffer = new ByteArrayOutputStream(256);
			while (true) {
				String line = readLine(manifest, buffer);
				/* The java.util.jar classes in JDK 1.3 use the value of the last
				 * encountered manifest header. So we do the same to emulate
				 * this behavior. We no longer throw a BundleException
				 * for duplicate manifest headers.
				 */

				if ((line == null) || (line.length() == 0)) /* EOF or empty line */
				{
					break; /* done processing main attributes */
				}

				int colon = line.indexOf(':');
				if (colon == -1) /* no colon */
				{
					throw new BundleException(NLS.bind(Msg.MANIFEST_INVALID_LINE_NOCOLON, line), BundleException.MANIFEST_ERROR);
				}
				String header = line.substring(0, colon).trim();
				String value = line.substring(colon + 1).trim();
				headers.put(header, value);
			}
		} finally {
			try {
				manifest.close();
			} catch (IOException ee) {
				// do nothing
			}
		}
		return headers;
	}

	private static String readLine(InputStream input, ByteArrayOutputStream buffer) throws IOException {
		// Read a header 'line'
		// A header line may span multiple lines with line continuations using a beginning space.
		// This method reads all the line continuations into a single string.
		// Care must be taken for cases where double byte UTF characters are split
		// across line continuations.
		// This is why BufferedReader.readLine is not used here.  We must process the 
		// CR LF chars ourselves
		lineLoop: while (true) {
			int c = input.read();
			if (c == '\n') { // LF
				// next char is either a continuation (space) char or the first char of the next header
				input.mark(1);
				c = input.read();
				if (c != ' ') {
					// This first char of the next header, reset so we don't loose the char
					input.reset();
					break lineLoop;
				}
				// This is a continuation, skip the space and read the next char
				c = input.read();
			} else if (c == '\r') { // CR
				// next char is either a continuation (space) char, LF or the first char of the next header
				input.mark(1);
				c = input.read();
				if (c == '\n') { // LF
					// next char is either a continuation (space) char or the first char of the next header
					input.mark(1);
					c = input.read();
				}
				if (c != ' ') {
					// This first char of the next header, reset so we don't loose the char
					input.reset();
					break lineLoop;
				}
				c = input.read();
			}
			if (c == -1) {
				break lineLoop;
			}
			buffer.write(c);
		}
		String result = buffer.toString("UTF8"); //$NON-NLS-1$
		buffer.reset();
		return result;
	}

	public String toString() {
		Enumeration<String> attrKeys = getKeys();
		Enumeration<String> directiveKeys = getDirectiveKeys();
		if (attrKeys == null && directiveKeys == null)
			return mainValue;
		StringBuffer result = new StringBuffer(mainValue);
		if (attrKeys != null) {
			while (attrKeys.hasMoreElements()) {
				String key = attrKeys.nextElement();
				addValues(false, key, getAttributes(key), result);
			}
		}
		if (directiveKeys != null) {
			while (directiveKeys.hasMoreElements()) {
				String key = directiveKeys.nextElement();
				addValues(true, key, getDirectives(key), result);
			}
		}
		return result.toString();
	}

	private void addValues(boolean directive, String key, String[] values, StringBuffer result) {
		if (values == null)
			return;
		for (int i = 0; i < values.length; i++) {
			result.append(';').append(key);
			if (directive)
				result.append(':');
			result.append("=\"").append(values[i]).append('\"'); //$NON-NLS-1$			
		}
	}
}
