/**********************************************************************
 * This file is part of "Object Teams Development Tooling"-Software
 * 
 * Copyright 2009 Germany and Technical University Berlin, Germany.
 * 
 * All rights reserved. This program and the accompanying materials
 * are made available under the terms of the Eclipse Public License v1.0
 * which accompanies this distribution, and is available at
 * http://www.eclipse.org/legal/epl-v10.html
 * 
 * Please visit http://www.eclipse.org/objectteams for updates and contact.
 * 
 * Contributors:
 * Technical University Berlin - Initial API and implementation
 **********************************************************************/
package org.eclipse.objectteams.internal.osgi.weaving;

import static org.eclipse.objectteams.otequinox.AspectPermission.DENY;
import static org.eclipse.objectteams.otequinox.AspectPermission.GRANT;
import static org.eclipse.objectteams.otequinox.AspectPermission.UNDEFINED;
import static org.eclipse.objectteams.otequinox.TransformerPlugin.log;

import java.io.BufferedReader;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileReader;
import java.io.FileWriter;
import java.io.IOException;
import java.util.*;

import org.eclipse.core.internal.runtime.InternalPlatform;
import org.eclipse.core.runtime.CoreException;
import org.eclipse.core.runtime.IConfigurationElement;
import org.eclipse.core.runtime.IExtensionRegistry;
import org.eclipse.core.runtime.IPath;
import org.eclipse.core.runtime.IStatus;
import org.eclipse.jdt.annotation.NonNull;
import org.eclipse.jdt.annotation.NonNullByDefault;
import org.eclipse.jdt.annotation.Nullable;
import org.eclipse.objectteams.internal.osgi.weaving.AspectBinding.BaseBundle;
import org.eclipse.objectteams.internal.osgi.weaving.AspectBinding.TeamBinding;
import org.eclipse.objectteams.otequinox.ActivationKind;
import org.eclipse.objectteams.otequinox.AspectBindingRequestAnswer;
import org.eclipse.objectteams.otequinox.AspectPermission;
import org.eclipse.objectteams.otequinox.Constants;
import org.eclipse.objectteams.otequinox.IAspectRequestNegotiator;
import org.eclipse.objectteams.otequinox.TransformerPlugin;
import org.eclipse.osgi.internal.hookregistry.HookConfigurator;
import org.eclipse.osgi.service.datalocation.Location;
import org.objectteams.Team;
import org.osgi.framework.Bundle;
import org.osgi.framework.BundleException;

/**
 * Manage permissions of aspect bundles requesting to apply aspectBindings and forcedExports.
 * The following pieces of information are checked:
 * <ul>
 * <li>properties set in installation-wide config.ini or as command line args (handled by {@link HookConfigurator} (plus internal class OTStorageHook))</li>
 * <li>defaults set per workspace (file negotiationDefaults.txt)</li>
 * <li>individual GRANT/DENY per workspace (files grantedForcedExports.txt, deniedForcedExports.txt)</li>
 * <li>answers from registered negotiators (extension point org.eclipse.objectteams.otequinox.aspectBindingNegotiators, see {@link IAspectRequestNegotiator})</li>
 * </ul>
 *
 * <p>
 * The final answer for a given request is combined from all sources where the priority of any {@link #DENY} answer is highest, 
 * of {@link #UNDEFINED} is lowest.
 * </p>
 * <p>
 * If a negotiator has determined a decision and its answer has the <code>persistent</code> flag set,
 * this particular aspect permission is stored as per-workspace configuration.
 * </p>
 * @author stephan
 * @since 1.2.6
 */
@SuppressWarnings("restriction")
@NonNullByDefault
public class AspectPermissionManager {

	// property names for default configuration:
	private static final String FORCED_EXPORT_DEFAULT  = "forced.export.default";
	private static final String ASPECT_BINDING_DEFAULT = "aspect.binding.default";
	
	// workspace files where negotiation configuration is stored:
	private static final String NEGOTIATION_DEFAULTS_FILE   = "negotiationDefaults.txt";  
	private static final String GRANTED_FORCED_EXPORTS_FILE = "grantedForcedExports.txt";
	private static final String DENIED_FORCED_EXPORTS_FILE  = "deniedForcedExports.txt";

	private static final String GRANTED_TEAMS_FILE = "grantedTeams.txt";
	private static final String DENIED_TEAMS_FILE  = "deniedTeams.txt";

	// set of aspect plug-ins for which some permission has been denied:
	private Set<String> deniedAspects = new HashSet<String>();
	// default permission for aspect bindings:
	private AspectPermission defaultAspectBindingPermission = GRANT;
	// default permission for forced exports:
	private AspectPermission defaultForcedExportPermission = UNDEFINED; // not yet granted, but open for receiving a GRANT
	// for negotiation of aspect binding requests (incl. forced export):
	private List<IAspectRequestNegotiator> negotiators = new ArrayList<IAspectRequestNegotiator>();
	
	
	// collect all forced exports (denied/granted), granted should balance to an empty structure.
	// structure is: aspect-id -> (base bundle x base package)*
	private Map<String, List<@NonNull String[]>> deniedForcedExportsByAspect= new HashMap<>();
	private Map<String, List<@NonNull String[]>> grantedForcedExportsByAspect= new HashMap<>();
	
	// key is aspectId+"->"+baseId, value is array of team names
	private Map<String, Set<String>> deniedTeamsByAspectBinding = new HashMap<String, Set<String>>();
	private Map<String, Set<String>> grantedTeamsByAspectBinding = new HashMap<String, Set<String>>();

	// the workspace directory for storing the state of this plugin
	@Nullable private IPath otequinoxState;
	// back link needed for accessing the state location:
	private Bundle transformerBundle;
	// helper instance needed to stop bundles by name
	@SuppressWarnings("deprecation")
	private org.osgi.service.packageadmin.@Nullable PackageAdmin packageAdmin;
	
	private ForcedExportsDelegate forcedExportsDelegate;
	
	public AspectPermissionManager(Bundle bundle, 
			@SuppressWarnings("deprecation") org.osgi.service.packageadmin.@Nullable PackageAdmin packageAdmin)
	{
		this.transformerBundle = bundle;
		this.packageAdmin = packageAdmin;
		this.forcedExportsDelegate = new ForcedExportsDelegate();
	}

	/* local cache for isReady(): */
	private boolean isWaitingForLocation = true;
	
	/** Before using this permission manager a client must check whether we're ready (instance location set). */
	public boolean isReady() {
		if (!isWaitingForLocation)
			return true;
		try {
			InternalPlatform platform = InternalPlatform.getDefault();
			Location instanceLocation = platform.getInstanceLocation();
			if (!instanceLocation.isSet())
				return false; // not yet capable
			this.isWaitingForLocation = false;
			fetchAspectBindingPermssionsFromWorkspace();
		} catch (NoClassDefFoundError ncdfe) {
			log(IStatus.WARNING, "Optional class InternalPlatform not found, cannot access workspace location");
			this.isWaitingForLocation = false;
			return true;
		}
		if (!this.obligations.isEmpty())
			for (Runnable job : this.obligations)
				job.run();
		return true;
	}

	/** 
	 * Fetch stored permissions from this plugin's workspace state.
	 * 
	 * @pre instance location should be set (see {@link #isReady()}),
	 *    otherwise will silently return without accessing workspace settings. 
	 */
	private void fetchAspectBindingPermssionsFromWorkspace() {
		try {
			IPath state = InternalPlatform.getDefault().getStateLocation(this.transformerBundle, true);
			this.otequinoxState = state;
			internalFetchAspectBindingPermssionsFromWorkspace(state);
		} catch (NoClassDefFoundError ncdfe) {
			log(IStatus.WARNING, "Optional class InternalPlatform not found, cannot access workspace location");
			return;
		}
	}

	/** Load extensions for EP org.eclipse.objectteams.otequinox.aspectBindingNegotiators. */
	public void loadAspectBindingNegotiators(IExtensionRegistry extensionRegistry) {
		IConfigurationElement[] aspectBindingNegotiatorsConfigs = extensionRegistry.getConfigurationElementsFor(
				Constants.TRANSFORMER_PLUGIN_ID, Constants.ASPECT_NEGOTIATOR_EXTPOINT_ID);		
		for (int i = 0; i < aspectBindingNegotiatorsConfigs.length; i++) {
			IConfigurationElement currentNegotiatorConfig = aspectBindingNegotiatorsConfigs[i];
			try {
				Object negotiator = currentNegotiatorConfig.createExecutableExtension("class");
				if (negotiator != null)
					this.negotiators.add(((IAspectRequestNegotiator)negotiator));
			} catch (CoreException e) {
				log(e, "Failed to instantiate extension "+currentNegotiatorConfig);
			}
		}
	}

	/** Delegatee of internal API {@link TransformerPlugin#isDeniedAspectPlugin(String)}. */
	public boolean isDeniedAspectPlugin(String symbolicName) {
		return this.deniedAspects.contains(symbolicName);
	}

	
	/**
	 * Check whether a given aspect requests forced exports from base, 
	 * and whether these requests are granted/denied by checking all available sources.
	 * 
	 * Clients should ask {@link #isReady()} (ie., instance location is set) before calling this method,
	 * otherwise workspace settings have to be silently ignored (any error should be signaled by client).
	 * 
	 * @param aspectId      symbolic name of the aspect bundle
	 * @param baseBundleId  symbolic name of the bound base bundle
     * @param forcedExports any forced exports requested in this aspect binding.
	 * @return whether all requests (if any) have been granted
	 */
	public boolean checkForcedExports(AspectBinding aspectBinding) {
		switch (aspectBinding.forcedExportsPermission) {
			case GRANT: return true;
			case DENY: return false;
			case UNDEFINED: 
				aspectBinding.forcedExportsPermission = internalCheckForcedExports(aspectBinding);
				return aspectBinding.forcedExportsPermission == GRANT;
		}
		return true;
	}
	private AspectPermission internalCheckForcedExports(AspectBinding aspectBinding) {
		IConfigurationElement[] forcedExports = aspectBinding.forcedExports;
		if (forcedExports.length == 0)
			return GRANT;
		
		String aspectId = aspectBinding.aspectPlugin;
		String baseBundleId = aspectBinding.basePluginName; 
		List<String[]> deniedForcedExports = getConfiguredForcedExports(aspectId, DENY,  deniedForcedExportsByAspect);
		List<String[]> grantedForcedExports= getConfiguredForcedExports(aspectId, GRANT, grantedForcedExportsByAspect);

		// iterate all requested forcedExports to search for a matching permission:
		for (IConfigurationElement forcedExport : forcedExports) { // [0..1] (as defined in the schema)
			String forcedExportsRequest = forcedExport.getValue();
			if (forcedExportsRequest == null)
				continue;
			for (@NonNull String singleForcedExportRequest : forcedExportsRequest.split(","))
			{
				singleForcedExportRequest = singleForcedExportRequest.trim();

				String[] listEntry;
				boolean grantReported = false;
				AspectPermission negotiatedPermission = this.defaultForcedExportPermission;
				
				// DENY by default?
				if (negotiatedPermission == DENY) {
					log(IStatus.ERROR, "Default denial of forced export regarding package "+singleForcedExportRequest+
									   " from bundle "+baseBundleId+" as requested by bundle "+aspectId+"; bundle not activated");
					this.deniedAspects.add(aspectId); // keep for answering the TransformerHook.
					return DENY; // NOPE!					
				}
				
				// DENY from configuration?
				listEntry = findRequestInList(baseBundleId, singleForcedExportRequest, deniedForcedExports);
				if (listEntry != null) {
					log(IStatus.ERROR, "Explicit denial of forced export regarding package "+singleForcedExportRequest+
									   " from bundle "+baseBundleId+" as requested by bundle "+aspectId+"; bundle not activated");
					this.deniedAspects.add(aspectId); // keep for answering the TransformerHook.
					return DENY; // NOPE!
				}

				// GRANT from configuration?
				listEntry = findRequestInList(baseBundleId, singleForcedExportRequest, grantedForcedExports);
				if (listEntry != null) {
					log(IStatus.INFO, "Forced export granted for "+aspectId+": "+singleForcedExportRequest+" (from bundle "+baseBundleId+")");
					grantReported = true;
					grantedForcedExports.remove(listEntry);
					negotiatedPermission = GRANT;
				}

				// default and persistent configuration did not DENY, proceed to the negotiators:
				boolean shouldPersist = false;
				for (IAspectRequestNegotiator negotiator : this.negotiators) {
					AspectBindingRequestAnswer answer = negotiator.checkForcedExport(aspectId, baseBundleId, singleForcedExportRequest, negotiatedPermission);
					if (answer.permission.compareTo(negotiatedPermission) > 0) // increasing priority of answer?
					{ 
						shouldPersist = answer.persistent;
						negotiatedPermission = answer.permission;
						// locally store as default for subsequent requests (not persistent, see below):
						if (answer.allRequests)
							this.defaultForcedExportPermission = negotiatedPermission;
						if (negotiatedPermission == DENY)
							break; // end of discussion.
					}
				}

				// make decision persistent?
				if (shouldPersist && negotiatedPermission != UNDEFINED)
					// FIXME(SH): handle "allRequests":
					persistForcedExportsAnswer(aspectId, baseBundleId, singleForcedExportRequest, negotiatedPermission);
				
				// report:
				if (negotiatedPermission == GRANT) {
					if (!grantReported)
						log(IStatus.INFO, "Negotiation granted forced export for "+aspectId+
										  ": "+singleForcedExportRequest+" (from bundle "+baseBundleId+')');
				} else {
					String verb = "did not grant";
					if (negotiatedPermission == DENY)
						verb = "denied";
					log(IStatus.ERROR, "Negotiation "+verb+" forced export for "+aspectId+
									   ": "+singleForcedExportRequest+" (from bundle "+baseBundleId+")"+
									   ". Aspect is not activated.");
					this.deniedAspects.add(aspectId); // keep for answering the TransformerHook.
					return DENY; // don't install illegal aspect
				}
			}
		}
		if (!grantedForcedExports.isEmpty())
			reportUnmatchForcedExports(aspectId, grantedForcedExports);
		return GRANT;
	}

	/**
	 * Get the forced exports configured for a given aspect bundle with permission <code>perm</code>.
	 * Consult {@link HookConfigurator} and store the result in <code>map</code>.
	 * 
	 * @param aspectId  symbolic name of the aspect in focus
	 * @param perm		are we asking about DENY or GRANT?
	 * @param map		in/out param for storing results from OTStorageHook
	 * @return		 	list of pairs (base bundle x base package)
	 */
	private List<@NonNull String[]> getConfiguredForcedExports( String                          aspectId, 
														AspectPermission 				perm, 
														Map<String, List<@NonNull String[]>> map)
    {
		List<@NonNull String[]> forcedExports= map.get(aspectId);
		if (forcedExports == null) {
			// fetch declarations from config.ini or other locations.
			forcedExports= forcedExportsDelegate.getForcedExportsByAspect(aspectId, perm);
			map.put(aspectId, forcedExports);
		}
		return forcedExports;
	}

	private String @Nullable[] findRequestInList(String baseBundleId, String basePackage, List<String[]> list) {
		for (String[] singleExport : list)
			if (   singleExport[0].equals(baseBundleId)
				&& singleExport[1].equals(basePackage))
			{
				return singleExport;
			}
		return null;
	}

	/**
	 * If the structure of grantedForcedExports is not empty we have mismatches between forced-export declarations.
	 * Report these mismatches as warnings.
	 */
	void reportUnmatchForcedExports(String aspectId, List<String[]> unmatchedForcedExports) 
	{
		for (String[] export: unmatchedForcedExports) {
			String baseId = export[0];
			String pack   = export[1];
			log(IStatus.WARNING, "Aspect "+aspectId+
							  " does not declare forced export of package "+
							  pack+" from bundle "+baseId+
							  " as declared in config.ini (or system property)");
		}
	}

	/* Simple strategy to append a forced export to a file (existing or to be created). */
	private void persistForcedExportsAnswer(String aspectId, String baseBundleId, String basePackage, AspectPermission negotiatedPermission) 
	{
		IPath state = this.otequinoxState;
		if (state == null) {
			log(IStatus.ERROR, "Can't persist forcedExports permission, no workspace location accessable.");
			return;
		}
		try {
			String fileName = (negotiatedPermission == DENY) ? DENIED_FORCED_EXPORTS_FILE : GRANTED_FORCED_EXPORTS_FILE;
			IPath forcedExportsPath = state.append(fileName);
			File forcedExportsFile = new File(forcedExportsPath.toOSString());
			if (!forcedExportsFile.exists())
				forcedExportsFile.createNewFile();
			try (FileWriter writer = new FileWriter(forcedExportsFile, true)) { // FIXME(SH): consider merge (after decision about file format)
				writer.append('\n');
				writer.append(baseBundleId);
				writer.append("\n[\n\t");
				writer.append(basePackage);
				writer.append(";x-friends:=\"");
				writer.append(aspectId);
				writer.append("\"\n]\n");
				writer.flush();
			}
		} catch (IOException ioe) {
			log(ioe, "Failed to persist negotiation result");
		}
	}
	
	/**
	 * Check the permissions for all given teams.
	 * @param teamsForBase the teams to check
	 * @return the set of denied teams
	 */
	Set<TeamBinding> checkAspectPermissionDenial(Collection<TeamBinding> teamsForBase)
	{
		Set<TeamBinding> deniedTeams = new HashSet<TeamBinding>();
		for (TeamBinding teamForBase : teamsForBase) {
			AspectBinding aspectBinding = teamForBase.getAspectBinding();
			String aspectBundleName = aspectBinding.aspectPlugin;
			if (aspectBinding.hasBeenDenied) {
				deniedTeams.add(teamForBase);
			} else {
				if (!checkForcedExports(aspectBinding)) {
					deniedTeams.add(teamForBase);
					stopAspectBundle(aspectBinding, aspectBundleName, "requests unconfirmed forced export(s).");
				} else if (!checkTeamBinding(aspectBundleName, aspectBinding.basePluginName, teamForBase)) {
					deniedTeams.add(teamForBase);
					stopAspectBundle(aspectBinding, aspectBundleName, "requests unconfirmed aspect binding(s).");
				}
			}
		}
		return deniedTeams;
	}

	void stopAspectBundle(AspectBinding aspectBinding, String aspectBundleName, String reason) {
		try {
			aspectBinding.hasBeenDenied = true;
			Bundle aspectBundle = aspectBinding.aspectBundle;
			if (aspectBundle != null) {
				aspectBundle.stop();
				log(IStatus.ERROR, "Stopped bundle "+aspectBundleName+" which "+reason);
			} else {
				log(IStatus.ERROR, "Cannot stop aspect bundle "+aspectBundleName);
			}
		} catch (Throwable t) { // don't let the aspect bundle get by by throwing an unexpected exception!
			log(t, "Failed to stop bundle "+aspectBundleName+" which "+reason);
		}
	}

	/**
	 * Check permission for the aspect binding of one specific team.
	 * 
	 * Clients should ask {@link #isReady()} (ie., instance location is set) before calling this method,
	 * otherwise workspace settings have to be silently ignored (any error should be signaled by client).
 	 * 
	 * @param aspectBundleId
	 * @param baseBundleId
	 * @param teamBinding
	 * @return whether this team is permitted to adapt classes from the given base bundle.
	 */
	boolean checkTeamBinding(String aspectBundleId, String baseBundleId, TeamBinding teamBinding) {
		if (teamBinding.checkedPermission != null)
			return teamBinding.checkedPermission == AspectPermission.GRANT;

		boolean isGranted = internalCheckTeamBinding(aspectBundleId, baseBundleId, teamBinding.teamName);
		teamBinding.checkedPermission = isGranted ? AspectPermission.GRANT : AspectPermission.DENY;
		return isGranted;
	}

	boolean internalCheckTeamBinding(String aspectBundleId, String baseBundleId, String teamClass) 
	{
		boolean shouldReportGrant = false; // grant by default should not be reported
		AspectPermission negotiatedPermission = this.defaultAspectBindingPermission;

		// DENY by default?
		if (negotiatedPermission == DENY) {
			log(IStatus.ERROR, "Default denial of aspect binding regarding base bundle "+baseBundleId+
							   " as requested by bundle "+aspectBundleId+"; bundle not activated");
			this.deniedAspects.add(aspectBundleId); // keep for answering the TransformerHook.
			return false; // NOPE!					
		}

		
		String key = aspectBundleId+"->"+baseBundleId;
		
		// denied from configuration?
		Set<String> deniedTeams = deniedTeamsByAspectBinding.get(key);
		if (deniedTeams != null && !deniedTeams.isEmpty()) {
			if (deniedTeams.contains(teamClass)) {
				log(IStatus.ERROR, "Configured denial of aspect binding regarding base bundle "+baseBundleId+
						   " as requested by bundle "+aspectBundleId+"; bundle not activated");
				deniedAspects.add(aspectBundleId);
				return false;
			}
		}
		
		// granted from configuration?
		Set<String> grantedTeams = grantedTeamsByAspectBinding.get(key);
		if (grantedTeams != null && grantedTeams.contains(teamClass)) {
			negotiatedPermission = GRANT;
			shouldReportGrant = true;
		}
		
		// default and persistent configuration did not DENY, proceed to the negotiators:
		boolean shouldPersist = false;
		String denyingNegotiator = null;
		for (IAspectRequestNegotiator negotiator : this.negotiators) {
			AspectBindingRequestAnswer answer = negotiator.checkAspectBinding(aspectBundleId, baseBundleId, teamClass, negotiatedPermission);
			if (answer.permission.compareTo(negotiatedPermission) > 0) // increasing priority of answer?
			{ 
				shouldPersist = answer.persistent;
				negotiatedPermission = answer.permission;
				shouldReportGrant = negotiatedPermission == GRANT;
				// locally store as default for subsequent requests:
				if (answer.allRequests)
					this.defaultAspectBindingPermission = negotiatedPermission; // FIXME: differentiate: apply to all / all of same aspect bundle

				if (negotiatedPermission == DENY) {
					denyingNegotiator = negotiator.getClass().getName();
					break; // end of discussion.
				}
			}
		}

		// make decision persistent?
		if (shouldPersist && negotiatedPermission != UNDEFINED)
			persistTeamBindingAnswer(aspectBundleId, baseBundleId, teamClass, negotiatedPermission);
		
		// report:
		if (negotiatedPermission == GRANT) {
			if (shouldReportGrant)
				log(IStatus.INFO, "Negotiation granted aspect binding for "+aspectBundleId+
								  " to base bundle "+baseBundleId+" by means of team "+teamClass+'.');
		} else {
			String front = (negotiatedPermission == DENY)
					? "Negotiator "+denyingNegotiator + " denied" 
					: "Negotiation did not grant";
			log(IStatus.ERROR, front+" aspect binding for "+aspectBundleId+
							   " to base bundle "+baseBundleId+" by means of team "+teamClass+
							   ". Aspect is not activated.");
			this.deniedAspects.add(aspectBundleId); // keep for answering the TransformerPlugin.
			return false; // don't install illegal aspect
		}
		return true;
	}

	List<Runnable> obligations = new ArrayList<Runnable>();
	public void addBaseBundleObligations(final List<Team> teamInstances, final Collection<TeamBinding> teamClasses, final BaseBundle baseBundle) {
		schedule(new Runnable() {
			public void run() {
				List<TeamBinding> teamsToRevert = new ArrayList<TeamBinding>();
				// aspect bindings:
				for (TeamBinding teamClass : teamClasses)
					if (!checkTeamBinding(teamClass.getAspectBinding().aspectPlugin, baseBundle.bundleName, teamClass))
						teamsToRevert.add(teamClass);
				if (!teamsToRevert.isEmpty())
					revert(teamsToRevert);
			}
			void revert(List<TeamBinding> teamsToRevert) {
				try {
					Set<Bundle> bundlesToStop = new HashSet<Bundle>();
					for (TeamBinding teamClass : teamClasses) {
						if (teamClass.getActivation() != ActivationKind.NONE) {
							for (Team teamInstance : teamInstances)
								if (teamInstance.getClass() == teamClass.teamClass)
									teamInstance.deactivate(Team.ALL_THREADS);
							// could also check if roles are present already ...
						}
						Bundle aspectBundle = teamClass.getAspectBinding().aspectBundle;
						if (aspectBundle != null)
							bundlesToStop.add(aspectBundle);
					}
					for (Bundle bundle : bundlesToStop) {
						if ((bundle.getState() & (Bundle.STARTING|Bundle.ACTIVE)) != 0) {
							log(IStatus.ERROR, "Stopping aspect bundle "+bundle.getSymbolicName()+" with denied aspect binding(s)");
							bundle.stop();
						}
					}
				} catch (Exception e) {
					log(e, "Failed to revert aspect bundle with denied aspect bindings.");
				}
			}
		});
	}

	void schedule(Runnable job) {
		if (isReady()) // became ready since last query?
			job.run();
		else
			synchronized(obligations) {
				obligations.add(job);
			}
	}
		
	void stopIllegalBundle(String symbolicName) {
		String msgCore = "stop bundle "+symbolicName+" whose requests for forced exports have been denied";
		@SuppressWarnings("deprecation")
		org.osgi.service.packageadmin.PackageAdmin packAdmin = this.packageAdmin;
		if (packAdmin == null) {
			log(IStatus.ERROR, "Needing to "+msgCore+" but package admin is not available");
		} else {
			@SuppressWarnings("deprecation")
			Bundle[] bundles = packAdmin.getBundles(symbolicName, null);
			if (bundles == null)
				log(IStatus.ERROR, "Needing to "+msgCore+" but bundle cannot be retrieved");
			else
				try {
					bundles[0].stop();
				} catch (BundleException e) {
					log(e, "Failed to " + msgCore);
				}
		}
	}

	// ==== File I/O: ====

	private void internalFetchAspectBindingPermssionsFromWorkspace(IPath state) {
		// defaults:
		IPath configFilePath = state.append(NEGOTIATION_DEFAULTS_FILE);
		File configFile = new File(configFilePath.toOSString());		
		if (configFile.exists()) {
			Properties props = new Properties();
			try {
				try (FileInputStream inStream = new FileInputStream(configFile)) {
					props.load(inStream);
				}
				String value = (String) props.get(ASPECT_BINDING_DEFAULT);
				if (value != null)
					try {
						defaultAspectBindingPermission = AspectPermission.valueOf(value);
					} catch (IllegalArgumentException iae) {
						defaultAspectBindingPermission = AspectPermission.DENY;
						log(iae, "Cannot set default aspect permission from file "+NEGOTIATION_DEFAULTS_FILE+", assuming DENY.");
					}
				value = (String) props.get(FORCED_EXPORT_DEFAULT);
				if (value != null)
					try {
						defaultForcedExportPermission = AspectPermission.valueOf(value);
					} catch (IllegalArgumentException iae) {
						defaultForcedExportPermission = AspectPermission.DENY;
						log(iae, "Cannot set default forced exports permission from file "+NEGOTIATION_DEFAULTS_FILE+", assuming DENY.");
					}
			} catch (IOException ioex) {
				log(ioex, "Failed to read configuration file "+configFilePath.toOSString());
			}
		} else {
			try {
				File stateDir = new File(state.toOSString());
				if (!stateDir.exists())
					stateDir.mkdirs();
				configFile.createNewFile();
				writeNegotiationDefaults(configFile);
			} catch (IOException ioex) {
				log(ioex, "Failed to create configuration file "+configFilePath.toOSString());
			}
		}

		// configured grant / deny per team:

		configFilePath = state.append(GRANTED_TEAMS_FILE);
		configFile = new File(configFilePath.toOSString());
		if (configFile.exists())
			parseTeamPermissionFile(grantedTeamsByAspectBinding, configFile);
		
		configFilePath = state.append(DENIED_TEAMS_FILE);
		configFile = new File(configFilePath.toOSString());
		if (configFile.exists())
			parseTeamPermissionFile(deniedTeamsByAspectBinding, configFile);

		// configured grant / denied for forced exports:
		configFilePath = state.append(DENIED_FORCED_EXPORTS_FILE);
		configFile = new File(configFilePath.toOSString());
		if (configFile.exists())
			forcedExportsDelegate.parseForcedExportsFile(configFile, DENY);
		
		configFilePath = state.append(GRANTED_FORCED_EXPORTS_FILE);
		configFile = new File(configFilePath.toOSString());
		if (configFile.exists())
			forcedExportsDelegate.parseForcedExportsFile(configFile, GRANT);
	}

	private void writeNegotiationDefaults(File configFile)
			throws IOException 
	{
		try (FileWriter writer = new FileWriter(configFile)) {
			writer.append(ASPECT_BINDING_DEFAULT+'='+defaultAspectBindingPermission.toString()+'\n');
			writer.append(FORCED_EXPORT_DEFAULT+'='+defaultForcedExportPermission.toString()+'\n');
			writer.flush();
		}
		log(IStatus.INFO, "Created aspect binding defaults file "+configFile.getCanonicalPath());
	}

	private void parseTeamPermissionFile(Map<String, Set<String>> teamsByAspectBinding, File configFile) {
		try (BufferedReader reader = new BufferedReader(new FileReader(configFile))) {
			String line;
			while ((line = reader.readLine()) != null) {
				if (line.length() > 0 && line.charAt(0) == '#') continue;
				@NonNull String[] parts = line.split("=");
				if (parts.length == 2) {
					Set<String> teams = new HashSet<String>();
					StringTokenizer teamToks = new StringTokenizer(parts[1], ",");
					while (teamToks.hasMoreElements())
						teams.add(teamToks.nextToken());
					teamsByAspectBinding.put(parts[0], teams);
				}
			}
		} catch (IOException e) {
			log(e, "Failed to read permission file "+configFile.getAbsolutePath());
		}
	}

	private void persistTeamBindingAnswer(String aspectBundleId, String baseBundleId, String teamClass, AspectPermission negotiatedPermission) 
	{
		IPath state = this.otequinoxState;
		if (state != null) {
			Map<String, Set<String>> teamsByAspect = null;
			IPath configFilePath = null;
			switch (negotiatedPermission) {
			case GRANT:
				teamsByAspect = this.grantedTeamsByAspectBinding;
				configFilePath = state.append(GRANTED_TEAMS_FILE);
				break;
			case DENY:
				teamsByAspect = this.deniedTeamsByAspectBinding;
				configFilePath = state.append(DENIED_TEAMS_FILE);
				break;
			default: return; // TODO: also persist UNDEFINED (just to avoid asking again?)
			}
			
			// in fact we store the entire state for the given category (grant / deny)
			// so first insert the new answer into the existing map:
			String key = aspectBundleId+"->"+baseBundleId;
			Set<String> teams = teamsByAspect.get(key);
			if (teams == null)
				teamsByAspect.put(key, teams = new HashSet<String>());
			teams.add(teamClass);

			// now dump the entire map:
			File configFile = new File(configFilePath.toOSString());
			try {
				if (!configFile.exists())
					configFile.createNewFile();
				try (FileWriter writer = new FileWriter(configFile, false)) {
					writer.write("# Aspect permission file generated from aspect negotiation results.\n");
					for (Map.Entry<String, Set<String>> entry : teamsByAspect.entrySet()) {
						writer.append(entry.getKey()).append('=');
						String sep = "";
						for (String t : entry.getValue()) {
							writer.append(sep).append(t);
							sep = ",";
						}
						writer.append('\n');
					}
					writer.flush();
				}
			} catch (IOException ioe) {
				log(ioe, "Failed to persist negotiation result");
			}
		}
	}
}
