/*******************************************************************************
 * Copyright (c) 1997-2009 by ProSyst Software GmbH
 * http://www.prosyst.com
 * 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
 *
 * Contributors:
 *    ProSyst Software GmbH - initial API and implementation
 *    Jeremy Volkman 		- bug.id = 182560
 *    Simon Archer 		    - bug.id = 223454
 *******************************************************************************/
package org.eclipse.equinox.internal.ds.model;

import java.io.*;
import java.lang.reflect.Method;
import java.lang.reflect.Modifier;
import java.util.*;
import org.eclipse.equinox.internal.ds.*;
import org.eclipse.equinox.internal.ds.impl.ComponentInstanceImpl;
import org.eclipse.equinox.internal.util.io.Externalizable;
import org.eclipse.osgi.util.NLS;
import org.osgi.framework.ServiceReference;
import org.osgi.service.component.ComponentInstance;
import org.osgi.service.log.LogService;

/**
 * @author Stoyan Boshev
 * @author Pavlin Dobrev
 */
public class ComponentReference implements Externalizable {

	public static final int CARDINALITY_0_1 = 0;
	public static final int CARDINALITY_0_N = 1;
	public static final int CARDINALITY_1_1 = 2;
	public static final int CARDINALITY_1_N = 3;
	public static final int POLICY_STATIC = 0;
	public static final int POLICY_DYNAMIC = 1;

	// --- begin: XML def
	public String name; // required
	public String interfaceName; // required
	public int cardinality = CARDINALITY_1_1;
	public int policy = POLICY_STATIC;
	public String target;
	public String bind;
	public String unbind;
	public ServiceComponent component;
	// --- end: XML def

	// --- begin: cache
	private boolean bindCached;
	private boolean unbindCached;
	Method bindMethod;
	Method unbindMethod;
	// --- end: cache

	// --- begin: model

	// Contains mapping of ServiceReference to ComponentInstance or Vector of ComponentInstances.
	// The service reference is bound to the ComponentInstance or to each of the ComponentInstances in the Vector 
	public Hashtable serviceReferences = new Hashtable(3);

	// avoids recursive calling of unbind method for one and the same instance 
	private Hashtable serviceReferencesToUnbind = new Hashtable(3);

	static final Class[] SERVICE_REFERENCE = new Class[] {ServiceReference.class};

	// --- end: model;

	ComponentReference(ServiceComponent component) {
		this.component = component;
		if (this.component.references == null) {
			this.component.references = new Vector(2);
		}
		this.component.references.addElement(this);
	}

	Method getMethod(ComponentInstanceImpl componentInstance, Reference reference, String methodName, ServiceReference serviceReference) {

		Class consumerClass = componentInstance.getInstance().getClass();
		Object serviceObject = null;
		Class serviceObjectClass = null;
		Class interfaceClass = null;
		Class[] param_interfaceClass = null;
		Method method = null;
		while (consumerClass != null) {

			// search this class' methods
			// look for various forms of bind methods

			// 1) check for bind(ServiceReference) method
			try {
				method = consumerClass.getDeclaredMethod(methodName, SERVICE_REFERENCE);
			} catch (NoSuchMethodException e) {
				//
			} catch (NoClassDefFoundError err) {
				// this may happen on skelmir VM or in case of class loading problems
				logWarning(NLS.bind(Messages.EXCEPTION_GETTING_METHOD, methodName, consumerClass.getName()), err, reference);
			}

			if (method != null && SCRUtil.checkMethodAccess(componentInstance.getInstance().getClass(), consumerClass, method, component.namespace11))
				break;

			// we need a serviceObject to keep looking, create one if necessary
			if (serviceObject == null) {
				serviceObject = componentInstance.bindedServices.get(serviceReference);
				if (serviceObject == null) {
					serviceObject = InstanceProcess.staticRef.getService(reference, serviceReference);
				}
				if (serviceObject == null) {
					// we could not create a serviceObject because of circularity
					logWarning(Messages.CANT_GET_SERVICE_OBJECT, null, reference);
					return null;
				}
				componentInstance.bindedServices.put(serviceReference, serviceObject);
				serviceObjectClass = serviceObject.getClass();

				// figure out the interface class - this is guaranteed to succeed or else
				// the framework would not have let us have the service object
				Class searchForInterfaceClass = serviceObjectClass;
				while (searchForInterfaceClass != null) {
					// first look through interfaces
					Class[] interfaceClasses = searchForInterfaceClass.getInterfaces();
					for (int i = 0; i < interfaceClasses.length; i++) {
						if (interfaceClasses[i].getName().equals(interfaceName)) {
							interfaceClass = interfaceClasses[i];
							break;
						}
					}
					if (interfaceClass != null) {
						break;
					}

					// also check the class itself
					if (searchForInterfaceClass.getName().equals(interfaceName)) {
						interfaceClass = searchForInterfaceClass;
						break;
					}

					// advance up the superclasses
					searchForInterfaceClass = searchForInterfaceClass.getSuperclass();
				}

				param_interfaceClass = new Class[] {interfaceClass};

			} // end if(serviceObject == null)

			// 2) check for bind(Service interface) method
			try {
				method = consumerClass.getDeclaredMethod(methodName, param_interfaceClass);
			} catch (NoSuchMethodException e) {
				//
			} catch (NoClassDefFoundError err) {
				// this may happen on skelmir VM or in case of class loading problems
				logWarning(NLS.bind(Messages.EXCEPTION_GETTING_METHOD, methodName, consumerClass.getName()), err, reference);
			}
			if (method != null && SCRUtil.checkMethodAccess(componentInstance.getInstance().getClass(), consumerClass, method, component.namespace11))
				break;

			// 3) check for bind(class.isAssignableFrom(serviceObjectClass))
			// method
			Method[] methods = consumerClass.getDeclaredMethods();
			for (int i = 0; i < methods.length; i++) {
				Class[] params = methods[i].getParameterTypes();
				if (params.length == 1 && methods[i].getName().equals(methodName) && params[0].isAssignableFrom(serviceObjectClass)) {

					method = methods[i];
					break;
				}
			}
			if (method != null && SCRUtil.checkMethodAccess(componentInstance.getInstance().getClass(), consumerClass, method, component.namespace11))
				break;

			//implement search for bind/unbind methods according to schema v1.1.0
			if (component.namespace11) {
				for (int i = 0; i < methods.length; i++) {
					Class[] params = methods[i].getParameterTypes();
					if (params.length == 2 && methods[i].getName().equals(methodName) && params[0] == interfaceClass && params[1] == Map.class) {
						method = methods[i];
						break;
					}
				}
				if (method != null && SCRUtil.checkMethodAccess(componentInstance.getInstance().getClass(), consumerClass, method, true))
					break;

				for (int i = 0; i < methods.length; i++) {
					Class[] params = methods[i].getParameterTypes();
					if (params.length == 2 && methods[i].getName().equals(methodName) && params[0].isAssignableFrom(serviceObjectClass) && params[1] == Map.class) {
						method = methods[i];
						break;
					}
				}
			}
			if (method != null)
				break;

			// we couldn't find the method - try the superclass
			consumerClass = consumerClass.getSuperclass();
		}

		if (method == null) {
			logMethodNotFoundError(componentInstance, reference, methodName);
			return null;
		}

		if (!SCRUtil.checkMethodAccess(componentInstance.getInstance().getClass(), consumerClass, method, component.namespace11)) {
			// if method is not visible, log error message
			logMethodNotVisible(componentInstance, reference, methodName, method.getParameterTypes());
			return null;
		}

		int modifier = method.getModifiers();
		if (!Modifier.isPublic(modifier)) {
			SCRUtil.setAccessible(method);
		}

		return method;
	}

	private void logMethodNotVisible(ComponentInstanceImpl componentInstance, Reference reference, String methodName, Class[] param_interfaceClasses) {
		StringBuffer buffer = createBuffer();
		buffer.append("[SCR] Method "); //$NON-NLS-1$
		buffer.append(methodName);
		buffer.append('(');
		for (int i = 0; i < param_interfaceClasses.length; i++) {
			buffer.append(param_interfaceClasses[i].getName());
			if (i < param_interfaceClasses.length - 1) {
				buffer.append(',');
			}
		}
		buffer.append(')');
		buffer.append(" is not accessible!"); //$NON-NLS-1$
		appendDetails(buffer, reference);
		String message = buffer.toString();
		Activator.log(reference.reference.component.bc, LogService.LOG_ERROR, message, null);
	}

	private void logMethodNotFoundError(ComponentInstanceImpl componentInstance, Reference reference, String methodName) {
		StringBuffer buffer = createBuffer();
		buffer.append("[SCR] Method was not found: "); //$NON-NLS-1$
		buffer.append(methodName);
		buffer.append('(');
		buffer.append("..."); //$NON-NLS-1$
		buffer.append(')');
		appendDetails(buffer, reference);
		String message = buffer.toString();
		Activator.log(reference.reference.component.bc, LogService.LOG_ERROR, message, null);
	}

	private void appendDetails(StringBuffer buffer, Reference reference) {
		try {
			String indent = "\n\t"; //$NON-NLS-1$
			buffer.append(indent);
			buffer.append("Details:"); //$NON-NLS-1$
			buffer.append(indent);
			buffer.append("Problematic reference = " + reference.reference); //$NON-NLS-1$
			buffer.append(indent);
			buffer.append("of service component = "); //$NON-NLS-1$
			buffer.append(reference.reference.component.name);
			buffer.append(indent);
			buffer.append("component implementation class = "); //$NON-NLS-1$
			buffer.append(reference.reference.component.implementation);
			buffer.append(indent);
			buffer.append("located in bundle with symbolic name = "); //$NON-NLS-1$
			buffer.append(component.bc.getBundle().getSymbolicName());
			buffer.append(indent);
			buffer.append("bundle location = "); //$NON-NLS-1$
			buffer.append(component.bc.getBundle().getLocation());
		} catch (Throwable t) {
			//prevent possible exceptions in case the component's bundle becomes uninstalled 
		}
	}

	private void logWarning(String message, Throwable t, Reference reference) {
		StringBuffer buffer = createBuffer();
		buffer.append(message);
		appendDetails(buffer, reference);
		Activator.log(reference.reference.component.bc, LogService.LOG_WARNING, buffer.toString(), t);
	}

	private void logError(String message, Throwable t, Reference reference) {
		StringBuffer buffer = createBuffer();
		buffer.append(message);
		appendDetails(buffer, reference);
		Activator.log(reference.reference.component.bc, LogService.LOG_ERROR, buffer.toString(), t);
	}

	private StringBuffer createBuffer() {
		return new StringBuffer(400);
	}

	final void bind(Reference reference, ComponentInstance instance, ServiceReference serviceReference) throws Exception {
		if (bind != null) {
			// DON'T rebind the same object again
			synchronized (serviceReferences) {
				Vector instances = (Vector) serviceReferences.get(serviceReference);
				if (instances == null) {
					instances = new Vector(1);
					instances.addElement(instance);
					serviceReferences.put(serviceReference, instances);
				} else if (instances.contains(instance)) {
					if (reference.isUnary()) {
						logWarning(NLS.bind(Messages.SERVICE_REFERENCE_ALREADY_BOUND, serviceReference, instance), null, reference);
					}
					return;
				} else {
					instances.addElement(instance);
				}
			}
			// retrieve the method from cache
			if (!bindCached) {
				bindMethod = getMethod((ComponentInstanceImpl) instance, reference, bind, serviceReference);
				// bindMethod can be null in case of circularity
				if (bindMethod != null) {
					bindCached = true;
				}
			}
			// invoke the method
			if (bindMethod != null) {
				Object methodParam = null;
				Class[] paramTypes = bindMethod.getParameterTypes();
				if (paramTypes.length == 1 && paramTypes[0].equals(ServiceReference.class)) {
					methodParam = serviceReference;
				} else {
					// bindedServices is filled by the getMethod function
					methodParam = ((ComponentInstanceImpl) instance).bindedServices.get(serviceReference);
					if (methodParam == null) {
						methodParam = InstanceProcess.staticRef.getService(reference, serviceReference);
						if (methodParam != null) {
							((ComponentInstanceImpl) instance).bindedServices.put(serviceReference, methodParam);
						}
					}
					if (methodParam == null) {
						// cannot get serviceObject because of circularity

						//remove the component instance marked as bound
						removeServiceReference(serviceReference, instance);
						return;
					}
				}

				Object[] params = null;
				if (paramTypes.length == 1) {
					params = SCRUtil.getObjectArray();
					params[0] = methodParam;
				} else {
					//this is the case where we have 2 parameters: a service object and a Map, holding the service properties
					HashMap map = new HashMap();
					String[] keys = serviceReference.getPropertyKeys();
					for (int i = 0; i < keys.length; i++) {
						map.put(keys[i], serviceReference.getProperty(keys[i]));
					}
					params = new Object[] {methodParam, map};
				}

				try {
					bindMethod.invoke(instance.getInstance(), params);
				} catch (Throwable t) {
					logError(NLS.bind(Messages.ERROR_BINDING_REFERENCE, this), t, reference);
					//remove the component instance marked as bound
					removeServiceReference(serviceReference, instance);
				} finally {
					if (params.length == 1) {
						SCRUtil.release(params);
					}
				}
			} else {
				//remove the component instance marked as bound
				removeServiceReference(serviceReference, instance);
				// could be also circularity break
				logWarning(NLS.bind(Messages.BIND_METHOD_NOT_FOUND_OR_NOT_ACCESSIBLE, bind), null, reference);
			}
		}
	}

	private void removeServiceReference(ServiceReference serviceReference, ComponentInstance instance) {
		Vector instances = (Vector) serviceReferences.get(serviceReference);
		instances.removeElement(instance);
		if (instances.isEmpty()) {
			serviceReferences.remove(serviceReference);
		}
	}

	public final void unbind(Reference reference, ComponentInstance instance, ServiceReference serviceReference) {
		// don't unbind an object that wasn't bound
		boolean referenceExists = true;
		synchronized (serviceReferences) {
			Vector instances = (Vector) serviceReferences.get(serviceReference);
			if (instances == null) {
				referenceExists = false;
			} else {
				if (!instances.contains(instance)) {
					logWarning(NLS.bind(Messages.INSTANCE_NOT_BOUND, instance), null, reference);
					return;
				}
			}
			if (referenceExists) {
				Vector instancesToUnbind = (Vector) serviceReferencesToUnbind.get(serviceReference);
				if (instancesToUnbind != null && instancesToUnbind.contains(instance)) {
					//the service reference is already in process of unbinding
					return;
				}
				if (instancesToUnbind == null) {
					instancesToUnbind = new Vector(1);
					serviceReferencesToUnbind.put(serviceReference, instancesToUnbind);
				}
				instancesToUnbind.addElement(instance);
			}
		}
		if (!referenceExists) {
			logWarning(NLS.bind(Messages.INVALID_SERVICE_REFERENCE, serviceReference), null, reference);
			return;
		}
		try {
			if (unbind != null) {
				// retrieve the unbind method from cache
				if (!unbindCached) {
					unbindCached = true;
					unbindMethod = getMethod((ComponentInstanceImpl) instance, reference, unbind, serviceReference);
				}
				// invoke the method
				if (unbindMethod != null) {
					Object methodParam = null;
					Class[] paramTypes = unbindMethod.getParameterTypes();
					if (paramTypes.length == 1 && paramTypes[0].equals(ServiceReference.class)) {
						methodParam = serviceReference;
					} else {
						// bindedServices is filled by the getMethod function
						methodParam = ((ComponentInstanceImpl) instance).bindedServices.get(serviceReference);
						if (methodParam == null) {
							methodParam = InstanceProcess.staticRef.getService(reference, serviceReference);
						}
						if (methodParam == null) {
							// probably cannot get serviceObject because of
							// circularity
							return;
						}
					}

					Object[] params = null;
					if (paramTypes.length == 1) {
						params = SCRUtil.getObjectArray();
						params[0] = methodParam;
					} else {
						//this is the case where we have 2 parameters: a service object and a Map, holding the service properties
						HashMap map = new HashMap();
						String[] keys = serviceReference.getPropertyKeys();
						for (int i = 0; i < keys.length; i++) {
							map.put(keys[i], serviceReference.getProperty(keys[i]));
						}
						params = new Object[] {methodParam, map};
					}
					try {
						unbindMethod.invoke(instance.getInstance(), params);
					} catch (Throwable t) {
						logError(NLS.bind(Messages.EXCEPTION_UNBINDING_REFERENCE, this), t, reference);
					} finally {
						if (params.length == 1) {
							SCRUtil.release(params);
						}
					}
				}
			}
		} finally {
			synchronized (serviceReferences) {
				Vector instances = (Vector) serviceReferences.get(serviceReference);
				instances.removeElement(instance);
				if (instances.isEmpty()) {
					serviceReferences.remove(serviceReference);
				}

				instances = (Vector) serviceReferencesToUnbind.get(serviceReference);
				instances.removeElement(instance);
				if (instances.isEmpty()) {
					serviceReferencesToUnbind.remove(serviceReference);
				}
			}
		}
		if (((ComponentInstanceImpl) instance).bindedServices.remove(serviceReference) != null) {
			component.bc.ungetService(serviceReference);
		}
	}

	public final void dispose() {
		bindCached = unbindCached = false;
		bindMethod = unbindMethod = null;
		serviceReferences = null;
	}

	public final String toString() {
		StringBuffer buffer = new StringBuffer();
		buffer.append("Reference["); //$NON-NLS-1$
		buffer.append("name = ").append(name); //$NON-NLS-1$
		buffer.append(", interface = ").append(interfaceName); //$NON-NLS-1$
		buffer.append(", policy = "); //$NON-NLS-1$
		switch (policy) {
			case POLICY_DYNAMIC :
				buffer.append("dynamic"); //$NON-NLS-1$
				break;
			case POLICY_STATIC :
				buffer.append("static"); //$NON-NLS-1$
		}

		buffer.append(", cardinality = "); //$NON-NLS-1$
		switch (cardinality) {
			case CARDINALITY_0_1 :
				buffer.append("0..1"); //$NON-NLS-1$
				break;
			case CARDINALITY_0_N :
				buffer.append("0..n"); //$NON-NLS-1$
				break;
			case CARDINALITY_1_1 :
				buffer.append("1..1"); //$NON-NLS-1$
				break;
			case CARDINALITY_1_N :
				buffer.append("1..n"); //$NON-NLS-1$
		}
		buffer.append(", target = ").append(target); //$NON-NLS-1$
		buffer.append(", bind = ").append(bind); //$NON-NLS-1$
		buffer.append(", unbind = ").append(unbind); //$NON-NLS-1$
		buffer.append("]"); //$NON-NLS-1$
		return buffer.toString();
	}

	/*
	 * (non-Javadoc)
	 * 
	 * @see org.eclipse.equinox.internal.util.io.Externalizable#writeObject(java.io.OutputStream)
	 */
	public synchronized void writeObject(OutputStream o) throws Exception {
		try {
			DataOutputStream out;
			if (o instanceof DataOutputStream) {
				out = (DataOutputStream) o;
			} else {
				out = new DataOutputStream(o);
			}
			boolean flag;
			out.writeUTF(name);
			out.writeUTF(interfaceName);
			out.writeInt(cardinality);
			out.writeInt(policy);

			flag = target != null;
			out.writeBoolean(flag);
			if (flag)
				out.writeUTF(target);

			flag = bind != null;
			out.writeBoolean(flag);
			if (flag)
				out.writeUTF(bind);

			flag = unbind != null;
			out.writeBoolean(flag);
			if (flag)
				out.writeUTF(unbind);
		} catch (Exception e) {
			Activator.log.error(Messages.ERROR_WRITING_OBJECT, e);
		}
	}

	/*
	 * (non-Javadoc)
	 * 
	 * @see org.eclipse.equinox.internal.util.io.Externalizable#readObject(java.io.InputStream)
	 */
	public synchronized void readObject(InputStream s) throws Exception {
		try {
			DataInputStream in;
			if (s instanceof DataInputStream) {
				in = (DataInputStream) s;
			} else {
				in = new DataInputStream(s);
			}
			boolean flag;
			name = in.readUTF();
			interfaceName = in.readUTF();
			cardinality = in.readInt();
			policy = in.readInt();
			flag = in.readBoolean();
			if (flag)
				target = in.readUTF();

			flag = in.readBoolean();
			if (flag)
				bind = in.readUTF();

			flag = in.readBoolean();
			if (flag)
				unbind = in.readUTF();
		} catch (Exception e) {
			Activator.log.error(Messages.ERROR_READING_OBJECT, e);
		}
	}

}
