package org.aspectj.apache.bcel.classfile;

/* ====================================================================
 * The Apache Software License, Version 1.1
 *
 * Copyright (c) 2001 The Apache Software Foundation.  All rights
 * reserved.
 *
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions
 * are met:
 *
 * 1. Redistributions of source code must retain the above copyright
 *    notice, this list of conditions and the following disclaimer.
 *
 * 2. Redistributions in binary form must reproduce the above copyright
 *    notice, this list of conditions and the following disclaimer in
 *    the documentation and/or other materials provided with the
 *    distribution.
 *
 * 3. The end-user documentation included with the redistribution,
 *    if any, must include the following acknowledgment:
 *       "This product includes software developed by the
 *        Apache Software Foundation (http://www.apache.org/)."
 *    Alternately, this acknowledgment may appear in the software itself,
 *    if and wherever such third-party acknowledgments normally appear.
 *
 * 4. The names "Apache" and "Apache Software Foundation" and
 *    "Apache BCEL" must not be used to endorse or promote products
 *    derived from this software without prior written permission. For
 *    written permission, please contact apache@apache.org.
 *
 * 5. Products derived from this software may not be called "Apache",
 *    "Apache BCEL", nor may "Apache" appear in their name, without
 *    prior written permission of the Apache Software Foundation.
 *
 * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED
 * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
 * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
 * DISCLAIMED.  IN NO EVENT SHALL THE APACHE SOFTWARE FOUNDATION OR
 * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
 * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
 * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
 * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
 * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
 * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
 * SUCH DAMAGE.
 * ====================================================================
 *
 * This software consists of voluntary contributions made by many
 * individuals on behalf of the Apache Software Foundation.  For more
 * information on the Apache Software Foundation, please see
 * <http://www.apache.org/>.
 */

import java.io.ByteArrayOutputStream;
import java.io.DataOutputStream;
import java.io.File;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.OutputStream;
import java.util.ArrayList;
import java.util.Collection;
import java.util.LinkedList;
import java.util.List;
import java.util.Queue;
import java.util.StringTokenizer;

import org.aspectj.apache.bcel.Constants;
import org.aspectj.apache.bcel.classfile.annotation.AnnotationGen;
import org.aspectj.apache.bcel.classfile.annotation.RuntimeAnnos;
import org.aspectj.apache.bcel.generic.Type;
import org.aspectj.apache.bcel.util.SyntheticRepository;

/**
 * Represents a Java class, i.e., the data structures, constant pool, fields, methods and commands contained in a Java .class file.
 * See <a href="ftp://java.sun.com/docs/specs/">JVM specification</a> for details.
 * 
 * The intent of this class is to represent a parsed or otherwise existing class file. Those interested in programatically
 * generating classes should see the <a href="../generic/ClassGen.html">ClassGen</a> class.
 * 
 * @version $Id: JavaClass.java,v 1.22 2009/09/15 19:40:14 aclement Exp $
 * @see org.aspectj.apache.bcel.generic.ClassGen
 * @author <A HREF="mailto:markus.dahm@berlin.de">M. Dahm</A>
 */
public class JavaClass extends Modifiers implements Cloneable, Node {

	private static final String[] NoInterfaceNames = new String[0];
	private static final Field[] NoFields = new Field[0];
	private static final Method[] NoMethod = new Method[0];
	private static final int[] NoInterfaceIndices = new int[0];
	private static final Attribute[] NoAttributes = new Attribute[0];

	private String fileName;
	private String packageName;
	private String sourcefileName;
	private int classnameIdx;
	private int superclassnameIdx;
	private String classname;
	private String superclassname;
	private int major, minor;
	private ConstantPool cpool;
	private int[] interfaces;
	private String[] interfacenames;
	private Field[] fields;
	private Method[] methods;
	private Attribute[] attributes;
	private AnnotationGen[] annotations;

	private boolean isGeneric = false;
	private boolean isAnonymous = false;
	private boolean isNested = false;
	private boolean computedNestedTypeStatus = false;

	// Annotations are collected from certain attributes, don't do it more than necessary!
	private boolean annotationsOutOfDate = true;

	// state for dealing with generic signature string
	private String signatureAttributeString = null;
	private Signature signatureAttribute = null;
	private boolean searchedForSignatureAttribute = false;

	/**
	 * In cases where we go ahead and create something, use the default SyntheticRepository, because we don't know any better.
	 */
	private transient org.aspectj.apache.bcel.util.Repository repository = null;

	public JavaClass(int classnameIndex, int superclassnameIndex, String filename, int major, int minor, int access_flags,
			ConstantPool cpool, int[] interfaces, Field[] fields, Method[] methods, Attribute[] attributes) {
		if (interfaces == null) {
			interfaces = NoInterfaceIndices;
		}

		this.classnameIdx = classnameIndex;
		this.superclassnameIdx = superclassnameIndex;
		this.fileName = filename;
		this.major = major;
		this.minor = minor;
		this.modifiers = access_flags;
		this.cpool = cpool;
		this.interfaces = interfaces;
		this.fields = (fields == null ? NoFields : fields);
		this.methods = (methods == null ? NoMethod : methods);
		this.attributes = (attributes == null ? NoAttributes : attributes);
		annotationsOutOfDate = true;

		// Get source file name if available
		SourceFile sfAttribute = AttributeUtils.getSourceFileAttribute(attributes);
		sourcefileName = sfAttribute == null ? "<Unknown>" : sfAttribute.getSourceFileName();

		/*
		 * According to the specification the following entries must be of type `ConstantClass' but we check that anyway via the
		 * `ConstPool.getConstant' method.
		 */
		classname = cpool.getConstantString(classnameIndex, Constants.CONSTANT_Class);
		classname = Utility.compactClassName(classname, false);

		int index = classname.lastIndexOf('.');
		if (index < 0) {
			packageName = "";
		} else {
			packageName = classname.substring(0, index);
		}

		if (superclassnameIndex > 0) { // May be zero -> class is java.lang.Object
			superclassname = cpool.getConstantString(superclassnameIndex, Constants.CONSTANT_Class);
			superclassname = Utility.compactClassName(superclassname, false);
		} else {
			superclassname = "java.lang.Object";
		}

		if (interfaces.length == 0) {
			interfacenames = NoInterfaceNames;
		} else {
			interfacenames = new String[interfaces.length];
			for (int i = 0; i < interfaces.length; i++) {
				String str = cpool.getConstantString(interfaces[i], Constants.CONSTANT_Class);
				interfacenames[i] = Utility.compactClassName(str, false);
			}
		}
	}

	/**
	 * Called by objects that are traversing the nodes of the tree implicitely defined by the contents of a Java class. I.e., the
	 * hierarchy of methods, fields, attributes, etc. spawns a tree of objects.
	 * 
	 * @param v Visitor object
	 */
	public void accept(ClassVisitor v) {
		v.visitJavaClass(this);
	}

	/**
	 * Dump class to a file.
	 * 
	 * @param file Output file
	 * @throws IOException
	 */
	public void dump(File file) throws IOException {
		String parent = file.getParent();
		if (parent != null) {
			File dir = new File(parent);
			dir.mkdirs();
		}
		dump(new DataOutputStream(new FileOutputStream(file)));
	}

	/**
	 * Dump class to a file named file_name.
	 * 
	 * @param file_name Output file name
	 * @exception IOException
	 */
	public void dump(String file_name) throws IOException {
		dump(new File(file_name));
	}

	/**
	 * @return class in binary format
	 */
	public byte[] getBytes() {
		ByteArrayOutputStream s = new ByteArrayOutputStream();
		DataOutputStream ds = new DataOutputStream(s);

		try {
			dump(ds);
		} catch (IOException e) {
			e.printStackTrace();
		} finally {
			try {
				ds.close();
			} catch (IOException e2) {
				e2.printStackTrace();
			}
		}

		return s.toByteArray();
	}

	/**
	 * Dump Java class to output stream in binary format.
	 */
	public void dump(OutputStream file) throws IOException {
		dump(new DataOutputStream(file));
	}

	/**
	 * Dump Java class to output stream in binary format.
	 */
	public void dump(DataOutputStream file) throws IOException {
		file.writeInt(0xcafebabe);
		file.writeShort(minor);
		file.writeShort(major);

		cpool.dump(file);

		file.writeShort(modifiers);
		file.writeShort(classnameIdx);
		file.writeShort(superclassnameIdx);

		file.writeShort(interfaces.length);
		for (int i = 0; i < interfaces.length; i++) {
			file.writeShort(interfaces[i]);
		}

		file.writeShort(fields.length);
		for (int i = 0; i < fields.length; i++) {
			fields[i].dump(file);
		}

		file.writeShort(methods.length);
		for (int i = 0; i < methods.length; i++) {
			methods[i].dump(file);
		}

		AttributeUtils.writeAttributes(attributes, file);

		file.close();
	}

	public Attribute[] getAttributes() {
		return attributes;
	}

	public AnnotationGen[] getAnnotations() {
		if (annotationsOutOfDate) {
			// Find attributes that contain annotation data
			List<AnnotationGen> accumulatedAnnotations = new ArrayList<AnnotationGen>();
			for (int i = 0; i < attributes.length; i++) {
				Attribute attribute = attributes[i];
				if (attribute instanceof RuntimeAnnos) {
					RuntimeAnnos runtimeAnnotations = (RuntimeAnnos) attribute;
					accumulatedAnnotations.addAll(runtimeAnnotations.getAnnotations());
				}
			}
			annotations = accumulatedAnnotations.toArray(new AnnotationGen[] {});
			annotationsOutOfDate = false;
		}
		return annotations;
	}

	/**
	 * @return Class name.
	 */
	public String getClassName() {
		return classname;
	}

	/**
	 * @return Package name.
	 */
	public String getPackageName() {
		return packageName;
	}

	public int getClassNameIndex() {
		return classnameIdx;
	}

	public ConstantPool getConstantPool() {
		return cpool;
	}

	/**
	 * @return Fields, i.e., variables of the class. Like the JVM spec mandates for the classfile format, these fields are those
	 *         specific to this class, and not those of the superclass or superinterfaces.
	 */
	public Field[] getFields() {
		return fields;
	}

	/**
	 * @return File name of class, aka SourceFile attribute value
	 */
	public String getFileName() {
		return fileName;
	}

	/**
	 * @return Names of implemented interfaces.
	 */
	public String[] getInterfaceNames() {
		return interfacenames;
	}

	/**
	 * @return Indices in constant pool of implemented interfaces.
	 */
	public int[] getInterfaceIndices() {
		return interfaces;
	}

	public int getMajor() {
		return major;
	}

	/**
	 * @return Methods of the class.
	 */
	public Method[] getMethods() {
		return methods;
	}

	/**
	 * @return A org.aspectj.apache.bcel.classfile.Method corresponding to java.lang.reflect.Method if any
	 */
	public Method getMethod(java.lang.reflect.Method m) {
		for (int i = 0; i < methods.length; i++) {
			Method method = methods[i];

			if (m.getName().equals(method.getName()) && m.getModifiers() == method.getModifiers()
					&& Type.getSignature(m).equals(method.getSignature())) {
				return method;
			}
		}

		return null;
	}

	public Method getMethod(java.lang.reflect.Constructor<?> c) {
		for (int i = 0; i < methods.length; i++) {
			Method method = methods[i];
			if (method.getName().equals("<init>") && c.getModifiers() == method.getModifiers()
					&& Type.getSignature(c).equals(method.getSignature())) {
				return method;
			}
		}

		return null;
	}

	public Field getField(java.lang.reflect.Field field) {
		String fieldName = field.getName();
		for (Field f : fields) {
			if (f.getName().equals(fieldName)) {
				return f;
			}
		}
		return null;
	}

	/**
	 * @return Minor number of class file version.
	 */
	public int getMinor() {
		return minor;
	}

	/**
	 * @return sbsolute path to file where this class was read from
	 */
	public String getSourceFileName() {
		return sourcefileName;
	}

	/**
	 * @return Superclass name.
	 */
	public String getSuperclassName() {
		return superclassname;
	}

	/**
	 * @return Class name index.
	 */
	public int getSuperclassNameIndex() {
		return superclassnameIdx;
	}

	/**
	 * @param attributes .
	 */
	public void setAttributes(Attribute[] attributes) {
		this.attributes = attributes;
		annotationsOutOfDate = true;
	}

	/**
	 * @param class_name .
	 */
	public void setClassName(String class_name) {
		this.classname = class_name;
	}

	/**
	 * @param class_name_index .
	 */
	public void setClassNameIndex(int class_name_index) {
		this.classnameIdx = class_name_index;
	}

	/**
	 * @param constant_pool .
	 */
	public void setConstantPool(ConstantPool constant_pool) {
		this.cpool = constant_pool;
	}

	/**
	 * @param fields .
	 */
	public void setFields(Field[] fields) {
		this.fields = fields;
	}

	/**
	 * Set File name of class, aka SourceFile attribute value
	 */
	public void setFileName(String file_name) {
		this.fileName = file_name;
	}

	/**
	 * @param interface_names .
	 */
	public void setInterfaceNames(String[] interface_names) {
		this.interfacenames = interface_names;
	}

	/**
	 * @param interfaces .
	 */
	public void setInterfaces(int[] interfaces) {
		this.interfaces = interfaces;
	}

	public void setMajor(int major) {
		this.major = major;
	}

	public void setMethods(Method[] methods) {
		this.methods = methods;
	}

	public void setMinor(int minor) {
		this.minor = minor;
	}

	/**
	 * Set absolute path to file this class was read from.
	 */
	public void setSourceFileName(String source_file_name) {
		this.sourcefileName = source_file_name;
	}

	/**
	 * @param superclass_name .
	 */
	public void setSuperclassName(String superclass_name) {
		this.superclassname = superclass_name;
	}

	/**
	 * @param superclass_name_index .
	 */
	public void setSuperclassNameIndex(int superclass_name_index) {
		this.superclassnameIdx = superclass_name_index;
	}

	/**
	 * @return String representing class contents.
	 */
	@Override
	public String toString() {
		String access = Utility.accessToString(modifiers, true);
		access = access.equals("") ? "" : access + " ";

		StringBuffer buf = new StringBuffer(access + Utility.classOrInterface(modifiers) + " " + classname + " extends "
				+ Utility.compactClassName(superclassname, false) + '\n');
		int size = interfaces.length;

		if (size > 0) {
			buf.append("implements\t\t");

			for (int i = 0; i < size; i++) {
				buf.append(interfacenames[i]);
				if (i < size - 1) {
					buf.append(", ");
				}
			}

			buf.append('\n');
		}

		buf.append("filename\t\t" + fileName + '\n');
		buf.append("compiled from\t\t" + sourcefileName + '\n');
		buf.append("compiler version\t" + major + "." + minor + '\n');
		buf.append("access flags\t\t" + modifiers + '\n');
		buf.append("constant pool\t\t" + cpool.getLength() + " entries\n");
		buf.append("ACC_SUPER flag\t\t" + isSuper() + "\n");

		if (attributes.length > 0) {
			buf.append("\nAttribute(s):\n");
			for (int i = 0; i < attributes.length; i++) {
				buf.append(indent(attributes[i]));
			}
		}

		if (annotations != null && annotations.length > 0) {
			buf.append("\nAnnotation(s):\n");
			for (int i = 0; i < annotations.length; i++) {
				buf.append(indent(annotations[i]));
			}
		}

		if (fields.length > 0) {
			buf.append("\n" + fields.length + " fields:\n");
			for (int i = 0; i < fields.length; i++) {
				buf.append("\t" + fields[i] + '\n');
			}
		}

		if (methods.length > 0) {
			buf.append("\n" + methods.length + " methods:\n");
			for (int i = 0; i < methods.length; i++) {
				buf.append("\t" + methods[i] + '\n');
			}
		}

		return buf.toString();
	}

	private static final String indent(Object obj) {
		StringTokenizer tok = new StringTokenizer(obj.toString(), "\n");
		StringBuffer buf = new StringBuffer();

		while (tok.hasMoreTokens()) {
			buf.append("\t" + tok.nextToken() + "\n");
		}

		return buf.toString();
	}

	public final boolean isSuper() {
		return (modifiers & Constants.ACC_SUPER) != 0;
	}

	public final boolean isClass() {
		return (modifiers & Constants.ACC_INTERFACE) == 0;
	}

	public final boolean isAnonymous() {
		computeNestedTypeStatus();
		return this.isAnonymous;
	}

	public final boolean isNested() {
		computeNestedTypeStatus();
		return this.isNested;
	}

	private final void computeNestedTypeStatus() {
		if (computedNestedTypeStatus) {
			return;
		}
		// Attribute[] attrs = attributes.getAttributes();
		for (int i = 0; i < attributes.length; i++) {
			if (attributes[i] instanceof InnerClasses) {
				InnerClass[] innerClasses = ((InnerClasses) attributes[i]).getInnerClasses();
				for (int j = 0; j < innerClasses.length; j++) {
					boolean innerClassAttributeRefersToMe = false;
					String inner_class_name = cpool.getConstantString(innerClasses[j].getInnerClassIndex(),
							Constants.CONSTANT_Class);
					inner_class_name = Utility.compactClassName(inner_class_name);
					if (inner_class_name.equals(getClassName())) {
						innerClassAttributeRefersToMe = true;
					}
					if (innerClassAttributeRefersToMe) {
						this.isNested = true;
						if (innerClasses[j].getInnerNameIndex() == 0) {
							this.isAnonymous = true;
						}
					}
				}
			}
		}
		this.computedNestedTypeStatus = true;
	}

	// J5SUPPORT:
	/**
	 * Returns true if this class represents an annotation, i.e. it was a 'public @interface blahblah' declaration
	 */
	public final boolean isAnnotation() {
		return (modifiers & Constants.ACC_ANNOTATION) != 0;
	}

	/**
	 * Returns true if this class represents an enum type
	 */
	public final boolean isEnum() {
		return (modifiers & Constants.ACC_ENUM) != 0;
	}

	/********************* New repository functionality *********************/

	/**
	 * Gets the ClassRepository which holds its definition. By default this is the same as SyntheticRepository.getInstance();
	 */
	public org.aspectj.apache.bcel.util.Repository getRepository() {
		if (repository == null) {
			repository = SyntheticRepository.getInstance();
		}
		return repository;
	}

	/**
	 * Sets the ClassRepository which loaded the JavaClass. Should be called immediately after parsing is done.
	 */
	public void setRepository(org.aspectj.apache.bcel.util.Repository repository) {
		this.repository = repository;
	}

	/**
	 * Equivalent to runtime "instanceof" operator.
	 * 
	 * @return true if this JavaClass is derived from teh super class
	 */
	public final boolean instanceOf(JavaClass super_class) {
		if (this.equals(super_class)) {
			return true;
		}

		JavaClass[] super_classes = getSuperClasses();

		for (int i = 0; i < super_classes.length; i++) {
			if (super_classes[i].equals(super_class)) {
				return true;
			}
		}

		if (super_class.isInterface()) {
			return implementationOf(super_class);
		}

		return false;
	}

	/**
	 * @return true, if clazz is an implementation of interface inter
	 */
	public boolean implementationOf(JavaClass inter) {
		if (!inter.isInterface()) {
			throw new IllegalArgumentException(inter.getClassName() + " is no interface");
		}

		if (this.equals(inter)) {
			return true;
		}

		Collection<JavaClass> superInterfaces = getAllInterfaces();

		for (JavaClass superInterface : superInterfaces) {
			if (superInterface.equals(inter)) {
				return true;
			}
		}
		// for (int i = 0; i < super_interfaces.length; i++) {
		// if (super_interfaces[i].equals(inter)) {
		// return true;
		// }
		// }

		return false;
	}

	/**
	 * @return the superclass for this JavaClass object, or null if this is java.lang.Object
	 */
	public JavaClass getSuperClass() {
		if ("java.lang.Object".equals(getClassName())) {
			return null;
		}

		try {
			return getRepository().loadClass(getSuperclassName());
		} catch (ClassNotFoundException e) {
			System.err.println(e);
			return null;
		}
	}

	/**
	 * @return list of super classes of this class in ascending order, i.e., java.lang.Object is always the last element
	 */
	public JavaClass[] getSuperClasses() {
		JavaClass clazz = this;
		List<JavaClass> vec = new ArrayList<JavaClass>();
		for (clazz = clazz.getSuperClass(); clazz != null; clazz = clazz.getSuperClass()) {
			vec.add(clazz);
		}
		return vec.toArray(new JavaClass[vec.size()]);
	}

	/**
	 * Get interfaces directly implemented by this JavaClass.
	 */
	public JavaClass[] getInterfaces() {
		String[] interfaces = getInterfaceNames();
		JavaClass[] classes = new JavaClass[interfaces.length];

		try {
			for (int i = 0; i < interfaces.length; i++) {
				classes[i] = getRepository().loadClass(interfaces[i]);
			}
		} catch (ClassNotFoundException e) {
			System.err.println(e);
			return null;
		}

		return classes;
	}

	/**
	 * Get all interfaces implemented by this JavaClass (transitively).
	 */
	public Collection<JavaClass> getAllInterfaces() {
		Queue<JavaClass> queue = new LinkedList<JavaClass>();
		List<JavaClass> interfaceList = new ArrayList<JavaClass>();

		queue.add(this);

		while (!queue.isEmpty()) {
			JavaClass clazz = queue.remove();

			JavaClass souper = clazz.getSuperClass();
			JavaClass[] interfaces = clazz.getInterfaces();

			if (clazz.isInterface()) {
				interfaceList.add(clazz);
			} else {
				if (souper != null) {
					queue.add(souper);
				}
			}

			for (int i = 0; i < interfaces.length; i++) {
				queue.add(interfaces[i]);
			}
		}

		return interfaceList;
		// return interfaceList.toArray(new JavaClass[interfaceList.size()]);
	}

	/**
	 * Hunts for a signature attribute on the member and returns its contents. So where the 'regular' signature may be
	 * Ljava/util/Vector; the signature attribute will tell us e.g. "<E:>Ljava/lang/Object". We can learn the type variable names,
	 * their bounds, and the true superclass and superinterface types (including any parameterizations) Coded for performance -
	 * searches for the attribute only when requested - only searches for it once.
	 */
	public final String getGenericSignature() {
		loadGenericSignatureInfoIfNecessary();
		return signatureAttributeString;
	}

	public boolean isGeneric() {
		loadGenericSignatureInfoIfNecessary();
		return isGeneric;
	}

	private void loadGenericSignatureInfoIfNecessary() {
		if (!searchedForSignatureAttribute) {
			signatureAttribute = AttributeUtils.getSignatureAttribute(attributes);
			signatureAttributeString = signatureAttribute == null ? null : signatureAttribute.getSignature();
			isGeneric = signatureAttribute != null && signatureAttributeString.charAt(0) == '<';
			searchedForSignatureAttribute = true;
		}
	}

	public final Signature getSignatureAttribute() {
		loadGenericSignatureInfoIfNecessary();
		return signatureAttribute;
	}

}
