/*******************************************************************************
 * Copyright (c) 2003 IBM Corporation and others.
 * All rights reserved. This program and the accompanying materials 
 * are made available under the terms of the Common Public License v1.0
 * which accompanies this distribution, and is available at
 * http://www.eclipse.org/legal/cpl-v10.html
 * 
 * Contributors:
 *     IBM Corporation - initial API and implementation
 *******************************************************************************/

package org.eclipse.osgi.framework.internal.core;

import java.io.*;
import java.security.*;
import java.util.Vector;
import org.eclipse.osgi.framework.adaptor.PermissionStorage;
import org.eclipse.osgi.framework.debug.Debug;
import org.osgi.framework.FrameworkEvent;
import org.osgi.service.permissionadmin.PermissionAdmin;
import org.osgi.service.permissionadmin.PermissionInfo;

/**
 * Permission Admin service for the OSGi specification.
 *
 * The Permission Admin service allows operators to
 * manage the permissions of bundles. There is at most one Permission Admin
 * service present in the Framework.
 * <p>
 * Access to the Permission Admin service is protected by
 * corresponding
 * <tt>ServicePermission</tt>. In addition the <tt>AdminPermission</tt>
 * is required to actually set permissions.
 *
 * <p>Bundle permissions are managed using a permission table. A bundle's location
 * serves as the key into this permission table. The value of a table entry is
 * the set of permissions (of type <tt>PermissionInfo</tt>) granted to the
 * bundle with the given location.
 * A bundle may have an entry in the permission table prior to being installed
 * in the Framework.
 *
 * <p>The permissions specified in <tt>setDefaultPermissions</tt> are used as the
 * default
 * permissions which are granted to all bundles that do not have an entry in
 * the permission table.
 *
 * <p>Any changes to a bundle's permissions in the permission table will take
 * effect no later than when bundle's <tt>java.security.ProtectionDomain</tt>
 * is involved in a permission check, and will be made persistent.
 *
 * <p>Only permission classes on the system classpath or from an exported
 * package are considered during a permission check.
 * Additionally, only permission classes that are subclasses of
 * <tt>java.security.Permission</tt> and define a 2-argument constructor
 * that takes a <i>name</i> string and an <i>actions</i> string can be used.
 * <p>
 * Permissions implicitly granted by the Framework (for example, a bundle's
 * permission to access its persistent storage area) cannot be changed, and
 * are not reflected in the permissions returned by <tt>getPermissions</tt>
 * and <tt>getDefaultPermissions</tt>.
 */
public class PermissionAdminImpl implements PermissionAdmin {
	/** framework object */
	protected Framework framework;

	/** permission storage object */
	protected PermissionStorage storage;

	/** The permissions to use if no other permissions can be determined */
	protected PermissionInfo[] defaultDefaultPermissionInfos;

	/** The basic implied permissions for a bundle */
	protected PermissionInfo[] baseImpliedPermissionInfos;

	/** The permission collection containing the default assigned permissions */
	protected BundleCombinedPermissions defaultAssignedPermissions;

	/**
	 * Construstor.
	 *
	 * @param framework Framework object.
	 */
	protected PermissionAdminImpl(Framework framework, PermissionStorage storage) {
		this.framework = framework;
		this.storage = storage;

		defaultDefaultPermissionInfos = getPermissionInfos(Constants.OSGI_DEFAULT_DEFAULT_PERMISSIONS);
		baseImpliedPermissionInfos = getPermissionInfos(Constants.OSGI_BASE_IMPLIED_PERMISSIONS);

		//      if (Debug.DEBUG)
		//      {
		//          // This is necessary to allow File.getAbsolutePath() in debug statements.
		//          int _length = baseImpliedPermissionInfos.length;
		//
		//          PermissionInfo[] debugBaseImpliedPermissionInfos = new PermissionInfo[_length + 1];
		//
		//          System.arraycopy(baseImpliedPermissionInfos, 0, debugBaseImpliedPermissionInfos, 0, _length);
		//
		//          debugBaseImpliedPermissionInfos[_length] = new PermissionInfo("(java.util.PropertyPermission \"user.dir\" \"read\")");
		//
		//          baseImpliedPermissionInfos = debugBaseImpliedPermissionInfos;
		//      }

		if (Debug.DEBUG && Debug.DEBUG_SECURITY) {
			Debug.println("Default default assigned bundle permissions");
			if (defaultDefaultPermissionInfos == null) {
				Debug.println("  <none>");
			} else {
				for (int i = 0; i < defaultDefaultPermissionInfos.length; i++) {
					Debug.println("  " + defaultDefaultPermissionInfos[i]);
				}
			}

			Debug.println("Base implied bundle permissions");
			if (baseImpliedPermissionInfos == null) {
				Debug.println("  <none>");
			} else {
				for (int i = 0; i < baseImpliedPermissionInfos.length; i++) {
					Debug.println("  " + baseImpliedPermissionInfos[i]);
				}
			}
		}

		defaultAssignedPermissions = new BundleCombinedPermissions(null);
		defaultAssignedPermissions.setAssignedPermissions(createDefaultAssignedPermissions(getDefaultPermissions()));
	}

	/**
	 * Gets the permissions assigned to the bundle with the specified
	 * location.
	 *
	 * @param location The location of the bundle whose permissions are to
	 * be returned.
	 *
	 * @return The permissions assigned to the bundle with the specified
	 * location, or <tt>null</tt> if that bundle has not been assigned any
	 * permissions.
	 */
	public PermissionInfo[] getPermissions(String location) {
		if (location == null) {
			throw new NullPointerException();
		}

		PermissionStorage storage = new org.eclipse.osgi.framework.util.SecurePermissionStorage(this.storage);

		try {
			String[] data = storage.getPermissionData(location);

			if (Debug.DEBUG && Debug.DEBUG_SECURITY) {
				Debug.println("Getting permissions for location: " + location);
				if (data == null) {
					Debug.println("  <none>");
				} else {
					for (int i = 0; i < data.length; i++) {
						Debug.println("  " + data[i]);
					}
				}
			}

			return makePermissionInfo(data);
		} catch (IOException e) {
			framework.publishFrameworkEvent(FrameworkEvent.ERROR, framework.systemBundle, e);

			return null;
		}
	}

	/**
	 * Assigns the specified permissions to the bundle with the specified
	 * location.
	 *
	 * @param location The location of the bundle that will be assigned the
	 *                 permissions.
	 * @param perms The permissions to be assigned, or <tt>null</tt>
	 * if the specified location is to be removed from the permission table.
	 * @exception SecurityException if the caller does not have the
	 * <tt>AdminPermission</tt>.
	 */
	public void setPermissions(String location, PermissionInfo[] permissions) {
		framework.checkAdminPermission();

		if (location == null) {
			throw new NullPointerException();
		}

		PermissionStorage storage = new org.eclipse.osgi.framework.util.SecurePermissionStorage(this.storage);

		try {
			String[] data = makePermissionData(permissions);

			if (Debug.DEBUG && Debug.DEBUG_SECURITY) {
				Debug.println("Setting permissions for location: " + location);
				if (data == null) {
					Debug.println("  <none>");
				} else {
					for (int i = 0; i < data.length; i++) {
						Debug.println("  " + data[i]);
					}
				}
			}

			storage.setPermissionData(location, data);
		} catch (IOException e) {
			framework.publishFrameworkEvent(FrameworkEvent.ERROR, framework.systemBundle, e);

			return;
		}

		AbstractBundle bundle = framework.getBundleByLocation(location);

		if ((bundle != null) && (bundle.getBundleId() != 0)) {
			ProtectionDomain domain = bundle.getProtectionDomain();

			if (domain != null) {
				BundleCombinedPermissions combined = (BundleCombinedPermissions) domain.getPermissions();

				if (permissions == null) {
					combined.setAssignedPermissions(defaultAssignedPermissions);
				} else {
					combined.setAssignedPermissions(createPermissions(permissions, bundle));
				}
			}
		}
	}

	/**
	 * Returns the bundle locations that have permissions assigned to them,
	 * that is, bundle locations for which an entry
	 * exists in the permission table.
	 *
	 * @return The locations of bundles that have been assigned any
	 * permissions, or <tt>null</tt> if the permission table is empty.
	 */
	public String[] getLocations() {
		PermissionStorage storage = new org.eclipse.osgi.framework.util.SecurePermissionStorage(this.storage);

		try {
			String[] locations = storage.getLocations();

			return locations;
		} catch (IOException e) {
			framework.publishFrameworkEvent(FrameworkEvent.ERROR, framework.systemBundle, e);

			return null;
		}
	}

	/**
	 * Gets the default permissions.
	 *
	 * <p>These are the permissions granted to any bundle that does not
	 * have permissions assigned to its location.
	 *
	 * @return The default permissions, or <tt>null</tt> if default
	 * permissions have not been defined.
	 */
	public PermissionInfo[] getDefaultPermissions() {
		PermissionStorage storage = new org.eclipse.osgi.framework.util.SecurePermissionStorage(this.storage);

		try {
			String[] data = storage.getPermissionData(null);

			if (Debug.DEBUG && Debug.DEBUG_SECURITY) {
				Debug.println("Getting default permissions");
				if (data == null) {
					Debug.println("  <none>");
				} else {
					for (int i = 0; i < data.length; i++) {
						Debug.println("  " + data[i]);
					}
				}
			}

			return makePermissionInfo(data);
		} catch (IOException e) {
			framework.publishFrameworkEvent(FrameworkEvent.ERROR, framework.systemBundle, e);

			return null;
		}
	}

	/**
	 * Sets the default permissions.
	 *
	 * <p>These are the permissions granted to any bundle that does not
	 * have permissions assigned to its location.
	 *
	 * @param permissions The default permissions.
	 * @exception SecurityException if the caller does not have the
	 * <tt>AdminPermission</tt>.
	 */
	public void setDefaultPermissions(PermissionInfo[] permissions) {
		framework.checkAdminPermission();

		PermissionStorage storage = new org.eclipse.osgi.framework.util.SecurePermissionStorage(this.storage);

		try {
			String[] data = makePermissionData(permissions);

			if (Debug.DEBUG && Debug.DEBUG_SECURITY) {
				Debug.println("Setting default permissions");
				if (data == null) {
					Debug.println("  <none>");
				} else {
					for (int i = 0; i < data.length; i++) {
						Debug.println("  " + data[i]);
					}
				}
			}

			storage.setPermissionData(null, data);
		} catch (IOException e) {
			framework.publishFrameworkEvent(FrameworkEvent.ERROR, framework.systemBundle, e);

			return;
		}

		defaultAssignedPermissions.setAssignedPermissions(createDefaultAssignedPermissions(permissions));
	}

	/**
	 * Make a PermissionInfo array from an array of encoded permission Strings.
	 *
	 * @param data Array of encoded permission Strings
	 * @return Array of PermissionInfo objects.
	 */
	protected PermissionInfo[] makePermissionInfo(String[] data) {
		if (data == null) {
			return null;
		}

		int size = data.length;

		PermissionInfo[] permissions = new PermissionInfo[size];

		for (int i = 0; i < size; i++) {
			permissions[i] = new PermissionInfo(data[i]);
		}

		return permissions;
	}

	/**
	 * Make an array of encoded permission Strings from a PermissionInfo array.
	 *
	 * @param permissions Array of PermissionInfor objects.
	 * @return Array of encoded permission Strings
	 */
	protected String[] makePermissionData(PermissionInfo[] permissions) {
		if (permissions == null) {
			return null;
		}

		int size = permissions.length;

		String[] data = new String[size];

		for (int i = 0; i < size; i++) {
			data[i] = permissions[i].getEncoded();
		}

		return data;
	}

	/**
	 * This method is called by the Bundle object to create the
	 * PermissionCollection used by the bundle's ProtectionDomain.
	 *
	 * @param location Location string of the bundle.
	 * @return BundleCombinedPermission object with the bundle's
	 * dynamic permissions.
	 */
	protected PermissionCollection createPermissionCollection(AbstractBundle bundle) {
		BundlePermissionCollection implied = getImpliedPermissions(bundle);

		BundleCombinedPermissions combined = new BundleCombinedPermissions(implied);

		BundlePermissionCollection assigned = getAssignedPermissions(bundle);

		combined.setAssignedPermissions(assigned);

		return combined;
	}

	/**
	 * Creates the default assigned permissions for bundles that
	 * have no assigned permissions.
	 * The default permissions are assigned via the PermissionAdmin service
	 * and may change dynamically.
	 *
	 * @return A PermissionCollection of the default assigned permissions.
	 */
	protected BundlePermissionCollection createDefaultAssignedPermissions(PermissionInfo[] info) {
		if (Debug.DEBUG && Debug.DEBUG_SECURITY) {
			Debug.println("Creating default assigned permissions");
		}

		if (info == null) {
			info = defaultDefaultPermissionInfos;
		}

		return createPermissions(info, null);
	}

	/**
	 * Returns the assigned permissions for a bundle.
	 * These permissions are assigned via the PermissionAdmin service
	 * and may change dynamically.
	 *
	 * @param bundle The bundle to create the permissions for.
	 * @return A PermissionCollection of the assigned permissions.
	 */
	protected BundlePermissionCollection getAssignedPermissions(AbstractBundle bundle) {
		String location = bundle.getLocation();

		PermissionInfo[] info = getPermissions(location);

		if (info == null) {
			return defaultAssignedPermissions;
		}

		if (Debug.DEBUG && Debug.DEBUG_SECURITY) {
			Debug.println("Creating assigned permissions for " + bundle);
		}

		return createPermissions(info, bundle);
	}

	/**
	 * Returns the implied permissions for a bundle.
	 * These permissions never change.
	 *
	 * @param bundle The bundle to create the permissions for.
	 * @return A PermissionCollection of the implied permissions.
	 */
	protected BundlePermissionCollection getImpliedPermissions(AbstractBundle bundle) {
		if (Debug.DEBUG && Debug.DEBUG_SECURITY) {
			Debug.println("Creating implied permissions for " + bundle);
		}

		BundlePermissionCollection collection = createPermissions(baseImpliedPermissionInfos, bundle);

		Permission permission = new BundleResourcePermission(bundle.getBundleId());

		if (Debug.DEBUG && Debug.DEBUG_SECURITY) {
			Debug.println("Created permission: " + permission);
		}

		collection.add(permission);

		return collection;
	}

	/**
	 * Read the permissions from the specified resource.
	 *
	 * @return An array of PermissionInfo objects from the specified
	 * resource.
	 */
	protected PermissionInfo[] getPermissionInfos(String resource) {
		PermissionInfo[] info = null;

		InputStream in = getClass().getResourceAsStream(resource);

		if (in != null) {
			try {
				Vector permissions = new Vector();

				BufferedReader reader;
				try {
					reader = new BufferedReader(new InputStreamReader(in, "UTF8"));
				} catch (UnsupportedEncodingException e) {
					reader = new BufferedReader(new InputStreamReader(in));
				}

				while (true) {
					String line = reader.readLine();

					if (line == null) /* EOF */{
						break;
					}

					line = line.trim();

					if ((line.length() == 0) || line.startsWith("#") || line.startsWith("//")) /* comments */{
						continue;
					}

					try {
						permissions.addElement(new PermissionInfo(line));
					} catch (IllegalArgumentException iae) {
						/* incorrectly encoded permission */

						framework.publishFrameworkEvent(FrameworkEvent.ERROR, framework.systemBundle, iae);
					}
				}

				int size = permissions.size();

				if (size > 0) {
					info = new PermissionInfo[size];

					permissions.copyInto(info);
				}
			} catch (IOException e) {
			} finally {
				try {
					in.close();
				} catch (IOException ee) {
				}
			}
		}

		return info;
	}

	/**
	 * Create a PermissionCollection from a PermissionInfo array.
	 *
	 * @param info Array of PermissionInfo objects.
	 * @param bundle The target bundle for the permissions.
	 * @return A PermissionCollection containing Permission objects.
	 */
	protected BundlePermissionCollection createPermissions(PermissionInfo[] info, final AbstractBundle bundle) {
		BundlePermissionCollection collection = new BundlePermissions(framework.packageAdmin);

		/* add the permissions */
		int size = info.length;
		for (int i = 0; i < size; i++) {
			PermissionInfo perm = info[i];

			String type = perm.getType();

			if (type.equals("java.io.FilePermission")) {
				/* map FilePermissions for relative names to
				 * the bundle's data area
				 */
				String name = perm.getName();

				if (!name.equals("<<ALL FILES>>")) {
					File file = new File(name);

					if (!file.isAbsolute()) /* relative name */{
						if (bundle == null) /* default permissions */{
							continue; /* no relative file permissions */
						}

						File target = framework.getDataFile(bundle, name);

						if (target == null) /* no bundle data file area */{
							continue; /* no relative file permissions */
						}

						perm = new PermissionInfo(type, target.getPath(), perm.getActions());
					}
				}
			}

			collection.add(createPermission(perm));
		}

		return collection;
	}

	/**
	 * Create a Permission object from a PermissionInfo object.
	 * If the type of the permission is not loadable from
	 * this object's classloader (i.e. the system classloader)
	 * then an UnresolvedPermission is returned.
	 *
	 * @param info Description of the desired permission.
	 * @return A permission object.
	 */
	protected Permission createPermission(PermissionInfo info) {
		String type = info.getType();
		String name = info.getName();
		String actions = info.getActions();

		UnresolvedPermission permission = new UnresolvedPermission(type, name, actions);

		try {
			/* Only search the system classloader (ours) at this point.
			 * Permission classes exported by bundles will be
			 * resolved later.
			 * This is done so that permission classes exported by bundles
			 * may be easily unresolved during packageRefresh.
			 */
			Class clazz = Class.forName(type);

			Permission resolved = permission.resolve(clazz);

			if (resolved != null) {
				if (Debug.DEBUG && Debug.DEBUG_SECURITY) {
					Debug.println("Created permission: " + resolved);
				}

				return resolved;
			}
		} catch (ClassNotFoundException e) {
		}

		if (Debug.DEBUG && Debug.DEBUG_SECURITY) {
			Debug.println("Created permission: " + permission);
		}

		return permission;
	}
}