package aQute.lib.osgi;

import java.io.*;
import java.net.*;
import java.util.*;
import java.util.concurrent.*;
import java.util.jar.*;
import java.util.regex.*;

import aQute.bnd.service.*;
import aQute.lib.io.*;
import aQute.libg.generics.*;
import aQute.libg.header.*;
import aQute.libg.reporter.*;

public class Processor implements Reporter, Registry, Constants, Closeable {
	static ThreadLocal<Processor>	current			= new ThreadLocal<Processor>();
	static ExecutorService			executor		= Executors.newCachedThreadPool();
	static Random					random			= new Random();

	// TODO handle include files out of date
	// TODO make splitter skip eagerly whitespace so trim is not necessary
	public static String			LIST_SPLITTER	= "\\s*,\\s*";
	final List<String>				errors			= new ArrayList<String>();
	final List<String>				warnings		= new ArrayList<String>();
	final Set<Object>				basicPlugins	= new HashSet<Object>();
	final Set<Closeable>			toBeClosed		= new HashSet<Closeable>();
	Set<Object>						plugins;

	boolean							pedantic;
	boolean							trace;
	boolean							exceptions;
	boolean							fileMustExist	= true;

	private File					base			= new File("").getAbsoluteFile();

	Properties						properties;
	private Macro					replacer;
	private long					lastModified;
	private File					propertiesFile;
	private boolean					fixup			= true;
	long							modified;
	Processor						parent;
	Set<File>						included;
	CL								pluginLoader;
	Collection<String>				filter;
	HashSet<String>					missingCommand;

	public Processor() {
		properties = new Properties();
	}

	public Processor(Properties parent) {
		properties = new Properties(parent);
	}

	public Processor(Processor parent) {
		this(parent.properties);
		this.parent = parent;
	}

	public void setParent(Processor processor) {
		this.parent = processor;
		Properties ext = new Properties(processor.properties);
		ext.putAll(this.properties);
		this.properties = ext;
	}

	public Processor getParent() {
		return parent;
	}

	public Processor getTop() {
		if (parent == null)
			return this;
		else
			return parent.getTop();
	}

	public void getInfo(Processor processor, String prefix) {
		if (isFailOk())
			addAll(warnings, processor.getErrors(), prefix);
		else
			addAll(errors, processor.getErrors(), prefix);
		addAll(warnings, processor.getWarnings(), prefix);

		processor.errors.clear();
		processor.warnings.clear();
	}

	public void getInfo(Processor processor) {
		getInfo(processor, "");
	}

	private <T> void addAll(List<String> to, List<? extends T> from, String prefix) {
		for (T x : from) {
			to.add(prefix + x);
		}
	}

	/**
	 * A processor can mark itself current for a thread.
	 * 
	 * @return
	 */
	private Processor current() {
		Processor p = current.get();
		if (p == null)
			return this;
		else
			return p;
	}

	public void warning(String string, Object... args) {
		Processor p = current();
		String s = String.format(string, args);
		if (!p.warnings.contains(s))
			p.warnings.add(s);
	}

	public void error(String string, Object... args) {
		Processor p = current();
		if (p.isFailOk())
			p.warning(string, args);
		else {
			String s = String.format(string, args);
			if (!p.errors.contains(s))
				p.errors.add(s);
		}
	}

	public void error(String string, Throwable t, Object... args) {
		Processor p = current();

		if (p.isFailOk())
			p.warning(string + ": " + t, args);
		else {
			p.errors.add("Exception: " + t.getMessage());
			String s = String.format(string, args);
			if (!p.errors.contains(s))
				p.errors.add(s);
		}
		if (p.exceptions)
			t.printStackTrace();
	}

	public List<String> getWarnings() {
		return warnings;
	}

	public List<String> getErrors() {
		return errors;
	}

	public Map<String, Map<String, String>> parseHeader(String value) {
		return parseHeader(value, this);
	}

	/**
	 * Standard OSGi header parser.
	 * 
	 * @param value
	 * @return
	 */
	static public Map<String, Map<String, String>> parseHeader(String value, Processor logger) {
		return OSGiHeader.parseHeader(value, logger);
	}

	Map<String, Map<String, String>> getClauses(String header) {
		return parseHeader(getProperty(header));
	}

	public void addClose(Closeable jar) {
		toBeClosed.add(jar);
	}

	/**
	 * Remove all entries from a map that start with a specific prefix
	 * 
	 * @param <T>
	 * @param source
	 * @param prefix
	 * @return
	 */
	static <T> Map<String, T> removeKeys(Map<String, T> source, String prefix) {
		Map<String, T> temp = new TreeMap<String, T>(source);
		for (Iterator<String> p = temp.keySet().iterator(); p.hasNext();) {
			String pack = (String) p.next();
			if (pack.startsWith(prefix))
				p.remove();
		}
		return temp;
	}

	public void progress(String s, Object... args) {
		trace(s, args);
	}

	public boolean isPedantic() {
		return current().pedantic;
	}

	public void setPedantic(boolean pedantic) {
		this.pedantic = pedantic;
	}

	public static File getFile(File base, String file) {
		return IO.getFile(base, file);
	}

	public File getFile(String file) {
		return getFile(base, file);
	}

	/**
	 * Return a list of plugins that implement the given class.
	 * 
	 * @param clazz
	 *            Each returned plugin implements this class/interface
	 * @return A list of plugins
	 */
	public <T> List<T> getPlugins(Class<T> clazz) {
		List<T> l = new ArrayList<T>();
		Set<Object> all = getPlugins();
		for (Object plugin : all) {
			if (clazz.isInstance(plugin))
				l.add(clazz.cast(plugin));
		}
		return l;
	}

	/**
	 * Returns the first plugin it can find of the given type.
	 * 
	 * @param <T>
	 * @param clazz
	 * @return
	 */
	public <T> T getPlugin(Class<T> clazz) {
		Set<Object> all = getPlugins();
		for (Object plugin : all) {
			if (clazz.isInstance(plugin))
				return clazz.cast(plugin);
		}
		return null;
	}

	/**
	 * Return a list of plugins. Plugins are defined with the -plugin command.
	 * They are class names, optionally associated with attributes. Plugins can
	 * implement the Plugin interface to see these attributes.
	 * 
	 * Any object can be a plugin.
	 * 
	 * @return
	 */
	protected synchronized Set<Object> getPlugins() {
		if (this.plugins != null)
			return this.plugins;

		missingCommand = new HashSet<String>();
		Set<Object> list = new LinkedHashSet<Object>();

		// The owner of the plugin is always in there.
		list.add(this);
		setTypeSpecificPlugins(list);

		if (parent != null)
			list.addAll(parent.getPlugins());

		// We only use plugins now when they are defined on our level
		// and not if it is in our parent. We inherit from our parent
		// through the previous block.

		if (properties.containsKey(PLUGIN)) {
			String spe = getProperty(PLUGIN);
			if (spe.equals(NONE))
				return new LinkedHashSet<Object>();

			loadPlugins(list, spe);
		}

		return this.plugins = list;
	}

	/**
	 * @param list
	 * @param spe
	 */
	protected void loadPlugins(Set<Object> list, String spe) {
		Map<String, Map<String, String>> plugins = parseHeader(spe);
		for (Map.Entry<String, Map<String, String>> entry : plugins.entrySet()) {
			String key = (String) entry.getKey();

			try {
				CL loader = getLoader();
				String path = entry.getValue().get(PATH_DIRECTIVE);
				if (path != null) {
					String parts[] = path.split("\\s*,\\s*");
					for (String p : parts) {
						File f = getFile(p).getAbsoluteFile();
						loader.add(f.toURI().toURL());
					}
				}

				trace("Using plugin %s", key);

				// Plugins could use the same class with different
				// parameters so we could have duplicate names Remove
				// the ! added by the parser to make each name unique.
				key = removeDuplicateMarker(key);

				try {
					Class<?> c = (Class<?>) loader.loadClass(key);
					Object plugin = c.newInstance();
					customize(plugin, entry.getValue());
					list.add(plugin);
				} catch (Throwable t) {
					// We can defer the error if the plugin specifies
					// a command name. In that case, we'll verify that
					// a bnd file does not contain any references to a
					// plugin
					// command. The reason this feature was added was
					// to compile plugin classes with the same build.
					String commands = entry.getValue().get(COMMAND_DIRECTIVE);
					if (commands == null)
						error("Problem loading the plugin: %s exception: (%s)", key, t);
					else {
						Collection<String> cs = split(commands);
						missingCommand.addAll(cs);
					}
				}
			} catch (Throwable e) {
				error("Problem loading the plugin: " + key + " exception: " + e);
			}
		}
	}

	protected void setTypeSpecificPlugins(Set<Object> list) {
		list.add(executor);
		list.add(random);
		list.addAll(basicPlugins);
	}

	/**
	 * @param plugin
	 * @param entry
	 */
	protected <T> T customize(T plugin, Map<String, String> map) {
		if (plugin instanceof Plugin) {
			if (map != null)
				((Plugin) plugin).setProperties(map);

			((Plugin) plugin).setReporter(this);
		}
		if (plugin instanceof RegistryPlugin) {
			((RegistryPlugin) plugin).setRegistry(this);
		}
		return plugin;
	}

	public boolean isFailOk() {
		String v = getProperty(Analyzer.FAIL_OK, null);
		return v != null && v.equalsIgnoreCase("true");
	}

	public File getBase() {
		return base;
	}

	public void setBase(File base) {
		this.base = base;
	}

	public void clear() {
		errors.clear();
		warnings.clear();
	}

	public void trace(String msg, Object... parms) {
		Processor p = current();
		if (p.trace) {
			System.out.printf("# " + msg + "\n", parms);
		}
	}

	public <T> List<T> newList() {
		return new ArrayList<T>();
	}

	public <T> Set<T> newSet() {
		return new TreeSet<T>();
	}

	public static <K, V> Map<K, V> newMap() {
		return new LinkedHashMap<K, V>();
	}

	public static <K, V> Map<K, V> newHashMap() {
		return new HashMap<K, V>();
	}

	public <T> List<T> newList(Collection<T> t) {
		return new ArrayList<T>(t);
	}

	public <T> Set<T> newSet(Collection<T> t) {
		return new TreeSet<T>(t);
	}

	public <K, V> Map<K, V> newMap(Map<K, V> t) {
		return new LinkedHashMap<K, V>(t);
	}

	public void close() {
		for (Closeable c : toBeClosed) {
			try {
				c.close();
			} catch (IOException e) {
				// Who cares?
			}
		}
		toBeClosed.clear();
	}

	public String _basedir(String args[]) {
		if (base == null)
			throw new IllegalArgumentException("No base dir set");

		return base.getAbsolutePath();
	}

	/**
	 * Property handling ...
	 * 
	 * @return
	 */

	public Properties getProperties() {
		if (fixup) {
			fixup = false;
			begin();
		}

		return properties;
	}

	public String getProperty(String key) {
		return getProperty(key, null);
	}

	public void mergeProperties(File file, boolean override) {
		if (file.isFile()) {
			try {
				Properties properties = loadProperties(file);
				mergeProperties(properties, override);
			} catch (Exception e) {
				error("Error loading properties file: " + file);
			}
		} else {
			if (!file.exists())
				error("Properties file does not exist: " + file);
			else
				error("Properties file must a file, not a directory: " + file);
		}
	}

	public void mergeProperties(Properties properties, boolean override) {
		for (Enumeration<?> e = properties.propertyNames(); e.hasMoreElements();) {
			String key = (String) e.nextElement();
			String value = properties.getProperty(key);
			if (override || !getProperties().containsKey(key))
				setProperty(key, value);
		}
	}

	public void setProperties(Properties properties) {
		doIncludes(getBase(), properties);
		this.properties.putAll(properties);
	}

	public void addProperties(File file) throws Exception {
		addIncluded(file);
		Properties p = loadProperties(file);
		setProperties(p);
	}

	public synchronized void addIncluded(File file) {
		if (included == null)
			included = new HashSet<File>();
		included.add(file);
	}

	/**
	 * Inspect the properties and if you find -includes parse the line included
	 * manifest files or properties files. The files are relative from the given
	 * base, this is normally the base for the analyzer.
	 * 
	 * @param ubase
	 * @param p
	 * @param done
	 * @throws IOException
	 * @throws IOException
	 */

	private void doIncludes(File ubase, Properties p) {
		String includes = p.getProperty(INCLUDE);
		if (includes != null) {
			includes = getReplacer().process(includes);
			p.remove(INCLUDE);
			Collection<String> clauses = parseHeader(includes).keySet();

			for (String value : clauses) {
				boolean fileMustExist = true;
				boolean overwrite = true;
				while (true) {
					if (value.startsWith("-")) {
						fileMustExist = false;
						value = value.substring(1).trim();
					} else if (value.startsWith("~")) {
						// Overwrite properties!
						overwrite = false;
						value = value.substring(1).trim();
					} else
						break;
				}
				try {
					File file = getFile(ubase, value).getAbsoluteFile();
					if (!file.isFile() && fileMustExist) {
						error("Included file " + file
								+ (file.exists() ? " does not exist" : " is directory"));
					} else
						doIncludeFile(file, overwrite, p);
				} catch (Exception e) {
					if (fileMustExist)
						error("Error in processing included file: " + value, e);
				}
			}
		}
	}

	/**
	 * @param file
	 * @param parent
	 * @param done
	 * @param overwrite
	 * @throws FileNotFoundException
	 * @throws IOException
	 */
	public void doIncludeFile(File file, boolean overwrite, Properties target) throws Exception {
		if (included != null && included.contains(file)) {
			error("Cyclic or multiple include of " + file);
		} else {
			addIncluded(file);
			updateModified(file.lastModified(), file.toString());
			InputStream in = new FileInputStream(file);
			Properties sub;
			if (file.getName().toLowerCase().endsWith(".mf")) {
				sub = getManifestAsProperties(in);
			} else
				sub = loadProperties(in, file.getAbsolutePath());

			in.close();

			doIncludes(file.getParentFile(), sub);
			// make sure we do not override properties
			for (Map.Entry<?, ?> entry : sub.entrySet()) {
				if (overwrite || !target.containsKey(entry.getKey()))
					target.setProperty((String) entry.getKey(), (String) entry.getValue());
			}
		}
	}

	public void unsetProperty(String string) {
		getProperties().remove(string);

	}

	public boolean refresh() {
		plugins = null; // We always refresh our plugins

		if (propertiesFile == null)
			return false;

		updateModified(propertiesFile.lastModified(), "properties file");
		boolean changed = false;
		if (included != null) {
			for (File file : included) {

				if (file.exists() == false || file.lastModified() > modified) {
					updateModified(file.lastModified(), "include file: " + file);
					changed = true;
				}
			}
		}

		// System.out.println("Modified " + modified + " file: "
		// + propertiesFile.lastModified() + " diff "
		// + (modified - propertiesFile.lastModified()));

		// Date last = new Date(propertiesFile.lastModified());
		// Date current = new Date(modified);
		changed |= modified < propertiesFile.lastModified();
		if (changed) {
			included = null;
			properties.clear();
			setProperties(propertiesFile, base);
			propertiesChanged();
			return true;
		}
		return false;
	}

	public void propertiesChanged() {
	}

	/**
	 * Set the properties by file. Setting the properties this way will also set
	 * the base for this analyzer. After reading the properties, this will call
	 * setProperties(Properties) which will handle the includes.
	 * 
	 * @param propertiesFile
	 * @throws FileNotFoundException
	 * @throws IOException
	 */
	public void setProperties(File propertiesFile) throws IOException {
		propertiesFile = propertiesFile.getAbsoluteFile();
		setProperties(propertiesFile, propertiesFile.getParentFile());
	}

	public void setProperties(File propertiesFile, File base) {
		this.propertiesFile = propertiesFile.getAbsoluteFile();
		setBase(base);
		try {
			if (propertiesFile.isFile()) {
				// System.out.println("Loading properties " + propertiesFile);
				long modified = propertiesFile.lastModified();
				if (modified > System.currentTimeMillis() + 100) {
					System.out.println("Huh? This is in the future " + propertiesFile);
					this.modified = System.currentTimeMillis();
				} else
					this.modified = modified;

				included = null;
				Properties p = loadProperties(propertiesFile);
				setProperties(p);
			} else {
				if (fileMustExist) {
					error("No such properties file: " + propertiesFile);
				}
			}
		} catch (IOException e) {
			error("Could not load properties " + propertiesFile);
		}
	}

	protected void begin() {
		if (isTrue(getProperty(PEDANTIC)))
			setPedantic(true);
	}

	public static boolean isTrue(String value) {
		if (value == null)
			return false;

		return !"false".equalsIgnoreCase(value);
	}

	/**
	 * Get a property with a proper default
	 * 
	 * @param headerName
	 * @param deflt
	 * @return
	 */
	public String getProperty(String key, String deflt) {
		String value = null;
		Processor source = this;

		if (filter != null && filter.contains(key)) {
			value = (String) getProperties().get(key);
		} else {
			while (source != null) {
				value = (String) source.getProperties().get(key);
				if (value != null)
					break;

				source = source.getParent();
			}
		}

		if (value != null)
			return getReplacer().process(value, source);
		else if (deflt != null)
			return getReplacer().process(deflt, this);
		else
			return null;
	}

	/**
	 * Helper to load a properties file from disk.
	 * 
	 * @param file
	 * @return
	 * @throws IOException
	 */
	public Properties loadProperties(File file) throws IOException {
		updateModified(file.lastModified(), "Properties file: " + file);
		InputStream in = new FileInputStream(file);
		Properties p = loadProperties(in, file.getAbsolutePath());
		in.close();
		return p;
	}

	Properties loadProperties(InputStream in, String name) throws IOException {
		int n = name.lastIndexOf('/');
		if (n > 0)
			name = name.substring(0, n);
		if (name.length() == 0)
			name = ".";

		try {
			Properties p = new Properties();
			p.load(in);
			return replaceAll(p, "\\$\\{\\.\\}", name);
		} catch (Exception e) {
			error("Error during loading properties file: " + name + ", error:" + e);
			return new Properties();
		}
	}

	/**
	 * Replace a string in all the values of the map. This can be used to
	 * preassign variables that change. I.e. the base directory ${.} for a
	 * loaded properties
	 */

	public static Properties replaceAll(Properties p, String pattern, String replacement) {
		Properties result = new Properties();
		for (Iterator<Map.Entry<Object, Object>> i = p.entrySet().iterator(); i.hasNext();) {
			Map.Entry<Object, Object> entry = i.next();
			String key = (String) entry.getKey();
			String value = (String) entry.getValue();
			value = value.replaceAll(pattern, replacement);
			result.put(key, value);
		}
		return result;
	}

	/**
	 * Merge the attributes of two maps, where the first map can contain
	 * wildcarded names. The idea is that the first map contains patterns (for
	 * example *) with a set of attributes. These patterns are matched against
	 * the found packages in actual. If they match, the result is set with the
	 * merged set of attributes. It is expected that the instructions are
	 * ordered so that the instructor can define which pattern matches first.
	 * Attributes in the instructions override any attributes from the actual.<br/>
	 * 
	 * A pattern is a modified regexp so it looks like globbing. The * becomes a
	 * .* just like the ? becomes a .?. '.' are replaced with \\. Additionally,
	 * if the pattern starts with an exclamation mark, it will remove that
	 * matches for that pattern (- the !) from the working set. So the following
	 * patterns should work:
	 * <ul>
	 * <li>com.foo.bar</li>
	 * <li>com.foo.*</li>
	 * <li>com.foo.???</li>
	 * <li>com.*.[^b][^a][^r]</li>
	 * <li>!com.foo.* (throws away any match for com.foo.*)</li>
	 * </ul>
	 * Enough rope to hang the average developer I would say.
	 * 
	 * 
	 * @param instructions
	 *            the instructions with patterns. A
	 * @param actual
	 *            the actual found packages
	 */

	public static Map<String, Map<String, String>> merge(String type,
			Map<String, Map<String, String>> instructions, Map<String, Map<String, String>> actual,
			Set<String> superfluous, Map<String, Map<String, String>> ignored) {
		Map<String, Map<String, String>> toVisit = new HashMap<String, Map<String, String>>(actual); // we
		// do
		// not
		// want
		// to
		// ruin
		// our
		// original
		Map<String, Map<String, String>> result = newMap();
		for (Iterator<String> i = instructions.keySet().iterator(); i.hasNext();) {
			String instruction = i.next();
			String originalInstruction = instruction;

			Map<String, String> instructedAttributes = instructions.get(instruction);

			// Check if we have a fixed (starts with '=') or a
			// duplicate name. A fixed name is added to the output without
			// checking against the contents. Duplicates are marked
			// at the end. In that case we do not pick up any contained
			// information but just add them to the output including the
			// marker.
			if (instruction.startsWith("=")) {
				result.put(instruction.substring(1), instructedAttributes);
				superfluous.remove(originalInstruction);
				continue;
			}
			if (isDuplicate(instruction)) {
				result.put(instruction, instructedAttributes);
				superfluous.remove(originalInstruction);
				continue;
			}

			Instruction instr = Instruction.getPattern(instruction);

			for (Iterator<String> p = toVisit.keySet().iterator(); p.hasNext();) {
				String packageName = p.next();

				if (instr.matches(packageName)) {
					superfluous.remove(originalInstruction);
					if (!instr.isNegated()) {
						Map<String, String> newAttributes = new HashMap<String, String>();
						newAttributes.putAll(actual.get(packageName));
						newAttributes.putAll(instructedAttributes);
						result.put(packageName, newAttributes);
					} else if (ignored != null) {
						ignored.put(packageName, new HashMap<String, String>());
					}
					p.remove(); // Can never match again for another pattern
				}
			}

		}
		return result;
	}

	/**
	 * Print a standard Map based OSGi header.
	 * 
	 * @param exports
	 *            map { name => Map { attribute|directive => value } }
	 * @return the clauses
	 */
	public static String printClauses(Map<String, Map<String, String>> exports) {
		return printClauses(exports, false);
	}

	public static String printClauses(Map<String, Map<String, String>> exports,boolean checkMultipleVersions) {
		StringBuffer sb = new StringBuffer();
		String del = "";
		for (Iterator<String> i = exports.keySet().iterator(); i.hasNext();) {
			String name = i.next();
			Map<String, String> clause = exports.get(name);

			// We allow names to be duplicated in the input
			// by ending them with '~'. This is necessary to use
			// the package names as keys. However, we remove these
			// suffixes in the output so that you can set multiple
			// exports with different attributes.
			String outname = removeDuplicateMarker(name);
			sb.append(del);
			sb.append(outname);
			printClause(clause,  sb);
			del = ",";
		}
		return sb.toString();
	}

	public static void printClause(Map<String, String> map, 
			StringBuffer sb) {

		for (Iterator<String> j = map.keySet().iterator(); j.hasNext();) {
			String key = j.next();

			// Skip directives we do not recognize
			if (key.equals(NO_IMPORT_DIRECTIVE) || key.equals(PROVIDE_DIRECTIVE) || key.equals(SPLIT_PACKAGE_DIRECTIVE) || key.equals(FROM_DIRECTIVE))
				continue;

			String value = ((String) map.get(key)).trim();
			sb.append(";");
			sb.append(key);
			sb.append("=");

			boolean clean = (value.length() >= 2 && value.charAt(0) == '"' && value.charAt(value
					.length() - 1) == '"') || Verifier.TOKEN.matcher(value).matches();
			if (!clean)
				sb.append("\"");
			sb.append(value);
			if (!clean)
				sb.append("\"");
		}
	}

	public Macro getReplacer() {
		if (replacer == null)
			return replacer = new Macro(this, getMacroDomains());
		else
			return replacer;
	}

	/**
	 * This should be overridden by subclasses to add extra macro command
	 * domains on the search list.
	 * 
	 * @return
	 */
	protected Object[] getMacroDomains() {
		return new Object[] {};
	}

	/**
	 * Return the properties but expand all macros. This always returns a new
	 * Properties object that can be used in any way.
	 * 
	 * @return
	 */
	public Properties getFlattenedProperties() {
		return getReplacer().getFlattenedProperties();

	}

	public void updateModified(long time, String reason) {
		if (time > lastModified) {
			lastModified = time;
		}
	}

	public long lastModified() {
		return lastModified;
	}

	/**
	 * Add or override a new property.
	 * 
	 * @param key
	 * @param value
	 */
	public void setProperty(String key, String value) {
		checkheader: for (int i = 0; i < headers.length; i++) {
			if (headers[i].equalsIgnoreCase(value)) {
				value = headers[i];
				break checkheader;
			}
		}
		getProperties().put(key, value);
	}

	/**
	 * Read a manifest but return a properties object.
	 * 
	 * @param in
	 * @return
	 * @throws IOException
	 */
	public static Properties getManifestAsProperties(InputStream in) throws IOException {
		Properties p = new Properties();
		Manifest manifest = new Manifest(in);
		for (Iterator<Object> it = manifest.getMainAttributes().keySet().iterator(); it.hasNext();) {
			Attributes.Name key = (Attributes.Name) it.next();
			String value = manifest.getMainAttributes().getValue(key);
			p.put(key.toString(), value);
		}
		return p;
	}

	public File getPropertiesFile() {
		return propertiesFile;
	}

	public void setFileMustExist(boolean mustexist) {
		fileMustExist = mustexist;
	}

	static public String read(InputStream in) throws Exception {
		InputStreamReader ir = new InputStreamReader(in, "UTF8");
		StringBuilder sb = new StringBuilder();

		try {
			char chars[] = new char[1000];
			int size = ir.read(chars);
			while (size > 0) {
				sb.append(chars, 0, size);
				size = ir.read(chars);
			}
		} finally {
			ir.close();
		}
		return sb.toString();
	}

	/**
	 * Join a list.
	 * 
	 * @param args
	 * @return
	 */
	public static String join(Collection<?> list, String delimeter) {
		return join(delimeter, list);
	}

	public static String join(String delimeter, Collection<?>... list) {
		StringBuilder sb = new StringBuilder();
		String del = "";
		for (Collection<?> l : list) {
			if (list != null) {
				for (Object item : l) {
					sb.append(del);
					sb.append(item);
					del = delimeter;
				}
			}
		}
		return sb.toString();
	}

	public static String join(Object[] list, String delimeter) {
		if (list == null)
			return "";
		StringBuilder sb = new StringBuilder();
		String del = "";
		for (Object item : list) {
			sb.append(del);
			sb.append(item);
			del = delimeter;
		}
		return sb.toString();
	}

	public static String join(Collection<?>... list) {
		return join(",", list);
	}

	public static <T> String join(T list[]) {
		return join(list, ",");
	}

	public static void split(String s, Collection<String> set) {

		String elements[] = s.trim().split(LIST_SPLITTER);
		for (String element : elements) {
			if (element.length() > 0)
				set.add(element);
		}
	}

	public static Collection<String> split(String s) {
		return split(s, LIST_SPLITTER);
	}

	public static Collection<String> split(String s, String splitter) {
		if (s != null)
			s = s.trim();
		if (s == null || s.trim().length() == 0)
			return Collections.emptyList();

		return Arrays.asList(s.split(splitter));
	}

	public static String merge(String... strings) {
		ArrayList<String> result = new ArrayList<String>();
		for (String s : strings) {
			if (s != null)
				split(s, result);
		}
		return join(result);
	}

	public boolean isExceptions() {
		return exceptions;
	}

	public void setExceptions(boolean exceptions) {
		this.exceptions = exceptions;
	}

	/**
	 * Make the file short if it is inside our base directory, otherwise long.
	 * 
	 * @param f
	 * @return
	 */
	public String normalize(String f) {
		if (f.startsWith(base.getAbsolutePath() + "/"))
			return f.substring(base.getAbsolutePath().length() + 1);
		else
			return f;
	}

	public String normalize(File f) {
		return normalize(f.getAbsolutePath());
	}

	public static String removeDuplicateMarker(String key) {
		int i = key.length() - 1;
		while (i >= 0 && key.charAt(i) == DUPLICATE_MARKER)
			--i;

		return key.substring(0, i + 1);
	}

	public static boolean isDuplicate(String name) {
		return name.length() > 0 && name.charAt(name.length() - 1) == DUPLICATE_MARKER;
	}

	public void setTrace(boolean x) {
		trace = x;
	}

	static class CL extends URLClassLoader {

		CL() {
			super(new URL[0], Processor.class.getClassLoader());
		}

		void add(URL url) {
			URL urls[] = getURLs();
			for (URL u : urls) {
				if (u.equals(url))
					return;
			}
			super.addURL(url);
		}

		public Class<?> loadClass(String name) throws NoClassDefFoundError {
			try {
				Class<?> c = super.loadClass(name);
				return c;
			} catch (Throwable t) {
				StringBuilder sb = new StringBuilder();
				sb.append(name);
				sb.append(" not found, parent:  ");
				sb.append(getParent());
				sb.append(" urls:");
				sb.append(Arrays.toString(getURLs()));
				sb.append(" exception:");
				sb.append(t);
				throw new NoClassDefFoundError(sb.toString());
			}
		}
	}

	private CL getLoader() {
		if (pluginLoader == null) {
			pluginLoader = new CL();
		}
		return pluginLoader;
	}

	/*
	 * Check if this is a valid project.
	 */
	public boolean exists() {
		return base != null && base.isDirectory() && propertiesFile != null
				&& propertiesFile.isFile();
	}

	public boolean isOk() {
		return isFailOk() || (getErrors().size() == 0);
	}

	public boolean isPerfect() {
		return getErrors().size() == 0 && getWarnings().size() == 0;
	}

	public void setForceLocal(Collection<String> local) {
		filter = local;
	}

	/**
	 * Answer if the name is a missing plugin's command name. If a bnd file
	 * contains the command name of a plugin, and that plugin is not available,
	 * then an error is reported during manifest calculation. This allows the
	 * plugin to fail to load when it is not needed.
	 * 
	 * We first get the plugins to ensure it is properly initialized.
	 * 
	 * @param name
	 * @return
	 */
	public boolean isMissingPlugin(String name) {
		getPlugins();
		return missingCommand != null && missingCommand.contains(name);
	}

	/**
	 * Append two strings to for a path in a ZIP or JAR file. It is guaranteed
	 * to return a string that does not start, nor ends with a '/', while it is
	 * properly separated with slashes. Double slashes are properly removed.
	 * 
	 * <pre>
	 *  &quot;/&quot; + &quot;abc/def/&quot; becomes &quot;abc/def&quot;
	 *  
	 * &#064;param prefix
	 * &#064;param suffix
	 * &#064;return
	 * 
	 */
	public static String appendPath(String... parts) {
		StringBuilder sb = new StringBuilder();
		boolean lastSlash = true;
		for (String part : parts) {
			for (int i = 0; i < part.length(); i++) {
				char c = part.charAt(i);
				if (c == '/') {
					if (!lastSlash)
						sb.append('/');
					lastSlash = true;
				} else {
					sb.append(c);
					lastSlash = false;
				}
			}
			if (!lastSlash & sb.length() > 0) {
				sb.append('/');
				lastSlash = true;
			}
		}
		if (lastSlash && sb.length() > 0)
			sb.deleteCharAt(sb.length() - 1);

		return sb.toString();
	}

	/**
	 * Parse the a=b strings and return a map of them.
	 * 
	 * @param attrs
	 * @param clazz
	 * @return
	 */
	public static Map<String, String> doAttrbutes(Object[] attrs, Clazz clazz, Macro macro) {
		if (attrs == null || attrs.length == 0)
			return Collections.emptyMap();

		Map<String, String> map = newMap();
		for (Object a : attrs) {
			String attr = (String) a;
			int n = attr.indexOf("=");
			if (n > 0) {
				map.put(attr.substring(0, n), macro.process(attr.substring(n + 1)));
			} else
				throw new IllegalArgumentException(String.format(
						"Invalid attribute on package-info.java in %s , %s. Must be <key>=<name> ",
						clazz, attr));
		}
		return map;
	}

	public static String append(String... strings) {
		List<String> result = Create.list();
		for (String s : strings) {
			result.addAll(split(s));
		}
		return join(result);
	}

	public synchronized Class<?> getClass(String type, File jar) throws Exception {
		CL cl = getLoader();
		cl.add(jar.toURI().toURL());
		return cl.loadClass(type);
	}

	public boolean isTrace() {
		return current().trace;
	}

	public static long getDuration(String tm, long dflt) {
		if (tm == null)
			return dflt;

		tm = tm.toUpperCase();
		TimeUnit unit = TimeUnit.MILLISECONDS;
		Matcher m = Pattern
				.compile(
						"\\s*(\\d+)\\s*(NANOSECONDS|MICROSECONDS|MILLISECONDS|SECONDS|MINUTES|HOURS|DAYS)?")
				.matcher(tm);
		if (m.matches()) {
			long duration = Long.parseLong(tm);
			String u = m.group(2);
			if (u != null)
				unit = TimeUnit.valueOf(u);
			duration = TimeUnit.MILLISECONDS.convert(duration, unit);
			return duration;
		}
		return dflt;
	}

	/**
	 * Generate a random string, which is guaranteed to be a valid Java
	 * identifier (first character is an ASCII letter, subsequent characters are
	 * ASCII letters or numbers). Takes an optional parameter for the length of
	 * string to generate; default is 8 characters.
	 */
	public String _random(String[] args) {
		int numchars = 8;
		if (args.length > 1) {
			try {
				numchars = Integer.parseInt(args[1]);
			} catch (NumberFormatException e) {
				throw new IllegalArgumentException(
						"Invalid character count parameter in ${random} macro.");
			}
		}

		if (random == null)
			random = new Random();

		char[] letters = "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ".toCharArray();
		char[] alphanums = "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789"
				.toCharArray();

		char[] array = new char[numchars];
		for (int i = 0; i < numchars; i++) {
			char c;
			if (i == 0)
				c = letters[random.nextInt(letters.length)];
			else
				c = alphanums[random.nextInt(alphanums.length)];
			array[i] = c;
		}

		return new String(array);
	}

	/**
	 * Set the current command thread. This must be balanced with the
	 * {@link #end(Processor)} method. The method returns the previous command
	 * owner or null.
	 * 
	 * The command owner will receive all warnings and error reports.
	 */

	protected Processor beginHandleErrors(String message) {
		trace("begin %s", message);
		Processor previous = current.get();
		current.set(this);
		return previous;
	}

	/**
	 * End a command. Will restore the previous command owner.
	 * 
	 * @param previous
	 */
	protected void endHandleErrors(Processor previous) {
		trace("end");
		current.set(previous);
	}

	public static Executor getExecutor() {
		return executor;
	}

	/**
	 * These plugins are added to the total list of plugins. The separation
	 * is necessary because the list of plugins is refreshed now and then
	 * so we need to be able to add them at any moment in time.
	 * 
	 * @param plugin
	 */
	public synchronized void addBasicPlugin(Object plugin) {
		basicPlugins.add(plugin);
		if (plugins != null)
			plugins.add(plugin);
	}

	public synchronized void removeBasicPlugin(Object plugin) {
		basicPlugins.remove(plugin);
		if (plugins != null)
			plugins.remove(plugin);
	}
}
