/*******************************************************************************
 * 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<>();
			StringBuilder headerValue = new StringBuilder(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;
	}

	@Override
	public String toString() {
		Enumeration<String> attrKeys = getKeys();
		Enumeration<String> directiveKeys = getDirectiveKeys();
		if (attrKeys == null && directiveKeys == null)
			return mainValue;
		StringBuilder result = new StringBuilder(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, StringBuilder result) {
		if (values == null)
			return;
		for (String value : values) {
			result.append(';').append(key);
			if (directive)
				result.append(':');
			result.append("=\"").append(value).append('\"'); //$NON-NLS-1$
		}
	}
}
