/**********************************************************************
 * This file is part of the "Object Teams Runtime Environment"
 * 
 * Copyright 2003, 2009 Technical University Berlin, Germany.
 * 
 * This program and the accompanying materials
 * are made available under the terms of the Eclipse Public License 2.0
 * which accompanies this distribution, and is available at
 * https://www.eclipse.org/legal/epl-2.0/
 *
 * SPDX-License-Identifier: EPL-2.0
 * 
 * Please visit http://www.objectteams.org for updates and contact.
 * 
 * Contributors:
 * Technical University Berlin - Initial API and implementation
 **********************************************************************/
package org.eclipse.objectteams.otre;

import java.util.HashSet;
import java.util.Iterator;
import java.util.List;

import org.eclipse.objectteams.otre.util.CallinBindingManager;
import org.eclipse.objectteams.otre.util.FieldDescriptor;
import org.eclipse.objectteams.otre.util.SuperMethodDescriptor;

import org.apache.bcel.Constants;
import org.apache.bcel.classfile.Method;
import org.apache.bcel.generic.ClassGen;
import org.apache.bcel.generic.ConstantPoolGen;
import org.apache.bcel.generic.InstructionFactory;
import org.apache.bcel.generic.InstructionList;
import org.apache.bcel.generic.MethodGen;
import org.apache.bcel.generic.ObjectType;
import org.apache.bcel.generic.Type;

/**
 *  For each base method that is bound by callout and has
 *  insufficient visibility, the visibility is set to public.
 *  Check whether the affected base class resides in a sealed package.
 *  In that case dissallow decapsulation by throwing an IllegalAccessError.
 *  
 *  @version $Id: Decapsulation.java 23408 2010-02-03 18:07:35Z stephan $
 *  @author Stephan Herrmann
 */
public class Decapsulation 
	extends ObjectTeamsTransformation
	implements Constants 
{
	
//	HashSet modifiedPackages = new HashSet();

	private HashSet<String/*callout accessed fields*/> generatedFieldCalloutAccessors = new HashSet<String>();
	private HashSet<String/*super-accessed methods (sign)*/> generatedSuperAccessors  = new HashSet<String>();
	
    public Decapsulation(Object loader) {
    	super(loader);
    }

	/**
	 * Main entry for this transformer.
	 */
	public void doTransformInterface(ClassEnhancer ce, ClassGen cg) {		
		String          class_name = cg.getClassName();
		ConstantPoolGen cpg        = cg.getConstantPool();

		checkReadClassAttributes(ce, cg, class_name, cpg);


		generateFieldAccessForCallout(ce, cg, class_name, cpg);
		
		generateSuperAccessors(ce, cg, class_name, cpg);

		HashSet<String> calloutBindings = CallinBindingManager.getCalloutBindings(class_name);

		if (calloutBindings == null) {
            if(logging) printLogMessage("\nClass " + class_name 
					+ " requires no callout adjustment.");
			return; 
		}
			
        if(logging) printLogMessage("\nCallout bindings might be changing class " 
					+ class_name + ":");

		HashSet<String> oldStyleBinding = new HashSet<String>();
		
		// try new style decapsulation first (since 1.2.8):
		for (String calloutBinding : calloutBindings) {
			DecapsulationDescriptor desc = new DecapsulationDescriptor();
			if (!desc.decode(calloutBinding, cg))
				oldStyleBinding.add(calloutBinding); // old style attribute
			else if (!desc.existsAlready) 
				ce.addMethod(desc.generate(class_name, cpg), cg);
		}
		
		if (oldStyleBinding.isEmpty()) return;
		
		// --> follows: old style decapsulation for remaining bindings:
		int pos = class_name.lastIndexOf('.');
		String package_name = "NO_PACKAGE";
		if (pos != -1)
			package_name = class_name.substring(0,pos);
			
		Method[] methods = cg.getMethods();
		for (int i = 0; i < methods.length; i++) {
			Method m           = methods[i];
			String method_name = m.getName();
			
			boolean requiresAdjustment = CallinBindingManager.
			requiresCalloutAdjustment(oldStyleBinding, 
										method_name,
										m.getSignature());
				
			if (requiresAdjustment) {
				ce.decapsulateMethod(m, cg, package_name, cpg);
			}
		}
	}

	class DecapsulationDescriptor {
		short invokeKind;
		String targetClass;
		String methodName;
		String methodSign;
		Type returnType; 
		Type[] args;
		String accessorName;
		
		boolean existsAlready;
		
		/**
		 * new style encoding is
		 * targetClassName ('!' | '?') methodName '.' methodSign 
		 */
		boolean decode(String encodedBinding, ClassGen cg) {
			int sepPos = encodedBinding.indexOf('!');
			if (sepPos != -1) { // static method:
				invokeKind = INVOKESTATIC;
			} else {
				sepPos = encodedBinding.indexOf('?');
				if (sepPos != -1) {
					invokeKind = INVOKEVIRTUAL;
				} else {
					return false; // old style
				}
			}
			targetClass = encodedBinding.substring(0, sepPos);
			int sigPos = encodedBinding.indexOf('(', sepPos);
			methodName = encodedBinding.substring(sepPos+1, sigPos);
			methodSign = encodedBinding.substring(sigPos);
			
			returnType = Type.getReturnType(methodSign); 
			args = Type.getArgumentTypes(methodSign);

			accessorName = "_OT$decaps$"+methodName;
			existsAlready = cg.containsMethod(accessorName, methodSign) != null;
			if (invokeKind == INVOKEVIRTUAL) {
				Method existing = cg.containsMethod(methodName, methodSign);
				if (existing != null && existing.isPrivate())
					invokeKind = INVOKESPECIAL; // accessing private
			}
			
			return true;
		}
		Method generate(String currentClass, ConstantPoolGen cpg) {
			InstructionList il = new InstructionList();
			int instanceOffset = 0;
			short flags = Constants.ACC_PUBLIC;
			if (invokeKind != INVOKESTATIC) {
				instanceOffset=1;
				il.append(InstructionFactory.createThis());
			} else {
				flags |= Constants.ACC_STATIC;
			}
			int pos= 0;
			for (int i = 0; i < args.length; i++) {
				il.append(InstructionFactory.createLoad(args[i], pos+instanceOffset));
				pos += args[i].getSize();
			}
			il.append(new InstructionFactory(cpg).createInvoke(targetClass, methodName, returnType, args, invokeKind));
			il.append(InstructionFactory.createReturn(returnType));
			MethodGen newMethod = new MethodGen(flags, returnType, args, /*argNames*/null, accessorName, currentClass, il, cpg);
			newMethod.setMaxLocals();
			newMethod.setMaxStack();
			return newMethod.getMethod();
		}
	}

	/**
	 * Generates getter and setter methods for all fields of the class 'class_name' which are accessed via callout. 
	 * Informations are received via attributs (CallinBindingManager). 
	 * @param cg					the ClassGen of the appropriate class
	 * @param class_name		the name of the class
	 * @param cpg					the ConstantPoolGen of the class
	 * @param es					the ExtensionSet to add the new access methods
	 */
	private void generateFieldAccessForCallout(ClassEnhancer ce, ClassGen cg, String class_name, ConstantPoolGen cpg) {
		InstructionFactory factory = null;
		
		HashSet<String> addedAccessMethods = this.generatedFieldCalloutAccessors;

		List<FieldDescriptor> getter = CallinBindingManager.getCalloutGetFields(class_name);
		if (getter != null) {
	    	factory = new InstructionFactory(cg);
			Iterator<FieldDescriptor> it = getter.iterator();
			while (it.hasNext()) {
				FieldDescriptor fd = it.next();
				String key = "get_" + class_name +"." + fd.getFieldName() + fd.getFieldSignature();
				if (logging)
					printLogMessage("Generating getter method "+key);
				if (addedAccessMethods == null)
					addedAccessMethods = new HashSet<String>();
				if (addedAccessMethods.contains(key))
					continue; // this getter has already been created
				ce.addMethod(generateGetter(cpg, class_name, fd, factory), cg);
				addedAccessMethods.add(key);
			}
		}

		List<FieldDescriptor> setter = CallinBindingManager.getCalloutSetFields(class_name);
		if (setter != null) {
			if (factory == null)
		    	factory = new InstructionFactory(cg);
			Iterator<FieldDescriptor> it = setter.iterator();
			while (it.hasNext()) {
				FieldDescriptor fd = it.next();
				String key = "set_"+ class_name +"." + fd.getFieldName()+fd.getFieldSignature();
				if (logging)
					printLogMessage("Generating setter method "+key);
				if (addedAccessMethods == null)
					addedAccessMethods = new HashSet<String>();
				if (addedAccessMethods.contains(key))
					continue; // this setter has already been created
				ce.addMethod(generateSetter(cpg, class_name, fd, factory), cg);
				addedAccessMethods.add(key);
			}
		}
	}


	/**
	 * Generates a getter method for the field described by 'fd' in the class 'class_name'. 
	 * @param cpg					the ConstantPoolGen of the class
	 * @param class_name		the name of the class
	 * @param fd						the FieldDescriptor describing the affected field
	 * @param factory				an InstructionFactory for this class
	 * @return							the generated getter method
	 */
	private Method generateGetter(ConstantPoolGen cpg, String class_name, FieldDescriptor fd, InstructionFactory factory) {
		String fieldName = fd.getFieldName();
		Type fieldType =  Type.getType(fd.getFieldSignature());
		Type baseType = new ObjectType(class_name);
		
		InstructionList il = new InstructionList();
		String[] argumentNames;
		Type[]   argumentTypes;
		if (fd.isStaticField()) {
			argumentNames = new String[0];
			argumentTypes = new Type[0];
		} else {
			argumentNames = new String[] {"base_obj"};
			argumentTypes = new Type[]   {baseType};
		}
		MethodGen mg = new MethodGen((Constants.ACC_PUBLIC|Constants.ACC_STATIC),
	 			  												  fieldType,
																  argumentTypes,
																  argumentNames,
																  OT_PREFIX+"get$"+fieldName,
																  class_name,
																  il, cpg);
		if (!fd.isStaticField())
			il.append(InstructionFactory.createLoad(baseType, 0)); // first argument is at slot 0 in static methods
		short fieldKind = fd.isStaticField()?Constants.GETSTATIC:Constants.GETFIELD;
		il.append(factory.createFieldAccess(class_name, fieldName, fieldType, fieldKind));
		il.append(InstructionFactory.createReturn(fieldType));

		mg.removeNOPs();
		mg.setMaxStack();
		mg.setMaxLocals();
		return mg.getMethod();
	}
	

	/**
	 * Generates a setter method for the field described by 'fd' in the class 'class_name'. 
	 * @param cpg					the ConstantPoolGen of the class
	 * @param class_name		the name of the class
	 * @param fd						the FieldDescriptor describing the affected field
	 * @param factory				an InstructionFactory for this class
	 * @return							the generated getter method
	 */
	private Method generateSetter(ConstantPoolGen cpg, String class_name, FieldDescriptor fd, InstructionFactory factory ) {
		String fieldName = fd.getFieldName();
		Type fieldType =  Type.getType(fd.getFieldSignature());
		Type baseType = new ObjectType(class_name);

		Type[]   argumentTypes;
		String[] argumentNames;
		if (fd.isStaticField()) {
			argumentTypes = new Type[]   { fieldType};
			argumentNames = new String[] {"new_value"};			
		} else {
			argumentTypes = new Type[]   {baseType,   fieldType};
			argumentNames = new String[] {"base_obj", "new_value"};
		}
		
		InstructionList il = new InstructionList();
		MethodGen mg = new MethodGen((Constants.ACC_PUBLIC|Constants.ACC_STATIC),
	 			  												  Type.VOID,
																  argumentTypes,
																  argumentNames,
																  OT_PREFIX+"set$"+fieldName,
																  class_name,
																  il, cpg);

		int argumentPosition; // position for the argument holding the new field value.
		if (!fd.isStaticField()) {
			il.append(InstructionFactory.createLoad(baseType, 0)); // first argument is at slot 0 in static methods
			argumentPosition = 1;
		} else {
			argumentPosition = 0;
		}
		il.append(InstructionFactory.createLoad(fieldType, argumentPosition));
		short fieldKind = fd.isStaticField()?Constants.PUTSTATIC:Constants.PUTFIELD;
		il.append(factory.createFieldAccess(class_name, fieldName, fieldType, fieldKind));
		il.append(InstructionFactory.createReturn(Type.VOID));

		mg.removeNOPs();
		mg.setMaxStack();
		mg.setMaxLocals();
		return mg.getMethod();
	}
	
	private void generateSuperAccessors(ClassEnhancer ce, ClassGen cg, String class_name, ConstantPoolGen cpg) {
		InstructionFactory factory = null;
		
		HashSet<String> addedAccessMethods = this.generatedSuperAccessors;

		List<SuperMethodDescriptor> methods = CallinBindingManager.getSuperAccesses(class_name);
		if (methods != null) {
	    	factory = new InstructionFactory(cg);
	    	for (SuperMethodDescriptor superMethod : methods) {
				String key = superMethod.methodName+'.'+superMethod.signature;
				if (logging)
					printLogMessage("Generating super access method "+key);
				if (addedAccessMethods == null)
					addedAccessMethods = new HashSet<String>();
				if (addedAccessMethods.contains(key))
					continue; // this accessor has already been created
				ce.addMethod(generateSuperAccessor(cpg, class_name, superMethod, factory), cg);
				addedAccessMethods.add(key);
			}
		}
	}
	
	private Method generateSuperAccessor(ConstantPoolGen cpg, String className, SuperMethodDescriptor superMethod, InstructionFactory factory) 
	{ 
		int endPos = superMethod.signature.indexOf(')');
		String segment = superMethod.signature.substring(1, endPos);
		String[] typeNames = (segment.length() > 0) ? segment.split(",") : new String[0];
		Type[] argTypes = new Type[typeNames.length];
		for (int i = 0; i < argTypes.length; i++) 
			argTypes[i] = Type.getType(typeNames[i]);
		
		int index = superMethod.signature.lastIndexOf(')') + 1;
		Type returnType = Type.getType(superMethod.signature.substring(index));
		
		Type baseType = new ObjectType(className);
		Type[] wrapperTypes = new Type[argTypes.length+1];
		System.arraycopy(argTypes, 0, wrapperTypes, 1, argTypes.length);
		wrapperTypes[0] = baseType;
		String[] argNames = new String[wrapperTypes.length];
		for (int i = 0; i < argNames.length; i++) {
			argNames[i] = "arg"+i;
		}
		InstructionList il = new InstructionList();
		MethodGen mg = new MethodGen((Constants.ACC_PUBLIC|Constants.ACC_STATIC),
									 returnType,
									 wrapperTypes,
									 argNames,
									 OT_PREFIX+superMethod.methodName+"$super",
									 className,
									 il, cpg);
		il.append(InstructionFactory.createLoad(baseType, 0)); // first argument is base instance
		for (int i = 0; i < argTypes.length; i++) 
			il.append(InstructionFactory.createLoad(argTypes[i], i+1));
		
		// if super method is also callin bound directly invoke the orig-version 
		// (to avoid that BaseMethodTransformation.checkReplaceWickedSuper() has to rewrite this code again): 
		String methodName = (CallinBindingManager.isBoundBaseMethod(superMethod.superClass, superMethod.methodName, superMethod.signature))
								? genOrigMethName(superMethod.methodName)
								: superMethod.methodName;
		
		il.append(factory.createInvoke(superMethod.superClass, methodName, returnType, argTypes, INVOKESPECIAL));
		il.append(InstructionFactory.createReturn(returnType));
		mg.setMaxStack();
		mg.setMaxLocals();
		return mg.getMethod();
	}
	
}
